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
 
   9  *     IBM Corporation - initial API and implementation
 
  10  *******************************************************************************/
 
  11 package net.sourceforge.phpdt.internal.compiler.lookup;
 
  13 import java.util.ArrayList;
 
  15 import net.sourceforge.phpdt.core.compiler.CharOperation;
 
  16 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
 
  17 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
 
  18 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
 
  19 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
 
  20 import net.sourceforge.phpdt.internal.compiler.util.CompoundNameVector;
 
  21 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfObject;
 
  22 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfType;
 
  23 import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
 
  24 import net.sourceforge.phpdt.internal.compiler.util.SimpleNameVector;
 
  26 import org.eclipse.core.resources.IFile;
 
  27 import org.eclipse.core.runtime.IPath;
 
  29 public class CompilationUnitScope extends Scope {
 
  31         public LookupEnvironment environment;
 
  33         public CompilationUnitDeclaration referenceContext;
 
  35         public char[][] currentPackageName;
 
  37         public PackageBinding fPackage;
 
  39         public ImportBinding[] imports;
 
  41         public SourceTypeBinding[] topLevelTypes;
 
  43         private CompoundNameVector qualifiedReferences;
 
  45         private SimpleNameVector simpleNameReferences;
 
  47         private ObjectVector referencedTypes;
 
  49         HashtableOfType constantPoolNameUsage;
 
  51         public HashtableOfObject resolvedSingeTypeImports;
 
  53         public CompilationUnitScope(CompilationUnitDeclaration unit,
 
  54                         LookupEnvironment environment) {
 
  55                 super(COMPILATION_UNIT_SCOPE, null);
 
  56                 this.environment = environment;
 
  57                 this.referenceContext = unit;
 
  59                 // this.currentPackageName = unit.currentPackage == null ?
 
  60                 // CharOperation.NO_CHAR_CHAR : unit.currentPackage.tokens;
 
  61                 this.currentPackageName = null;
 
  62                 // if (environment.options.produceReferenceInfo) {
 
  63                 // this.qualifiedReferences = new CompoundNameVector();
 
  64                 // this.simpleNameReferences = new SimpleNameVector();
 
  65                 // this.referencedTypes = new ObjectVector();
 
  67                 this.qualifiedReferences = null; // used to test if dependencies
 
  69                 this.simpleNameReferences = null;
 
  70                 this.referencedTypes = null;
 
  74         void buildFieldsAndMethods() {
 
  75                 for (int i = 0, length = topLevelTypes.length; i < length; i++)
 
  76                         topLevelTypes[i].scope.buildFieldsAndMethods();
 
  79         void buildTypeBindings() {
 
  80                 if (referenceContext.compilationResult.compilationUnit != null) {
 
  81                         char[][] expectedPackageName = referenceContext.compilationResult.compilationUnit
 
  83                         if (expectedPackageName != null
 
  84                                         && !CharOperation.equals(currentPackageName,
 
  85                                                         expectedPackageName)) {
 
  87                                 // only report if the unit isn't structurally empty
 
  88                                 // if (referenceContext.currentPackage != null
 
  89                                 // || referenceContext.types != null
 
  90                                 // || referenceContext.imports != null) {
 
  91                                 // problemReporter().packageIsNotExpectedPackage(referenceContext);
 
  93                                 currentPackageName = expectedPackageName.length == 0 ? CharOperation.NO_CHAR_CHAR
 
  94                                                 : expectedPackageName;
 
  97                 if (currentPackageName == CharOperation.NO_CHAR_CHAR) {
 
  98                         if ((fPackage = environment.defaultPackage) == null) {
 
  99                                 problemReporter().mustSpecifyPackage(referenceContext);
 
 103                         if ((fPackage = environment.createPackage(currentPackageName)) == null) {
 
 104                                 // problemReporter().packageCollidesWithType(referenceContext);
 
 107                         recordQualifiedReference(currentPackageName); // always dependent
 
 112                 // Skip typeDeclarations which know of previously reported errors
 
 113                 ArrayList types = referenceContext.types;
 
 114                 int typeLength = (types == null) ? 0 : types.size();
 
 115                 topLevelTypes = new SourceTypeBinding[typeLength];
 
 117                 nextType: for (int i = 0; i < typeLength; i++) {
 
 118                         if (types.get(i) instanceof TypeDeclaration) {
 
 119                                 TypeDeclaration typeDecl = (TypeDeclaration) types.get(i);
 
 120                                 ReferenceBinding typeBinding = fPackage.getType0(typeDecl.name);
 
 121                                 recordSimpleReference(typeDecl.name); // needed to detect
 
 123                                 if (typeBinding != null
 
 124                                                 && !(typeBinding instanceof UnresolvedReferenceBinding)) {
 
 125                                         // if a type exists, it must be a valid type - cannot be a
 
 126                                         // NotFound problem type
 
 127                                         // unless its an unresolved type which is now being defined
 
 129                                                         .duplicateTypes(referenceContext, typeDecl);
 
 132                                 if (fPackage != environment.defaultPackage
 
 133                                                 && fPackage.getPackage(typeDecl.name) != null) {
 
 134                                         // if a package exists, it must be a valid package - cannot
 
 135                                         // be a NotFound problem package
 
 136                                         problemReporter().typeCollidesWithPackage(referenceContext,
 
 141                                 if ((typeDecl.modifiers & AccPublic) != 0) {
 
 143                                         if ((mainTypeName = referenceContext.getMainTypeName()) != null
 
 144                                                         // mainTypeName == null means that implementor of
 
 145                                                         // ICompilationUnit decided to return null
 
 146                                                         && !CharOperation.equals(mainTypeName,
 
 148                                                 problemReporter().publicClassMustMatchFileName(
 
 149                                                                 referenceContext, typeDecl);
 
 154                                 ClassScope child = new ClassScope(this, typeDecl);
 
 155                                 SourceTypeBinding type = child.buildType(null, fPackage);
 
 157                                         topLevelTypes[count++] = type;
 
 162                 // shrink topLevelTypes... only happens if an error was reported
 
 163                 if (count != topLevelTypes.length)
 
 164                         System.arraycopy(topLevelTypes, 0,
 
 165                                         topLevelTypes = new SourceTypeBinding[count], 0, count);
 
 168         void checkAndSetImports() {
 
 169                 // initialize the default imports if necessary... share the default
 
 170                 // java.lang.* import
 
 171                 if (environment.defaultImports == null) {
 
 172                         Binding importBinding = environment.getTopLevelPackage(JAVA);
 
 173                         if (importBinding != null)
 
 174                                 importBinding = ((PackageBinding) importBinding)
 
 175                                                 .getTypeOrPackage(JAVA_LANG[1]);
 
 177                         // abort if java.lang cannot be found...
 
 178                         if (importBinding == null || !importBinding.isValidBinding())
 
 179                                 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT,
 
 180                                                 referenceCompilationUnit());
 
 182                         environment.defaultImports = new ImportBinding[] { new ImportBinding(
 
 183                                         JAVA_LANG, true, importBinding, null) };
 
 185                 if (referenceContext.imports == null) {
 
 186                         imports = environment.defaultImports;
 
 190                 // allocate the import array, add java.lang.* by default
 
 191                 int numberOfStatements = referenceContext.imports.length;
 
 192                 // int numberOfImports = numberOfStatements + 1;
 
 193                 int numberOfImports = numberOfStatements;
 
 194                 // for (int i = 0; i < numberOfStatements; i++) {
 
 195                 // ImportReference importReference = referenceContext.imports[i];
 
 196                 // if (importReference.onDemand && CharOperation.equals(JAVA_LANG,
 
 197                 // importReference.tokens)) {
 
 198                 // numberOfImports--;
 
 202                 ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
 
 203                 resolvedImports[0] = environment.defaultImports[0];
 
 206                 nextImport: for (int i = 0; i < numberOfStatements; i++) {
 
 207                         ImportReference importReference = referenceContext.imports[i];
 
 208                         IFile file = importReference.getFile();
 
 209                         SourceTypeBinding typeBinding;
 
 210                         // char[][] compoundName = importReference.tokens;
 
 211                         char[][] compoundName = null;
 
 213                                 IPath path = file.getProjectRelativePath();
 
 214                                 String[] segs = path.segments();
 
 215                                 compoundName = new char[segs.length][];
 
 216                                 for (int j = 0; j < segs.length; j++) {
 
 217                                         compoundName[j] = segs[j].toCharArray();
 
 220                         if (compoundName == null) {
 
 224                         // skip duplicates or imports of the current package
 
 225                         for (int j = 0; j < index; j++)
 
 226                                 if (resolvedImports[j].onDemand == importReference.onDemand)
 
 227                                         if (CharOperation.equals(compoundName,
 
 228                                                         resolvedImports[j].compoundName))
 
 230                         if (importReference.onDemand == true)
 
 231                                 if (CharOperation.equals(compoundName, currentPackageName))
 
 234                         if (importReference.onDemand) {
 
 235                                 Binding importBinding = findOnDemandImport(compoundName);
 
 236                                 if (!importBinding.isValidBinding())
 
 237                                         continue nextImport; // we report all problems in
 
 239                                 resolvedImports[index++] = new ImportBinding(compoundName,
 
 240                                                 true, importBinding, importReference);
 
 242                                 resolvedImports[index++] = new ImportBinding(compoundName,
 
 243                                                 false, null, importReference);
 
 247                 // shrink resolvedImports... only happens if an error was reported
 
 248                 if (resolvedImports.length > index)
 
 249                         System.arraycopy(resolvedImports, 0,
 
 250                                         resolvedImports = new ImportBinding[index], 0, index);
 
 251                 imports = resolvedImports;
 
 255          * INTERNAL USE-ONLY Innerclasses get their name computed as they are
 
 256          * generated, since some may not be actually outputed if sitting inside
 
 259         public char[] computeConstantPoolName(LocalTypeBinding localType) {
 
 260                 if (localType.constantPoolName() != null) {
 
 261                         return localType.constantPoolName();
 
 263                 // delegates to the outermost enclosing classfile, since it is the only
 
 264                 // one with a global vision of its innertypes.
 
 266                 if (constantPoolNameUsage == null)
 
 267                         constantPoolNameUsage = new HashtableOfType();
 
 269                 ReferenceBinding outerMostEnclosingType = localType.scope
 
 270                                 .outerMostClassScope().enclosingSourceType();
 
 272                 // ensure there is not already such a local type name defined by the
 
 275                 char[] candidateName;
 
 277                         if (localType.isMemberType()) {
 
 279                                         candidateName = CharOperation.concat(localType
 
 280                                                         .enclosingType().constantPoolName(),
 
 281                                                         localType.sourceName, '$');
 
 283                                         // in case of collision, then member name gets extra $1
 
 285                                         // e.g. class X { { class L{} new X(){ class L{} } } }
 
 286                                         candidateName = CharOperation.concat(localType
 
 287                                                         .enclosingType().constantPoolName(), '$', String
 
 288                                                         .valueOf(index).toCharArray(), '$',
 
 289                                                         localType.sourceName);
 
 291                         } else if (localType.isAnonymousType()) {
 
 292                                 candidateName = CharOperation.concat(outerMostEnclosingType
 
 293                                                 .constantPoolName(), String.valueOf(index + 1)
 
 294                                                 .toCharArray(), '$');
 
 296                                 candidateName = CharOperation.concat(outerMostEnclosingType
 
 297                                                 .constantPoolName(), '$', String.valueOf(index + 1)
 
 298                                                 .toCharArray(), '$', localType.sourceName);
 
 300                         if (constantPoolNameUsage.get(candidateName) != null) {
 
 303                                 constantPoolNameUsage.put(candidateName, localType);
 
 307                 return candidateName;
 
 310         void connectTypeHierarchy() {
 
 311                 for (int i = 0, length = topLevelTypes.length; i < length; i++)
 
 312                         topLevelTypes[i].scope.connectTypeHierarchy();
 
 315         void faultInImports() {
 
 316                 if (referenceContext.imports == null)
 
 319                 // // collect the top level type names if a single type import exists
 
 320                 int numberOfStatements = referenceContext.imports.length;
 
 321                 // HashtableOfType typesBySimpleNames = null;
 
 322                 // for (int i = 0; i < numberOfStatements; i++) {
 
 323                 // if (!referenceContext.imports[i].onDemand) {
 
 324                 // typesBySimpleNames = new HashtableOfType(topLevelTypes.length +
 
 325                 // numberOfStatements);
 
 326                 // for (int j = 0, length = topLevelTypes.length; j < length; j++)
 
 327                 // typesBySimpleNames.put(topLevelTypes[j].sourceName,
 
 328                 // topLevelTypes[j]);
 
 333                 // // allocate the import array, add java.lang.* by default
 
 334                 // int numberOfImports = numberOfStatements + 1;
 
 335                 // for (int i = 0; i < numberOfStatements; i++) {
 
 336                 // ImportReference importReference = referenceContext.imports[i];
 
 337                 // if (importReference.onDemand && CharOperation.equals(JAVA_LANG,
 
 338                 // importReference.tokens)) {
 
 339                 // numberOfImports--;
 
 343                 ImportBinding[] resolvedImports = new ImportBinding[numberOfStatements];
 
 344                 // resolvedImports[0] = environment.defaultImports[0];
 
 347                 nextImport: for (int i = 0; i < numberOfStatements; i++) {
 
 348                         ImportReference importReference = referenceContext.imports[i];
 
 349                         // create the file name segments here:
 
 350                         // char[][] compoundName = importReference.tokens;
 
 352                         // // skip duplicates or imports of the current package
 
 353                         // for (int j = 0; j < index; j++)
 
 354                         // if (resolvedImports[j].onDemand == importReference.onDemand)
 
 355                         // if (CharOperation.equals(compoundName,
 
 356                         // resolvedImports[j].compoundName)) {
 
 357                         // problemReporter().unusedImport(importReference); // since
 
 358                         // skipped, must be reported now
 
 359                         // continue nextImport;
 
 361                         // if (importReference.onDemand == true)
 
 362                         // if (CharOperation.equals(compoundName, currentPackageName)) {
 
 363                         // problemReporter().unusedImport(importReference); // since
 
 364                         // skipped, must be reported now
 
 365                         // continue nextImport;
 
 367                         // if (importReference.onDemand) {
 
 368                         // Binding importBinding = findOnDemandImport(compoundName);
 
 369                         // if (!importBinding.isValidBinding()) {
 
 370                         // problemReporter().importProblem(importReference, importBinding);
 
 371                         // continue nextImport;
 
 373                         // resolvedImports[index++] = new ImportBinding(compoundName, true,
 
 374                         // importBinding, importReference);
 
 376                         IFile file = importReference.getFile();
 
 377                         SourceTypeBinding typeBinding;
 
 378                         char[][] compoundName;
 
 380                                 typeBinding = new SourceTypeBinding();
 
 381                                 // findSingleTypeImport(compoundName);
 
 382                                 IPath path = file.getProjectRelativePath();
 
 383                                 String[] segs = path.segments();
 
 384                                 compoundName = new char[segs.length][];
 
 385                                 for (int j = 0; j < segs.length; j++) {
 
 386                                         compoundName[j] = segs[j].toCharArray();
 
 388                                 typeBinding.compoundName = compoundName; // compoundName;
 
 389                                 // this.fPackage = fPackage;
 
 390                                 typeBinding.fileName = file.getLocation().toString()
 
 392                                 // typeBinding.modifiers = scope.referenceContext.modifiers;
 
 393                                 // typeBinding.sourceName = scope.referenceContext.name;
 
 394                                 typeBinding.sourceName = path.lastSegment().toCharArray();
 
 395                                 // this.scope = scope;
 
 397                                 // if (!typeBinding.isValidBinding()) {
 
 398                                 // problemReporter().importProblem(importReference,
 
 403                         // if (typeBinding instanceof PackageBinding) {
 
 404                         // problemReporter().cannotImportPackage(importReference);
 
 405                         // continue nextImport;
 
 407                         // if (typeBinding instanceof ReferenceBinding) {
 
 408                         // ReferenceBinding referenceBinding = (ReferenceBinding)
 
 410                         // if (importReference.isTypeUseDeprecated(referenceBinding, this))
 
 412                         // problemReporter().deprecatedType((TypeBinding) typeBinding,
 
 416                         // ReferenceBinding existingType =
 
 417                         // typesBySimpleNames.get(compoundName[compoundName.length - 1]);
 
 418                         // if (existingType != null) {
 
 419                         // // duplicate test above should have caught this case, but make
 
 421                         // if (existingType == typeBinding) {
 
 422                         // continue nextImport;
 
 424                         // // either the type collides with a top level type or another
 
 426                         // for (int j = 0, length = topLevelTypes.length; j < length; j++) {
 
 427                         // if (CharOperation.equals(topLevelTypes[j].sourceName,
 
 428                         // existingType.sourceName)) {
 
 429                         // problemReporter().conflictingImport(importReference);
 
 430                         // continue nextImport;
 
 433                         // problemReporter().duplicateImport(importReference);
 
 434                         // continue nextImport;
 
 436                         resolvedImports[index++] = new ImportBinding(compoundName, false,
 
 437                                         typeBinding, importReference);
 
 438                         imports = resolvedImports;
 
 439                         // typesBySimpleNames.put(compoundName[compoundName.length - 1],
 
 440                         // (ReferenceBinding) typeBinding);
 
 444                 // // shrink resolvedImports... only happens if an error was reported
 
 445                 if (resolvedImports.length > index)
 
 446                         System.arraycopy(resolvedImports, 0,
 
 447                                         resolvedImports = new ImportBinding[index], 0, index);
 
 448                 imports = resolvedImports;
 
 450                 int length = imports.length;
 
 451                 resolvedSingeTypeImports = new HashtableOfObject(length);
 
 452                 for (int i = 0; i < length; i++) {
 
 453                         ImportBinding binding = imports[i];
 
 454                         if (!binding.onDemand)
 
 455                                 resolvedSingeTypeImports.put(
 
 456                                                 binding.compoundName[binding.compoundName.length - 1],
 
 461         public void faultInTypes() {
 
 463                 if (topLevelTypes == null) {
 
 464                         topLevelTypes = new SourceTypeBinding[0];
 
 466                 for (int i = 0, length = topLevelTypes.length; i < length; i++)
 
 467                         topLevelTypes[i].faultInTypesForFieldsAndMethods();
 
 470         private Binding findOnDemandImport(char[][] compoundName) {
 
 471                 recordQualifiedReference(compoundName);
 
 473                 Binding binding = environment.getTopLevelPackage(compoundName[0]);
 
 475                 int length = compoundName.length;
 
 476                 foundNothingOrType: if (binding != null) {
 
 477                         PackageBinding packageBinding = (PackageBinding) binding;
 
 479                                 binding = packageBinding.getTypeOrPackage(compoundName[i++]);
 
 480                                 if (binding == null || !binding.isValidBinding()) {
 
 482                                         break foundNothingOrType;
 
 484                                 if (!(binding instanceof PackageBinding))
 
 485                                         break foundNothingOrType;
 
 487                                 packageBinding = (PackageBinding) binding;
 
 489                         return packageBinding;
 
 492                 ReferenceBinding type;
 
 493                 if (binding == null) {
 
 494                         // if (environment.defaultPackage == null
 
 495                         // || environment.options.complianceLevel >=
 
 496                         // CompilerOptions.JDK1_4){
 
 497                         // return new ProblemReferenceBinding(
 
 498                         // CharOperation.subarray(compoundName, 0, i),
 
 501                         type = findType(compoundName[0], environment.defaultPackage,
 
 502                                         environment.defaultPackage);
 
 503                         if (type == null || !type.isValidBinding())
 
 504                                 return new ProblemReferenceBinding(CharOperation.subarray(
 
 505                                                 compoundName, 0, i), NotFound);
 
 506                         i = 1; // reset to look for member types inside the default package
 
 509                         type = (ReferenceBinding) binding;
 
 512                 for (; i < length; i++) {
 
 513                         if (!type.canBeSeenBy(fPackage)) {
 
 514                                 return new ProblemReferenceBinding(CharOperation.subarray(
 
 515                                                 compoundName, 0, i), type, NotVisible);
 
 517                         // does not look for inherited member types on purpose
 
 518                         if ((type = type.getMemberType(compoundName[i])) == null) {
 
 519                                 return new ProblemReferenceBinding(CharOperation.subarray(
 
 520                                                 compoundName, 0, i + 1), NotFound);
 
 523                 if (!type.canBeSeenBy(fPackage))
 
 524                         return new ProblemReferenceBinding(compoundName, type, NotVisible);
 
 528         private Binding findSingleTypeImport(char[][] compoundName) {
 
 529                 // if (compoundName.length == 1) {
 
 530                 // findType records the reference
 
 531                 // the name cannot be a package
 
 532                 // if (environment.defaultPackage == null
 
 533                 // || environment.options.complianceLevel >= CompilerOptions.JDK1_4)
 
 534                 // return new ProblemReferenceBinding(compoundName, NotFound);
 
 535                 ReferenceBinding typeBinding = findType(compoundName[0],
 
 536                                 environment.defaultPackage, fPackage);
 
 537                 if (typeBinding == null)
 
 538                         return new ProblemReferenceBinding(compoundName, NotFound);
 
 542                 // return findOnDemandImport(compoundName);
 
 546          * Answer the problem reporter to use for raising new problems.
 
 548          * Note that as a side-effect, this updates the current reference context
 
 549          * (unit, type or method) in case the problem handler decides it is
 
 550          * necessary to abort.
 
 553         public ProblemReporter problemReporter() {
 
 554                 ProblemReporter problemReporter = referenceContext.problemReporter;
 
 555                 problemReporter.referenceContext = referenceContext;
 
 556                 return problemReporter;
 
 560          * What do we hold onto:
 
 562          * 1. when we resolve 'a.b.c', say we keep only 'a.b.c' & when we fail to
 
 563          * resolve 'c' in 'a.b', lets keep 'a.b.c' THEN when we come across a
 
 564          * new/changed/removed item named 'a.b.c', we would find all references to
 
 565          * 'a.b.c' -> This approach fails because every type is resolved in every
 
 566          * onDemand import to detect collision cases... so the references could be
 
 567          * 10 times bigger than necessary.
 
 569          * 2. when we resolve 'a.b.c', lets keep 'a.b' & 'c' & when we fail to
 
 570          * resolve 'c' in 'a.b', lets keep 'a.b' & 'c' THEN when we come across a
 
 571          * new/changed/removed item named 'a.b.c', we would find all references to
 
 572          * 'a.b' & 'c' -> This approach does not have a space problem but fails to
 
 573          * handle collision cases. What happens if a type is added named 'a.b'? We
 
 574          * would search for 'a' & 'b' but would not find a match.
 
 576          * 3. when we resolve 'a.b.c', lets keep 'a', 'a.b' & 'a', 'b', 'c' & when
 
 577          * we fail to resolve 'c' in 'a.b', lets keep 'a', 'a.b' & 'a', 'b', 'c'
 
 578          * THEN when we come across a new/changed/removed item named 'a.b.c', we
 
 579          * would find all references to 'a.b' & 'c' OR 'a.b' -> 'a' & 'b' OR 'a' -> '' &
 
 580          * 'a' -> As long as each single char[] is interned, we should not have a
 
 581          * space problem and can handle collision cases.
 
 583          * 4. when we resolve 'a.b.c', lets keep 'a.b' & 'a', 'b', 'c' & when we
 
 584          * fail to resolve 'c' in 'a.b', lets keep 'a.b' & 'a', 'b', 'c' THEN when
 
 585          * we come across a new/changed/removed item named 'a.b.c', we would find
 
 586          * all references to 'a.b' & 'c' OR 'a.b' -> 'a' & 'b' in the simple name
 
 587          * collection OR 'a' -> 'a' in the simple name collection -> As long as each
 
 588          * single char[] is interned, we should not have a space problem and can
 
 589          * handle collision cases.
 
 591         void recordQualifiedReference(char[][] qualifiedName) {
 
 592                 if (qualifiedReferences == null)
 
 593                         return; // not recording dependencies
 
 595                 int length = qualifiedName.length;
 
 597                         while (!qualifiedReferences.contains(qualifiedName)) {
 
 598                                 qualifiedReferences.add(qualifiedName);
 
 600                                         recordSimpleReference(qualifiedName[0]);
 
 601                                         recordSimpleReference(qualifiedName[1]);
 
 605                                 recordSimpleReference(qualifiedName[length]);
 
 606                                 System.arraycopy(qualifiedName, 0,
 
 607                                                 qualifiedName = new char[length][], 0, length);
 
 609                 } else if (length == 1) {
 
 610                         recordSimpleReference(qualifiedName[0]);
 
 614         void recordReference(char[][] qualifiedEnclosingName, char[] simpleName) {
 
 615                 recordQualifiedReference(qualifiedEnclosingName);
 
 616                 recordSimpleReference(simpleName);
 
 619         void recordSimpleReference(char[] simpleName) {
 
 620                 if (simpleNameReferences == null)
 
 621                         return; // not recording dependencies
 
 623                 if (!simpleNameReferences.contains(simpleName))
 
 624                         simpleNameReferences.add(simpleName);
 
 627         void recordTypeReference(TypeBinding type) {
 
 628                 if (referencedTypes == null)
 
 629                         return; // not recording dependencies
 
 631                 if (type.isArrayType())
 
 632                         type = ((ArrayBinding) type).leafComponentType;
 
 633                 if (!type.isBaseType() && !referencedTypes.containsIdentical(type))
 
 634                         referencedTypes.add(type);
 
 637         void recordTypeReferences(TypeBinding[] types) {
 
 638                 if (qualifiedReferences == null)
 
 639                         return; // not recording dependencies
 
 640                 if (types == null || types.length == 0)
 
 643                 for (int i = 0, max = types.length; i < max; i++) {
 
 644                         // No need to record supertypes of method arguments & thrown
 
 645                         // exceptions, just the compoundName
 
 646                         // If a field/method is retrieved from such a type then a separate
 
 648                         TypeBinding type = types[i];
 
 649                         if (type.isArrayType())
 
 650                                 type = ((ArrayBinding) type).leafComponentType;
 
 651                         if (!type.isBaseType()) {
 
 652                                 ReferenceBinding actualType = (ReferenceBinding) type;
 
 653                                 if (!actualType.isLocalType())
 
 654                                         recordQualifiedReference(actualType.isMemberType() ? CharOperation
 
 655                                                         .splitOn('.', actualType.readableName())
 
 656                                                         : actualType.compoundName);
 
 661         Binding resolveSingleTypeImport(ImportBinding importBinding) {
 
 662                 if (importBinding.resolvedImport == null) {
 
 663                         importBinding.resolvedImport = findSingleTypeImport(importBinding.compoundName);
 
 664                         if (!importBinding.resolvedImport.isValidBinding()
 
 665                                         || importBinding.resolvedImport instanceof PackageBinding) {
 
 666                                 if (this.imports != null) {
 
 667                                         ImportBinding[] newImports = new ImportBinding[imports.length - 1];
 
 668                                         for (int i = 0, n = 0, max = this.imports.length; i < max; i++)
 
 669                                                 if (this.imports[i] != importBinding) {
 
 670                                                         newImports[n++] = this.imports[i];
 
 672                                         this.imports = newImports;
 
 677                 return importBinding.resolvedImport;
 
 680         public void storeDependencyInfo() {
 
 681                 // add the type hierarchy of each referenced type
 
 682                 // cannot do early since the hierarchy may not be fully resolved
 
 683                 for (int i = 0; i < referencedTypes.size; i++) { // grows as more
 
 685                         ReferenceBinding type = (ReferenceBinding) referencedTypes
 
 687                         if (!type.isLocalType()) {
 
 688                                 recordQualifiedReference(type.isMemberType() ? CharOperation
 
 689                                                 .splitOn('.', type.readableName()) : type.compoundName);
 
 690                                 ReferenceBinding enclosing = type.enclosingType();
 
 691                                 if (enclosing != null
 
 692                                                 && !referencedTypes.containsIdentical(enclosing))
 
 693                                         referencedTypes.add(enclosing); // to record its supertypes
 
 695                         ReferenceBinding superclass = type.superclass();
 
 696                         if (superclass != null
 
 697                                         && !referencedTypes.containsIdentical(superclass))
 
 698                                 referencedTypes.add(superclass); // to record its supertypes
 
 699                         ReferenceBinding[] interfaces = type.superInterfaces();
 
 700                         if (interfaces != null && interfaces.length > 0)
 
 701                                 for (int j = 0, length = interfaces.length; j < length; j++)
 
 702                                         if (!referencedTypes.containsIdentical(interfaces[j]))
 
 703                                                 referencedTypes.add(interfaces[j]); // to record its
 
 707                 int size = qualifiedReferences.size;
 
 708                 char[][][] qualifiedRefs = new char[size][][];
 
 709                 for (int i = 0; i < size; i++)
 
 710                         qualifiedRefs[i] = qualifiedReferences.elementAt(i);
 
 711                 referenceContext.compilationResult.qualifiedReferences = qualifiedRefs;
 
 713                 size = simpleNameReferences.size;
 
 714                 char[][] simpleRefs = new char[size][];
 
 715                 for (int i = 0; i < size; i++)
 
 716                         simpleRefs[i] = simpleNameReferences.elementAt(i);
 
 717                 referenceContext.compilationResult.simpleNameReferences = simpleRefs;
 
 720         public String toString() {
 
 721                 return "--- CompilationUnit Scope : " + new String(referenceContext.getFileName()); //$NON-NLS-1$
 
 724         public void verifyMethods(MethodVerifier verifier) {
 
 725                 for (int i = 0, length = topLevelTypes.length; i < length; i++)
 
 726                         topLevelTypes[i].verifyMethods(verifier);