KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > hierarchy > HierarchyResolver


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core.hierarchy;
12
13 /**
14  * This is the public entry point to resolve type hierarchies.
15  *
16  * When requesting additional types from the name environment, the resolver
17  * accepts all forms (binary, source & compilation unit) for additional types.
18  *
19  * Side notes: Binary types already know their resolved supertypes so this
20  * only makes sense for source types. Even though the compiler finds all binary
21  * types to complete the hierarchy of a given source type, is there any reason
22  * why the requestor should be informed that binary type X subclasses Y &
23  * implements I & J?
24  */

25
26 import java.util.HashMap JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Map JavaDoc;
29
30 import org.eclipse.core.resources.IFile;
31 import org.eclipse.core.resources.IResource;
32 import org.eclipse.core.runtime.IPath;
33 import org.eclipse.core.runtime.IProgressMonitor;
34 import org.eclipse.core.runtime.OperationCanceledException;
35 import org.eclipse.jdt.core.IType;
36 import org.eclipse.jdt.core.JavaModelException;
37 import org.eclipse.jdt.core.Signature;
38 import org.eclipse.jdt.core.compiler.CharOperation;
39 import org.eclipse.jdt.internal.compiler.CompilationResult;
40 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
41 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
42 import org.eclipse.jdt.internal.compiler.IProblemFactory;
43 import org.eclipse.jdt.internal.compiler.ast.*;
44 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
45 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
46 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
47 import org.eclipse.jdt.internal.compiler.env.IGenericType;
48 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
49 import org.eclipse.jdt.internal.compiler.env.ISourceType;
50 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
51 import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
52 import org.eclipse.jdt.internal.compiler.lookup.*;
53 import org.eclipse.jdt.internal.compiler.parser.Parser;
54 import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
55 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
56 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
57 import org.eclipse.jdt.internal.compiler.util.Messages;
58 import org.eclipse.jdt.internal.core.*;
59 import org.eclipse.jdt.internal.core.util.ASTNodeFinder;
60 import org.eclipse.jdt.internal.core.util.HandleFactory;
61
62 public class HierarchyResolver implements ITypeRequestor {
63     
64     private ReferenceBinding focusType;
65     private boolean superTypesOnly;
66     private boolean hasMissingSuperClass;
67     LookupEnvironment lookupEnvironment;
68     private CompilerOptions options;
69     HierarchyBuilder builder;
70     private ReferenceBinding[] typeBindings;
71
72     private int typeIndex;
73     private IGenericType[] typeModels;
74     
75 public HierarchyResolver(INameEnvironment nameEnvironment, Map JavaDoc settings, HierarchyBuilder builder, IProblemFactory problemFactory) {
76     // create a problem handler with the 'exit after all problems' handling policy
77
this.options = new CompilerOptions(settings);
78     IErrorHandlingPolicy policy = DefaultErrorHandlingPolicies.exitAfterAllProblems();
79     ProblemReporter problemReporter = new ProblemReporter(policy, this.options, problemFactory);
80
81     this.setEnvironment(
82         new LookupEnvironment(this, this.options, problemReporter, nameEnvironment),
83         builder);
84 }
85 public HierarchyResolver(LookupEnvironment lookupEnvironment, HierarchyBuilder builder) {
86     this.setEnvironment(lookupEnvironment, builder);
87 }
88
89 /**
90  * Add an additional binary type
91  * @param binaryType
92  * @param packageBinding
93  */

94 public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
95     IProgressMonitor progressMonitor = this.builder.hierarchy.progressMonitor;
96     if (progressMonitor != null && progressMonitor.isCanceled())
97         throw new OperationCanceledException();
98     
99     BinaryTypeBinding typeBinding = this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
100     try {
101         this.remember(binaryType, typeBinding);
102     } catch (AbortCompilation e) {
103         // ignore
104
}
105 }
106
107 /**
108  * Add an additional compilation unit.
109  * @param sourceUnit
110  */

111 public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
112     //System.out.println("Cannot accept compilation units inside the HierarchyResolver.");
113
this.lookupEnvironment.problemReporter.abortDueToInternalError(
114         new StringBuffer JavaDoc(Messages.accept_cannot)
115             .append(sourceUnit.getFileName())
116             .toString());
117 }
118
119 /**
120  * Add additional source types
121  * @param sourceTypes
122  * @param packageBinding
123  */

124 public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
125     IProgressMonitor progressMonitor = this.builder.hierarchy.progressMonitor;
126     if (progressMonitor != null && progressMonitor.isCanceled())
127         throw new OperationCanceledException();
128     
129     // find most enclosing type first (needed when explicit askForType(...) is done
130
// with a member type (e.g. p.A$B))
131
ISourceType sourceType = sourceTypes[0];
132     while (sourceType.getEnclosingType() != null)
133         sourceType = sourceType.getEnclosingType();
134     
135     // build corresponding compilation unit
136
CompilationResult result = new CompilationResult(sourceType.getFileName(), 1, 1, this.options.maxProblemsPerUnit);
137     CompilationUnitDeclaration unit =
138         SourceTypeConverter.buildCompilationUnit(
139             new ISourceType[] {sourceType}, // ignore secondary types, to improve laziness
140
SourceTypeConverter.MEMBER_TYPE, // need member types
141
// no need for field initialization
142
this.lookupEnvironment.problemReporter,
143             result);
144         
145     // build bindings
146
if (unit != null) {
147         try {
148             this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
149             
150             org.eclipse.jdt.core.ICompilationUnit cu = ((SourceTypeElementInfo)sourceType).getHandle().getCompilationUnit();
151             rememberAllTypes(unit, cu, false);
152
153             this.lookupEnvironment.completeTypeBindings(unit, true/*build constructor only*/);
154         } catch (AbortCompilation e) {
155             // missing 'java.lang' package: ignore
156
}
157     }
158 }
159 /*
160  * Creates the super class handle of the given type.
161  * Returns null if the type has no super class.
162  * Adds the simple name to the hierarchy missing types if the class is not found and returns null.
163  */

164 private IType findSuperClass(IGenericType type, ReferenceBinding typeBinding) {
165     ReferenceBinding superBinding = typeBinding.superclass();
166     
167     if (superBinding != null) {
168         superBinding = (ReferenceBinding) superBinding.erasure();
169         if (typeBinding.isHierarchyInconsistent()) {
170             if (superBinding.problemId() == ProblemReasons.NotFound) {
171                 this.hasMissingSuperClass = true;
172                 this.builder.hierarchy.missingTypes.add(new String JavaDoc(superBinding.sourceName)); // note: this could be Map$Entry
173
return null;
174             } else if ((superBinding.id == TypeIds.T_JavaLangObject)) {
175                 char[] superclassName;
176                 char separator;
177                 if (type instanceof IBinaryType) {
178                     superclassName = ((IBinaryType)type).getSuperclassName();
179                     separator = '/';
180                 } else if (type instanceof ISourceType) {
181                     superclassName = ((ISourceType)type).getSuperclassName();
182                     separator = '.';
183                 } else if (type instanceof HierarchyType) {
184                     superclassName = ((HierarchyType)type).superclassName;
185                     separator = '.';
186                 } else {
187                     return null;
188                 }
189                 
190                 if (superclassName != null) { // check whether subclass of Object due to broken hierarchy (as opposed to explicitly extending it)
191
int lastSeparator = CharOperation.lastIndexOf(separator, superclassName);
192                     char[] simpleName = lastSeparator == -1 ? superclassName : CharOperation.subarray(superclassName, lastSeparator+1, superclassName.length);
193                     if (!CharOperation.equals(simpleName, TypeConstants.OBJECT)) {
194                         this.hasMissingSuperClass = true;
195                         this.builder.hierarchy.missingTypes.add(new String JavaDoc(simpleName));
196                         return null;
197                     }
198                 }
199             }
200         }
201         for (int t = this.typeIndex; t >= 0; t--) {
202             if (this.typeBindings[t] == superBinding) {
203                 return this.builder.getHandle(this.typeModels[t], superBinding);
204             }
205         }
206     }
207     return null;
208 }
209 /*
210  * Returns the handles of the super interfaces of the given type.
211  * Adds the simple name to the hierarchy missing types if an interface is not found (but don't put null in the returned array)
212  */

213 private IType[] findSuperInterfaces(IGenericType type, ReferenceBinding typeBinding) {
214     char[][] superInterfaceNames;
215     char separator;
216     if (type instanceof IBinaryType) {
217         superInterfaceNames = ((IBinaryType)type).getInterfaceNames();
218         separator = '/';
219     } else if (type instanceof ISourceType) {
220         ISourceType sourceType = (ISourceType)type;
221         if (sourceType.getName().length == 0) { // if anonymous type
222
if (typeBinding.superInterfaces() != null && typeBinding.superInterfaces().length > 0) {
223                 superInterfaceNames = new char[][] {sourceType.getSuperclassName()};
224             } else {
225                 superInterfaceNames = sourceType.getInterfaceNames();
226             }
227         } else {
228             if (TypeDeclaration.kind(sourceType.getModifiers()) == TypeDeclaration.ANNOTATION_TYPE_DECL)
229                 superInterfaceNames = new char[][] {TypeConstants.CharArray_JAVA_LANG_ANNOTATION_ANNOTATION};
230             else
231                 superInterfaceNames = sourceType.getInterfaceNames();
232         }
233         separator = '.';
234     } else if (type instanceof HierarchyType) {
235         HierarchyType hierarchyType = (HierarchyType)type;
236         if (hierarchyType.name.length == 0) { // if anonymous type
237
if (typeBinding.superInterfaces() != null && typeBinding.superInterfaces().length > 0) {
238                 superInterfaceNames = new char[][] {hierarchyType.superclassName};
239             } else {
240                 superInterfaceNames = hierarchyType.superInterfaceNames;
241             }
242         } else {
243             superInterfaceNames = hierarchyType.superInterfaceNames;
244         }
245         separator = '.';
246     } else{
247         return null;
248     }
249     
250     ReferenceBinding[] interfaceBindings = typeBinding.superInterfaces();
251     int bindingIndex = 0;
252     int bindingLength = interfaceBindings == null ? 0 : interfaceBindings.length;
253     int length = superInterfaceNames == null ? 0 : superInterfaceNames.length;
254     IType[] superinterfaces = new IType[length];
255     int index = 0;
256     next : for (int i = 0; i < length; i++) {
257         char[] superInterfaceName = superInterfaceNames[i];
258         int end = superInterfaceName.length;
259         
260         // find the end of simple name
261
int genericStart = CharOperation.indexOf(Signature.C_GENERIC_START, superInterfaceName);
262         if (genericStart != -1) end = genericStart;
263                 
264         // find the start of simple name
265
int lastSeparator = CharOperation.lastIndexOf(separator, superInterfaceName, 0, end);
266         int start = lastSeparator + 1;
267         
268         // case of binary inner type -> take the last part
269
int lastDollar = CharOperation.lastIndexOf('$', superInterfaceName, start);
270         if (lastDollar != -1) start = lastDollar + 1;
271         
272         char[] simpleName = CharOperation.subarray(superInterfaceName, start, end);
273         
274         if (bindingIndex < bindingLength) {
275             ReferenceBinding interfaceBinding = (ReferenceBinding) interfaceBindings[bindingIndex].erasure();
276
277             // ensure that the binding corresponds to the interface defined by the user
278
if (CharOperation.equals(simpleName, interfaceBinding.sourceName)) {
279                 bindingIndex++;
280                 for (int t = this.typeIndex; t >= 0; t--) {
281                     if (this.typeBindings[t] == interfaceBinding) {
282                         superinterfaces[index++] = this.builder.getHandle(this.typeModels[t], interfaceBinding);
283                         continue next;
284                     }
285                 }
286             }
287         }
288         this.builder.hierarchy.missingTypes.add(new String JavaDoc(simpleName));
289     }
290     if (index != length)
291         System.arraycopy(superinterfaces, 0, superinterfaces = new IType[index], 0, index);
292     return superinterfaces;
293 }
294 private void fixSupertypeBindings() {
295     for (int current = this.typeIndex; current >= 0; current--) {
296         ReferenceBinding typeBinding = this.typeBindings[current];
297     
298         
299         if (typeBinding instanceof SourceTypeBinding) {
300             ClassScope scope = ((SourceTypeBinding) typeBinding).scope;
301             if (scope != null) {
302                 TypeDeclaration typeDeclaration = scope.referenceContext;
303                 TypeReference superclassRef = typeDeclaration == null ? null : typeDeclaration.superclass;
304                 TypeBinding superclass = superclassRef == null ? null : superclassRef.resolvedType;
305                 if (superclass instanceof ProblemReferenceBinding) {
306                     superclass = ((ProblemReferenceBinding) superclass).closestMatch();
307                 }
308                 if (superclass != null)
309                     ((SourceTypeBinding) typeBinding).superclass = (ReferenceBinding) superclass;
310     
311                 TypeReference[] superInterfaces = typeDeclaration == null ? null : typeDeclaration.superInterfaces;
312                 int length;
313                 ReferenceBinding[] interfaceBindings = typeBinding.superInterfaces();
314                 if (superInterfaces != null && (length = superInterfaces.length) > (interfaceBindings == null ? 0 : interfaceBindings.length)) { // check for interfaceBindings being null (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=139689)
315
interfaceBindings = new ReferenceBinding[length];
316                     int index = 0;
317                     for (int i = 0; i < length; i++) {
318                         ReferenceBinding superInterface = (ReferenceBinding) superInterfaces[i].resolvedType;
319                         if (superInterface instanceof ProblemReferenceBinding)
320                             superInterface = superInterface.closestMatch();
321                         if (superInterface != null)
322                             interfaceBindings[index++] = superInterface;
323                     }
324                     if (index < length)
325                         System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[index], 0 , index);
326                     ((SourceTypeBinding) typeBinding).superInterfaces = interfaceBindings;
327                 }
328             }
329         } else if (typeBinding instanceof BinaryTypeBinding) {
330             try {
331                 typeBinding.superclass();
332             } catch (AbortCompilation e) {
333                 // allow subsequent call to superclass() to succeed so that we don't have to catch AbortCompilation everywhere
334
((BinaryTypeBinding) typeBinding).tagBits &= ~TagBits.HasUnresolvedSuperclass;
335                 this.builder.hierarchy.missingTypes.add(new String JavaDoc(typeBinding.superclass().sourceName()));
336                 this.hasMissingSuperClass = true;
337             }
338             try {
339                 typeBinding.superInterfaces();
340             } catch (AbortCompilation e) {
341                 // allow subsequent call to superInterfaces() to succeed so that we don't have to catch AbortCompilation everywhere
342
((BinaryTypeBinding) typeBinding).tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
343             }
344         }
345     }
346 }
347 private void remember(IGenericType suppliedType, ReferenceBinding typeBinding) {
348     if (typeBinding == null) return;
349     
350     if (++this.typeIndex == this.typeModels.length) {
351         System.arraycopy(this.typeModels, 0, this.typeModels = new IGenericType[this.typeIndex * 2], 0, this.typeIndex);
352         System.arraycopy(this.typeBindings, 0, this.typeBindings = new ReferenceBinding[this.typeIndex * 2], 0, this.typeIndex);
353     }
354     this.typeModels[this.typeIndex] = suppliedType;
355     this.typeBindings[this.typeIndex] = typeBinding;
356 }
357 private void remember(IType type, ReferenceBinding typeBinding) {
358     if (((CompilationUnit)type.getCompilationUnit()).isOpen()) {
359         try {
360             IGenericType genericType = (IGenericType)((JavaElement)type).getElementInfo();
361             remember(genericType, typeBinding);
362         } catch (JavaModelException e) {
363             // cannot happen since element is open
364
return;
365         }
366     } else {
367         if (typeBinding == null) return;
368         
369         TypeDeclaration typeDeclaration = ((SourceTypeBinding)typeBinding).scope.referenceType();
370     
371         // simple super class name
372
char[] superclassName = null;
373         TypeReference superclass;
374         if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
375             superclass = typeDeclaration.allocation.type;
376         } else {
377             superclass = typeDeclaration.superclass;
378         }
379         if (superclass != null) {
380             char[][] typeName = superclass.getTypeName();
381             superclassName = typeName == null ? null : typeName[typeName.length-1];
382         }
383         
384         // simple super interface names
385
char[][] superInterfaceNames = null;
386         TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
387         if (superInterfaces != null) {
388             int length = superInterfaces.length;
389             superInterfaceNames = new char[length][];
390             for (int i = 0; i < length; i++) {
391                 TypeReference superInterface = superInterfaces[i];
392                 char[][] typeName = superInterface.getTypeName();
393                 superInterfaceNames[i] = typeName[typeName.length-1];
394             }
395         }
396     
397         HierarchyType hierarchyType = new HierarchyType(
398             type,
399             typeDeclaration.name,
400             typeDeclaration.binding.modifiers,
401             superclassName,
402             superInterfaceNames);
403         remember(hierarchyType, typeDeclaration.binding);
404     }
405
406 }
407 /*
408  * Remembers all type bindings defined in the given parsed unit, adding local/anonymous types if specified.
409  */

410 private void rememberAllTypes(CompilationUnitDeclaration parsedUnit, org.eclipse.jdt.core.ICompilationUnit cu, boolean includeLocalTypes) {
411     TypeDeclaration[] types = parsedUnit.types;
412     if (types != null) {
413         for (int i = 0, length = types.length; i < length; i++) {
414             TypeDeclaration type = types[i];
415             rememberWithMemberTypes(type, cu.getType(new String JavaDoc(type.name)));
416         }
417     }
418     if (includeLocalTypes && parsedUnit.localTypes != null) {
419         HandleFactory factory = new HandleFactory();
420         HashSet JavaDoc existingElements = new HashSet JavaDoc(parsedUnit.localTypeCount);
421         HashMap JavaDoc knownScopes = new HashMap JavaDoc(parsedUnit.localTypeCount);
422         for (int i = 0; i < parsedUnit.localTypeCount; i++) {
423             LocalTypeBinding localType = parsedUnit.localTypes[i];
424             ClassScope classScope = localType.scope;
425             TypeDeclaration typeDecl = classScope.referenceType();
426             IType typeHandle = (IType)factory.createElement(classScope, cu, existingElements, knownScopes);
427             rememberWithMemberTypes(typeDecl, typeHandle);
428         }
429     }
430 }
431 private void rememberWithMemberTypes(TypeDeclaration typeDecl, IType typeHandle) {
432     remember(typeHandle, typeDecl.binding);
433     
434     TypeDeclaration[] memberTypes = typeDecl.memberTypes;
435     if (memberTypes != null) {
436         for (int i = 0, length = memberTypes.length; i < length; i++) {
437             TypeDeclaration memberType = memberTypes[i];
438             rememberWithMemberTypes(memberType, typeHandle.getType(new String JavaDoc(memberType.name)));
439         }
440     }
441 }
442 /*
443  * Reports the hierarchy from the remembered bindings.
444  * Note that 'binaryTypeBinding' is null if focus type is a source type.
445  */

446 private void reportHierarchy(IType focus, CompilationUnitDeclaration parsedUnit, ReferenceBinding binaryTypeBinding) {
447     
448     // set focus type binding
449
if (focus != null) {
450         if (binaryTypeBinding != null) {
451             // binary type
452
this.focusType = binaryTypeBinding;
453         } else {
454             // source type
455
Member declaringMember = ((Member)focus).getOuterMostLocalContext();
456             if (declaringMember == null) {
457                 // top level or member type
458
char[] fullyQualifiedName = focus.getFullyQualifiedName().toCharArray();
459                 setFocusType(CharOperation.splitOn('.', fullyQualifiedName));
460             } else {
461                 // anonymous or local type
462
if (parsedUnit != null) {
463                     TypeDeclaration typeDecl = new ASTNodeFinder(parsedUnit).findType(focus);
464                     if (typeDecl != null) {
465                         this.focusType = typeDecl.binding;
466                     }
467                 }
468             }
469         }
470     }
471     
472     // be resilient and fix super type bindings
473
fixSupertypeBindings();
474     
475     int objectIndex = -1;
476     for (int current = this.typeIndex; current >= 0; current--) {
477         ReferenceBinding typeBinding = this.typeBindings[current];
478
479         // java.lang.Object treated at the end
480
if (typeBinding.id == TypeIds.T_JavaLangObject) {
481             objectIndex = current;
482             continue;
483         }
484
485         IGenericType suppliedType = this.typeModels[current];
486
487         if (!subOrSuperOfFocus(typeBinding)) {
488             continue; // ignore types outside of hierarchy
489
}
490
491         IType superclass;
492         if (typeBinding.isInterface()){ // do not connect interfaces to Object
493
superclass = null;
494         } else {
495             superclass = findSuperClass(suppliedType, typeBinding);
496         }
497         IType[] superinterfaces = findSuperInterfaces(suppliedType, typeBinding);
498         
499         this.builder.connect(suppliedType, this.builder.getHandle(suppliedType, typeBinding), superclass, superinterfaces);
500     }
501     // add java.lang.Object only if the super class is not missing
502
if (!this.hasMissingSuperClass && objectIndex > -1) {
503         IGenericType objectType = this.typeModels[objectIndex];
504         this.builder.connect(objectType, this.builder.getHandle(objectType, this.typeBindings[objectIndex]), null, null);
505     }
506 }
507 private void reset(){
508     this.lookupEnvironment.reset();
509
510     this.focusType = null;
511     this.superTypesOnly = false;
512     this.typeIndex = -1;
513     this.typeModels = new IGenericType[5];
514     this.typeBindings = new ReferenceBinding[5];
515 }
516
517 /**
518  * Resolve the supertypes for the supplied source type.
519  * Inform the requestor of the resolved supertypes using:
520  * connect(ISourceType suppliedType, IGenericType superclass, IGenericType[] superinterfaces)
521  * @param suppliedType
522  */

523 public void resolve(IGenericType suppliedType) {
524     try {
525         if (suppliedType.isBinaryType()) {
526             BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType((IBinaryType) suppliedType, false/*don't need field and method (bug 125067)*/, null /*no access restriction*/);
527             remember(suppliedType, binaryTypeBinding);
528             // We still need to add superclasses and superinterfaces bindings (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53095)
529
int startIndex = this.typeIndex;
530             for (int i = startIndex; i <= this.typeIndex; i++) {
531                 IGenericType igType = this.typeModels[i];
532                 if (igType != null && igType.isBinaryType()) {
533                     // fault in its hierarchy...
534
try {
535                         ReferenceBinding typeBinding = this.typeBindings[i];
536                         typeBinding.superclass();
537                         typeBinding.superInterfaces();
538                     } catch (AbortCompilation e) {
539                         // classpath problem for this type: ignore
540
}
541                 }
542             }
543             this.superTypesOnly = true;
544             reportHierarchy(this.builder.getType(), null, binaryTypeBinding);
545         } else {
546             org.eclipse.jdt.core.ICompilationUnit cu = ((SourceTypeElementInfo)suppliedType).getHandle().getCompilationUnit();
547             HashSet JavaDoc localTypes = new HashSet JavaDoc();
548             localTypes.add(cu.getPath().toString());
549             this.superTypesOnly = true;
550             resolve(new Openable[] {(Openable)cu}, localTypes, null);
551         }
552     } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
553
} finally {
554         reset();
555     }
556 }
557
558 /**
559  * Resolve the supertypes for the types contained in the given openables (ICompilationUnits and/or IClassFiles).
560  * Inform the requestor of the resolved supertypes for each
561  * supplied source type using:
562  * connect(ISourceType suppliedType, IGenericType superclass, IGenericType[] superinterfaces)
563  *
564  * Also inform the requestor of the supertypes of each
565  * additional requested super type which is also a source type
566  * instead of a binary type.
567  * @param openables
568  * @param localTypes
569  * @param monitor
570  */

571 public void resolve(Openable[] openables, HashSet JavaDoc localTypes, IProgressMonitor monitor) {
572     try {
573         int openablesLength = openables.length;
574         CompilationUnitDeclaration[] parsedUnits = new CompilationUnitDeclaration[openablesLength];
575         boolean[] hasLocalType = new boolean[openablesLength];
576         org.eclipse.jdt.core.ICompilationUnit[] cus = new org.eclipse.jdt.core.ICompilationUnit[openablesLength];
577         int unitsIndex = 0;
578         
579         CompilationUnitDeclaration focusUnit = null;
580         ReferenceBinding focusBinaryBinding = null;
581         IType focus = this.builder.getType();
582         Openable focusOpenable = null;
583         if (focus != null) {
584             if (focus.isBinary()) {
585                 focusOpenable = (Openable)focus.getClassFile();
586             } else {
587                 focusOpenable = (Openable)focus.getCompilationUnit();
588             }
589         }
590         
591         // build type bindings
592
Parser parser = new Parser(this.lookupEnvironment.problemReporter, true);
593         for (int i = 0; i < openablesLength; i++) {
594             Openable openable = openables[i];
595             if (openable instanceof org.eclipse.jdt.core.ICompilationUnit) {
596                 org.eclipse.jdt.core.ICompilationUnit cu = (org.eclipse.jdt.core.ICompilationUnit)openable;
597
598                 // contains a potential subtype as a local or anonymous type?
599
boolean containsLocalType = false;
600                 if (localTypes == null) { // case of hierarchy on region
601
containsLocalType = true;
602                 } else {
603                     IPath path = cu.getPath();
604                     containsLocalType = localTypes.contains(path.toString());
605                 }
606                 
607                 // build parsed unit
608
CompilationUnitDeclaration parsedUnit = null;
609                 if (cu.isOpen()) {
610                     // create parsed unit from source element infos
611
CompilationResult result = new CompilationResult(((ICompilationUnit)cu).getFileName(), i, openablesLength, this.options.maxProblemsPerUnit);
612                     SourceTypeElementInfo[] typeInfos = null;
613                     try {
614                         IType[] topLevelTypes = cu.getTypes();
615                         int topLevelLength = topLevelTypes.length;
616                         if (topLevelLength == 0) continue; // empty cu: no need to parse (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=65677)
617
typeInfos = new SourceTypeElementInfo[topLevelLength];
618                         for (int j = 0; j < topLevelLength; j++) {
619                             IType topLevelType = topLevelTypes[j];
620                             typeInfos[j] = (SourceTypeElementInfo)((JavaElement)topLevelType).getElementInfo();
621                         }
622                     } catch (JavaModelException e) {
623                         // types/cu exist since cu is opened
624
}
625                     int flags = !containsLocalType
626                         ? SourceTypeConverter.MEMBER_TYPE
627                         : SourceTypeConverter.FIELD_AND_METHOD | SourceTypeConverter.MEMBER_TYPE | SourceTypeConverter.LOCAL_TYPE;
628                     parsedUnit =
629                         SourceTypeConverter.buildCompilationUnit(
630                             typeInfos,
631                             flags,
632                             this.lookupEnvironment.problemReporter,
633                             result);
634                     if (containsLocalType) parsedUnit.bits |= ASTNode.HasAllMethodBodies;
635                 } else {
636                     // create parsed unit from file
637
IFile file = (IFile) cu.getResource();
638                     ICompilationUnit sourceUnit = this.builder.createCompilationUnitFromPath(openable, file);
639                     
640                     CompilationResult unitResult = new CompilationResult(sourceUnit, i, openablesLength, this.options.maxProblemsPerUnit);
641                     parsedUnit = parser.dietParse(sourceUnit, unitResult);
642                 }
643
644                 if (parsedUnit != null) {
645                     hasLocalType[unitsIndex] = containsLocalType;
646                     cus[unitsIndex] = cu;
647                     parsedUnits[unitsIndex++] = parsedUnit;
648                     try {
649                         this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
650                         if (openable.equals(focusOpenable)) {
651                             focusUnit = parsedUnit;
652                         }
653                     } catch (AbortCompilation e) {
654                         // classpath problem for this type: ignore
655
}
656                 }
657             } else {
658                 // cache binary type binding
659
ClassFile classFile = (ClassFile)openable;
660                 IBinaryType binaryType = null;
661                 if (classFile.isOpen()) {
662                     // create binary type from info
663
IType type = classFile.getType();
664                     try {
665                         binaryType = (IBinaryType)((JavaElement)type).getElementInfo();
666                     } catch (JavaModelException e) {
667                         // type exists since class file is opened
668
}
669                 } else {
670                     // create binary type from file
671
if (classFile.getPackageFragmentRoot().isArchive()) {
672                         binaryType = this.builder.createInfoFromClassFileInJar(classFile);
673                     } else {
674                         IResource file = classFile.getResource();
675                         binaryType = this.builder.createInfoFromClassFile(classFile, file);
676                     }
677                 }
678                 if (binaryType != null) {
679                     try {
680                         BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType(binaryType, false/*don't need field and method (bug 125067)*/, null /*no access restriction*/);
681                         remember(binaryType, binaryTypeBinding);
682                         if (openable.equals(focusOpenable)) {
683                             focusBinaryBinding = binaryTypeBinding;
684                         }
685                     } catch (AbortCompilation e) {
686                         // classpath problem for this type: ignore
687
}
688                 }
689             }
690         }
691         
692         for (int i = 0; i <= this.typeIndex; i++) {
693             IGenericType suppliedType = this.typeModels[i];
694             if (suppliedType != null && suppliedType.isBinaryType()) {
695                 // fault in its hierarchy...
696
try {
697                     ReferenceBinding typeBinding = this.typeBindings[i];
698                     typeBinding.superclass();
699                     typeBinding.superInterfaces();
700                 } catch (AbortCompilation e) {
701                     // classpath problem for this type: ignore
702
}
703             }
704         }
705         
706         // complete type bindings (ie. connect super types)
707
for (int i = 0; i < unitsIndex; i++) {
708             CompilationUnitDeclaration parsedUnit = parsedUnits[i];
709             if (parsedUnit != null) {
710                 try {
711                     boolean containsLocalType = hasLocalType[i];
712                     if (containsLocalType) { // NB: no-op if method bodies have been already parsed
713
parser.getMethodBodies(parsedUnit);
714                     }
715                     // complete type bindings and build fields and methods only for local types
716
// (in this case the constructor is needed when resolving local types)
717
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=145333)
718
this.lookupEnvironment.completeTypeBindings(parsedUnit, containsLocalType);
719                 } catch (AbortCompilation e) {
720                     // classpath problem for this type: don't try to resolve (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49809)
721
hasLocalType[i] = false;
722                 }
723             }
724             worked(monitor, 1);
725         }
726         
727         // remember type bindings
728
for (int i = 0; i < unitsIndex; i++) {
729             CompilationUnitDeclaration parsedUnit = parsedUnits[i];
730             if (parsedUnit != null) {
731                 boolean containsLocalType = hasLocalType[i];
732                 if (containsLocalType) {
733                     parsedUnit.scope.faultInTypes();
734                     parsedUnit.resolve();
735                 }
736                     
737                 rememberAllTypes(parsedUnit, cus[i], containsLocalType);
738             }
739         }
740         
741         // if no potential subtype was a real subtype of the binary focus type, no need to go further
742
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=54043)
743
if (focusBinaryBinding == null && focus != null && focus.isBinary()) {
744             char[] fullyQualifiedName = focus.getFullyQualifiedName().toCharArray();
745             focusBinaryBinding = this.lookupEnvironment.getCachedType(CharOperation.splitOn('.', fullyQualifiedName));
746             if (focusBinaryBinding == null)
747                 return;
748         }
749
750         reportHierarchy(focus, focusUnit, focusBinaryBinding);
751         
752     } catch (ClassCastException JavaDoc e){ // work-around for 1GF5W1S - can happen in case duplicates are fed to the hierarchy with binaries hiding sources
753
} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
754
if (TypeHierarchy.DEBUG)
755             e.printStackTrace();
756     } finally {
757         reset();
758     }
759 }
760 private void setEnvironment(LookupEnvironment lookupEnvironment, HierarchyBuilder builder) {
761     this.lookupEnvironment = lookupEnvironment;
762     this.builder = builder;
763
764     this.typeIndex = -1;
765     this.typeModels = new IGenericType[5];
766     this.typeBindings = new ReferenceBinding[5];
767 }
768
769 /*
770  * Set the focus type (ie. the type that this resolver is computing the hierarch for.
771  * Returns the binding of this focus type or null if it could not be found.
772  */

773 public ReferenceBinding setFocusType(char[][] compoundName) {
774     if (compoundName == null || this.lookupEnvironment == null) return null;
775     this.focusType = this.lookupEnvironment.getCachedType(compoundName);
776     if (this.focusType == null) {
777         this.focusType = this.lookupEnvironment.askForType(compoundName);
778     }
779     return this.focusType;
780 }
781 public boolean subOrSuperOfFocus(ReferenceBinding typeBinding) {
782     if (this.focusType == null) return true; // accept all types (case of hierarchy in a region)
783
try {
784         if (this.subTypeOfType(this.focusType, typeBinding)) return true;
785         if (!this.superTypesOnly && this.subTypeOfType(typeBinding, this.focusType)) return true;
786     } catch (AbortCompilation e) {
787         // unresolved superclass/superinterface -> ignore
788
}
789     return false;
790 }
791 private boolean subTypeOfType(ReferenceBinding subType, ReferenceBinding typeBinding) {
792     if (typeBinding == null || subType == null) return false;
793     if (subType == typeBinding) return true;
794     ReferenceBinding superclass = subType.superclass();
795     if (superclass != null) superclass = (ReferenceBinding) superclass.erasure();
796 // if (superclass != null && superclass.id == TypeIds.T_JavaLangObject && subType.isHierarchyInconsistent()) return false;
797
if (this.subTypeOfType(superclass, typeBinding)) return true;
798     ReferenceBinding[] superInterfaces = subType.superInterfaces();
799     if (superInterfaces != null) {
800         for (int i = 0, length = superInterfaces.length; i < length; i++) {
801             ReferenceBinding superInterface = (ReferenceBinding) superInterfaces[i].erasure();
802             if (this.subTypeOfType(superInterface, typeBinding)) return true;
803         }
804     }
805     return false;
806 }
807 protected void worked(IProgressMonitor monitor, int work) {
808     if (monitor != null) {
809         if (monitor.isCanceled()) {
810             throw new OperationCanceledException();
811         } else {
812             monitor.worked(work);
813         }
814     }
815 }
816 }
817
Popular Tags