improved PHP Completion for -> operator
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / CompilationUnitScope.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
12
13 import java.util.ArrayList;
14
15 import net.sourceforge.phpdt.core.compiler.CharOperation;
16 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
17 import net.sourceforge.phpdt.internal.compiler.util.CompoundNameVector;
18 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfType;
19 import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
20 import net.sourceforge.phpdt.internal.compiler.util.SimpleNameVector;
21 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
22 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
23
24 public class CompilationUnitScope extends Scope {
25
26   public LookupEnvironment environment;
27   public CompilationUnitDeclaration referenceContext;
28   public char[][] currentPackageName;
29   public PackageBinding fPackage;
30   public ImportBinding[] imports;
31
32   public SourceTypeBinding[] topLevelTypes;
33
34   private CompoundNameVector qualifiedReferences;
35   private SimpleNameVector simpleNameReferences;
36   private ObjectVector referencedTypes;
37
38   HashtableOfType constantPoolNameUsage;
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     this.currentPackageName = null; 
47     //  if (environment.options.produceReferenceInfo) {
48     //          this.qualifiedReferences = new CompoundNameVector();
49     //          this.simpleNameReferences = new SimpleNameVector();
50     //          this.referencedTypes = new ObjectVector();
51     //  } else {
52     this.qualifiedReferences = null; // used to test if dependencies should be recorded
53     this.simpleNameReferences = null;
54     this.referencedTypes = null;
55     //  }
56   }
57   void buildFieldsAndMethods() {
58     for (int i = 0, length = topLevelTypes.length; i < length; i++)
59       topLevelTypes[i].scope.buildFieldsAndMethods();
60   }
61   void buildTypeBindings() {
62     if (referenceContext.compilationResult.compilationUnit != null) {
63       char[][] expectedPackageName = referenceContext.compilationResult.compilationUnit.getPackageName();
64       if (expectedPackageName != null && !CharOperation.equals(currentPackageName, expectedPackageName)) {
65
66         // only report if the unit isn't structurally empty
67         //                      if (referenceContext.currentPackage != null 
68         //                                      || referenceContext.types != null 
69         //                                      || referenceContext.imports != null) {
70         //                              problemReporter().packageIsNotExpectedPackage(referenceContext);
71         //                      }
72         currentPackageName = expectedPackageName.length == 0 ? CharOperation.NO_CHAR_CHAR : expectedPackageName;
73       }
74     }
75     if (currentPackageName == CharOperation.NO_CHAR_CHAR) {
76       if ((fPackage = environment.defaultPackage) == null) {
77         problemReporter().mustSpecifyPackage(referenceContext);
78         return;
79       }
80     } else {
81                 if ((fPackage = environment.createPackage(currentPackageName)) == null) {
82 //                              problemReporter().packageCollidesWithType(referenceContext);
83                         return;
84                 }
85       recordQualifiedReference(currentPackageName); // always dependent on your own package
86     }
87
88     // Skip typeDeclarations which know of previously reported errors
89     ArrayList types = referenceContext.types;
90     int typeLength = (types == null) ? 0 : types.size();
91     topLevelTypes = new SourceTypeBinding[typeLength];
92     int count = 0;
93     nextType : for (int i = 0; i < typeLength; i++) {
94       if (types.get(i) instanceof TypeDeclaration) {
95         TypeDeclaration typeDecl = (TypeDeclaration) types.get(i);
96         ReferenceBinding typeBinding = fPackage.getType0(typeDecl.name);
97         recordSimpleReference(typeDecl.name); // needed to detect collision cases
98         if (typeBinding != null && !(typeBinding instanceof UnresolvedReferenceBinding)) {
99           // if a type exists, it must be a valid type - cannot be a NotFound problem type
100           // unless its an unresolved type which is now being defined
101           problemReporter().duplicateTypes(referenceContext, typeDecl);
102           continue nextType;
103         }
104         if (fPackage != environment.defaultPackage && fPackage.getPackage(typeDecl.name) != null) {
105           // if a package exists, it must be a valid package - cannot be a NotFound problem package
106           problemReporter().typeCollidesWithPackage(referenceContext, typeDecl);
107           continue nextType;
108         }
109
110         if ((typeDecl.modifiers & AccPublic) != 0) {
111           char[] mainTypeName;
112             if ((mainTypeName = referenceContext.getMainTypeName()) != null
113             // mainTypeName == null means that implementor of ICompilationUnit decided to return null
114               && !CharOperation.equals(mainTypeName, typeDecl.name)) {
115             problemReporter().publicClassMustMatchFileName(referenceContext, typeDecl);
116             continue nextType;
117           }
118         }
119
120         ClassScope child = new ClassScope(this, typeDecl);
121         SourceTypeBinding type = child.buildType(null, fPackage);
122         if (type != null) {
123           topLevelTypes[count++] = type;
124         }
125       }
126     }
127
128     // shrink topLevelTypes... only happens if an error was reported
129     if (count != topLevelTypes.length)
130       System.arraycopy(topLevelTypes, 0, topLevelTypes = new SourceTypeBinding[count], 0, count);
131   }
132 //  void checkAndSetImports() {
133 //    // initialize the default imports if necessary... share the default java.lang.* import
134 //    if (environment.defaultImports == null) {
135 //      Binding importBinding = environment.getTopLevelPackage(JAVA);
136 //      if (importBinding != null)
137 //        importBinding = ((PackageBinding) importBinding).getTypeOrPackage(JAVA_LANG[1]);
138 //
139 //      // abort if java.lang cannot be found...
140 //      if (importBinding == null || !importBinding.isValidBinding())
141 //        problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
142 //
143 //      environment.defaultImports = new ImportBinding[] { new ImportBinding(JAVA_LANG, true, importBinding, null)};
144 //    }
145 //    if (referenceContext.imports == null) {
146 //      imports = environment.defaultImports;
147 //      return;
148 //    }
149 //
150 //    // allocate the import array, add java.lang.* by default
151 //    int numberOfStatements = referenceContext.imports.length;
152 //    int numberOfImports = numberOfStatements + 1;
153 //    for (int i = 0; i < numberOfStatements; i++) {
154 //      ImportReference importReference = referenceContext.imports[i];
155 //      if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens)) {
156 //        numberOfImports--;
157 //        break;
158 //      }
159 //    }
160 //    ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
161 //    resolvedImports[0] = environment.defaultImports[0];
162 //    int index = 1;
163 //
164 //    nextImport : for (int i = 0; i < numberOfStatements; i++) {
165 //      ImportReference importReference = referenceContext.imports[i];
166 //      char[][] compoundName = importReference.tokens;
167 //
168 //      // skip duplicates or imports of the current package
169 //      for (int j = 0; j < index; j++)
170 //        if (resolvedImports[j].onDemand == importReference.onDemand)
171 //          if (CharOperation.equals(compoundName, resolvedImports[j].compoundName))
172 //            continue nextImport;
173 //      if (importReference.onDemand == true)
174 //        if (CharOperation.equals(compoundName, currentPackageName))
175 //          continue nextImport;
176 //
177 //      if (importReference.onDemand) {
178 //        Binding importBinding = findOnDemandImport(compoundName);
179 //        if (!importBinding.isValidBinding())
180 //          continue nextImport; // we report all problems in faultInImports()
181 //        resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
182 //      } else {
183 //        resolvedImports[index++] = new ImportBinding(compoundName, false, null, importReference);
184 //      }
185 //    }
186 //
187 //    // shrink resolvedImports... only happens if an error was reported
188 //    if (resolvedImports.length > index)
189 //      System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[index], 0, index);
190 //    imports = resolvedImports;
191 //  }
192   /*
193    * INTERNAL USE-ONLY
194    * Innerclasses get their name computed as they are generated, since some may not
195    * be actually outputed if sitting inside unreachable code.
196    */
197   public char[] computeConstantPoolName(LocalTypeBinding localType) {
198     if (localType.constantPoolName() != null) {
199       return localType.constantPoolName();
200     }
201     // delegates to the outermost enclosing classfile, since it is the only one with a global vision of its innertypes.
202
203     if (constantPoolNameUsage == null)
204       constantPoolNameUsage = new HashtableOfType();
205
206     ReferenceBinding outerMostEnclosingType = localType.scope.outerMostClassScope().enclosingSourceType();
207
208     // ensure there is not already such a local type name defined by the user
209     int index = 0;
210     char[] candidateName;
211     while (true) {
212       if (localType.isMemberType()) {
213         if (index == 0) {
214           candidateName = CharOperation.concat(localType.enclosingType().constantPoolName(), localType.sourceName, '$');
215         } else {
216           // in case of collision, then member name gets extra $1 inserted
217           // e.g. class X { { class L{} new X(){ class L{} } } }
218           candidateName =
219             CharOperation.concat(localType.enclosingType().constantPoolName(), '$', String.valueOf(index).toCharArray(), '$', localType.sourceName);
220         }
221       } else if (localType.isAnonymousType()) {
222         candidateName = CharOperation.concat(outerMostEnclosingType.constantPoolName(), String.valueOf(index + 1).toCharArray(), '$');
223       } else {
224         candidateName =
225           CharOperation.concat(outerMostEnclosingType.constantPoolName(), '$', String.valueOf(index + 1).toCharArray(), '$', localType.sourceName);
226       }
227       if (constantPoolNameUsage.get(candidateName) != null) {
228         index++;
229       } else {
230         constantPoolNameUsage.put(candidateName, localType);
231         break;
232       }
233     }
234     return candidateName;
235   }
236
237   void connectTypeHierarchy() {
238     for (int i = 0, length = topLevelTypes.length; i < length; i++)
239       topLevelTypes[i].scope.connectTypeHierarchy();
240   }
241 //  void faultInImports() {
242 //    if (referenceContext.imports == null)
243 //      return;
244 //
245 //    // collect the top level type names if a single type import exists
246 //    int numberOfStatements = referenceContext.imports.length;
247 //    HashtableOfType typesBySimpleNames = null;
248 //    for (int i = 0; i < numberOfStatements; i++) {
249 //      if (!referenceContext.imports[i].onDemand) {
250 //        typesBySimpleNames = new HashtableOfType(topLevelTypes.length + numberOfStatements);
251 //        for (int j = 0, length = topLevelTypes.length; j < length; j++)
252 //          typesBySimpleNames.put(topLevelTypes[j].sourceName, topLevelTypes[j]);
253 //        break;
254 //      }
255 //    }
256 //
257 //    // allocate the import array, add java.lang.* by default
258 //    int numberOfImports = numberOfStatements + 1;
259 //    for (int i = 0; i < numberOfStatements; i++) {
260 //      ImportReference importReference = referenceContext.imports[i];
261 //      if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens)) {
262 //        numberOfImports--;
263 //        break;
264 //      }
265 //    }
266 //    ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
267 //    resolvedImports[0] = environment.defaultImports[0];
268 //    int index = 1;
269 //
270 //    nextImport : for (int i = 0; i < numberOfStatements; i++) {
271 //      ImportReference importReference = referenceContext.imports[i];
272 //      char[][] compoundName = importReference.tokens;
273 //
274 //      // skip duplicates or imports of the current package
275 //      for (int j = 0; j < index; j++)
276 //        if (resolvedImports[j].onDemand == importReference.onDemand)
277 //          if (CharOperation.equals(compoundName, resolvedImports[j].compoundName)) {
278 //            problemReporter().unusedImport(importReference); // since skipped, must be reported now
279 //            continue nextImport;
280 //          }
281 //      if (importReference.onDemand == true)
282 //        if (CharOperation.equals(compoundName, currentPackageName)) {
283 //          problemReporter().unusedImport(importReference); // since skipped, must be reported now
284 //          continue nextImport;
285 //        }
286 //      if (importReference.onDemand) {
287 //        Binding importBinding = findOnDemandImport(compoundName);
288 //        if (!importBinding.isValidBinding()) {
289 //          problemReporter().importProblem(importReference, importBinding);
290 //          continue nextImport;
291 //        }
292 //        resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
293 //      } else {
294 //        Binding typeBinding = findSingleTypeImport(compoundName);
295 //        if (!typeBinding.isValidBinding()) {
296 //          problemReporter().importProblem(importReference, typeBinding);
297 //          continue nextImport;
298 //        }
299 //        if (typeBinding instanceof PackageBinding) {
300 //          problemReporter().cannotImportPackage(importReference);
301 //          continue nextImport;
302 //        }
303 //        if (typeBinding instanceof ReferenceBinding) {
304 //          ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
305 //          if (importReference.isTypeUseDeprecated(referenceBinding, this)) {
306 //            problemReporter().deprecatedType((TypeBinding) typeBinding, importReference);
307 //          }
308 //        }
309 //        ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]);
310 //        if (existingType != null) {
311 //          // duplicate test above should have caught this case, but make sure
312 //          if (existingType == typeBinding) {
313 //            continue nextImport;
314 //          }
315 //          // either the type collides with a top level type or another imported type
316 //          for (int j = 0, length = topLevelTypes.length; j < length; j++) {
317 //            if (CharOperation.equals(topLevelTypes[j].sourceName, existingType.sourceName)) {
318 //              problemReporter().conflictingImport(importReference);
319 //              continue nextImport;
320 //            }
321 //          }
322 //          problemReporter().duplicateImport(importReference);
323 //          continue nextImport;
324 //        }
325 //        resolvedImports[index++] = new ImportBinding(compoundName, false, typeBinding, importReference);
326 //        typesBySimpleNames.put(compoundName[compoundName.length - 1], (ReferenceBinding) typeBinding);
327 //      }
328 //    }
329 //
330 //    // shrink resolvedImports... only happens if an error was reported
331 //    if (resolvedImports.length > index)
332 //      System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[index], 0, index);
333 //    imports = resolvedImports;
334 //  }
335   public void faultInTypes() {
336 //    faultInImports();
337     if (topLevelTypes==null) {
338                         topLevelTypes = new SourceTypeBinding[0];
339     }
340     for (int i = 0, length = topLevelTypes.length; i < length; i++)
341       topLevelTypes[i].faultInTypesForFieldsAndMethods();
342   }
343   private Binding findOnDemandImport(char[][] compoundName) {
344     recordQualifiedReference(compoundName);
345
346     Binding binding = environment.getTopLevelPackage(compoundName[0]);
347     int i = 1;
348     int length = compoundName.length;
349     foundNothingOrType : if (binding != null) {
350       PackageBinding packageBinding = (PackageBinding) binding;
351       while (i < length) {
352         binding = packageBinding.getTypeOrPackage(compoundName[i++]);
353         if (binding == null || !binding.isValidBinding()) {
354           binding = null;
355           break foundNothingOrType;
356         }
357         if (!(binding instanceof PackageBinding))
358           break foundNothingOrType;
359
360         packageBinding = (PackageBinding) binding;
361       }
362       return packageBinding;
363     }
364
365     ReferenceBinding type;
366     if (binding == null) {
367       //                if (environment.defaultPackage == null
368       //                                || environment.options.complianceLevel >= CompilerOptions.JDK1_4){
369       //                        return new ProblemReferenceBinding(
370       //                                CharOperation.subarray(compoundName, 0, i),
371       //                                NotFound);
372       //                }
373       type = findType(compoundName[0], environment.defaultPackage, environment.defaultPackage);
374       if (type == null || !type.isValidBinding())
375         return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), NotFound);
376       i = 1; // reset to look for member types inside the default package type
377     } else {
378       type = (ReferenceBinding) binding;
379     }
380
381     for (; i < length; i++) {
382       if (!type.canBeSeenBy(fPackage)) {
383         return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), type, NotVisible);
384       }
385       // does not look for inherited member types on purpose
386       if ((type = type.getMemberType(compoundName[i])) == null) {
387         return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i + 1), NotFound);
388       }
389     }
390     if (!type.canBeSeenBy(fPackage))
391       return new ProblemReferenceBinding(compoundName, type, NotVisible);
392     return type;
393   }
394   private Binding findSingleTypeImport(char[][] compoundName) {
395     if (compoundName.length == 1) {
396       // findType records the reference
397       // the name cannot be a package
398       //                if (environment.defaultPackage == null 
399       //                        || environment.options.complianceLevel >= CompilerOptions.JDK1_4)
400       //                        return new ProblemReferenceBinding(compoundName, NotFound);
401       ReferenceBinding typeBinding = findType(compoundName[0], environment.defaultPackage, fPackage);
402       if (typeBinding == null)
403         return new ProblemReferenceBinding(compoundName, NotFound);
404       else
405         return typeBinding;
406     }
407     return findOnDemandImport(compoundName);
408   }
409   /* Answer the problem reporter to use for raising new problems.
410   *
411   * Note that as a side-effect, this updates the current reference context
412   * (unit, type or method) in case the problem handler decides it is necessary
413   * to abort.
414   */
415
416   public ProblemReporter problemReporter() {
417     ProblemReporter problemReporter = referenceContext.problemReporter;
418     problemReporter.referenceContext = referenceContext;
419     return problemReporter;
420   }
421
422   /*
423   What do we hold onto:
424   
425   1. when we resolve 'a.b.c', say we keep only 'a.b.c'
426    & when we fail to resolve 'c' in 'a.b', lets keep 'a.b.c'
427   THEN when we come across a new/changed/removed item named 'a.b.c',
428    we would find all references to 'a.b.c'
429   -> This approach fails because every type is resolved in every onDemand import to
430    detect collision cases... so the references could be 10 times bigger than necessary.
431   
432   2. when we resolve 'a.b.c', lets keep 'a.b' & 'c'
433    & when we fail to resolve 'c' in 'a.b', lets keep 'a.b' & 'c'
434   THEN when we come across a new/changed/removed item named 'a.b.c',
435    we would find all references to 'a.b' & 'c'
436   -> This approach does not have a space problem but fails to handle collision cases.
437    What happens if a type is added named 'a.b'? We would search for 'a' & 'b' but
438    would not find a match.
439   
440   3. when we resolve 'a.b.c', lets keep 'a', 'a.b' & 'a', 'b', 'c'
441    & when we fail to resolve 'c' in 'a.b', lets keep 'a', 'a.b' & 'a', 'b', 'c'
442   THEN when we come across a new/changed/removed item named 'a.b.c',
443    we would find all references to 'a.b' & 'c'
444   OR 'a.b' -> 'a' & 'b'
445   OR 'a' -> '' & 'a'
446   -> As long as each single char[] is interned, we should not have a space problem
447    and can handle collision cases.
448   
449   4. when we resolve 'a.b.c', lets keep 'a.b' & 'a', 'b', 'c'
450    & when we fail to resolve 'c' in 'a.b', lets keep 'a.b' & 'a', 'b', 'c'
451   THEN when we come across a new/changed/removed item named 'a.b.c',
452    we would find all references to 'a.b' & 'c'
453   OR 'a.b' -> 'a' & 'b' in the simple name collection
454   OR 'a' -> 'a' in the simple name collection
455   -> As long as each single char[] is interned, we should not have a space problem
456    and can handle collision cases.
457   */
458   void recordQualifiedReference(char[][] qualifiedName) {
459     if (qualifiedReferences == null)
460       return; // not recording dependencies
461
462     int length = qualifiedName.length;
463     if (length > 1) {
464       while (!qualifiedReferences.contains(qualifiedName)) {
465         qualifiedReferences.add(qualifiedName);
466         if (length == 2) {
467           recordSimpleReference(qualifiedName[0]);
468           recordSimpleReference(qualifiedName[1]);
469           return;
470         }
471         length--;
472         recordSimpleReference(qualifiedName[length]);
473         System.arraycopy(qualifiedName, 0, qualifiedName = new char[length][], 0, length);
474       }
475     } else if (length == 1) {
476       recordSimpleReference(qualifiedName[0]);
477     }
478   }
479   void recordReference(char[][] qualifiedEnclosingName, char[] simpleName) {
480     recordQualifiedReference(qualifiedEnclosingName);
481     recordSimpleReference(simpleName);
482   }
483   void recordSimpleReference(char[] simpleName) {
484     if (simpleNameReferences == null)
485       return; // not recording dependencies
486
487     if (!simpleNameReferences.contains(simpleName))
488       simpleNameReferences.add(simpleName);
489   }
490   void recordTypeReference(TypeBinding type) {
491     if (referencedTypes == null)
492       return; // not recording dependencies
493
494     if (type.isArrayType())
495       type = ((ArrayBinding) type).leafComponentType;
496     if (!type.isBaseType() && !referencedTypes.containsIdentical(type))
497       referencedTypes.add(type);
498   }
499   void recordTypeReferences(TypeBinding[] types) {
500     if (qualifiedReferences == null)
501       return; // not recording dependencies
502     if (types == null || types.length == 0)
503       return;
504
505     for (int i = 0, max = types.length; i < max; i++) {
506       // No need to record supertypes of method arguments & thrown exceptions, just the compoundName
507       // If a field/method is retrieved from such a type then a separate call does the job
508       TypeBinding type = types[i];
509       if (type.isArrayType())
510         type = ((ArrayBinding) type).leafComponentType;
511       if (!type.isBaseType()) {
512         ReferenceBinding actualType = (ReferenceBinding) type;
513         if (!actualType.isLocalType())
514           recordQualifiedReference(actualType.isMemberType() ? CharOperation.splitOn('.', actualType.readableName()) : actualType.compoundName);
515       }
516     }
517   }
518   Binding resolveSingleTypeImport(ImportBinding importBinding) {
519     if (importBinding.resolvedImport == null) {
520       importBinding.resolvedImport = findSingleTypeImport(importBinding.compoundName);
521       if (!importBinding.resolvedImport.isValidBinding() || importBinding.resolvedImport instanceof PackageBinding) {
522         if (this.imports != null) {
523           ImportBinding[] newImports = new ImportBinding[imports.length - 1];
524           for (int i = 0, n = 0, max = this.imports.length; i < max; i++)
525             if (this.imports[i] != importBinding) {
526               newImports[n++] = this.imports[i];
527             }
528           this.imports = newImports;
529         }
530         return null;
531       }
532     }
533     return importBinding.resolvedImport;
534   }
535   public void storeDependencyInfo() {
536     // add the type hierarchy of each referenced type
537     // cannot do early since the hierarchy may not be fully resolved
538     for (int i = 0; i < referencedTypes.size; i++) { // grows as more types are added
539       ReferenceBinding type = (ReferenceBinding) referencedTypes.elementAt(i);
540       if (!type.isLocalType()) {
541         recordQualifiedReference(type.isMemberType() ? CharOperation.splitOn('.', type.readableName()) : type.compoundName);
542         ReferenceBinding enclosing = type.enclosingType();
543         if (enclosing != null && !referencedTypes.containsIdentical(enclosing))
544           referencedTypes.add(enclosing); // to record its supertypes
545       }
546       ReferenceBinding superclass = type.superclass();
547       if (superclass != null && !referencedTypes.containsIdentical(superclass))
548         referencedTypes.add(superclass); // to record its supertypes
549       ReferenceBinding[] interfaces = type.superInterfaces();
550       if (interfaces != null && interfaces.length > 0)
551         for (int j = 0, length = interfaces.length; j < length; j++)
552           if (!referencedTypes.containsIdentical(interfaces[j]))
553             referencedTypes.add(interfaces[j]); // to record its supertypes
554     }
555
556     int size = qualifiedReferences.size;
557     char[][][] qualifiedRefs = new char[size][][];
558     for (int i = 0; i < size; i++)
559       qualifiedRefs[i] = qualifiedReferences.elementAt(i);
560     referenceContext.compilationResult.qualifiedReferences = qualifiedRefs;
561
562     size = simpleNameReferences.size;
563     char[][] simpleRefs = new char[size][];
564     for (int i = 0; i < size; i++)
565       simpleRefs[i] = simpleNameReferences.elementAt(i);
566     referenceContext.compilationResult.simpleNameReferences = simpleRefs;
567   }
568   public String toString() {
569     return "--- CompilationUnit Scope : " + new String(referenceContext.getFileName()); //$NON-NLS-1$
570   }
571   public void verifyMethods(MethodVerifier verifier) {
572     for (int i = 0, length = topLevelTypes.length; i < length; i++)
573       topLevelTypes[i].verifyMethods(verifier);
574   }
575 }