import eclipse 3.1 M4 compiler
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / lookup / CompilationUnitScope.java
index d4a8d4f..9033073 100644 (file)
 package org.eclipse.jdt.internal.compiler.lookup;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
-import org.eclipse.jdt.internal.compiler.util.CompoundNameVector;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
-import org.eclipse.jdt.internal.compiler.util.ObjectVector;
-import org.eclipse.jdt.internal.compiler.util.SimpleNameVector;
+import org.eclipse.jdt.internal.compiler.util.*;
 
 public class CompilationUnitScope extends Scope {
        
@@ -36,6 +31,7 @@ public class CompilationUnitScope extends Scope {
        private CompoundNameVector qualifiedReferences;
        private SimpleNameVector simpleNameReferences;
        private ObjectVector referencedTypes;
+       private ObjectVector referencedSuperTypes;
        
        HashtableOfType constantPoolNameUsage;
 
@@ -50,17 +46,19 @@ public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment e
                this.qualifiedReferences = new CompoundNameVector();
                this.simpleNameReferences = new SimpleNameVector();
                this.referencedTypes = new ObjectVector();
+               this.referencedSuperTypes = new ObjectVector();
        } else {
                this.qualifiedReferences = null; // used to test if dependencies should be recorded
                this.simpleNameReferences = null;
                this.referencedTypes = null;
+               this.referencedSuperTypes = null;
        }
 }
 void buildFieldsAndMethods() {
        for (int i = 0, length = topLevelTypes.length; i < length; i++)
                topLevelTypes[i].scope.buildFieldsAndMethods();
 }
-void buildTypeBindings() {
+void buildTypeBindings(AccessRestriction accessRestriction) {
        topLevelTypes = new SourceTypeBinding[0]; // want it initialized if the package cannot be resolved
        if (referenceContext.compilationResult.compilationUnit != null) {
                char[][] expectedPackageName = referenceContext.compilationResult.compilationUnit.getPackageName();
@@ -120,7 +118,7 @@ void buildTypeBindings() {
                }
 
                ClassScope child = new ClassScope(this, typeDecl);
-               SourceTypeBinding type = child.buildType(null, fPackage);
+               SourceTypeBinding type = child.buildType(null, fPackage, accessRestriction);
                if(type != null) {
                        topLevelTypes[count++] = type;
                }
@@ -141,7 +139,7 @@ void checkAndSetImports() {
        int numberOfImports = numberOfStatements + 1;
        for (int i = 0; i < numberOfStatements; i++) {
                ImportReference importReference = referenceContext.imports[i];
-               if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens)) {
+               if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens) && !importReference.isStatic()) {
                        numberOfImports--;
                        break;
                }
@@ -155,20 +153,23 @@ void checkAndSetImports() {
                char[][] compoundName = importReference.tokens;
 
                // skip duplicates or imports of the current package
-               for (int j = 0; j < index; j++)
-                       if (resolvedImports[j].onDemand == importReference.onDemand)
+               for (int j = 0; j < index; j++) {
+                       ImportBinding resolved = resolvedImports[j];
+                       if (resolved.onDemand == importReference.onDemand && resolved.isStatic() == importReference.isStatic())
                                if (CharOperation.equals(compoundName, resolvedImports[j].compoundName))
                                        continue nextImport;
-               if (importReference.onDemand == true)
+               }
+
+               if (importReference.onDemand) {
                        if (CharOperation.equals(compoundName, currentPackageName))
                                continue nextImport;
 
-               if (importReference.onDemand) {
-                       Binding importBinding = findOnDemandImport(compoundName);
-                       if (!importBinding.isValidBinding())
+                       Binding importBinding = findImport(compoundName, compoundName.length);
+                       if (!importBinding.isValidBinding() || (importReference.isStatic() && importBinding instanceof PackageBinding))
                                continue nextImport;    // we report all problems in faultInImports()
                        resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
                } else {
+                       // resolve single imports only when the last name matches
                        resolvedImports[index++] = new ImportBinding(compoundName, false, null, importReference);
                }
        }
@@ -261,7 +262,7 @@ void faultInImports() {
        int numberOfImports = numberOfStatements + 1;
        for (int i = 0; i < numberOfStatements; i++) {
                ImportReference importReference = referenceContext.imports[i];
-               if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens)) {
+               if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens) && !importReference.isStatic()) {
                        numberOfImports--;
                        break;
                }
@@ -270,63 +271,73 @@ void faultInImports() {
        resolvedImports[0] = getDefaultImports()[0];
        int index = 1;
 
+       // keep static imports with normal imports until there is a reason to split them up
+       // on demand imports continue to be packages & types. need to check on demand type imports for fields/methods
+       // single imports change from being just types to types or fields
        nextImport : for (int i = 0; i < numberOfStatements; i++) {
                ImportReference importReference = referenceContext.imports[i];
                char[][] compoundName = importReference.tokens;
 
                // skip duplicates or imports of the current package
-               for (int j = 0; j < index; j++)
-                       if (resolvedImports[j].onDemand == importReference.onDemand)
-                               if (CharOperation.equals(compoundName, resolvedImports[j].compoundName)) {
+               for (int j = 0; j < index; j++) {
+                       ImportBinding resolved = resolvedImports[j];
+                       if (resolved.onDemand == importReference.onDemand && resolved.isStatic() == importReference.isStatic()) {
+                               if (CharOperation.equals(compoundName, resolved.compoundName)) {
                                        problemReporter().unusedImport(importReference); // since skipped, must be reported now
                                        continue nextImport;
                                }
-               if (importReference.onDemand == true)
+                       }
+               }
+               if (importReference.onDemand) {
                        if (CharOperation.equals(compoundName, currentPackageName)) {
                                problemReporter().unusedImport(importReference); // since skipped, must be reported now
                                continue nextImport;
                        }
-               if (importReference.onDemand) {
-                       Binding importBinding = findOnDemandImport(compoundName);
+
+                       Binding importBinding = findImport(compoundName, compoundName.length);
                        if (!importBinding.isValidBinding()) {
                                problemReporter().importProblem(importReference, importBinding);
                                continue nextImport;
                        }
+                       if (importReference.isStatic() && importBinding instanceof PackageBinding) {
+                               problemReporter().cannotImportPackage(importReference);
+                               continue nextImport;
+                       }
                        resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
                } else {
-                       Binding typeBinding = findSingleTypeImport(compoundName);
-                       if (!typeBinding.isValidBinding()) {
-                               problemReporter().importProblem(importReference, typeBinding);
+                       Binding importBinding = findSingleImport(compoundName, importReference.isStatic());
+                       if (!importBinding.isValidBinding()) {
+                               problemReporter().importProblem(importReference, importBinding);
                                continue nextImport;
                        }
-                       if (typeBinding instanceof PackageBinding) {
+                       if (importBinding instanceof PackageBinding) {
                                problemReporter().cannotImportPackage(importReference);
                                continue nextImport;
                        }
-                       if (typeBinding instanceof ReferenceBinding) {
-                               ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
-                               if (importReference.isTypeUseDeprecated(referenceBinding, this)) {
-                                       problemReporter().deprecatedType((TypeBinding) typeBinding, importReference);
-                               }
-                       }
-                       ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]);
-                       if (existingType != null) {
-                               // duplicate test above should have caught this case, but make sure
-                               if (existingType == typeBinding) {
-                                       continue nextImport;
-                               }
-                               // either the type collides with a top level type or another imported type
-                               for (int j = 0, length = topLevelTypes.length; j < length; j++) {
-                                       if (CharOperation.equals(topLevelTypes[j].sourceName, existingType.sourceName)) {
-                                               problemReporter().conflictingImport(importReference);
+                       // collisions between an imported static field & a type should be checked according to spec... but currently not by javac
+                       if (importBinding instanceof ReferenceBinding) {
+                               ReferenceBinding referenceBinding = (ReferenceBinding) importBinding;
+                               if (importReference.isTypeUseDeprecated(referenceBinding, this))
+                                       problemReporter().deprecatedType(referenceBinding, importReference);
+
+                               ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]);
+                               if (existingType != null) {
+                                       // duplicate test above should have caught this case, but make sure
+                                       if (existingType == referenceBinding)
                                                continue nextImport;
+                                       // either the type collides with a top level type or another imported type
+                                       for (int j = 0, length = topLevelTypes.length; j < length; j++) {
+                                               if (CharOperation.equals(topLevelTypes[j].sourceName, existingType.sourceName)) {
+                                                       problemReporter().conflictingImport(importReference);
+                                                       continue nextImport;
+                                               }
                                        }
+                                       problemReporter().duplicateImport(importReference);
+                                       continue nextImport;
                                }
-                               problemReporter().duplicateImport(importReference);
-                               continue nextImport;
+                               typesBySimpleNames.put(compoundName[compoundName.length - 1], referenceBinding);
                        }
-                       resolvedImports[index++] = new ImportBinding(compoundName, false, typeBinding, importReference);
-                       typesBySimpleNames.put(compoundName[compoundName.length - 1], (ReferenceBinding) typeBinding);
+                       resolvedImports[index++] = new ImportBinding(compoundName, false, importBinding, importReference);
                }
        }
 
@@ -339,7 +350,7 @@ void faultInImports() {
        resolvedSingeTypeImports = new HashtableOfObject(length);
        for (int i = 0; i < length; i++) {
                ImportBinding binding = imports[i];
-               if (!binding.onDemand)
+               if (!binding.onDemand && binding.resolvedImport instanceof ReferenceBinding)
                        resolvedSingeTypeImports.put(binding.compoundName[binding.compoundName.length - 1], binding);
        }
 }
@@ -349,12 +360,11 @@ public void faultInTypes() {
        for (int i = 0, length = topLevelTypes.length; i < length; i++)
                topLevelTypes[i].faultInTypesForFieldsAndMethods();
 }
-private Binding findOnDemandImport(char[][] compoundName) {
+private Binding findImport(char[][] compoundName, int length) {
        recordQualifiedReference(compoundName);
 
        Binding binding = environment.getTopLevelPackage(compoundName[0]);
        int i = 1;
-       int length = compoundName.length;
        foundNothingOrType: if (binding != null) {
                PackageBinding packageBinding = (PackageBinding) binding;
                while (i < length) {
@@ -373,50 +383,70 @@ private Binding findOnDemandImport(char[][] compoundName) {
 
        ReferenceBinding type;
        if (binding == null) {
-               if (environment.defaultPackage == null
-                               || environment.options.complianceLevel >= ClassFileConstants.JDK1_4){
-                       return new ProblemReferenceBinding(
-                               CharOperation.subarray(compoundName, 0, i),
-                               NotFound);
-               }
+               if (environment.defaultPackage == null || environment.options.complianceLevel >= ClassFileConstants.JDK1_4)
+                       return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), NotFound);
                type = findType(compoundName[0], environment.defaultPackage, environment.defaultPackage);
                if (type == null || !type.isValidBinding())
-                       return new ProblemReferenceBinding(
-                               CharOperation.subarray(compoundName, 0, i),
-                               NotFound);
+                       return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), NotFound);
                i = 1; // reset to look for member types inside the default package type
        } else {
                type = (ReferenceBinding) binding;
        }
 
-       for (; i < length; i++) {
-               if (!type.canBeSeenBy(fPackage)) {
-                       return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), type, NotVisible);               
-               }
-               // does not look for inherited member types on purpose
-               if ((type = type.getMemberType(compoundName[i])) == null) {
-                       return new ProblemReferenceBinding(
-                               CharOperation.subarray(compoundName, 0, i + 1),
-                               NotFound);
-               }
+       while (i < length) {
+               if (!type.canBeSeenBy(fPackage))
+                       return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), type, NotVisible);
+
+               char[] name = compoundName[i++];
+               // does not look for inherited member types on purpose, only immediate members
+               type = type.getMemberType(name);
+               if (type == null)
+                       return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), NotFound);
        }
        if (!type.canBeSeenBy(fPackage))
                return new ProblemReferenceBinding(compoundName, type, NotVisible);
        return type;
 }
-private Binding findSingleTypeImport(char[][] compoundName) {
+private Binding findSingleImport(char[][] compoundName, boolean findStaticImports) {
        if (compoundName.length == 1) {
                // findType records the reference
                // the name cannot be a package
-               if (environment.defaultPackage == null 
-                       || environment.options.complianceLevel >= ClassFileConstants.JDK1_4)
+               if (environment.defaultPackage == null || environment.options.complianceLevel >= ClassFileConstants.JDK1_4)
                        return new ProblemReferenceBinding(compoundName, NotFound);
                ReferenceBinding typeBinding = findType(compoundName[0], environment.defaultPackage, fPackage);
                if (typeBinding == null)
                        return new ProblemReferenceBinding(compoundName, NotFound);
                return typeBinding;
        }
-       return findOnDemandImport(compoundName);
+
+       if (findStaticImports)
+               return findSingleStaticImport(compoundName);
+       return findImport(compoundName, compoundName.length);
+}
+private Binding findSingleStaticImport(char[][] compoundName) {
+       Binding binding = findImport(compoundName, compoundName.length - 1);
+       if (!binding.isValidBinding()) return binding;
+
+       char[] name = compoundName[compoundName.length - 1];
+       if (binding instanceof PackageBinding) {
+               Binding temp = ((PackageBinding) binding).getTypeOrPackage(name);
+               if (temp != null && temp instanceof ReferenceBinding) // must resolve to a member type or field, not a top level type
+                       return new ProblemReferenceBinding(compoundName, InvalidTypeForStaticImport);
+               return binding; // cannot be a package, error is caught in sender
+       }
+
+       // look to see if its a static field first
+       ReferenceBinding type = (ReferenceBinding) binding;
+       FieldBinding field = findField(type, name, null, true);
+       if (field != null && field.isStatic() && field.canBeSeenBy(fPackage))
+               return field;
+
+       type = findMemberType(name, type);
+       if (type == null || !type.isStatic())
+               return new ProblemReferenceBinding(compoundName, type, NotFound);
+       if (!type.canBeSeenBy(fPackage))
+               return new ProblemReferenceBinding(compoundName, type, NotVisible);
+       return type;
 }
 ImportBinding[] getDefaultImports() {
        // initialize the default imports if necessary... share the default java.lang.* import
@@ -432,6 +462,12 @@ ImportBinding[] getDefaultImports() {
 
        return environment.defaultImports = new ImportBinding[] {new ImportBinding(JAVA_LANG, true, importBinding, null)};
 }
+// NOT Public API
+public final Binding getImport(char[][] compoundName, boolean onDemand, boolean isStaticImport) {
+       if (onDemand)
+               return findImport(compoundName, compoundName.length);
+       return findSingleImport(compoundName, isStaticImport);
+}
 /* Answer the problem reporter to use for raising new problems.
 *
 * Note that as a side-effect, this updates the current reference context
@@ -505,53 +541,55 @@ void recordReference(char[][] qualifiedEnclosingName, char[] simpleName) {
        recordQualifiedReference(qualifiedEnclosingName);
        recordSimpleReference(simpleName);
 }
+void recordReference(ReferenceBinding type, char[] simpleName) {
+       ReferenceBinding actualType = typeToRecord(type);
+       if (actualType != null)
+               recordReference(actualType.compoundName, simpleName);
+}
 void recordSimpleReference(char[] simpleName) {
        if (simpleNameReferences == null) return; // not recording dependencies
 
        if (!simpleNameReferences.contains(simpleName))
                simpleNameReferences.add(simpleName);
 }
+void recordSuperTypeReference(TypeBinding type) {
+       if (referencedSuperTypes == null) return; // not recording dependencies
+
+       ReferenceBinding actualType = typeToRecord(type);
+       if (actualType != null && !referencedSuperTypes.containsIdentical(actualType))
+               referencedSuperTypes.add(actualType);
+}
+public void recordTypeConversion(TypeBinding superType, TypeBinding subType) {
+       recordSuperTypeReference(subType); // must record the hierarchy of the subType that is converted to the superType
+}
 void recordTypeReference(TypeBinding type) {
        if (referencedTypes == null) return; // not recording dependencies
 
-       if (type.isArrayType())
-               type = ((ArrayBinding) type).leafComponentType;
-
-       if (type.isBaseType()) return;
-       if (referencedTypes.containsIdentical(type)) return;
-       if (((ReferenceBinding) type).isLocalType()) return;
-
-       referencedTypes.add(type);
+       ReferenceBinding actualType = typeToRecord(type);
+       if (actualType != null && !referencedTypes.containsIdentical(actualType))
+               referencedTypes.add(actualType);
 }
 void recordTypeReferences(TypeBinding[] types) {
-       if (qualifiedReferences == null) return; // not recording dependencies
+       if (referencedTypes == null) return; // not recording dependencies
        if (types == null || types.length == 0) return;
 
        for (int i = 0, max = types.length; i < max; i++) {
                // No need to record supertypes of method arguments & thrown exceptions, just the compoundName
                // If a field/method is retrieved from such a type then a separate call does the job
-               TypeBinding type = types[i];
-               if (type.isArrayType())
-                       type = ((ArrayBinding) type).leafComponentType;
-               if (!type.isBaseType()) {
-                       ReferenceBinding actualType = (ReferenceBinding) type;
-                       if (!actualType.isLocalType())
-                               recordQualifiedReference(actualType.isMemberType()
-                                       ? CharOperation.splitOn('.', actualType.readableName())
-                                       : actualType.compoundName);
-               }
+               ReferenceBinding actualType = typeToRecord(types[i]);
+               if (actualType != null && !referencedTypes.containsIdentical(actualType))
+                       referencedTypes.add(actualType);
        }
 }
-Binding resolveSingleTypeImport(ImportBinding importBinding) {
+Binding resolveSingleImport(ImportBinding importBinding) {
        if (importBinding.resolvedImport == null) {
-               importBinding.resolvedImport = findSingleTypeImport(importBinding.compoundName);
+               importBinding.resolvedImport = findSingleImport(importBinding.compoundName, importBinding.isStatic());
                if (!importBinding.resolvedImport.isValidBinding() || importBinding.resolvedImport instanceof PackageBinding) {
-                       if (this.imports != null){
+                       if (this.imports != null) {
                                ImportBinding[] newImports = new ImportBinding[imports.length - 1];
                                for (int i = 0, n = 0, max = this.imports.length; i < max; i++)
-                                       if (this.imports[i] != importBinding){
+                                       if (this.imports[i] != importBinding)
                                                newImports[n++] = this.imports[i];
-                                       }
                                this.imports = newImports;
                        }
                        return null;
@@ -560,26 +598,33 @@ Binding resolveSingleTypeImport(ImportBinding importBinding) {
        return importBinding.resolvedImport;
 }
 public void storeDependencyInfo() {
-       // add the type hierarchy of each referenced type
+       // add the type hierarchy of each referenced supertype
        // cannot do early since the hierarchy may not be fully resolved
-       for (int i = 0; i < referencedTypes.size; i++) { // grows as more types are added
-               ReferenceBinding type = (ReferenceBinding) referencedTypes.elementAt(i);
+       for (int i = 0; i < referencedSuperTypes.size; i++) { // grows as more types are added
+               ReferenceBinding type = (ReferenceBinding) referencedSuperTypes.elementAt(i);
+               if (!referencedTypes.containsIdentical(type))
+                       referencedTypes.add(type);
+
                if (!type.isLocalType()) {
-                       recordQualifiedReference(type.isMemberType()
-                               ? CharOperation.splitOn('.', type.readableName())
-                               : type.compoundName);
                        ReferenceBinding enclosing = type.enclosingType();
-                       if (enclosing != null && !referencedTypes.containsIdentical(enclosing))
-                               referencedTypes.add(enclosing); // to record its supertypes
+                       if (enclosing != null)
+                               recordSuperTypeReference(enclosing);
                }
                ReferenceBinding superclass = type.superclass();
-               if (superclass != null && !referencedTypes.containsIdentical(superclass))
-                               referencedTypes.add(superclass); // to record its supertypes
+               if (superclass != null)
+                       recordSuperTypeReference(superclass);
                ReferenceBinding[] interfaces = type.superInterfaces();
-               if (interfaces != null && interfaces.length > 0)
+               if (interfaces != null)
                        for (int j = 0, length = interfaces.length; j < length; j++)
-                               if (!referencedTypes.containsIdentical(interfaces[j]))
-                                       referencedTypes.add(interfaces[j]); // to record its supertypes
+                               recordSuperTypeReference(interfaces[j]);
+       }
+
+       for (int i = 0, l = referencedTypes.size; i < l; i++) {
+               ReferenceBinding type = (ReferenceBinding) referencedTypes.elementAt(i);
+               if (!type.isLocalType())
+                       recordQualifiedReference(type.isMemberType()
+                               ? CharOperation.splitOn('.', type.readableName())
+                               : type.compoundName);
        }
 
        int size = qualifiedReferences.size;
@@ -597,6 +642,25 @@ public void storeDependencyInfo() {
 public String toString() {
        return "--- CompilationUnit Scope : " + new String(referenceContext.getFileName()); //$NON-NLS-1$
 }
+private ReferenceBinding typeToRecord(TypeBinding type) {
+       if (type.isArrayType())
+               type = ((ArrayBinding) type).leafComponentType;
+
+       switch (type.kind()) {
+               case Binding.TYPE_PARAMETER :
+               case Binding.WILDCARD_TYPE :
+                       return null;
+               case Binding.PARAMETERIZED_TYPE :
+               case Binding.RAW_TYPE :
+                       type = type.erasure();
+       }
+
+       if (type instanceof ReferenceBinding) {
+               ReferenceBinding refType = (ReferenceBinding) type;
+               if (!refType.isLocalType()) return refType;
+       }
+       return null;
+}
 public void verifyMethods(MethodVerifier verifier) {
        for (int i = 0, length = topLevelTypes.length; i < length; i++)
                topLevelTypes[i].verifyMethods(verifier);