From 114988ac823aedd9753d186df73c0cf75a5787bf Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Fri, 16 Mar 2012 17:09:18 +0400 Subject: [PATCH] KT-1579 "Can't import nested class/trait" partially: Entry can be imported, but Map.Entry in code is still unresolved --- .../codegen/ImplementationBodyCodegen.java | 4 +- .../jet/lang/descriptors/ClassDescriptor.java | 9 +- .../lang/descriptors/ClassDescriptorImpl.java | 9 +- .../LazySubstitutingClassDescriptor.java | 10 +- .../MutableClassDescriptorLite.java | 23 +- .../jet/lang/resolve/DescriptorUtils.java | 8 - .../jetbrains/jet/lang/resolve/Importer.java | 28 +- .../jet/lang/resolve/ImportsResolver.java | 279 +++++++++--------- .../scopes/InnerClassesScopeWrapper.java | 93 ++++++ .../diagnostics/tests/scopes/Imports.jet | 6 +- .../diagnostics/tests/scopes/kt1579.jet | 9 + .../tests/scopes/kt1579_map_entry.jet | 12 + .../diagnostics/tests/scopes/kt900-1.jet | 24 ++ .../diagnostics/tests/scopes/kt900-2.jet | 33 +++ .../diagnostics/tests/scopes/kt900.jet | 67 +---- 15 files changed, 341 insertions(+), 273 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/InnerClassesScopeWrapper.java create mode 100644 compiler/testData/diagnostics/tests/scopes/kt1579.jet create mode 100644 compiler/testData/diagnostics/tests/scopes/kt1579_map_entry.jet create mode 100644 compiler/testData/diagnostics/tests/scopes/kt900-1.jet create mode 100644 compiler/testData/diagnostics/tests/scopes/kt900-2.jet diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index d1cdde50073..90067e10b71 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -117,7 +117,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { v.visitOuterClass(typeMapper.mapType(container.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null); } - for (ClassDescriptor innerClass : descriptor.getInnerClassesAndObjects()) { + for (DeclarationDescriptor declarationDescriptor : descriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors()) { + assert declarationDescriptor instanceof ClassDescriptor; + ClassDescriptor innerClass = (ClassDescriptor) declarationDescriptor; // TODO: proper access int innerClassAccess = ACC_PUBLIC; if (innerClass.getModality() == Modality.FINAL) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java index bfe840f0c8a..1bc7952f732 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java @@ -36,6 +36,9 @@ public interface ClassDescriptor extends ClassifierDescriptor, MemberDescriptor, @NotNull JetScope getMemberScope(List typeArguments); + @NotNull + JetScope getUnsubstitutedInnerClassesScope(); + @NotNull Set getConstructors(); @@ -77,10 +80,4 @@ public interface ClassDescriptor extends ClassifierDescriptor, MemberDescriptor, @NotNull ReceiverDescriptor getImplicitReceiver(); - - @Nullable - ClassDescriptor getInnerClassOrObject(String name); - - @NotNull - Collection getInnerClassesAndObjects(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java index b7bdc83d6eb..314c44dd9a3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java @@ -176,14 +176,9 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl return implicitReceiver; } - @Override - public ClassDescriptor getInnerClassOrObject(String name) { - return null; - } - @NotNull @Override - public Collection getInnerClassesAndObjects() { - return Collections.emptyList(); + public JetScope getUnsubstitutedInnerClassesScope() { + return JetScope.EMPTY; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java index 8f9a090902a..8c22916b00d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java @@ -20,7 +20,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; @@ -204,14 +203,9 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor { throw new UnsupportedOperationException(); // TODO } - @Override - public ClassDescriptor getInnerClassOrObject(String name) { - return original.getInnerClassOrObject(name); - } - @NotNull @Override - public Collection getInnerClassesAndObjects() { - return original.getInnerClassesAndObjects(); + public JetScope getUnsubstitutedInnerClassesScope() { + return original.getUnsubstitutedInnerClassesScope(); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java index 84d4223d013..30310236120 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java @@ -23,9 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.scopes.JetScope; -import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; -import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.resolve.scopes.*; import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; @@ -42,8 +40,6 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp private List annotations = Lists.newArrayList(); - private Map innerClassesAndObjects = Maps.newHashMap(); - private List typeParameters; private Collection supertypes = Lists.newArrayList(); @@ -58,6 +54,7 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp private final ClassKind kind; private JetScope scopeForMemberLookup; + private JetScope innerClassesScope; private ClassReceiver implicitReceiver; @@ -109,6 +106,7 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp public void setScopeForMemberLookup(JetScope scopeForMemberLookup) { this.scopeForMemberLookup = scopeForMemberLookup; + this.innerClassesScope = new InnerClassesScopeWrapper(scopeForMemberLookup); } public void createTypeConstructor() { @@ -264,25 +262,17 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp @Override public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) { getScopeForMemberLookupAsWritableScope().addClassifierDescriptor(classDescriptor); - innerClassesAndObjects.put(classDescriptor.getName(), classDescriptor); } - @Override - @Nullable - public ClassDescriptor getInnerClassOrObject(String name) { - return innerClassesAndObjects.get(name); - } - - @Override @NotNull - public Collection getInnerClassesAndObjects() { - return innerClassesAndObjects.values(); + @Override + public JetScope getUnsubstitutedInnerClassesScope() { + return innerClassesScope; } @Override public void addObjectDescriptor(@NotNull MutableClassDescriptorLite objectDescriptor) { getScopeForMemberLookupAsWritableScope().addObjectDescriptor(objectDescriptor); - innerClassesAndObjects.put(objectDescriptor.getName(), objectDescriptor); } public void addSupertype(@NotNull JetType supertype) { @@ -304,7 +294,6 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp } } - public void lockScopes() { getScopeForMemberLookupAsWritableScope().changeLockLevel(WritableScope.LockLevel.READING); if (classObjectDescriptor != null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index ce144af5d0d..f9b61b8d9e1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -247,14 +247,6 @@ public class DescriptorUtils { return null; } - @Nullable - public static ClassDescriptor getObjectIfObjectOrClassObjectDescriptor(ClassDescriptor descriptor) { - if ((descriptor).getKind() == ClassKind.OBJECT) { - return descriptor; - } - return descriptor.getClassObjectDescriptor(); - } - @NotNull public static JetType getFunctionExpectedReturnType(@NotNull FunctionDescriptor descriptor, @NotNull JetElement function) { JetType expectedType; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Importer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Importer.java index 4737c57b149..7d0a615e9ed 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Importer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Importer.java @@ -21,9 +21,7 @@ import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; -import org.jetbrains.jet.lang.types.JetType; -import java.util.Collection; import java.util.List; /** @@ -68,26 +66,12 @@ import java.util.List; if (descriptor instanceof NamespaceDescriptor) { namespaceScope.importScope(((NamespaceDescriptor) descriptor).getMemberScope()); } - if (firstPhase) { - if (descriptor instanceof ClassDescriptor) { - ClassDescriptor objectDescriptor = DescriptorUtils.getObjectIfObjectOrClassObjectDescriptor((ClassDescriptor) descriptor); - if (objectDescriptor != null) { - Collection innerClassesAndObjects = objectDescriptor.getInnerClassesAndObjects(); - for (DeclarationDescriptor innerClassOrObject : innerClassesAndObjects) { - namespaceScope.importClassifierAlias(innerClassOrObject.getName(), (ClassifierDescriptor) innerClassOrObject); - } - } - } - return; - } - if (descriptor instanceof VariableDescriptor) { - JetType type = ((VariableDescriptor) descriptor).getType(); - namespaceScope.importScope(type.getMemberScope()); - } - else if (descriptor instanceof ClassDescriptor) { - JetType classObjectType = ((ClassDescriptor) descriptor).getClassObjectType(); - if (classObjectType != null) { - namespaceScope.importScope(classObjectType.getMemberScope()); + if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() != ClassKind.OBJECT) { + ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; + namespaceScope.importScope(classDescriptor.getUnsubstitutedInnerClassesScope()); + ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor(); + if (classObjectDescriptor != null) { + namespaceScope.importScope(classObjectDescriptor.getUnsubstitutedInnerClassesScope()); } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java index fb95ad6ac39..098a028ddae 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java @@ -20,20 +20,17 @@ import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.inject.Inject; import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; -import org.jetbrains.jet.lang.types.JetType; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import javax.inject.Inject; +import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; @@ -46,6 +43,8 @@ public class ImportsResolver { private TopDownAnalysisContext context; @NotNull private ModuleConfiguration configuration; + @NotNull + private SingleImportResolver singleImportResolver; @Inject public void setContext(@NotNull TopDownAnalysisContext context) { @@ -57,6 +56,9 @@ public class ImportsResolver { this.configuration = configuration; } + public ImportsResolver() { + this.singleImportResolver = new SingleImportResolver(); + } public void processTypeImports() { processImports(true); @@ -66,9 +68,10 @@ public class ImportsResolver { processImports(false); } + // On first phase all classes and objects are imported, + // on second phase previous imports are thrown and everything (including functions and properties at namespace level) is imported private void processImports(boolean firstPhase) { - SingleImportResolver importResolver = new SingleImportResolver(context.getTrace(), firstPhase); - SingleImportResolver defaultImportResolver = new SingleImportResolver(TemporaryBindingTrace.create(context.getTrace()), firstPhase);//not to trace errors of default imports + TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.getTrace()); //not to trace errors of default imports for (JetFile file : context.getNamespaceDescriptors().keySet()) { WritableScope namespaceScope = context.getNamespaceScopes().get(file); Importer.DelayedImporter delayedImporter = new Importer.DelayedImporter(namespaceScope, firstPhase); @@ -79,12 +82,12 @@ public class ImportsResolver { Collection defaultImportDirectives = Lists.newArrayList(); configuration.addDefaultImports(namespaceScope, defaultImportDirectives); for (JetImportDirective defaultImportDirective : defaultImportDirectives) { - defaultImportResolver.processImportReference(defaultImportDirective, namespaceScope, delayedImporter); + singleImportResolver.processImportReference(defaultImportDirective, namespaceScope, delayedImporter, temporaryTrace, firstPhase); } List importDirectives = file.getImportDirectives(); for (JetImportDirective importDirective : importDirectives) { - Collection descriptors = importResolver.processImportReference(importDirective, namespaceScope, delayedImporter); + Collection descriptors = singleImportResolver.processImportReference(importDirective, namespaceScope, delayedImporter, context.getTrace(), firstPhase); if (descriptors.size() == 1) { resolvedDirectives.put(importDirective, descriptors.iterator().next()); } @@ -162,23 +165,17 @@ public class ImportsResolver { @NotNull JetImportDirective importDirective, @NotNull JetScope scope, @NotNull BindingTrace trace ) { - ImportsResolver.SingleImportResolver importResolver = new ImportsResolver.SingleImportResolver(trace, false); - return importResolver.processImportReference(importDirective, scope, Importer.DO_NOTHING); + ImportsResolver.SingleImportResolver importResolver = new ImportsResolver.SingleImportResolver(); + return importResolver.processImportReference(importDirective, scope, Importer.DO_NOTHING, trace, false); } private static class SingleImportResolver { - private final BindingTrace trace; - /* On first phase all classes and objects are imported, - on second phase previous imports are thrown and everything (including functions and properties at namespace level) is imported */ - private final boolean firstPhase; - - public SingleImportResolver(BindingTrace trace, boolean firstPhase) { - this.trace = trace; - this.firstPhase = firstPhase; - } - @NotNull - public Collection processImportReference(@NotNull JetImportDirective importDirective, @NotNull JetScope scope, @NotNull Importer importer) { + public Collection processImportReference(@NotNull JetImportDirective importDirective, + @NotNull JetScope scope, + @NotNull Importer importer, + @NotNull BindingTrace trace, + boolean firstPhase) { if (importDirective.isAbsoluteInRootNamespace()) { trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO return Collections.emptyList(); @@ -190,16 +187,16 @@ public class ImportsResolver { Collection descriptors; if (importedReference instanceof JetQualifiedExpression) { - descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, scope); + descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, scope, trace, firstPhase); } else { assert importedReference instanceof JetSimpleNameExpression; - descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope, true); + descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope, trace, firstPhase, true); } JetSimpleNameExpression referenceExpression = getLastReference(importedReference); if (importDirective.isAllUnder()) { - if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression)) { + if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression, trace,firstPhase)) { return Collections.emptyList(); } @@ -223,147 +220,120 @@ public class ImportsResolver { @NotNull private Collection lookupDescriptorsForQualifiedExpression( - @NotNull JetQualifiedExpression importedReference, @NotNull JetScope outerScope) { + @NotNull JetQualifiedExpression importedReference, + @NotNull JetScope outerScope, + @NotNull BindingTrace trace, + boolean firstPhase) { JetExpression receiverExpression = importedReference.getReceiverExpression(); Collection declarationDescriptors; if (receiverExpression instanceof JetQualifiedExpression) { - declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) receiverExpression, outerScope); + declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) receiverExpression, outerScope, trace, firstPhase); } else { assert receiverExpression instanceof JetSimpleNameExpression; - declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, true); + declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, trace, firstPhase, true); } JetExpression selectorExpression = importedReference.getSelectorExpression(); - if (selectorExpression instanceof JetSimpleNameExpression) { - JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression; - JetSimpleNameExpression lastReference = getLastReference(receiverExpression); - if (lastReference == null || !canImportMembersFrom(declarationDescriptors, lastReference)) { - return Collections.emptyList(); - } + if (!(selectorExpression instanceof JetSimpleNameExpression)) return Collections.emptyList(); - Collection result; - for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { - if (declarationDescriptor instanceof NamespaceDescriptor) { - result = lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope(), true); - if (!result.isEmpty()) { - return result; - } - } - if (declarationDescriptor instanceof ClassDescriptor) { - result = lookupObjectMembers((ClassDescriptor) declarationDescriptor, selector); - if (!result.isEmpty()) { - return result; - } - } - if (declarationDescriptor instanceof VariableDescriptor) { - result = lookupVariableMembers((VariableDescriptor) declarationDescriptor, selector); - if (!result.isEmpty()) { - return result; - } + JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression; + JetSimpleNameExpression lastReference = getLastReference(receiverExpression); + if (lastReference == null || !canImportMembersFrom(declarationDescriptors, lastReference, trace, firstPhase)) { + return Collections.emptyList(); + } + + Set results = Sets.newHashSet(); + for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { + if (declarationDescriptor instanceof NamespaceDescriptor) { + addResult(results, lookupSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope(), firstPhase, true)); + } + if (declarationDescriptor instanceof ClassDescriptor) { + addResult(results, lookupSimpleNameReference(selector, getAppropriateScope((ClassDescriptor) declarationDescriptor, firstPhase), firstPhase, false)); + ClassDescriptor classObjectDescriptor = ((ClassDescriptor) declarationDescriptor).getClassObjectDescriptor(); + if (classObjectDescriptor != null) { + addResult(results, lookupSimpleNameReference(selector, getAppropriateScope(classObjectDescriptor, firstPhase), firstPhase, false)); } } } - - return Collections.emptyList(); + if (results.isEmpty()) { + return Collections.emptyList(); + } + return filterAndStoreResolutionResult(results, selector, trace, firstPhase); } - private boolean canImportMembersFrom(@NotNull Collection descriptors, @NotNull JetSimpleNameExpression reference) { + private static JetScope getAppropriateScope(ClassDescriptor classDescriptor, boolean firstPhase) { + return firstPhase ? classDescriptor.getUnsubstitutedInnerClassesScope() : classDescriptor.getDefaultType().getMemberScope(); + } + + private static void addResult(Set results, LookupResult result) { + if (result == LookupResult.EMPTY) return; + results.add((SuccessfulLookupResult) result); + } + + private boolean canImportMembersFrom(@NotNull Collection descriptors, + @NotNull JetSimpleNameExpression reference, + @NotNull BindingTrace trace, + boolean firstPhase) { if (firstPhase) { return true; } if (descriptors.size() == 1) { - return canImportMembersFrom(descriptors.iterator().next(), reference, trace); + return canImportMembersFrom(descriptors.iterator().next(), reference, trace, firstPhase); } TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace); boolean canImport = false; for (DeclarationDescriptor descriptor : descriptors) { - canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace); + canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace, firstPhase); } if (!canImport) { temporaryTrace.commit(); } return canImport; } - + private boolean canImportMembersFrom(@NotNull DeclarationDescriptor descriptor, @NotNull JetSimpleNameExpression reference, - @NotNull BindingTrace trace) { + @NotNull BindingTrace trace, + boolean firstPhase) { assert !firstPhase; if (descriptor instanceof NamespaceDescriptor) { return true; } - if (descriptor instanceof ClassDescriptor) { - ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; - JetType classObjectType = classDescriptor.getClassObjectType(); - if (classObjectType == null) { - trace.report(NO_CLASS_OBJECT.on(reference, classDescriptor)); - return false; - } - return true; - } - if (descriptor instanceof VariableDescriptor && ((VariableDescriptor) descriptor).isObjectDeclaration()) { + if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() != ClassKind.OBJECT) { return true; } trace.report(CANNOT_IMPORT_FROM_ELEMENT.on(reference, descriptor)); return false; } - @NotNull - private Collection lookupObjectMembers(@NotNull ClassDescriptor classDescriptor, @NotNull JetSimpleNameExpression memberReference) { - if (firstPhase) { - ClassDescriptor objectDescriptor = DescriptorUtils.getObjectIfObjectOrClassObjectDescriptor(classDescriptor); - if (objectDescriptor == null) { - return Collections.emptyList(); - } - return getInnerClassesAndObjectsByName(objectDescriptor, memberReference); - } - //on second phase class descriptor is only a descriptor for class object - JetType classObjectType = classDescriptor.getClassObjectType(); - if (classObjectType == null) { - return Collections.emptyList(); - } - return lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope(), false); - } - - @NotNull - private Collection getInnerClassesAndObjectsByName(@NotNull ClassDescriptor classDescriptor, @NotNull JetSimpleNameExpression memberReference) { - assert classDescriptor.getKind() == ClassKind.OBJECT; - Collection descriptors; - ClassDescriptor innerClass = classDescriptor.getInnerClassOrObject(memberReference.getReferencedName()); - if (innerClass == null) { - return Collections.emptyList(); - } - descriptors = Collections.singletonList(innerClass); - return filterResolutionResult(descriptors, memberReference, JetScope.EMPTY, false); - } - - private Collection lookupVariableMembers(@NotNull VariableDescriptor variableDescriptor, @NotNull JetSimpleNameExpression memberReference) { - if (firstPhase) { - return Collections.emptyList(); - } - - JetType variableType = variableDescriptor.getReturnType(); - if (variableType == null) { - return Collections.emptyList(); - } - return lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope(), false); - } - @NotNull private Collection lookupDescriptorsForSimpleNameReference( @NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope outerScope, + @NotNull BindingTrace trace, + boolean firstPhase, + boolean namespaceLevel) { + LookupResult lookupResult = lookupSimpleNameReference(referenceExpression, outerScope, firstPhase, namespaceLevel); + if (lookupResult == LookupResult.EMPTY) return Collections.emptyList(); + return filterAndStoreResolutionResult(Collections.singletonList((SuccessfulLookupResult) lookupResult), referenceExpression, trace, firstPhase); + } + + private LookupResult lookupSimpleNameReference( + @NotNull JetSimpleNameExpression referenceExpression, + @NotNull JetScope outerScope, + boolean firstPhase, boolean namespaceLevel) { String referencedName = referenceExpression.getReferencedName(); if (referencedName == null) { - return Collections.emptyList(); + //to store a scope where we tried to resolve this reference + return new SuccessfulLookupResult(Collections.emptyList(), outerScope, namespaceLevel); } - List descriptors = Lists.newArrayList(); + Set descriptors = Sets.newHashSet(); NamespaceDescriptor namespaceDescriptor = outerScope.getNamespace(referencedName); if (namespaceDescriptor != null) { descriptors.add(namespaceDescriptor); @@ -386,39 +356,55 @@ public class ImportsResolver { descriptors.add(localVariable); } } - return filterResolutionResult(descriptors, referenceExpression, outerScope, namespaceLevel); + return new SuccessfulLookupResult(descriptors, outerScope, namespaceLevel); } - private Collection filterResolutionResult( - @NotNull Collection descriptors, + private Collection filterAndStoreResolutionResult( + @NotNull Collection lookupResults, @NotNull JetSimpleNameExpression referenceExpression, - @NotNull JetScope resolutionScope, - //functions and properties can be imported if namespaceLevel == true - boolean namespaceLevel) { + @NotNull BindingTrace trace, + boolean firstPhase) { + //functions and properties can be imported if lookupResult.namespaceLevel == true + Collection descriptors = Sets.newLinkedHashSet(); + for (SuccessfulLookupResult lookupResult : lookupResults) { + descriptors.addAll(lookupResult.descriptors); + } if (firstPhase) { return Collections2.filter(descriptors, new Predicate() { @Override public boolean apply(@Nullable DeclarationDescriptor descriptor) { - return (descriptor instanceof ClassDescriptor) || + return (descriptor instanceof ClassDescriptor) || (descriptor instanceof NamespaceDescriptor); } }); } - Collection filteredDescriptors; - if (namespaceLevel) { - filteredDescriptors = descriptors; - } - else { - filteredDescriptors = Collections2.filter(descriptors, new Predicate() { + Collection filteredDescriptors = Sets.newLinkedHashSet(); + for (SuccessfulLookupResult lookupResult : lookupResults) { + if (lookupResult.namespaceLevel) { + filteredDescriptors.addAll(lookupResult.descriptors); + continue; + } + filteredDescriptors.addAll(Collections2.filter(lookupResult.descriptors, new Predicate() { @Override public boolean apply(@Nullable DeclarationDescriptor descriptor) { return (descriptor instanceof NamespaceDescriptor) || (descriptor instanceof ClassDescriptor) || (descriptor instanceof VariableDescriptor && ((VariableDescriptor) descriptor).isObjectDeclaration()); } - }); + })); } - storeResolutionResult(descriptors, filteredDescriptors, referenceExpression, resolutionScope); + Collection possibleResolutionScopes = Lists.newArrayList(); + for (SuccessfulLookupResult lookupResult : lookupResults) { + if (!lookupResult.descriptors.isEmpty()) { + possibleResolutionScopes.add(lookupResult.resolutionScope); + } + } + if (possibleResolutionScopes.isEmpty()) { + for (SuccessfulLookupResult lookupResult : lookupResults) { + possibleResolutionScopes.add(lookupResult.resolutionScope); + } + } + storeResolutionResult(descriptors, filteredDescriptors, referenceExpression, possibleResolutionScopes, trace); return filteredDescriptors; } @@ -426,12 +412,16 @@ public class ImportsResolver { @NotNull Collection descriptors, @NotNull Collection canBeImportedDescriptors, @NotNull JetSimpleNameExpression referenceExpression, - @NotNull JetScope resolutionScope) { + @NotNull Collection possibleResolutionScopes, + @NotNull BindingTrace trace) { assert canBeImportedDescriptors.size() <= descriptors.size(); + assert !possibleResolutionScopes.isEmpty(); + //todo completion here needs all possible resolution scopes, if there are many + JetScope resolutionScope = possibleResolutionScopes.iterator().next(); // A special case - will fill all trace information - if (resolveClassNamespaceAmbiguity(canBeImportedDescriptors, referenceExpression, resolutionScope)) { + if (resolveClassNamespaceAmbiguity(canBeImportedDescriptors, referenceExpression, resolutionScope, trace)) { return; } @@ -451,8 +441,6 @@ public class ImportsResolver { else if (canBeImportedDescriptors.size() == 1) { trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, canBeImportedDescriptors.iterator().next()); trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); - } else { - // trace.report(UNRESOLVED_REFERENCE.on(referenceExpression)); } // Check for more information and additional errors @@ -471,9 +459,10 @@ public class ImportsResolver { * * @return true if method has successfully resolved ambiguity */ - private boolean resolveClassNamespaceAmbiguity(Collection filteredDescriptors, - JetSimpleNameExpression referenceExpression, - JetScope resolutionScope) { + private boolean resolveClassNamespaceAmbiguity(@NotNull Collection filteredDescriptors, + @NotNull JetSimpleNameExpression referenceExpression, + @NotNull JetScope resolutionScope, + @NotNull BindingTrace trace) { if (filteredDescriptors.size() == 2) { NamespaceDescriptor namespaceDescriptor = null; @@ -499,5 +488,21 @@ public class ImportsResolver { return false; } + + private interface LookupResult { + LookupResult EMPTY = new LookupResult() {}; + } + + private static class SuccessfulLookupResult implements LookupResult { + final Collection descriptors; + final JetScope resolutionScope; + final boolean namespaceLevel; + + private SuccessfulLookupResult(Collection descriptors, JetScope resolutionScope, boolean namespaceLevel) { + this.descriptors = descriptors; + this.resolutionScope = resolutionScope; + this.namespaceLevel = namespaceLevel; + } + } } -} +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/InnerClassesScopeWrapper.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/InnerClassesScopeWrapper.java new file mode 100644 index 00000000000..4867b747fdc --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/InnerClassesScopeWrapper.java @@ -0,0 +1,93 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.scopes; + +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassKind; +import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; + +import java.util.Collection; +import java.util.List; + +/** + * @author svtk + */ +public class InnerClassesScopeWrapper extends JetScopeImpl { + private final JetScope actualScope; + + public InnerClassesScopeWrapper(JetScope actualScope) { + this.actualScope = actualScope; + } + + private boolean isClass(DeclarationDescriptor descriptor) { + return descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() != ClassKind.OBJECT; + } + + @Override + public ClassifierDescriptor getClassifier(@NotNull String name) { + ClassifierDescriptor classifier = actualScope.getClassifier(name); + if (isClass(classifier)) return classifier; + return null; + } + + @NotNull + @Override + public DeclarationDescriptor getContainingDeclaration() { + return actualScope.getContainingDeclaration(); + } + + @NotNull + @Override + public Collection getDeclarationsByLabel(String labelName) { + Collection declarationsByLabel = actualScope.getDeclarationsByLabel(labelName); + return Collections2.filter(declarationsByLabel, new Predicate() { + @Override + public boolean apply(@Nullable DeclarationDescriptor descriptor) { + return isClass(descriptor); + } + }); + } + + @NotNull + @Override + public Collection getAllDescriptors() { + Collection allDescriptors = actualScope.getAllDescriptors(); + return Collections2.filter(allDescriptors, new Predicate() { + @Override + public boolean apply(@Nullable DeclarationDescriptor descriptor) { + return isClass(descriptor); + } + }); + } + + @NotNull + @Override + public ReceiverDescriptor getImplicitReceiver() { + return actualScope.getImplicitReceiver(); + } + + @Override + public void getImplicitReceiversHierarchy(@NotNull List result) { + actualScope.getImplicitReceiversHierarchy(result); + } +} diff --git a/compiler/testData/diagnostics/tests/scopes/Imports.jet b/compiler/testData/diagnostics/tests/scopes/Imports.jet index 4b763e36fc3..192c751f12f 100644 --- a/compiler/testData/diagnostics/tests/scopes/Imports.jet +++ b/compiler/testData/diagnostics/tests/scopes/Imports.jet @@ -70,7 +70,7 @@ fun bar() {} //FILE:c.kt package c -import C.* +import C.* object C { fun f() { @@ -79,7 +79,7 @@ object C { } fun foo() { - if (i == 3) f() + if (i == 3) f() } //FILE:d.kt @@ -96,4 +96,4 @@ class A() { open class B() {} object C : B() {} } -} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/kt1579.jet b/compiler/testData/diagnostics/tests/scopes/kt1579.jet new file mode 100644 index 00000000000..f5ca40c278a --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/kt1579.jet @@ -0,0 +1,9 @@ +//FILE:a.kt +package lib +trait WithInner { + trait Inner { + } +} +//FILE:b.kt +package user +import lib.WithInner.Inner \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/kt1579_map_entry.jet b/compiler/testData/diagnostics/tests/scopes/kt1579_map_entry.jet new file mode 100644 index 00000000000..50e727fa6c0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/kt1579_map_entry.jet @@ -0,0 +1,12 @@ +//FILE:a.kt +//+JDK +package a +import java.util.Map.* + +fun foo(b : Entry) = b +//FILE:b.kt +//+JDK +package b + +import java.util.Map.Entry +fun bar(b : Entry) = b diff --git a/compiler/testData/diagnostics/tests/scopes/kt900-1.jet b/compiler/testData/diagnostics/tests/scopes/kt900-1.jet new file mode 100644 index 00000000000..4ed42574658 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/kt900-1.jet @@ -0,0 +1,24 @@ +// import all members from class object +package c + +import A.* +import M.* + +fun foo() { + val b: B = B() + var r: R = R() +} + +class A() { + class object { + class B() { + class object { + } + } + } +} + +object M { + fun foo() {} + class R() {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/kt900-2.jet b/compiler/testData/diagnostics/tests/scopes/kt900-2.jet new file mode 100644 index 00000000000..12f3aa2afcf --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/kt900-2.jet @@ -0,0 +1,33 @@ +package d + +//import from objects before properties resolve + +import A.* +import M.R +import M.R.bar +import M.T +import M.Y + +var r: T = T() +val y: T = Y + +fun f() { + bar() + R.bar() + B.foo() +} + +object M { + object R { + fun bar() {} + } + open class T() {} + + object Y : T() {} +} + +object A { + object B { + fun foo() {} + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/kt900.jet b/compiler/testData/diagnostics/tests/scopes/kt900.jet index c18452e8eef..f9461d0ff6f 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt900.jet +++ b/compiler/testData/diagnostics/tests/scopes/kt900.jet @@ -35,7 +35,7 @@ object N { //FILE:b.kt package b -import N.M +import N.M import A.P import b.A.B @@ -45,7 +45,7 @@ fun foo() { P.foo() - M.bar() + M.bar() } class A() { @@ -66,65 +66,4 @@ object N { object M { fun bar() {} } -} - -//FILE:c.kt -// import all members from class object -package c - -import A.* -import M.* - -fun foo() { - val b: B = B() - var r: R = R() -} - -class A() { - class object { - class B() { - class object { - } - } - } -} - -object M { - fun foo() {} - class R() {} -} - -//FILE:d.kt -package d - -//import from objects before properties resolve - -import A.* -import M.R -import M.R.bar -import M.T -import M.Y - -var r: T = T() -val y: T = Y - -fun f() { - bar() - R.bar() - B.foo() -} - -object M { - object R { - fun bar() {} - } - open class T() {} - - object Y : T() {} -} - -object A { - object B { - fun foo() {} - } -} +} \ No newline at end of file