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