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