1 /*******************************************************************************
2  * Copyright (c) 2000, 2020 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.internal.core;
15 
16 import java.io.InputStream;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 
20 import org.eclipse.core.runtime.Assert;
21 import org.eclipse.core.runtime.IProgressMonitor;
22 import org.eclipse.jdt.core.*;
23 import org.eclipse.jdt.core.compiler.*;
24 import org.eclipse.jdt.core.search.SearchEngine;
25 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
26 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
27 import org.eclipse.jdt.internal.compiler.lookup.Binding;
28 import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
29 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
30 import org.eclipse.jdt.internal.core.util.Messages;
31 
32 /**
33  * Handle for a source type. Info object is a SourceTypeElementInfo.
34  *
35  * Note: Parent is either an IClassFile, an ICompilationUnit or an IType.
36  *
37  * @see IType
38  */
39 
40 @SuppressWarnings({ "rawtypes", "unchecked" })
41 public class SourceType extends NamedMember implements IType {
42 
43 /*
44  * A count to uniquely identify this element within the context of the enclosing type.
45  * Currently this is computed and used only for anonymous types.
46  */
47 public int localOccurrenceCount = 1;
48 private static final IField[] NO_FIELDS = new IField[0];
49 
SourceType(JavaElement parent, String name)50 protected SourceType(JavaElement parent, String name) {
51 	super(parent, name);
52 }
53 @Override
closing(Object info)54 protected void closing(Object info) throws JavaModelException {
55 	super.closing(info);
56 	SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) info;
57 	ITypeParameter[] typeParameters = elementInfo.typeParameters;
58 	for (int i = 0, length = typeParameters.length; i < length; i++) {
59 		((TypeParameter) typeParameters[i]).close();
60 	}
61 }
62 /**
63  * @see IType
64  * @deprecated
65  */
66 @Override
codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor)67 public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor) throws JavaModelException {
68 	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY);
69 }
70 /**
71  * @see IType
72  * @deprecated
73  */
74 @Override
codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor, WorkingCopyOwner owner)75 public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
76 	if (requestor == null) {
77 		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
78 	}
79 	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, new org.eclipse.jdt.internal.codeassist.CompletionRequestorWrapper(requestor), owner);
80 
81 }
82 /**
83  * @see IType
84  */
85 @Override
codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor)86 public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor) throws JavaModelException {
87 	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY);
88 }
89 /**
90  * @see IType
91  */
92 @Override
codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor, IProgressMonitor monitor)93 public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
94 	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY, monitor);
95 }
96 /**
97  * @see IType
98  */
99 @Override
codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor, WorkingCopyOwner owner)100 public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,CompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
101 	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, owner, null);
102 }
103 /**
104  * @see IType
105  */
106 @Override
codeComplete( char[] snippet, int insertion, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic, CompletionRequestor requestor, WorkingCopyOwner owner, IProgressMonitor monitor)107 public void codeComplete(
108 		char[] snippet,
109 		int insertion,
110 		int position,
111 		char[][] localVariableTypeNames,
112 		char[][] localVariableNames,
113 		int[] localVariableModifiers,
114 		boolean isStatic,
115 		CompletionRequestor requestor,
116 		WorkingCopyOwner owner,
117 		IProgressMonitor monitor) throws JavaModelException {
118 	if (requestor == null) {
119 		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
120 	}
121 
122 	JavaProject project = (JavaProject) getJavaProject();
123 	SearchableEnvironment environment = project.newSearchableNameEnvironment(owner, requestor.isTestCodeExcluded());
124 	CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project, owner, monitor);
125 
126 	String source = getCompilationUnit().getSource();
127 	if (source != null && insertion > -1 && insertion < source.length()) {
128 
129 		char[] prefix = CharOperation.concat(source.substring(0, insertion).toCharArray(), new char[]{'{'});
130 		char[] suffix = CharOperation.concat(new char[]{'}'}, source.substring(insertion).toCharArray());
131 		char[] fakeSource = CharOperation.concat(prefix, snippet, suffix);
132 
133 		BasicCompilationUnit cu =
134 			new BasicCompilationUnit(
135 				fakeSource,
136 				null,
137 				getElementName(),
138 				getParent());
139 
140 		engine.complete(cu, prefix.length + position, prefix.length, null/*extended context isn't computed*/);
141 	} else {
142 		engine.complete(this, snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
143 	}
144 	if (NameLookup.VERBOSE) {
145 		System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
146 		System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
147 	}
148 }
149 /**
150  * @see IType
151  */
152 @Override
createField(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor)153 public IField createField(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws JavaModelException {
154 	CreateFieldOperation op = new CreateFieldOperation(this, contents, force);
155 	if (sibling != null) {
156 		op.createBefore(sibling);
157 	}
158 	op.runOperation(monitor);
159 	return (IField) op.getResultElements()[0];
160 }
161 /**
162  * @see IType
163  */
164 @Override
createInitializer(String contents, IJavaElement sibling, IProgressMonitor monitor)165 public IInitializer createInitializer(String contents, IJavaElement sibling, IProgressMonitor monitor) throws JavaModelException {
166 	CreateInitializerOperation op = new CreateInitializerOperation(this, contents);
167 	if (sibling != null) {
168 		op.createBefore(sibling);
169 	}
170 	op.runOperation(monitor);
171 	return (IInitializer) op.getResultElements()[0];
172 }
173 /**
174  * @see IType
175  */
176 @Override
createMethod(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor)177 public IMethod createMethod(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws JavaModelException {
178 	CreateMethodOperation op = new CreateMethodOperation(this, contents, force);
179 	if (sibling != null) {
180 		op.createBefore(sibling);
181 	}
182 	op.runOperation(monitor);
183 	return (IMethod) op.getResultElements()[0];
184 }
185 /**
186  * @see IType
187  */
188 @Override
createType(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor)189 public IType createType(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws JavaModelException {
190 	CreateTypeOperation op = new CreateTypeOperation(this, contents, force);
191 	if (sibling != null) {
192 		op.createBefore(sibling);
193 	}
194 	op.runOperation(monitor);
195 	return (IType) op.getResultElements()[0];
196 }
197 @Override
equals(Object o)198 public boolean equals(Object o) {
199 	if (!(o instanceof SourceType)) return false;
200 	if (((SourceType) o).isLambda())
201 		return false;
202 	return super.equals(o);
203 }
204 /*
205  * @see IType
206  */
207 @Override
findMethods(IMethod method)208 public IMethod[] findMethods(IMethod method) {
209 	try {
210 		return findMethods(method, getMethods());
211 	} catch (JavaModelException e) {
212 		// if type doesn't exist, no matching method can exist
213 		return null;
214 	}
215 }
216 @Override
getAnnotations()217 public IAnnotation[] getAnnotations() throws JavaModelException {
218 	AnnotatableInfo info = (AnnotatableInfo) getElementInfo();
219 	return info.annotations;
220 }
221 @Override
getChildrenForCategory(String category)222 public IJavaElement[] getChildrenForCategory(String category) throws JavaModelException {
223 	IJavaElement[] children = getChildren();
224 	int length = children.length;
225 	if (length == 0) return NO_ELEMENTS;
226 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
227 	HashMap categories = info.getCategories();
228 	if (categories == null) return NO_ELEMENTS;
229 	IJavaElement[] result = new IJavaElement[length];
230 	int index = 0;
231 	for (int i = 0; i < length; i++) {
232 		IJavaElement child = children[i];
233 		String[] elementCategories = (String[]) categories.get(child);
234 		if (elementCategories != null)
235 			for (int j = 0, length2 = elementCategories.length; j < length2; j++) {
236 				if (elementCategories[j].equals(category))
237 					result[index++] = child;
238 			}
239 	}
240 	if (index == 0) return NO_ELEMENTS;
241 	if (index < length)
242 		System.arraycopy(result, 0, result = new IJavaElement[index], 0, index);
243 	return result;
244 }
245 /**
246  * @see IMember
247  */
248 @Override
getDeclaringType()249 public IType getDeclaringType() {
250 	IJavaElement parentElement = getParent();
251 	while (parentElement != null) {
252 		if (parentElement.getElementType() == IJavaElement.TYPE) {
253 			return (IType) parentElement;
254 		} else
255 			if (parentElement instanceof IMember) {
256 				parentElement = parentElement.getParent();
257 			} else {
258 				return null;
259 			}
260 	}
261 	return null;
262 }
263 @Override
getClassFile()264 public IOrdinaryClassFile getClassFile() {
265 	return null;
266 }
267 /**
268  * @see IJavaElement
269  */
270 @Override
getElementType()271 public int getElementType() {
272 	return TYPE;
273 }
274 /**
275  * @see IType#getField
276  */
277 @Override
getField(String fieldName)278 public IField getField(String fieldName) {
279 	return new SourceField(this, fieldName);
280 }
281 /**
282  * @see IType
283  */
284 @Override
getFields()285 public IField[] getFields() throws JavaModelException {
286 	if (!isRecord()) {
287 		ArrayList list = getChildrenOfType(FIELD);
288 		if (list.size() == 0) {
289 			return NO_FIELDS;
290 		}
291 		IField[] array= new IField[list.size()];
292 		list.toArray(array);
293 		return array;
294 	}
295 	return getFieldsOrComponents(false);
296 }
297 @Override
getRecordComponents()298 public IField[] getRecordComponents() throws JavaModelException {
299 	if (!isRecord())
300 		return NO_FIELDS;
301 	return getFieldsOrComponents(true);
302 }
getFieldsOrComponents(boolean component)303 private IField[] getFieldsOrComponents(boolean component) throws JavaModelException {
304 	ArrayList list = getChildrenOfType(FIELD);
305 	if (list.size() == 0) {
306 		return NO_FIELDS;
307 	}
308 	ArrayList<IField> fields = new ArrayList<>();
309 	for (Object object : list) {
310 		IField field = (IField) object;
311 		if (field.isRecordComponent() == component)
312 			fields.add(field);
313 	}
314 	IField[] array= new IField[fields.size()];
315 	fields.toArray(array);
316 	return array;
317 }
318 @Override
getRecordComponent(String compName)319 public IField getRecordComponent(String compName) {
320 	try {
321 		if (isRecord())
322 			return new SourceField(this, compName);
323 	} catch (JavaModelException e) {
324 		// Should throw an exception instead?
325 	}
326 	return null;
327 }
328 /**
329  * @see IType#getFullyQualifiedName()
330  */
331 @Override
getFullyQualifiedName()332 public String getFullyQualifiedName() {
333 	return this.getFullyQualifiedName('$');
334 }
335 /**
336  * @see IType#getFullyQualifiedName(char)
337  */
338 @Override
getFullyQualifiedName(char enclosingTypeSeparator)339 public String getFullyQualifiedName(char enclosingTypeSeparator) {
340 	try {
341 		return getFullyQualifiedName(enclosingTypeSeparator, false/*don't show parameters*/);
342 	} catch (JavaModelException e) {
343 		// exception thrown only when showing parameters
344 		return null;
345 	}
346 }
347 
348 @Override
getFullyQualifiedParameterizedName()349 public String getFullyQualifiedParameterizedName() throws JavaModelException {
350 	return getFullyQualifiedName('.', true/*show parameters*/);
351 }
352 /*
353  * For source types, the occurrence count is the one computed in the context of the immediately enclosing type.
354  *
355  */
356 @Override
getOccurrenceCountSignature()357 protected String getOccurrenceCountSignature() {
358 	return Integer.toString(this.localOccurrenceCount);
359 }
360 /*
361  * @see JavaElement
362  */
363 @Override
getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner workingCopyOwner)364 public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner workingCopyOwner) {
365 	switch (token.charAt(0)) {
366 		case JEM_COUNT:
367 			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
368 		case JEM_FIELD:
369 			if (!memento.hasMoreTokens()) return this;
370 			String fieldName = memento.nextToken();
371 			JavaElement field = (JavaElement)getField(fieldName);
372 			return field.getHandleFromMemento(memento, workingCopyOwner);
373 		case JEM_INITIALIZER:
374 			if (!memento.hasMoreTokens()) return this;
375 			String count = memento.nextToken();
376 			JavaElement initializer = (JavaElement)getInitializer(Integer.parseInt(count));
377 			return initializer.getHandleFromMemento(memento, workingCopyOwner);
378 		case JEM_METHOD:
379 			if (!memento.hasMoreTokens()) return this;
380 			String selector = memento.nextToken();
381 			ArrayList params = new ArrayList();
382 			nextParam: while (memento.hasMoreTokens()) {
383 				token = memento.nextToken();
384 				switch (token.charAt(0)) {
385 					case JEM_TYPE:
386 					case JEM_TYPE_PARAMETER:
387 					case JEM_ANNOTATION:
388 						break nextParam;
389 					case JEM_METHOD:
390 						if (!memento.hasMoreTokens()) return this;
391 						String param = memento.nextToken();
392 						StringBuffer buffer = new StringBuffer();
393 						while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos
394 							buffer.append(Signature.C_ARRAY);
395 							if (!memento.hasMoreTokens()) return this;
396 							param = memento.nextToken();
397 						}
398 						params.add(buffer.toString() + param);
399 						break;
400 					default:
401 						break nextParam;
402 				}
403 			}
404 			String[] parameters = new String[params.size()];
405 			params.toArray(parameters);
406 			JavaElement method = (JavaElement)getMethod(selector, parameters);
407 			switch (token.charAt(0)) {
408 				case JEM_LAMBDA_EXPRESSION:
409 				case JEM_TYPE:
410 				case JEM_TYPE_PARAMETER:
411 				case JEM_LOCALVARIABLE:
412 				case JEM_ANNOTATION:
413 					return method.getHandleFromMemento(token, memento, workingCopyOwner);
414 				default:
415 					return method;
416 			}
417 		case JEM_TYPE:
418 			String typeName;
419 			if (memento.hasMoreTokens()) {
420 				typeName = memento.nextToken();
421 				char firstChar = typeName.charAt(0);
422 				if (firstChar == JEM_FIELD || firstChar == JEM_INITIALIZER || firstChar == JEM_METHOD || firstChar == JEM_TYPE || firstChar == JEM_COUNT) {
423 					token = typeName;
424 					typeName = ""; //$NON-NLS-1$
425 				} else {
426 					token = null;
427 				}
428 			} else {
429 				typeName = ""; //$NON-NLS-1$
430 				token = null;
431 			}
432 			JavaElement type = (JavaElement)getType(typeName);
433 			if (token == null) {
434 				return type.getHandleFromMemento(memento, workingCopyOwner);
435 			} else {
436 				return type.getHandleFromMemento(token, memento, workingCopyOwner);
437 			}
438 		case JEM_TYPE_PARAMETER:
439 			if (!memento.hasMoreTokens()) return this;
440 			String typeParameterName = memento.nextToken();
441 			JavaElement typeParameter = new TypeParameter(this, typeParameterName);
442 			return typeParameter.getHandleFromMemento(memento, workingCopyOwner);
443 		case JEM_ANNOTATION:
444 			if (!memento.hasMoreTokens()) return this;
445 			String annotationName = memento.nextToken();
446 			JavaElement annotation = new Annotation(this, annotationName);
447 			return annotation.getHandleFromMemento(memento, workingCopyOwner);
448 	}
449 	return null;
450 }
451 /**
452  * @see IType
453  */
454 @Override
getInitializer(int count)455 public IInitializer getInitializer(int count) {
456 	return new Initializer(this, count);
457 }
458 /**
459  * @see IType
460  */
461 @Override
getInitializers()462 public IInitializer[] getInitializers() throws JavaModelException {
463 	ArrayList list = getChildrenOfType(INITIALIZER);
464 	IInitializer[] array= new IInitializer[list.size()];
465 	list.toArray(array);
466 	return array;
467 }
468 
469 @Override
getKey()470 public String getKey() {
471 	try {
472 		return getKey(this, false/*don't open*/);
473 	} catch (JavaModelException e) {
474 		// happen only if force open is true
475 		return null;
476 	}
477 }
478 /**
479  * @see IType#getMethod
480  */
481 @Override
getMethod(String selector, String[] parameterTypeSignatures)482 public IMethod getMethod(String selector, String[] parameterTypeSignatures) {
483 	return new SourceMethod(this, selector, parameterTypeSignatures);
484 }
485 /**
486  * @see IType
487  */
488 @Override
getMethods()489 public IMethod[] getMethods() throws JavaModelException {
490 	ArrayList list = getChildrenOfType(METHOD);
491 	IMethod[] array= new IMethod[list.size()];
492 	list.toArray(array);
493 	return array;
494 }
495 /**
496  * @see IType
497  */
498 @Override
getPackageFragment()499 public IPackageFragment getPackageFragment() {
500 	IJavaElement parentElement = this.parent;
501 	while (parentElement != null) {
502 		if (parentElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
503 			return (IPackageFragment)parentElement;
504 		}
505 		else {
506 			parentElement = parentElement.getParent();
507 		}
508 	}
509 	Assert.isTrue(false);  // should not happen
510 	return null;
511 }
512 
513 @Override
getPrimaryElement(boolean checkOwner)514 public IJavaElement getPrimaryElement(boolean checkOwner) {
515 	if (checkOwner) {
516 		CompilationUnit cu = (CompilationUnit)getAncestor(COMPILATION_UNIT);
517 		if (cu.isPrimary()) return this;
518 	}
519 	IJavaElement primaryParent = this.parent.getPrimaryElement(false);
520 	switch (primaryParent.getElementType()) {
521 		case IJavaElement.COMPILATION_UNIT:
522 			return ((ICompilationUnit)primaryParent).getType(this.name);
523 		case IJavaElement.TYPE:
524 			return ((IType)primaryParent).getType(this.name);
525 		case IJavaElement.FIELD:
526 		case IJavaElement.INITIALIZER:
527 		case IJavaElement.METHOD:
528 			return ((IMember)primaryParent).getType(this.name, this.occurrenceCount);
529 	}
530 	return this;
531 }
532 /**
533  * @see IType
534  */
535 @Override
getSuperclassName()536 public String getSuperclassName() throws JavaModelException {
537 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
538 	char[] superclassName= info.getSuperclassName();
539 	if (superclassName == null) {
540 		return null;
541 	}
542 	return new String(superclassName);
543 }
544 
545 /**
546  * @see IType#getSuperclassTypeSignature()
547  * @since 3.0
548  */
549 @Override
getSuperclassTypeSignature()550 public String getSuperclassTypeSignature() throws JavaModelException {
551 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
552 	char[] superclassName= info.getSuperclassName();
553 	if (superclassName == null) {
554 		return null;
555 	}
556 	return Signature.createTypeSignature(superclassName, false);
557 }
558 
559 /**
560  * @see IType
561  */
562 @Override
getSuperInterfaceNames()563 public String[] getSuperInterfaceNames() throws JavaModelException {
564 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
565 	char[][] names= info.getInterfaceNames();
566 	return CharOperation.toStrings(names);
567 }
568 
569 /**
570  * @see IType#getSuperInterfaceTypeSignatures()
571  * @since 3.0
572  */
573 @Override
getSuperInterfaceTypeSignatures()574 public String[] getSuperInterfaceTypeSignatures() throws JavaModelException {
575 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
576 	char[][] names= info.getInterfaceNames();
577 	if (names == null) {
578 		return CharOperation.NO_STRINGS;
579 	}
580 	String[] strings= new String[names.length];
581 	for (int i= 0; i < names.length; i++) {
582 		strings[i]= Signature.createTypeSignature(names[i], false);
583 	}
584 	return strings;
585 }
586 
587 @Override
getTypeParameters()588 public ITypeParameter[] getTypeParameters() throws JavaModelException {
589 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
590 	return info.typeParameters;
591 }
592 
593 /**
594  * @see IType#getTypeParameterSignatures()
595  * @since 3.0
596  */
597 @Override
getTypeParameterSignatures()598 public String[] getTypeParameterSignatures() throws JavaModelException {
599 	ITypeParameter[] typeParameters = getTypeParameters();
600 	int length = typeParameters.length;
601 	String[] typeParameterSignatures = new String[length];
602 	for (int i = 0; i < length; i++) {
603 		TypeParameter typeParameter = (TypeParameter) typeParameters[i];
604 		TypeParameterElementInfo info = (TypeParameterElementInfo) typeParameter.getElementInfo();
605 		char[][] bounds = info.bounds;
606 		if (bounds == null) {
607 			typeParameterSignatures[i] = Signature.createTypeParameterSignature(typeParameter.getElementName(), CharOperation.NO_STRINGS);
608 		} else {
609 			int boundsLength = bounds.length;
610 			char[][] boundSignatures = new char[boundsLength][];
611 			for (int j = 0; j < boundsLength; j++) {
612 				boundSignatures[j] = Signature.createCharArrayTypeSignature(bounds[j], false);
613 			}
614 			typeParameterSignatures[i] = new String(Signature.createTypeParameterSignature(typeParameter.getElementName().toCharArray(), boundSignatures));
615 		}
616 	}
617 	return typeParameterSignatures;
618 }
619 
620 /**
621  * @see IType
622  */
623 @Override
getType(String typeName)624 public IType getType(String typeName) {
625 	return new SourceType(this, typeName);
626 }
627 @Override
getTypeParameter(String typeParameterName)628 public ITypeParameter getTypeParameter(String typeParameterName) {
629 	return new TypeParameter(this, typeParameterName);
630 }
631 /**
632  * @see IType#getTypeQualifiedName()
633  */
634 @Override
getTypeQualifiedName()635 public String getTypeQualifiedName() {
636 	return this.getTypeQualifiedName('$');
637 }
638 /**
639  * @see IType#getTypeQualifiedName(char)
640  */
641 @Override
getTypeQualifiedName(char enclosingTypeSeparator)642 public String getTypeQualifiedName(char enclosingTypeSeparator) {
643 	try {
644 		return getTypeQualifiedName(enclosingTypeSeparator, false/*don't show parameters*/);
645 	} catch (JavaModelException e) {
646 		// exception thrown only when showing parameters
647 		return null;
648 	}
649 }
650 
651 /**
652  * @see IType
653  */
654 @Override
getTypes()655 public IType[] getTypes() throws JavaModelException {
656 	ArrayList list= getChildrenOfType(TYPE);
657 	IType[] array= new IType[list.size()];
658 	list.toArray(array);
659 	return array;
660 }
661 /**
662  * @see IType#isAnonymous()
663  */
664 @Override
isAnonymous()665 public boolean isAnonymous() {
666 	return this.name.length() == 0;
667 }
668 
669 /**
670  * @see IType
671  */
672 @Override
isClass()673 public boolean isClass() throws JavaModelException {
674 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
675 	return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.CLASS_DECL;
676 }
677 
678 /**
679  * @see IType#isEnum()
680  * @since 3.0
681  */
682 @Override
isEnum()683 public boolean isEnum() throws JavaModelException {
684 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
685 	return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.ENUM_DECL;
686 }
687 
688 /**
689  * @see IType#isRecord()
690  * @noreference This method is not intended to be referenced by clients as it is a part of Java preview feature.
691  */
692 @Override
isRecord()693 public boolean isRecord() throws JavaModelException {
694 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
695 	return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.RECORD_DECL;
696 }
697 
698 /**
699  * @see IType
700  */
701 @Override
isInterface()702 public boolean isInterface() throws JavaModelException {
703 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
704 	switch (TypeDeclaration.kind(info.getModifiers())) {
705 		case TypeDeclaration.INTERFACE_DECL:
706 		case TypeDeclaration.ANNOTATION_TYPE_DECL: // annotation is interface too
707 			return true;
708 	}
709 	return false;
710 }
711 
712 /**
713  * @see IType#isAnnotation()
714  * @since 3.0
715  */
716 @Override
isAnnotation()717 public boolean isAnnotation() throws JavaModelException {
718 	SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
719 	return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.ANNOTATION_TYPE_DECL;
720 }
721 
722 /**
723  * @see IType#isLocal()
724  */
725 @Override
isLocal()726 public boolean isLocal() {
727 	switch (this.parent.getElementType()) {
728 		case IJavaElement.METHOD:
729 		case IJavaElement.INITIALIZER:
730 		case IJavaElement.FIELD:
731 			return true;
732 		default:
733 			return false;
734 	}
735 }
736 /**
737  * @see IType#isMember()
738  */
739 @Override
isMember()740 public boolean isMember() {
741 	return getDeclaringType() != null;
742 }
743 
744 @Override
isResolved()745 public boolean isResolved() {
746 	return false;
747 }
748 /**
749  * @see IType
750  */
751 @Override
loadTypeHierachy(InputStream input, IProgressMonitor monitor)752 public ITypeHierarchy loadTypeHierachy(InputStream input, IProgressMonitor monitor) throws JavaModelException {
753 	return loadTypeHierachy(input, DefaultWorkingCopyOwner.PRIMARY, monitor);
754 }
755 /**
756  * NOTE: This method is not part of the API has it is not clear clients would easily use it: they would need to
757  * first make sure all working copies for the given owner exist before calling it. This is especially har at startup
758  * time.
759  * In case clients want this API, here is how it should be specified:
760  * <p>
761  * Loads a previously saved ITypeHierarchy from an input stream. A type hierarchy can
762  * be stored using ITypeHierachy#store(OutputStream). A compilation unit of a
763  * loaded type has the given owner if such a working copy exists, otherwise the type's
764  * compilation unit is a primary compilation unit.
765  *
766  * Only hierarchies originally created by the following methods can be loaded:
767  * <ul>
768  * <li>IType#newSupertypeHierarchy(IProgressMonitor)</li>
769  * <li>IType#newSupertypeHierarchy(WorkingCopyOwner, IProgressMonitor)</li>
770  * <li>IType#newTypeHierarchy(IJavaProject, IProgressMonitor)</li>
771  * <li>IType#newTypeHierarchy(IJavaProject, WorkingCopyOwner, IProgressMonitor)</li>
772  * <li>IType#newTypeHierarchy(IProgressMonitor)</li>
773  * <li>IType#newTypeHierarchy(WorkingCopyOwner, IProgressMonitor)</li>
774  * </u>
775  *
776  * @param input stream where hierarchy will be read
777  * @param monitor the given progress monitor
778  * @return the stored hierarchy
779  * @exception JavaModelException if the hierarchy could not be restored, reasons include:
780  *      - type is not the focus of the hierarchy or
781  *		- unable to read the input stream (wrong format, IOException during reading, ...)
782  * @see ITypeHierarchy#store(java.io.OutputStream, IProgressMonitor)
783  * @since 3.0
784  */
loadTypeHierachy(InputStream input, WorkingCopyOwner owner, IProgressMonitor monitor)785 public ITypeHierarchy loadTypeHierachy(InputStream input, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
786 	// TODO monitor should be passed to TypeHierarchy.load(...)
787 	return TypeHierarchy.load(this, input, owner);
788 }
789 /**
790  * @see IType
791  */
792 @Override
newSupertypeHierarchy(IProgressMonitor monitor)793 public ITypeHierarchy newSupertypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
794 	return this.newSupertypeHierarchy(DefaultWorkingCopyOwner.PRIMARY, monitor);
795 }
796 
797 @Override
newSupertypeHierarchy( ICompilationUnit[] workingCopies, IProgressMonitor monitor)798 public ITypeHierarchy newSupertypeHierarchy(
799 	ICompilationUnit[] workingCopies,
800 	IProgressMonitor monitor)
801 	throws JavaModelException {
802 
803 	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), false);
804 	op.runOperation(monitor);
805 	return op.getResult();
806 }
807 /**
808  * @param workingCopies the working copies that take precedence over their original compilation units
809  * @param monitor the given progress monitor
810  * @return a type hierarchy for this type containing this type and all of its supertypes
811  * @exception JavaModelException if this element does not exist or if an
812  *		exception occurs while accessing its corresponding resource.
813  *
814  * @see IType#newSupertypeHierarchy(IWorkingCopy[], IProgressMonitor)
815  * @deprecated
816  */
817 @Override
newSupertypeHierarchy( IWorkingCopy[] workingCopies, IProgressMonitor monitor)818 public ITypeHierarchy newSupertypeHierarchy(
819 	IWorkingCopy[] workingCopies,
820 	IProgressMonitor monitor)
821 	throws JavaModelException {
822 
823 	ICompilationUnit[] copies;
824 	if (workingCopies == null) {
825 		copies = null;
826 	} else {
827 		int length = workingCopies.length;
828 		System.arraycopy(workingCopies, 0, copies = new ICompilationUnit[length], 0, length);
829 	}
830 	return newSupertypeHierarchy(copies, monitor);
831 }
832 /**
833  * @see IType#newSupertypeHierarchy(WorkingCopyOwner, IProgressMonitor)
834  */
835 @Override
newSupertypeHierarchy( WorkingCopyOwner owner, IProgressMonitor monitor)836 public ITypeHierarchy newSupertypeHierarchy(
837 	WorkingCopyOwner owner,
838 	IProgressMonitor monitor)
839 	throws JavaModelException {
840 
841 	ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
842 	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), false);
843 	op.runOperation(monitor);
844 	return op.getResult();
845 }
846 /**
847  * @see IType
848  */
849 @Override
newTypeHierarchy(IJavaProject project, IProgressMonitor monitor)850 public ITypeHierarchy newTypeHierarchy(IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
851 	return newTypeHierarchy(project, DefaultWorkingCopyOwner.PRIMARY, monitor);
852 }
853 /**
854  * @see IType#newTypeHierarchy(IJavaProject, WorkingCopyOwner, IProgressMonitor)
855  */
856 @Override
newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor)857 public ITypeHierarchy newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
858 	if (project == null) {
859 		throw new IllegalArgumentException(Messages.hierarchy_nullProject);
860 	}
861 	ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
862 	ICompilationUnit[] projectWCs = null;
863 	if (workingCopies != null) {
864 		int length = workingCopies.length;
865 		projectWCs = new ICompilationUnit[length];
866 		int index = 0;
867 		for (int i = 0; i < length; i++) {
868 			ICompilationUnit wc = workingCopies[i];
869 			if (project.equals(wc.getJavaProject())) {
870 				projectWCs[index++] = wc;
871 			}
872 		}
873 		if (index != length) {
874 			System.arraycopy(projectWCs, 0, projectWCs = new ICompilationUnit[index], 0, index);
875 		}
876 	}
877 	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(
878 		this,
879 		projectWCs,
880 		project,
881 		true);
882 	op.runOperation(monitor);
883 	return op.getResult();
884 }
885 /**
886  * @see IType
887  */
888 @Override
newTypeHierarchy(IProgressMonitor monitor)889 public ITypeHierarchy newTypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
890 	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=228845, The new type hierarchy should consider changes in primary
891 	// working copy.
892 	return newTypeHierarchy(DefaultWorkingCopyOwner.PRIMARY, monitor);
893 }
894 
895 @Override
newTypeHierarchy( ICompilationUnit[] workingCopies, IProgressMonitor monitor)896 public ITypeHierarchy newTypeHierarchy(
897 	ICompilationUnit[] workingCopies,
898 	IProgressMonitor monitor)
899 	throws JavaModelException {
900 
901 	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), true);
902 	op.runOperation(monitor);
903 	return op.getResult();
904 }
905 /**
906  * @see IType#newTypeHierarchy(IWorkingCopy[], IProgressMonitor)
907  * @deprecated
908  */
909 @Override
newTypeHierarchy( IWorkingCopy[] workingCopies, IProgressMonitor monitor)910 public ITypeHierarchy newTypeHierarchy(
911 	IWorkingCopy[] workingCopies,
912 	IProgressMonitor monitor)
913 	throws JavaModelException {
914 
915 	ICompilationUnit[] copies;
916 	if (workingCopies == null) {
917 		copies = null;
918 	} else {
919 		int length = workingCopies.length;
920 		System.arraycopy(workingCopies, 0, copies = new ICompilationUnit[length], 0, length);
921 	}
922 	return newTypeHierarchy(copies, monitor);
923 }
924 /**
925  * @see IType#newTypeHierarchy(WorkingCopyOwner, IProgressMonitor)
926  */
927 @Override
newTypeHierarchy( WorkingCopyOwner owner, IProgressMonitor monitor)928 public ITypeHierarchy newTypeHierarchy(
929 	WorkingCopyOwner owner,
930 	IProgressMonitor monitor)
931 	throws JavaModelException {
932 
933 	ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
934 	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), true);
935 	op.runOperation(monitor);
936 	return op.getResult();
937 }
938 @Override
resolved(Binding binding)939 public JavaElement resolved(Binding binding) {
940 	ResolvedSourceType resolvedHandle = new ResolvedSourceType(this.parent, this.name, new String(binding.computeUniqueKey()));
941 	resolvedHandle.occurrenceCount = this.occurrenceCount;
942 	resolvedHandle.localOccurrenceCount = this.localOccurrenceCount;
943 	return resolvedHandle;
944 }
945 /**
946  * @private Debugging purposes
947  */
948 @Override
toStringInfo(int tab, StringBuffer buffer, Object info, boolean showResolvedInfo)949 protected void toStringInfo(int tab, StringBuffer buffer, Object info, boolean showResolvedInfo) {
950 	buffer.append(tabString(tab));
951 	if (info == null) {
952 		if (isAnonymous()) {
953 			buffer.append("<anonymous #"); //$NON-NLS-1$
954 			buffer.append(this.occurrenceCount);
955 			buffer.append(">"); //$NON-NLS-1$
956 		} else {
957 			toStringName(buffer);
958 		}
959 		buffer.append(" (not open)"); //$NON-NLS-1$
960 	} else if (info == NO_INFO) {
961 		if (isAnonymous()) {
962 			buffer.append("<anonymous #"); //$NON-NLS-1$
963 			buffer.append(this.occurrenceCount);
964 			buffer.append(">"); //$NON-NLS-1$
965 		} else {
966 			toStringName(buffer);
967 		}
968 	} else {
969 		try {
970 			if (isRecord()) {
971 				buffer.append("record "); //$NON-NLS-1$
972 			} else if (isEnum()) {
973 				buffer.append("enum "); //$NON-NLS-1$
974 			} else if (isAnnotation()) {
975 				buffer.append("@interface "); //$NON-NLS-1$
976 			} else if (isInterface()) {
977 				buffer.append("interface "); //$NON-NLS-1$
978 			} else {
979 				buffer.append("class "); //$NON-NLS-1$
980 			}
981 			if (isAnonymous()) {
982 				buffer.append("<anonymous #"); //$NON-NLS-1$
983 				buffer.append(this.occurrenceCount);
984 				buffer.append(">"); //$NON-NLS-1$
985 			} else {
986 				toStringName(buffer);
987 			}
988 		} catch (JavaModelException e) {
989 			buffer.append("<JavaModelException in toString of " + getElementName()); //$NON-NLS-1$
990 		}
991 	}
992 }
993 @Override
isLambda()994 public boolean isLambda() {
995 	return false;
996 }
997 }
998