KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > lookup > CompilationUnitScope


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  * Erling Ellingsen - patch for bug 125570
11  *******************************************************************************/

12 package org.eclipse.jdt.internal.compiler.lookup;
13
14 import org.eclipse.jdt.core.compiler.CharOperation;
15 import org.eclipse.jdt.internal.compiler.ast.*;
16 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
17 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
18 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
19 import org.eclipse.jdt.internal.compiler.util.*;
20
21 public class CompilationUnitScope extends Scope {
22     
23     public LookupEnvironment environment;
24     public CompilationUnitDeclaration referenceContext;
25     public char[][] currentPackageName;
26     public PackageBinding fPackage;
27     public ImportBinding[] imports;
28     public HashtableOfObject typeOrPackageCache; // used in Scope.getTypeOrPackage()
29

30     public SourceTypeBinding[] topLevelTypes;
31     
32     private CompoundNameVector qualifiedReferences;
33     private SimpleNameVector simpleNameReferences;
34     private ObjectVector referencedTypes;
35     private ObjectVector referencedSuperTypes;
36     
37     HashtableOfType constantPoolNameUsage;
38     private int captureID = 1;
39
40 public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment environment) {
41     super(COMPILATION_UNIT_SCOPE, null);
42     this.environment = environment;
43     this.referenceContext = unit;
44     unit.scope = this;
45     this.currentPackageName = unit.currentPackage == null ? CharOperation.NO_CHAR_CHAR : unit.currentPackage.tokens;
46
47     if (compilerOptions().produceReferenceInfo) {
48         this.qualifiedReferences = new CompoundNameVector();
49         this.simpleNameReferences = new SimpleNameVector();
50         this.referencedTypes = new ObjectVector();
51         this.referencedSuperTypes = new ObjectVector();
52     } else {
53         this.qualifiedReferences = null; // used to test if dependencies should be recorded
54
this.simpleNameReferences = null;
55         this.referencedTypes = null;
56         this.referencedSuperTypes = null;
57     }
58 }
59 void buildFieldsAndMethods() {
60     for (int i = 0, length = topLevelTypes.length; i < length; i++)
61         topLevelTypes[i].scope.buildFieldsAndMethods();
62 }
63 void buildTypeBindings(AccessRestriction accessRestriction) {
64     topLevelTypes = new SourceTypeBinding[0]; // want it initialized if the package cannot be resolved
65
boolean firstIsSynthetic = false;
66     if (referenceContext.compilationResult.compilationUnit != null) {
67         char[][] expectedPackageName = referenceContext.compilationResult.compilationUnit.getPackageName();
68         if (expectedPackageName != null
69                 && !CharOperation.equals(currentPackageName, expectedPackageName)) {
70
71             // only report if the unit isn't structurally empty
72
if (referenceContext.currentPackage != null
73                     || referenceContext.types != null
74                     || referenceContext.imports != null) {
75                 problemReporter().packageIsNotExpectedPackage(referenceContext);
76             }
77             currentPackageName = expectedPackageName.length == 0 ? CharOperation.NO_CHAR_CHAR : expectedPackageName;
78         }
79     }
80     if (currentPackageName == CharOperation.NO_CHAR_CHAR) {
81         if ((fPackage = environment.defaultPackage) == null) {
82             problemReporter().mustSpecifyPackage(referenceContext);
83             return;
84         }
85     } else {
86         if ((fPackage = environment.createPackage(currentPackageName)) == null) {
87             problemReporter().packageCollidesWithType(referenceContext);
88             return;
89         } else if (referenceContext.isPackageInfo()) {
90             // resolve package annotations now if this is "package-info.java".
91
if (referenceContext.types == null || referenceContext.types.length == 0) {
92                 referenceContext.types = new TypeDeclaration[1];
93                 TypeDeclaration declaration = new TypeDeclaration(referenceContext.compilationResult);
94                 referenceContext.types[0] = declaration;
95                 declaration.name = TypeConstants.PACKAGE_INFO_NAME;
96                 declaration.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccInterface;
97                 firstIsSynthetic = true;
98             }
99         }
100         recordQualifiedReference(currentPackageName); // always dependent on your own package
101
}
102
103     // Skip typeDeclarations which know of previously reported errors
104
TypeDeclaration[] types = referenceContext.types;
105     int typeLength = (types == null) ? 0 : types.length;
106     topLevelTypes = new SourceTypeBinding[typeLength];
107     int count = 0;
108     nextType: for (int i = 0; i < typeLength; i++) {
109         TypeDeclaration typeDecl = types[i];
110         ReferenceBinding typeBinding = fPackage.getType0(typeDecl.name);
111         recordSimpleReference(typeDecl.name); // needed to detect collision cases
112
if (typeBinding != null && typeBinding.isValidBinding() && !(typeBinding instanceof UnresolvedReferenceBinding)) {
113             // if a type exists, check that its a valid type
114
// it can be a NotFound problem type if its a secondary type referenced before its primary type found in additional units
115
// and it can be an unresolved type which is now being defined
116
problemReporter().duplicateTypes(referenceContext, typeDecl);
117             continue nextType;
118         }
119         if (fPackage != environment.defaultPackage && fPackage.getPackage(typeDecl.name) != null) {
120             // if a package exists, it must be a valid package - cannot be a NotFound problem package
121
// this is now a warning since a package does not really 'exist' until it contains a type, see JLS v2, 7.4.3
122
problemReporter().typeCollidesWithPackage(referenceContext, typeDecl);
123         }
124
125         if ((typeDecl.modifiers & ClassFileConstants.AccPublic) != 0) {
126             char[] mainTypeName;
127             if ((mainTypeName = referenceContext.getMainTypeName()) != null // mainTypeName == null means that implementor of ICompilationUnit decided to return null
128
&& !CharOperation.equals(mainTypeName, typeDecl.name)) {
129                 problemReporter().publicClassMustMatchFileName(referenceContext, typeDecl);
130                 // tolerate faulty main type name (91091), allow to proceed into type construction
131
}
132         }
133
134         ClassScope child = new ClassScope(this, typeDecl);
135         SourceTypeBinding type = child.buildType(null, fPackage, accessRestriction);
136         if (firstIsSynthetic && i == 0)
137             type.modifiers |= ClassFileConstants.AccSynthetic;
138         if (type != null)
139             topLevelTypes[count++] = type;
140     }
141
142     // shrink topLevelTypes... only happens if an error was reported
143
if (count != topLevelTypes.length)
144         System.arraycopy(topLevelTypes, 0, topLevelTypes = new SourceTypeBinding[count], 0, count);
145 }
146 void checkAndSetImports() {
147     if (referenceContext.imports == null) {
148         imports = getDefaultImports();
149         return;
150     }
151
152     // allocate the import array, add java.lang.* by default
153
int numberOfStatements = referenceContext.imports.length;
154     int numberOfImports = numberOfStatements + 1;
155     for (int i = 0; i < numberOfStatements; i++) {
156         ImportReference importReference = referenceContext.imports[i];
157         if (((importReference.bits & ASTNode.OnDemand) != 0) && CharOperation.equals(JAVA_LANG, importReference.tokens) && !importReference.isStatic()) {
158             numberOfImports--;
159             break;
160         }
161     }
162     ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
163     resolvedImports[0] = getDefaultImports()[0];
164     int index = 1;
165
166     nextImport : for (int i = 0; i < numberOfStatements; i++) {
167         ImportReference importReference = referenceContext.imports[i];
168         char[][] compoundName = importReference.tokens;
169
170         // skip duplicates or imports of the current package
171
for (int j = 0; j < index; j++) {
172             ImportBinding resolved = resolvedImports[j];
173             if (resolved.onDemand == ((importReference.bits & ASTNode.OnDemand) != 0) && resolved.isStatic() == importReference.isStatic())
174                 if (CharOperation.equals(compoundName, resolvedImports[j].compoundName))
175                     continue nextImport;
176         }
177
178         if ((importReference.bits & ASTNode.OnDemand) != 0) {
179             if (CharOperation.equals(compoundName, currentPackageName))
180                 continue nextImport;
181
182             Binding importBinding = findImport(compoundName, compoundName.length);
183             if (!importBinding.isValidBinding() || (importReference.isStatic() && importBinding instanceof PackageBinding))
184                 continue nextImport; // we report all problems in faultInImports()
185
resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
186         } else {
187             // resolve single imports only when the last name matches
188
resolvedImports[index++] = new ImportBinding(compoundName, false, null, importReference);
189         }
190     }
191
192     // shrink resolvedImports... only happens if an error was reported
193
if (resolvedImports.length > index)
194         System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[index], 0, index);
195     imports = resolvedImports;
196 }
197
198 /**
199  * Perform deferred check specific to parameterized types: bound checks, supertype collisions
200  */

201 void checkParameterizedTypes() {
202     if (compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) return;
203
204     for (int i = 0, length = topLevelTypes.length; i < length; i++) {
205         ClassScope scope = topLevelTypes[i].scope;
206         scope.checkParameterizedTypeBounds();
207         scope.checkParameterizedSuperTypeCollisions();
208     }
209 }
210 /*
211  * INTERNAL USE-ONLY
212  * Innerclasses get their name computed as they are generated, since some may not
213  * be actually outputed if sitting inside unreachable code.
214  */

215 public char[] computeConstantPoolName(LocalTypeBinding localType) {
216     if (localType.constantPoolName() != null) {
217         return localType.constantPoolName();
218     }
219     // delegates to the outermost enclosing classfile, since it is the only one with a global vision of its innertypes.
220

221     if (constantPoolNameUsage == null)
222         constantPoolNameUsage = new HashtableOfType();
223
224     ReferenceBinding outerMostEnclosingType = localType.scope.outerMostClassScope().enclosingSourceType();
225     
226     // ensure there is not already such a local type name defined by the user
227
int index = 0;
228     char[] candidateName;
229     boolean isCompliant15 = compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5;
230     while(true) {
231         if (localType.isMemberType()){
232             if (index == 0){
233                 candidateName = CharOperation.concat(
234                     localType.enclosingType().constantPoolName(),
235                     localType.sourceName,
236                     '$');
237             } else {
238                 // in case of collision, then member name gets extra $1 inserted
239
// e.g. class X { { class L{} new X(){ class L{} } } }
240
candidateName = CharOperation.concat(
241                     localType.enclosingType().constantPoolName(),
242                     '$',
243                     String.valueOf(index).toCharArray(),
244                     '$',
245                     localType.sourceName);
246             }
247         } else if (localType.isAnonymousType()){
248             if (isCompliant15) {
249                 // from 1.5 on, use immediately enclosing type name
250
candidateName = CharOperation.concat(
251                     localType.enclosingType.constantPoolName(),
252                     String.valueOf(index+1).toCharArray(),
253                     '$');
254             } else {
255                 candidateName = CharOperation.concat(
256                     outerMostEnclosingType.constantPoolName(),
257                     String.valueOf(index+1).toCharArray(),
258                     '$');
259             }
260         } else {
261             // local type
262
if (isCompliant15) {
263                 candidateName = CharOperation.concat(
264                     CharOperation.concat(
265                         localType.enclosingType().constantPoolName(),
266                         String.valueOf(index+1).toCharArray(),
267                         '$'),
268                     localType.sourceName);
269             } else {
270                 candidateName = CharOperation.concat(
271                     outerMostEnclosingType.constantPoolName(),
272                     '$',
273                     String.valueOf(index+1).toCharArray(),
274                     '$',
275                     localType.sourceName);
276             }
277         }
278         if (constantPoolNameUsage.get(candidateName) != null) {
279             index ++;
280         } else {
281             constantPoolNameUsage.put(candidateName, localType);
282             break;
283         }
284     }
285     return candidateName;
286 }
287
288 void connectTypeHierarchy() {
289     for (int i = 0, length = topLevelTypes.length; i < length; i++)
290         topLevelTypes[i].scope.connectTypeHierarchy();
291 }
292 void faultInImports() {
293     if (this.typeOrPackageCache != null)
294         return; // can be called when a field constant is resolved before static imports
295
if (referenceContext.imports == null) {
296         this.typeOrPackageCache = new HashtableOfObject(1);
297         return;
298     }
299
300     // collect the top level type names if a single type import exists
301
int numberOfStatements = referenceContext.imports.length;
302     HashtableOfType typesBySimpleNames = null;
303     for (int i = 0; i < numberOfStatements; i++) {
304         if ((referenceContext.imports[i].bits & ASTNode.OnDemand) == 0) {
305             typesBySimpleNames = new HashtableOfType(topLevelTypes.length + numberOfStatements);
306             for (int j = 0, length = topLevelTypes.length; j < length; j++)
307                 typesBySimpleNames.put(topLevelTypes[j].sourceName, topLevelTypes[j]);
308             break;
309         }
310     }
311
312     // allocate the import array, add java.lang.* by default
313
int numberOfImports = numberOfStatements + 1;
314     for (int i = 0; i < numberOfStatements; i++) {
315         ImportReference importReference = referenceContext.imports[i];
316         if (((importReference.bits & ASTNode.OnDemand) != 0) && CharOperation.equals(JAVA_LANG, importReference.tokens) && !importReference.isStatic()) {
317             numberOfImports--;
318             break;
319         }
320     }
321     ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
322     resolvedImports[0] = getDefaultImports()[0];
323     int index = 1;
324
325     // keep static imports with normal imports until there is a reason to split them up
326
// on demand imports continue to be packages & types. need to check on demand type imports for fields/methods
327
// single imports change from being just types to types or fields
328
nextImport : for (int i = 0; i < numberOfStatements; i++) {
329         ImportReference importReference = referenceContext.imports[i];
330         char[][] compoundName = importReference.tokens;
331
332         // skip duplicates or imports of the current package
333
for (int j = 0; j < index; j++) {
334             ImportBinding resolved = resolvedImports[j];
335             if (resolved.onDemand == ((importReference.bits & ASTNode.OnDemand) != 0) && resolved.isStatic() == importReference.isStatic()) {
336                 if (CharOperation.equals(compoundName, resolved.compoundName)) {
337                     problemReporter().unusedImport(importReference); // since skipped, must be reported now
338
continue nextImport;
339                 }
340             }
341         }
342         if ((importReference.bits & ASTNode.OnDemand) != 0) {
343             if (CharOperation.equals(compoundName, currentPackageName)) {
344                 problemReporter().unusedImport(importReference); // since skipped, must be reported now
345
continue nextImport;
346             }
347
348             Binding importBinding = findImport(compoundName, compoundName.length);
349             if (!importBinding.isValidBinding()) {
350                 problemReporter().importProblem(importReference, importBinding);
351                 continue nextImport;
352             }
353             if (importReference.isStatic() && importBinding instanceof PackageBinding) {
354                 problemReporter().cannotImportPackage(importReference);
355                 continue nextImport;
356             }
357             resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
358         } else {
359             Binding importBinding = findSingleImport(compoundName, importReference.isStatic());
360             if (!importBinding.isValidBinding()) {
361                 problemReporter().importProblem(importReference, importBinding);
362                 continue nextImport;
363             }
364             if (importBinding instanceof PackageBinding) {
365                 problemReporter().cannotImportPackage(importReference);
366                 continue nextImport;
367             }
368             ReferenceBinding conflictingType = null;
369             if (importBinding instanceof MethodBinding) {
370                 conflictingType = (ReferenceBinding) getType(compoundName, compoundName.length);
371                 if (!conflictingType.isValidBinding())
372                     conflictingType = null;
373             }
374             // collisions between an imported static field & a type should be checked according to spec... but currently not by javac
375
if (importBinding instanceof ReferenceBinding || conflictingType != null) {
376                 ReferenceBinding referenceBinding = conflictingType == null ? (ReferenceBinding) importBinding : conflictingType;
377                 if (importReference.isTypeUseDeprecated(referenceBinding, this))
378                     problemReporter().deprecatedType(referenceBinding, importReference);
379
380                 ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]);
381                 if (existingType != null) {
382                     // duplicate test above should have caught this case, but make sure
383
if (existingType == referenceBinding)
384                         continue nextImport;
385                     // either the type collides with a top level type or another imported type
386
for (int j = 0, length = topLevelTypes.length; j < length; j++) {
387                         if (CharOperation.equals(topLevelTypes[j].sourceName, existingType.sourceName)) {
388                             problemReporter().conflictingImport(importReference);
389                             continue nextImport;
390                         }
391                     }
392                     problemReporter().duplicateImport(importReference);
393                     continue nextImport;
394                 }
395                 typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding);
396             } else if (importBinding instanceof FieldBinding) {
397                 for (int j = 0; j < index; j++) {
398                     ImportBinding resolved = resolvedImports[j];
399                     // find other static fields with the same name
400
if (resolved.isStatic() && resolved.resolvedImport instanceof FieldBinding && importBinding != resolved.resolvedImport) {
401                         if (CharOperation.equals(compoundName[compoundName.length - 1], resolved.compoundName[resolved.compoundName.length - 1])) {
402                             problemReporter().duplicateImport(importReference);
403                             continue nextImport;
404                         }
405                     }
406                 }
407             }
408             resolvedImports[index++] = conflictingType == null
409                 ? new ImportBinding(compoundName, false, importBinding, importReference)
410                 : new ImportConflictBinding(compoundName, importBinding, conflictingType, importReference);
411         }
412     }
413
414     // shrink resolvedImports... only happens if an error was reported
415
if (resolvedImports.length > index)
416         System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[index], 0, index);
417     imports = resolvedImports;
418
419     int length = imports.length;
420     this.typeOrPackageCache = new HashtableOfObject(length);
421     for (int i = 0; i < length; i++) {
422         ImportBinding binding = imports[i];
423         if (!binding.onDemand && binding.resolvedImport instanceof ReferenceBinding || binding instanceof ImportConflictBinding)
424             this.typeOrPackageCache.put(binding.compoundName[binding.compoundName.length - 1], binding);
425     }
426 }
427 public void faultInTypes() {
428     faultInImports();
429
430     for (int i = 0, length = topLevelTypes.length; i < length; i++)
431         topLevelTypes[i].faultInTypesForFieldsAndMethods();
432 }
433 // this API is for code assist purpose
434
public Binding findImport(char[][] compoundName, boolean findStaticImports, boolean onDemand) {
435     if(onDemand) {
436         return findImport(compoundName, compoundName.length);
437     } else {
438         return findSingleImport(compoundName, findStaticImports);
439     }
440 }
441 private Binding findImport(char[][] compoundName, int length) {
442     recordQualifiedReference(compoundName);
443
444     Binding binding = environment.getTopLevelPackage(compoundName[0]);
445     int i = 1;
446     foundNothingOrType: if (binding != null) {
447         PackageBinding packageBinding = (PackageBinding) binding;
448         while (i < length) {
449             binding = packageBinding.getTypeOrPackage(compoundName[i++]);
450             if (binding == null || !binding.isValidBinding()) {
451                 binding = null;
452                 break foundNothingOrType;
453             }
454             if (!(binding instanceof PackageBinding))
455                 break foundNothingOrType;
456
457             packageBinding = (PackageBinding) binding;
458         }
459         return packageBinding;
460     }
461
462     ReferenceBinding type;
463     if (binding == null) {
464         if (environment.defaultPackage == null || compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
465             return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound);
466         type = findType(compoundName[0], environment.defaultPackage, environment.defaultPackage);
467         if (type == null || !type.isValidBinding())
468             return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound);
469         i = 1; // reset to look for member types inside the default package type
470
} else {
471         type = (ReferenceBinding) binding;
472     }
473
474     while (i < length) {
475         type = (ReferenceBinding)environment.convertToRawType(type); // type imports are necessarily raw for all except last
476
if (!type.canBeSeenBy(fPackage))
477             return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), type, ProblemReasons.NotVisible);
478
479         char[] name = compoundName[i++];
480         // does not look for inherited member types on purpose, only immediate members
481
type = type.getMemberType(name);
482         if (type == null)
483             return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound);
484     }
485     if (!type.canBeSeenBy(fPackage))
486         return new ProblemReferenceBinding(compoundName, type, ProblemReasons.NotVisible);
487     return type;
488 }
489 private Binding findSingleImport(char[][] compoundName, boolean findStaticImports) {
490     if (compoundName.length == 1) {
491         // findType records the reference
492
// the name cannot be a package
493
if (environment.defaultPackage == null || compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
494             return new ProblemReferenceBinding(compoundName, null, ProblemReasons.NotFound);
495         ReferenceBinding typeBinding = findType(compoundName[0], environment.defaultPackage, fPackage);
496         if (typeBinding == null)
497             return new ProblemReferenceBinding(compoundName, null, ProblemReasons.NotFound);
498         return typeBinding;
499     }
500
501     if (findStaticImports)
502         return findSingleStaticImport(compoundName);
503     return findImport(compoundName, compoundName.length);
504 }
505 private Binding findSingleStaticImport(char[][] compoundName) {
506     Binding binding = findImport(compoundName, compoundName.length - 1);
507     if (!binding.isValidBinding()) return binding;
508
509     char[] name = compoundName[compoundName.length - 1];
510     if (binding instanceof PackageBinding) {
511         Binding temp = ((PackageBinding) binding).getTypeOrPackage(name);
512         if (temp != null && temp instanceof ReferenceBinding) // must resolve to a member type or field, not a top level type
513
return new ProblemReferenceBinding(compoundName, (ReferenceBinding) temp, ProblemReasons.InvalidTypeForStaticImport);
514         return binding; // cannot be a package, error is caught in sender
515
}
516
517     // look to see if its a static field first
518
ReferenceBinding type = (ReferenceBinding) binding;
519     FieldBinding field = findField(type, name, null, true);
520     if (field != null && field.isValidBinding() && field.isStatic() && field.canBeSeenBy(type, null, this))
521         return field;
522
523     // look to see if there is a static method with the same selector
524
MethodBinding method = findStaticMethod(type, name);
525     if (method != null) return method;
526
527     type = findMemberType(name, type);
528     if (type == null || !type.isStatic()) {
529         if (field != null && !field.isValidBinding() && field.problemId() != ProblemReasons.NotFound)
530             return field;
531         return new ProblemReferenceBinding(compoundName, type, ProblemReasons.NotFound);
532     }
533     if (!type.canBeSeenBy(fPackage))
534         return new ProblemReferenceBinding(compoundName, type, ProblemReasons.NotVisible);
535     return type;
536 }
537 MethodBinding findStaticMethod(ReferenceBinding currentType, char[] selector) {
538     if (!currentType.canBeSeenBy(this))
539         return null;
540
541     do {
542         MethodBinding[] methods = currentType.getMethods(selector);
543         if (methods != Binding.NO_METHODS) {
544             for (int i = methods.length; --i >= 0;) {
545                 MethodBinding method = methods[i];
546                 if (method.isStatic() && method.canBeSeenBy(fPackage))
547                     return method;
548             }
549         }
550         if (currentType.superInterfaces() == null) // needed for statically imported types which don't know their hierarchy yet
551
((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
552     } while ((currentType = currentType.superclass()) != null);
553     return null;
554 }
555 ImportBinding[] getDefaultImports() {
556     // initialize the default imports if necessary... share the default java.lang.* import
557
if (environment.defaultImports != null) return environment.defaultImports;
558
559     Binding importBinding = environment.getTopLevelPackage(JAVA);
560     if (importBinding != null)
561         importBinding = ((PackageBinding) importBinding).getTypeOrPackage(JAVA_LANG[1]);
562
563     if (importBinding == null || !importBinding.isValidBinding()) {
564         // create a proxy for the missing BinaryType
565
BinaryTypeBinding missingObject = environment.cacheMissingBinaryType(JAVA_LANG_OBJECT, this.referenceContext);
566         importBinding = missingObject.fPackage;
567     }
568
569     return environment.defaultImports = new ImportBinding[] {new ImportBinding(JAVA_LANG, true, importBinding, null)};
570 }
571 // NOT Public API
572
public final Binding getImport(char[][] compoundName, boolean onDemand, boolean isStaticImport) {
573     if (onDemand)
574         return findImport(compoundName, compoundName.length);
575     return findSingleImport(compoundName, isStaticImport);
576 }
577
578 public int nextCaptureID() {
579     return this.captureID++;
580 }
581
582 /* Answer the problem reporter to use for raising new problems.
583 *
584 * Note that as a side-effect, this updates the current reference context
585 * (unit, type or method) in case the problem handler decides it is necessary
586 * to abort.
587 */

588 public ProblemReporter problemReporter() {
589     ProblemReporter problemReporter = referenceContext.problemReporter;
590     problemReporter.referenceContext = referenceContext;
591     return problemReporter;
592 }
593
594 /*
595 What do we hold onto:
596
597 1. when we resolve 'a.b.c', say we keep only 'a.b.c'
598  & when we fail to resolve 'c' in 'a.b', lets keep 'a.b.c'
599 THEN when we come across a new/changed/removed item named 'a.b.c',
600  we would find all references to 'a.b.c'
601 -> This approach fails because every type is resolved in every onDemand import to
602  detect collision cases... so the references could be 10 times bigger than necessary.
603
604 2. when we resolve 'a.b.c', lets keep 'a.b' & 'c'
605  & when we fail to resolve 'c' in 'a.b', lets keep 'a.b' & 'c'
606 THEN when we come across a new/changed/removed item named 'a.b.c',
607  we would find all references to 'a.b' & 'c'
608 -> This approach does not have a space problem but fails to handle collision cases.
609  What happens if a type is added named 'a.b'? We would search for 'a' & 'b' but
610  would not find a match.
611
612 3. when we resolve 'a.b.c', lets keep 'a', 'a.b' & 'a', 'b', 'c'
613  & when we fail to resolve 'c' in 'a.b', lets keep 'a', 'a.b' & 'a', 'b', 'c'
614 THEN when we come across a new/changed/removed item named 'a.b.c',
615  we would find all references to 'a.b' & 'c'
616 OR 'a.b' -> 'a' & 'b'
617 OR 'a' -> '' & 'a'
618 -> As long as each single char[] is interned, we should not have a space problem
619  and can handle collision cases.
620
621 4. when we resolve 'a.b.c', lets keep 'a.b' & 'a', 'b', 'c'
622  & when we fail to resolve 'c' in 'a.b', lets keep 'a.b' & 'a', 'b', 'c'
623 THEN when we come across a new/changed/removed item named 'a.b.c',
624  we would find all references to 'a.b' & 'c'
625 OR 'a.b' -> 'a' & 'b' in the simple name collection
626 OR 'a' -> 'a' in the simple name collection
627 -> As long as each single char[] is interned, we should not have a space problem
628  and can handle collision cases.
629 */

630 void recordQualifiedReference(char[][] qualifiedName) {
631     if (qualifiedReferences == null) return; // not recording dependencies
632

633     int length = qualifiedName.length;
634     if (length > 1) {
635         while (!qualifiedReferences.contains(qualifiedName)) {
636             qualifiedReferences.add(qualifiedName);
637             if (length == 2) {
638                 recordSimpleReference(qualifiedName[0]);
639                 recordSimpleReference(qualifiedName[1]);
640                 return;
641             }
642             length--;
643             recordSimpleReference(qualifiedName[length]);
644             System.arraycopy(qualifiedName, 0, qualifiedName = new char[length][], 0, length);
645         }
646     } else if (length == 1) {
647         recordSimpleReference(qualifiedName[0]);
648     }
649 }
650 void recordReference(char[][] qualifiedEnclosingName, char[] simpleName) {
651     recordQualifiedReference(qualifiedEnclosingName);
652     recordSimpleReference(simpleName);
653 }
654 void recordReference(ReferenceBinding type, char[] simpleName) {
655     ReferenceBinding actualType = typeToRecord(type);
656     if (actualType != null)
657         recordReference(actualType.compoundName, simpleName);
658 }
659 void recordSimpleReference(char[] simpleName) {
660     if (simpleNameReferences == null) return; // not recording dependencies
661

662     if (!simpleNameReferences.contains(simpleName))
663         simpleNameReferences.add(simpleName);
664 }
665 void recordSuperTypeReference(TypeBinding type) {
666     if (referencedSuperTypes == null) return; // not recording dependencies
667

668     ReferenceBinding actualType = typeToRecord(type);
669     if (actualType != null && !referencedSuperTypes.containsIdentical(actualType))
670         referencedSuperTypes.add(actualType);
671 }
672 public void recordTypeConversion(TypeBinding superType, TypeBinding subType) {
673     recordSuperTypeReference(subType); // must record the hierarchy of the subType that is converted to the superType
674
}
675 void recordTypeReference(TypeBinding type) {
676     if (referencedTypes == null) return; // not recording dependencies
677

678     ReferenceBinding actualType = typeToRecord(type);
679     if (actualType != null && !referencedTypes.containsIdentical(actualType))
680         referencedTypes.add(actualType);
681 }
682 void recordTypeReferences(TypeBinding[] types) {
683     if (referencedTypes == null) return; // not recording dependencies
684
if (types == null || types.length == 0) return;
685
686     for (int i = 0, max = types.length; i < max; i++) {
687         // No need to record supertypes of method arguments & thrown exceptions, just the compoundName
688
// If a field/method is retrieved from such a type then a separate call does the job
689
ReferenceBinding actualType = typeToRecord(types[i]);
690         if (actualType != null && !referencedTypes.containsIdentical(actualType))
691             referencedTypes.add(actualType);
692     }
693 }
694 Binding resolveSingleImport(ImportBinding importBinding) {
695     if (importBinding.resolvedImport == null) {
696         importBinding.resolvedImport = findSingleImport(importBinding.compoundName, importBinding.isStatic());
697         if (!importBinding.resolvedImport.isValidBinding() || importBinding.resolvedImport instanceof PackageBinding) {
698             if (this.imports != null) {
699                 ImportBinding[] newImports = new ImportBinding[imports.length - 1];
700                 for (int i = 0, n = 0, max = this.imports.length; i < max; i++)
701                     if (this.imports[i] != importBinding)
702                         newImports[n++] = this.imports[i];
703                 this.imports = newImports;
704             }
705             return null;
706         }
707     }
708     return importBinding.resolvedImport;
709 }
710 public void storeDependencyInfo() {
711     // add the type hierarchy of each referenced supertype
712
// cannot do early since the hierarchy may not be fully resolved
713
for (int i = 0; i < referencedSuperTypes.size; i++) { // grows as more types are added
714
ReferenceBinding type = (ReferenceBinding) referencedSuperTypes.elementAt(i);
715         if (!referencedTypes.containsIdentical(type))
716             referencedTypes.add(type);
717
718         if (!type.isLocalType()) {
719             ReferenceBinding enclosing = type.enclosingType();
720             if (enclosing != null)
721                 recordSuperTypeReference(enclosing);
722         }
723         ReferenceBinding superclass = type.superclass();
724         if (superclass != null)
725             recordSuperTypeReference(superclass);
726         ReferenceBinding[] interfaces = type.superInterfaces();
727         if (interfaces != null)
728             for (int j = 0, length = interfaces.length; j < length; j++)
729                 recordSuperTypeReference(interfaces[j]);
730     }
731
732     for (int i = 0, l = referencedTypes.size; i < l; i++) {
733         ReferenceBinding type = (ReferenceBinding) referencedTypes.elementAt(i);
734         if (!type.isLocalType())
735             recordQualifiedReference(type.isMemberType()
736                 ? CharOperation.splitOn('.', type.readableName())
737                 : type.compoundName);
738     }
739
740     int size = qualifiedReferences.size;
741     char[][][] qualifiedRefs = new char[size][][];
742     for (int i = 0; i < size; i++)
743         qualifiedRefs[i] = qualifiedReferences.elementAt(i);
744     referenceContext.compilationResult.qualifiedReferences = qualifiedRefs;
745
746     size = simpleNameReferences.size;
747     char[][] simpleRefs = new char[size][];
748     for (int i = 0; i < size; i++)
749         simpleRefs[i] = simpleNameReferences.elementAt(i);
750     referenceContext.compilationResult.simpleNameReferences = simpleRefs;
751 }
752 public String JavaDoc toString() {
753     return "--- CompilationUnit Scope : " + new String JavaDoc(referenceContext.getFileName()); //$NON-NLS-1$
754
}
755 private ReferenceBinding typeToRecord(TypeBinding type) {
756     if (type.isArrayType())
757         type = ((ArrayBinding) type).leafComponentType;
758
759     switch (type.kind()) {
760         case Binding.BASE_TYPE :
761         case Binding.TYPE_PARAMETER :
762         case Binding.WILDCARD_TYPE :
763             return null;
764         case Binding.PARAMETERIZED_TYPE :
765         case Binding.RAW_TYPE :
766             type = type.erasure();
767     }
768     ReferenceBinding refType = (ReferenceBinding) type;
769     if (refType.isLocalType()) return null;
770     return refType;
771 }
772 public void verifyMethods(MethodVerifier verifier) {
773     for (int i = 0, length = topLevelTypes.length; i < length; i++)
774         topLevelTypes[i].verifyMethods(verifier);
775 }
776 }
777
Popular Tags