From f7cfb36f62110c9232dd74c267534df929c4fe79 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Tue, 27 Mar 2012 15:15:15 +0400 Subject: [PATCH] # KT-1579 Fixed Can't import nested class/trait --- .../di/InjectorForTopDownAnalyzerForJvm.java | 4 + .../resolve/java/JavaBridgeConfiguration.java | 4 +- .../jetbrains/jet/di/InjectorForMacros.java | 3 + .../di/InjectorForTopDownAnalyzerBasic.java | 4 + .../jet/lang/DefaultModuleConfiguration.java | 2 +- .../jet/lang/ModuleConfiguration.java | 4 +- .../jetbrains/jet/lang/psi/JetPsiUtil.java | 25 + .../jetbrains/jet/lang/resolve/Importer.java | 8 +- .../jet/lang/resolve/ImportsResolver.java | 425 ++--------------- .../resolve/QualifiedExpressionResolver.java | 428 ++++++++++++++++++ .../jet/lang/resolve/TypeResolver.java | 102 +---- .../expressions/ExpressionTypingUtils.java | 2 +- .../diagnostics/tests/ShiftFunctionTypes.jet | 4 +- .../ImportFromCurrentWithDifferentName.jet | 2 +- .../diagnostics/tests/scopes/Imports.jet | 6 +- .../scopes/ImportsUselessSimpleImport.jet | 2 +- .../diagnostics/tests/scopes/kt1579.jet | 1 + .../tests/scopes/kt1579_map_entry.jet | 8 + .../diagnostics/tests/scopes/kt900-1.jet | 4 +- .../diagnostics/tests/scopes/kt900-2.jet | 10 +- .../diagnostics/tests/scopes/kt900.jet | 4 +- .../jetbrains/jet/di/InjectorForTests.java | 3 + .../jet/plugin/caches/JetShortNamesCache.java | 2 +- idea/testData/checker/ResolveToJava.jet | 2 +- .../completion/basic/InEmptyImport.kt | 2 +- .../k2js/analyze/AnalyzerFacadeForJS.java | 3 +- 26 files changed, 548 insertions(+), 516 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index e3dfc362f42..9ca2ccc1e28 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -35,6 +35,7 @@ import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; import org.jetbrains.jet.lang.resolve.ImportsResolver; import org.jetbrains.jet.lang.resolve.DelegationResolver; @@ -89,6 +90,7 @@ public class InjectorForTopDownAnalyzerForJvm { CallResolver callResolver = new CallResolver(); ExpressionTypingServices expressionTypingServices = new ExpressionTypingServices(); TypeResolver typeResolver = new TypeResolver(); + QualifiedExpressionResolver qualifiedExpressionResolver = new QualifiedExpressionResolver(); OverloadingConflictResolver overloadingConflictResolver = new OverloadingConflictResolver(); ImportsResolver importsResolver = new ImportsResolver(); DelegationResolver delegationResolver = new DelegationResolver(); @@ -161,9 +163,11 @@ public class InjectorForTopDownAnalyzerForJvm { typeResolver.setAnnotationResolver(annotationResolver); typeResolver.setDescriptorResolver(descriptorResolver); + typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); importsResolver.setConfiguration(javaBridgeConfiguration); importsResolver.setContext(topDownAnalysisContext); + importsResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); importsResolver.setTrace(observableBindingTrace); delegationResolver.setContext(topDownAnalysisContext); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java index 68a3566205e..3fb94f94d98 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaBridgeConfiguration.java @@ -63,11 +63,11 @@ public class JavaBridgeConfiguration implements ModuleConfiguration { @Override - public void addDefaultImports(@NotNull WritableScope rootScope, @NotNull Collection directives) { + public void addDefaultImports(@NotNull Collection directives) { for (ImportPath importPath : DEFAULT_JAVA_IMPORTS) { directives.add(JetPsiFactory.createImportDirective(project, importPath)); } - delegateConfiguration.addDefaultImports(rootScope, directives); + delegateConfiguration.addDefaultImports(directives); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java index 752131e2b3a..ca570d75b93 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForMacros.java @@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.DescriptorResolver; import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; @@ -42,6 +43,7 @@ public class InjectorForMacros { DescriptorResolver descriptorResolver = new DescriptorResolver(); AnnotationResolver annotationResolver = new AnnotationResolver(); TypeResolver typeResolver = new TypeResolver(); + QualifiedExpressionResolver qualifiedExpressionResolver = new QualifiedExpressionResolver(); OverloadingConflictResolver overloadingConflictResolver = new OverloadingConflictResolver(); this.expressionTypingServices.setCallResolver(callResolver); @@ -63,6 +65,7 @@ public class InjectorForMacros { typeResolver.setAnnotationResolver(annotationResolver); typeResolver.setDescriptorResolver(descriptorResolver); + typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); } diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java index 250961def32..7c8405cfa5a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.AnnotationResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.resolve.TypeResolver; +import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; import org.jetbrains.jet.lang.resolve.ImportsResolver; import org.jetbrains.jet.lang.resolve.DelegationResolver; @@ -84,6 +85,7 @@ public class InjectorForTopDownAnalyzerBasic { CallResolver callResolver = new CallResolver(); ExpressionTypingServices expressionTypingServices = new ExpressionTypingServices(); TypeResolver typeResolver = new TypeResolver(); + QualifiedExpressionResolver qualifiedExpressionResolver = new QualifiedExpressionResolver(); OverloadingConflictResolver overloadingConflictResolver = new OverloadingConflictResolver(); ImportsResolver importsResolver = new ImportsResolver(); DelegationResolver delegationResolver = new DelegationResolver(); @@ -148,9 +150,11 @@ public class InjectorForTopDownAnalyzerBasic { typeResolver.setAnnotationResolver(annotationResolver); typeResolver.setDescriptorResolver(descriptorResolver); + typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); importsResolver.setConfiguration(moduleConfiguration); importsResolver.setContext(topDownAnalysisContext); + importsResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); importsResolver.setTrace(observableBindingTrace); delegationResolver.setContext(topDownAnalysisContext); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/DefaultModuleConfiguration.java b/compiler/frontend/src/org/jetbrains/jet/lang/DefaultModuleConfiguration.java index 3ced2d40b6a..f68aca9d57f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/DefaultModuleConfiguration.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/DefaultModuleConfiguration.java @@ -49,7 +49,7 @@ public class DefaultModuleConfiguration implements ModuleConfiguration { } @Override - public void addDefaultImports(@NotNull WritableScope rootScope, @NotNull Collection directives) { + public void addDefaultImports(@NotNull Collection directives) { for (ImportPath defaultJetImport : DEFAULT_JET_IMPORTS) { directives.add(JetPsiFactory.createImportDirective(project, defaultJetImport)); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/ModuleConfiguration.java b/compiler/frontend/src/org/jetbrains/jet/lang/ModuleConfiguration.java index 5c9c34bedb3..d5366ad5204 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/ModuleConfiguration.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/ModuleConfiguration.java @@ -30,7 +30,7 @@ import java.util.Collection; public interface ModuleConfiguration { ModuleConfiguration EMPTY = new ModuleConfiguration() { @Override - public void addDefaultImports(@NotNull WritableScope rootScope, @NotNull Collection directives) { + public void addDefaultImports(@NotNull Collection directives) { } @Override @@ -39,7 +39,7 @@ public interface ModuleConfiguration { }; - void addDefaultImports(@NotNull WritableScope rootScope, @NotNull Collection directives); + void addDefaultImports(@NotNull Collection directives); /** * diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index e824cacbd4f..97c7fe21711 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -274,4 +274,29 @@ public class JetPsiUtil { } } + @Nullable + public static String getAliasName(@NotNull JetImportDirective importDirective) { + String aliasName = importDirective.getAliasName(); + JetExpression importedReference = importDirective.getImportedReference(); + if (importedReference == null) { + return null; + } + JetSimpleNameExpression referenceExpression = getLastReference(importedReference); + if (aliasName == null) { + aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null; + } + return aliasName; + } + + @Nullable + public static JetSimpleNameExpression getLastReference(@NotNull JetExpression importedReference) { + if (importedReference instanceof JetDotQualifiedExpression) { + JetExpression selectorExpression = ((JetDotQualifiedExpression)importedReference).getSelectorExpression(); + return (selectorExpression instanceof JetSimpleNameExpression) ? (JetSimpleNameExpression)selectorExpression : null; + } + if (importedReference instanceof JetSimpleNameExpression) { + return (JetSimpleNameExpression)importedReference; + } + return null; + } } 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 7d0a615e9ed..d9538b7f845 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Importer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/Importer.java @@ -45,11 +45,9 @@ import java.util.List; class StandardImporter implements Importer { private final WritableScope namespaceScope; - private final boolean firstPhase; - public StandardImporter(WritableScope namespaceScope, boolean firstPhase) { + public StandardImporter(WritableScope namespaceScope) { this.namespaceScope = namespaceScope; - this.firstPhase = firstPhase; } @Override @@ -96,8 +94,8 @@ import java.util.List; class DelayedImporter extends StandardImporter { private final List> imports = Lists.newArrayList(); - public DelayedImporter(@NotNull WritableScope namespaceScope, boolean firstPhase) { - super(namespaceScope, firstPhase); + public DelayedImporter(@NotNull WritableScope namespaceScope) { + super(namespaceScope); } @Override 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 241474e51cb..225101cdb8c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java @@ -16,23 +16,25 @@ package org.jetbrains.jet.lang.resolve; -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 org.jetbrains.jet.lang.ModuleConfiguration; -import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import javax.inject.Inject; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; -import static org.jetbrains.jet.lang.diagnostics.Errors.*; +import static org.jetbrains.jet.lang.diagnostics.Errors.USELESS_HIDDEN_IMPORT; +import static org.jetbrains.jet.lang.diagnostics.Errors.USELESS_SIMPLE_IMPORT; /** * @author abreslav @@ -44,7 +46,7 @@ public class ImportsResolver { @NotNull private ModuleConfiguration configuration; @NotNull - private SingleImportResolver singleImportResolver; + private QualifiedExpressionResolver qualifiedExpressionResolver; @NotNull private ObservableBindingTrace trace; @@ -63,8 +65,9 @@ public class ImportsResolver { this.trace = trace; } - public ImportsResolver() { - this.singleImportResolver = new SingleImportResolver(); + @Inject + public void setQualifiedExpressionResolver(@NotNull QualifiedExpressionResolver qualifiedExpressionResolver) { + this.qualifiedExpressionResolver = qualifiedExpressionResolver; } public void processTypeImports() { @@ -75,67 +78,40 @@ 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) { + private void processImports(boolean onlyClasses) { TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace); //not to trace errors of default imports for (JetFile file : context.getNamespaceDescriptors().keySet()) { + //JetScope rootScope = context.getRootScope(); WritableScope namespaceScope = context.getNamespaceScopes().get(file); - Importer.DelayedImporter delayedImporter = new Importer.DelayedImporter(namespaceScope, firstPhase); - if (!firstPhase) { + Importer.DelayedImporter delayedImporter = new Importer.DelayedImporter(namespaceScope); + if (!onlyClasses) { namespaceScope.clearImports(); } Map resolvedDirectives = Maps.newHashMap(); Collection defaultImportDirectives = Lists.newArrayList(); - configuration.addDefaultImports(namespaceScope, defaultImportDirectives); + configuration.addDefaultImports(defaultImportDirectives); for (JetImportDirective defaultImportDirective : defaultImportDirectives) { - singleImportResolver.processImportReference(defaultImportDirective, namespaceScope, delayedImporter, temporaryTrace, firstPhase); + qualifiedExpressionResolver.processImportReference(defaultImportDirective, namespaceScope, delayedImporter, temporaryTrace, onlyClasses); } List importDirectives = file.getImportDirectives(); for (JetImportDirective importDirective : importDirectives) { - Collection descriptors = singleImportResolver.processImportReference(importDirective, namespaceScope, delayedImporter, trace, firstPhase); + Collection descriptors = + qualifiedExpressionResolver.processImportReference(importDirective, namespaceScope, delayedImporter, trace, onlyClasses); if (descriptors.size() == 1) { resolvedDirectives.put(importDirective, descriptors.iterator().next()); } } delayedImporter.processImports(); - if (firstPhase) { - continue; - } - for (JetImportDirective importDirective : importDirectives) { - reportUselessImport(importDirective, namespaceScope, resolvedDirectives); + if (!onlyClasses) { + for (JetImportDirective importDirective : importDirectives) { + reportUselessImport(importDirective, namespaceScope, resolvedDirectives); + } } } } - @Nullable - private static JetSimpleNameExpression getLastReference(@NotNull JetExpression importedReference) { - if (importedReference instanceof JetDotQualifiedExpression) { - JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference; - JetExpression selectorExpression = reference.getSelectorExpression(); - return (selectorExpression != null) ? (JetSimpleNameExpression) selectorExpression : null; - } - assert importedReference instanceof JetSimpleNameExpression; - return (JetSimpleNameExpression) importedReference; - } - - - @Nullable - private static String getAliasName(@NotNull JetImportDirective importDirective) { - String aliasName = importDirective.getAliasName(); - JetExpression importedReference = importDirective.getImportedReference(); - if (importedReference == null) { - return null; - } - JetSimpleNameExpression referenceExpression = getLastReference(importedReference); - if (aliasName == null) { - aliasName = referenceExpression != null ? referenceExpression.getReferencedName() : null; - } - return aliasName; - } - private void reportUselessImport(@NotNull JetImportDirective importDirective, @NotNull WritableScope namespaceScope, @NotNull Map resolvedDirectives) { @@ -144,7 +120,7 @@ public class ImportsResolver { if (importedReference == null || !resolvedDirectives.containsKey(importDirective)) { return; } - String aliasName = getAliasName(importDirective); + String aliasName = JetPsiUtil.getAliasName(importDirective); if (aliasName == null) { return; } @@ -163,353 +139,10 @@ public class ImportsResolver { if (isResolved != null && isResolved != wasResolved) { trace.report(USELESS_HIDDEN_IMPORT.on(importedReference)); } - if (!importDirective.isAllUnder() && importedReference instanceof JetSimpleNameExpression && importDirective.getAliasName() == null) { + if (!importDirective.isAllUnder() && + importedReference instanceof JetSimpleNameExpression && + importDirective.getAliasName() == null) { trace.report(USELESS_SIMPLE_IMPORT.on(importedReference)); } } - - public static Collection analyseImportReference( - @NotNull JetImportDirective importDirective, - @NotNull JetScope scope, @NotNull BindingTrace trace - ) { - ImportsResolver.SingleImportResolver importResolver = new ImportsResolver.SingleImportResolver(); - return importResolver.processImportReference(importDirective, scope, Importer.DO_NOTHING, trace, false); - } - - private static class SingleImportResolver { - @NotNull - 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(); - } - JetExpression importedReference = importDirective.getImportedReference(); - if (importedReference == null) { - return Collections.emptyList(); - } - - Collection descriptors; - if (importedReference instanceof JetQualifiedExpression) { - descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, scope, trace, firstPhase); - } - else { - assert importedReference instanceof JetSimpleNameExpression; - descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, scope, trace, firstPhase, true); - } - - JetSimpleNameExpression referenceExpression = getLastReference(importedReference); - if (importDirective.isAllUnder()) { - if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression, trace,firstPhase)) { - return Collections.emptyList(); - } - - for (DeclarationDescriptor descriptor : descriptors) { - importer.addAllUnderImport(descriptor); - } - return Collections.emptyList(); - } - - String aliasName = getAliasName(importDirective); - if (aliasName == null) { - return Collections.emptyList(); - } - - for (DeclarationDescriptor descriptor : descriptors) { - importer.addAliasImport(descriptor, aliasName); - } - - return descriptors; - } - - @NotNull - private Collection lookupDescriptorsForQualifiedExpression( - @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, trace, firstPhase); - } - else { - assert receiverExpression instanceof JetSimpleNameExpression; - declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, trace, firstPhase, true); - } - - JetExpression selectorExpression = importedReference.getSelectorExpression(); - - if (!(selectorExpression instanceof JetSimpleNameExpression)) return Collections.emptyList(); - - 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)); - } - } - } - if (results.isEmpty()) { - return Collections.emptyList(); - } - return filterAndStoreResolutionResult(results, selector, trace, firstPhase); - } - - 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, firstPhase); - } - TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace); - boolean canImport = false; - for (DeclarationDescriptor descriptor : descriptors) { - canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace, firstPhase); - } - if (!canImport) { - temporaryTrace.commit(); - } - return canImport; - } - - private boolean canImportMembersFrom(@NotNull DeclarationDescriptor descriptor, - @NotNull JetSimpleNameExpression reference, - @NotNull BindingTrace trace, - boolean firstPhase) { - assert !firstPhase; - if (descriptor instanceof NamespaceDescriptor) { - return true; - } - 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 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) { - //to store a scope where we tried to resolve this reference - return new SuccessfulLookupResult(Collections.emptyList(), outerScope, namespaceLevel); - } - - Set descriptors = Sets.newHashSet(); - NamespaceDescriptor namespaceDescriptor = outerScope.getNamespace(referencedName); - if (namespaceDescriptor != null) { - descriptors.add(namespaceDescriptor); - } - - ClassifierDescriptor classifierDescriptor = outerScope.getClassifier(referencedName); - if (classifierDescriptor != null) { - descriptors.add(classifierDescriptor); - } - - if (firstPhase) { - descriptors.add(outerScope.getObjectDescriptor(referencedName)); - } - else { - descriptors.addAll(outerScope.getFunctions(referencedName)); - descriptors.addAll(outerScope.getProperties(referencedName)); - - VariableDescriptor localVariable = outerScope.getLocalVariable(referencedName); - if (localVariable != null) { - descriptors.add(localVariable); - } - } - return new SuccessfulLookupResult(descriptors, outerScope, namespaceLevel); - } - - private Collection filterAndStoreResolutionResult( - @NotNull Collection lookupResults, - @NotNull JetSimpleNameExpression referenceExpression, - @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) || - (descriptor instanceof NamespaceDescriptor); - } - }); - } - 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()); - } - })); - } - 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; - } - - private void storeResolutionResult( - @NotNull Collection descriptors, - @NotNull Collection canBeImportedDescriptors, - @NotNull JetSimpleNameExpression referenceExpression, - @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, trace)) { - return; - } - - // Simple case of no descriptors - if (descriptors.isEmpty()) { - trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); - trace.report(UNRESOLVED_REFERENCE.on(referenceExpression)); - return; - } - - // Decide if expression has resolved reference - if (descriptors.size() == 1) { - assert canBeImportedDescriptors.size() <= 1; - trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next()); - trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); - } - else if (canBeImportedDescriptors.size() == 1) { - trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, canBeImportedDescriptors.iterator().next()); - trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); - } - - // Check for more information and additional errors - if (canBeImportedDescriptors.isEmpty()) { - assert descriptors.size() >= 1; - trace.report(CANNOT_BE_IMPORTED.on(referenceExpression, descriptors.iterator().next())); - } - else if (canBeImportedDescriptors.size() > 1) { - trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors); - } - } - - /** - * This method tries to resolve descriptors ambiguity between class descriptor and namespace descriptor for the same class. - * It's ok choose class for expression reference resolution. - * - * @return true if method has successfully resolved ambiguity - */ - private boolean resolveClassNamespaceAmbiguity(@NotNull Collection filteredDescriptors, - @NotNull JetSimpleNameExpression referenceExpression, - @NotNull JetScope resolutionScope, - @NotNull BindingTrace trace) { - - if (filteredDescriptors.size() == 2) { - NamespaceDescriptor namespaceDescriptor = null; - ClassDescriptor classDescriptor = null; - - for (DeclarationDescriptor filteredDescriptor : filteredDescriptors) { - if (filteredDescriptor instanceof NamespaceDescriptor) { - namespaceDescriptor = (NamespaceDescriptor) filteredDescriptor; - } - else if (filteredDescriptor instanceof ClassDescriptor) { - classDescriptor = (ClassDescriptor) filteredDescriptor; - } - } - - if (namespaceDescriptor != null && classDescriptor != null) { - if (DescriptorUtils.getFQName(namespaceDescriptor).equals(DescriptorUtils.getFQName(classDescriptor))) { - trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classDescriptor); - trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); - return true; - } - } - } - - 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/QualifiedExpressionResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java new file mode 100644 index 00000000000..25ce6c398f7 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/QualifiedExpressionResolver.java @@ -0,0 +1,428 @@ +/* + * 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; + +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.diagnostics.Errors; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import static org.jetbrains.jet.lang.diagnostics.Errors.*; + +/** + * @author svtk + */ +public class QualifiedExpressionResolver { + + @NotNull + public Collection analyseImportReference(@NotNull JetImportDirective importDirective, + @NotNull JetScope scope, + @NotNull BindingTrace trace) { + return processImportReference(importDirective, scope, Importer.DO_NOTHING, trace, false); + } + + @NotNull + public Collection processImportReference(@NotNull JetImportDirective importDirective, + @NotNull JetScope scope, + @NotNull Importer importer, + @NotNull BindingTrace trace, + boolean onlyClasses) { + if (importDirective.isAbsoluteInRootNamespace()) { + trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO + return Collections.emptyList(); + } + JetExpression importedReference = importDirective.getImportedReference(); + if (importedReference == null) { + return Collections.emptyList(); + } + + Collection descriptors; + if (importedReference instanceof JetQualifiedExpression) { + //store result only when we find all descriptors, not only classes on the second phase + descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression)importedReference, scope, trace, onlyClasses, !onlyClasses); + } + else { + assert importedReference instanceof JetSimpleNameExpression; + descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression)importedReference, scope, trace, onlyClasses, true, !onlyClasses); + } + + JetSimpleNameExpression referenceExpression = JetPsiUtil.getLastReference(importedReference); + if (importDirective.isAllUnder()) { + if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression, trace, onlyClasses)) { + return Collections.emptyList(); + } + + for (DeclarationDescriptor descriptor : descriptors) { + importer.addAllUnderImport(descriptor); + } + return Collections.emptyList(); + } + + String aliasName = JetPsiUtil.getAliasName(importDirective); + if (aliasName == null) { + return Collections.emptyList(); + } + + for (DeclarationDescriptor descriptor : descriptors) { + importer.addAliasImport(descriptor, aliasName); + } + + return descriptors; + } + + private boolean canImportMembersFrom(@NotNull Collection descriptors, + @NotNull JetSimpleNameExpression reference, + @NotNull BindingTrace trace, + boolean onlyClasses) { + if (onlyClasses) { + return true; + } + if (descriptors.size() == 1) { + return canImportMembersFrom(descriptors.iterator().next(), reference, trace, onlyClasses); + } + TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace); + boolean canImport = false; + for (DeclarationDescriptor descriptor : descriptors) { + canImport |= canImportMembersFrom(descriptor, reference, temporaryTrace, onlyClasses); + } + if (!canImport) { + temporaryTrace.commit(); + } + return canImport; + } + + private boolean canImportMembersFrom(@NotNull DeclarationDescriptor descriptor, + @NotNull JetSimpleNameExpression reference, + @NotNull BindingTrace trace, + boolean onlyClasses) { + assert !onlyClasses; + if (descriptor instanceof NamespaceDescriptor) { + return true; + } + if (descriptor instanceof ClassDescriptor && ((ClassDescriptor)descriptor).getKind() != ClassKind.OBJECT) { + return true; + } + trace.report(CANNOT_IMPORT_FROM_ELEMENT.on(reference, descriptor)); + return false; + } + + @NotNull + public Collection lookupDescriptorsForUserType(@NotNull JetUserType userType, + @NotNull JetScope outerScope, + @NotNull BindingTrace trace) { + if (userType.isAbsoluteInRootNamespace()) { + trace.report(Errors.UNSUPPORTED.on(userType, "package")); + return Collections.emptyList(); + } + JetSimpleNameExpression referenceExpression = userType.getReferenceExpression(); + if (referenceExpression == null) { + return Collections.emptyList(); + } + JetUserType qualifier = userType.getQualifier(); + if (qualifier == null) { + return lookupDescriptorsForSimpleNameReference(referenceExpression, outerScope, trace, true, false, true); + } + Collection declarationDescriptors = lookupDescriptorsForUserType(qualifier, outerScope, trace); + return lookupSelectorDescriptors(referenceExpression, declarationDescriptors, trace, true, true); + } + + @NotNull + public Collection lookupDescriptorsForQualifiedExpression(@NotNull JetQualifiedExpression importedReference, + @NotNull JetScope outerScope, + @NotNull BindingTrace trace, + boolean onlyClasses, + boolean storeResult) { + JetExpression receiverExpression = importedReference.getReceiverExpression(); + Collection declarationDescriptors; + if (receiverExpression instanceof JetQualifiedExpression) { + declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression)receiverExpression, outerScope, trace, onlyClasses, storeResult); + } + else { + assert receiverExpression instanceof JetSimpleNameExpression; + declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression)receiverExpression, outerScope, trace, onlyClasses, true, storeResult); + } + + JetExpression selectorExpression = importedReference.getSelectorExpression(); + if (!(selectorExpression instanceof JetSimpleNameExpression)) { + return Collections.emptyList(); + } + + JetSimpleNameExpression selector = (JetSimpleNameExpression)selectorExpression; + JetSimpleNameExpression lastReference = JetPsiUtil.getLastReference(receiverExpression); + if (lastReference == null || !canImportMembersFrom(declarationDescriptors, lastReference, trace, onlyClasses)) { + return Collections.emptyList(); + } + + return lookupSelectorDescriptors(selector, declarationDescriptors, trace, onlyClasses, storeResult); + } + + @NotNull + private Collection lookupSelectorDescriptors(@NotNull JetSimpleNameExpression selector, + @NotNull Collection declarationDescriptors, + @NotNull BindingTrace trace, + boolean onlyClasses, + boolean storeResult) { + Set results = Sets.newHashSet(); + for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { + if (declarationDescriptor instanceof NamespaceDescriptor) { + addResult(results, lookupSimpleNameReference(selector, ((NamespaceDescriptor)declarationDescriptor).getMemberScope(), onlyClasses, true)); + } + if (declarationDescriptor instanceof ClassDescriptor) { + addResult(results, lookupSimpleNameReference(selector, getAppropriateScope((ClassDescriptor)declarationDescriptor, onlyClasses), onlyClasses, false)); + ClassDescriptor classObjectDescriptor = ((ClassDescriptor)declarationDescriptor).getClassObjectDescriptor(); + if (classObjectDescriptor != null) { + addResult(results, lookupSimpleNameReference(selector, getAppropriateScope(classObjectDescriptor, onlyClasses), onlyClasses, false)); + } + } + } + return filterAndStoreResolutionResult(results, selector, trace, onlyClasses, storeResult); + } + + @NotNull + private JetScope getAppropriateScope(@NotNull ClassDescriptor classDescriptor, boolean onlyClasses) { + return onlyClasses ? classDescriptor.getUnsubstitutedInnerClassesScope() : classDescriptor.getDefaultType().getMemberScope(); + } + + private void addResult(@NotNull Set results, @NotNull LookupResult result) { + if (result == LookupResult.EMPTY) return; + results.add((SuccessfulLookupResult)result); + } + + + @NotNull + public Collection lookupDescriptorsForSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression, + @NotNull JetScope outerScope, + @NotNull BindingTrace trace, + boolean onlyClasses, + boolean namespaceLevel, + boolean storeResult) { + LookupResult lookupResult = lookupSimpleNameReference(referenceExpression, outerScope, onlyClasses, namespaceLevel); + if (lookupResult == LookupResult.EMPTY) return Collections.emptyList(); + return filterAndStoreResolutionResult(Collections.singletonList((SuccessfulLookupResult)lookupResult), referenceExpression, trace, + onlyClasses, storeResult); + } + + @NotNull + private LookupResult lookupSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression, + @NotNull JetScope outerScope, + boolean onlyClasses, + boolean namespaceLevel) { + + String referencedName = referenceExpression.getReferencedName(); + if (referencedName == null) { + //to store a scope where we tried to resolve this reference + return new SuccessfulLookupResult(Collections.emptyList(), outerScope, namespaceLevel); + } + + Set descriptors = Sets.newHashSet(); + NamespaceDescriptor namespaceDescriptor = outerScope.getNamespace(referencedName); + if (namespaceDescriptor != null) { + descriptors.add(namespaceDescriptor); + } + + ClassifierDescriptor classifierDescriptor = outerScope.getClassifier(referencedName); + if (classifierDescriptor != null) { + descriptors.add(classifierDescriptor); + } + + if (onlyClasses) { + ClassDescriptor objectDescriptor = outerScope.getObjectDescriptor(referencedName); + if (objectDescriptor != null) { + descriptors.add(objectDescriptor); + } + } + else { + descriptors.addAll(outerScope.getFunctions(referencedName)); + descriptors.addAll(outerScope.getProperties(referencedName)); + + VariableDescriptor localVariable = outerScope.getLocalVariable(referencedName); + if (localVariable != null) { + descriptors.add(localVariable); + } + } + return new SuccessfulLookupResult(descriptors, outerScope, namespaceLevel); + } + + @NotNull + private Collection filterAndStoreResolutionResult(@NotNull Collection lookupResults, + @NotNull JetSimpleNameExpression referenceExpression, + @NotNull BindingTrace trace, + boolean onlyClasses, + boolean storeResult) { + if (lookupResults.isEmpty()) { + return Collections.emptyList(); + } + Collection descriptors = Sets.newLinkedHashSet(); + for (SuccessfulLookupResult lookupResult : lookupResults) { + descriptors.addAll(lookupResult.descriptors); + } + + 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); + } + } + + Collection filteredDescriptors; + if (onlyClasses) { + filteredDescriptors = Collections2.filter(descriptors, new Predicate() { + @Override + public boolean apply(@Nullable DeclarationDescriptor descriptor) { + return (descriptor instanceof ClassifierDescriptor) || + (descriptor instanceof NamespaceDescriptor); + } + }); + } + else { + filteredDescriptors = Sets.newLinkedHashSet(); + //functions and properties can be imported if lookupResult.namespaceLevel == true + 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 ClassifierDescriptor) || + (descriptor instanceof VariableDescriptor && ((VariableDescriptor)descriptor).isObjectDeclaration()); + } + })); + } + } + if (storeResult) { + storeResolutionResult(descriptors, filteredDescriptors, referenceExpression, possibleResolutionScopes, trace); + } + return filteredDescriptors; + } + + private void storeResolutionResult(@NotNull Collection descriptors, + @NotNull Collection canBeImportedDescriptors, + @NotNull JetSimpleNameExpression referenceExpression, + @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, trace)) { + return; + } + + // Simple case of no descriptors + if (descriptors.isEmpty()) { + trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); + trace.report(UNRESOLVED_REFERENCE.on(referenceExpression)); + return; + } + + // Decide if expression has resolved reference + if (descriptors.size() == 1) { + assert canBeImportedDescriptors.size() <= 1; + trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next()); + trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); + } + else if (canBeImportedDescriptors.size() == 1) { + trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, canBeImportedDescriptors.iterator().next()); + trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); + } + + // Check for more information and additional errors + if (canBeImportedDescriptors.isEmpty()) { + assert descriptors.size() >= 1; + trace.report(CANNOT_BE_IMPORTED.on(referenceExpression, descriptors.iterator().next())); + } + else if (canBeImportedDescriptors.size() > 1) { + trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors); + } + } + + /** + * This method tries to resolve descriptors ambiguity between class descriptor and namespace descriptor for the same class. + * It's ok choose class for expression reference resolution. + * + * @return true if method has successfully resolved ambiguity + */ + private boolean resolveClassNamespaceAmbiguity(@NotNull Collection filteredDescriptors, + @NotNull JetSimpleNameExpression referenceExpression, + @NotNull JetScope resolutionScope, + @NotNull BindingTrace trace) { + + if (filteredDescriptors.size() == 2) { + NamespaceDescriptor namespaceDescriptor = null; + ClassDescriptor classDescriptor = null; + + for (DeclarationDescriptor filteredDescriptor : filteredDescriptors) { + if (filteredDescriptor instanceof NamespaceDescriptor) { + namespaceDescriptor = (NamespaceDescriptor)filteredDescriptor; + } + else if (filteredDescriptor instanceof ClassDescriptor) { + classDescriptor = (ClassDescriptor)filteredDescriptor; + } + } + + if (namespaceDescriptor != null && classDescriptor != null) { + if (DescriptorUtils.getFQName(namespaceDescriptor).equals(DescriptorUtils.getFQName(classDescriptor))) { + trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classDescriptor); + trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); + return true; + } + } + } + + 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; + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 2ba8a78f746..b98d0492e12 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -18,10 +18,7 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; -import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -32,11 +29,11 @@ import org.jetbrains.jet.util.lazy.LazyValue; import javax.inject.Inject; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import static org.jetbrains.jet.lang.diagnostics.Errors.*; -import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; /** * @author abreslav @@ -45,6 +42,7 @@ public class TypeResolver { private AnnotationResolver annotationResolver; private DescriptorResolver descriptorResolver; + private QualifiedExpressionResolver qualifiedExpressionResolver; @Inject public void setDescriptorResolver(DescriptorResolver descriptorResolver) { @@ -56,6 +54,11 @@ public class TypeResolver { this.annotationResolver = annotationResolver; } + @Inject + public void setQualifiedExpressionResolver(QualifiedExpressionResolver qualifiedExpressionResolver) { + this.qualifiedExpressionResolver = qualifiedExpressionResolver; + } + @NotNull public JetType resolveType(@NotNull final JetScope scope, @NotNull final JetTypeReference typeReference, BindingTrace trace, boolean checkBounds) { JetType cachedType = trace.getBindingContext().get(BindingContext.TYPE, typeReference); @@ -267,90 +270,13 @@ public class TypeResolver { @Nullable public ClassifierDescriptor resolveClass(JetScope scope, JetUserType userType, BindingTrace trace) { - ClassifierDescriptor classifierDescriptor = resolveClassWithoutErrorReporting(scope, userType, trace); - - if (classifierDescriptor == null) { - trace.report(UNRESOLVED_REFERENCE.on(userType.getReferenceExpression())); - } - else { - trace.record(REFERENCE_TARGET, userType.getReferenceExpression(), classifierDescriptor); - } - - return classifierDescriptor; - } - - @Nullable - private ClassifierDescriptor resolveClassWithoutErrorReporting(JetScope scope, JetUserType userType, BindingTrace trace) { - JetSimpleNameExpression expression = userType.getReferenceExpression(); - if (expression == null) { - return null; - } - String referencedName = expression.getReferencedName(); - if (referencedName == null) { - return null; - } - ClassifierDescriptor classifierDescriptor; - if (userType.isAbsoluteInRootNamespace()) { - classifierDescriptor = JetModuleUtil.getRootNamespaceType(userType).getMemberScope().getClassifier(referencedName); - trace.record(BindingContext.RESOLUTION_SCOPE, userType.getReferenceExpression(), - JetModuleUtil.getRootNamespaceType(userType).getMemberScope()); - } - else { - JetUserType qualifier = userType.getQualifier(); - if (qualifier != null) { - scope = resolveClassLookupScope(scope, qualifier, trace); - } - if (scope == null) { - return ErrorUtils.getErrorClass(); - } - classifierDescriptor = scope.getClassifier(referencedName); - trace.record(BindingContext.RESOLUTION_SCOPE, userType.getReferenceExpression(), scope); - } - - return classifierDescriptor; - } - - @Nullable - private JetScope resolveClassLookupScope(JetScope scope, JetUserType userType, BindingTrace trace) { - ClassifierDescriptor classifierDescriptor = resolveClassWithoutErrorReporting(scope, userType, trace); - if (classifierDescriptor instanceof ClassDescriptor) { - ClassDescriptor classDescriptor = (ClassDescriptor) classifierDescriptor; - JetType classObjectType = classDescriptor.getClassObjectType(); - if (classObjectType != null) { - return classObjectType.getMemberScope(); + Collection descriptors = qualifiedExpressionResolver + .lookupDescriptorsForUserType(userType, scope, trace); + for (DeclarationDescriptor descriptor : descriptors) { + if (descriptor instanceof ClassifierDescriptor) { + return (ClassifierDescriptor) descriptor; } } - - NamespaceDescriptor namespaceDescriptor = resolveNamespace(scope, userType, trace); - if (namespaceDescriptor == null) { - trace.report(UNRESOLVED_REFERENCE.on(userType.getReferenceExpression())); - return null; - } - return namespaceDescriptor.getMemberScope(); + return null; } - - @Nullable - private NamespaceDescriptor resolveNamespace(JetScope scope, JetUserType userType, BindingTrace trace) { - if (userType.isAbsoluteInRootNamespace()) { - return resolveNamespace(JetModuleUtil.getRootNamespaceType(userType).getMemberScope(), userType, trace); - } - - JetUserType qualifier = userType.getQualifier(); - NamespaceDescriptor namespace; - if (qualifier != null) { - NamespaceDescriptor domain = resolveNamespace(scope, qualifier, trace); - if (domain == null) { - return null; - } - namespace = domain.getMemberScope().getNamespace(userType.getReferencedName()); - } - else { - namespace = scope.getNamespace(userType.getReferencedName()); - } - if (namespace != null) { - trace.record(BindingContext.REFERENCE_TARGET, userType.getReferenceExpression(), namespace); - } - return namespace; - } - } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index c1d61912810..7839f8ff859 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -183,7 +183,7 @@ public class ExpressionTypingUtils { JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, callableFQN.getFqName()); - Collection declarationDescriptors = ImportsResolver.analyseImportReference(importDirective, scope, new BindingTraceContext()); + Collection declarationDescriptors = new QualifiedExpressionResolver().analyseImportReference(importDirective, scope, new BindingTraceContext()); List callableExtensionDescriptors = new ArrayList(); ReceiverDescriptor receiverDescriptor = new ExpressionReceiver(receiverExpression, receiverType); diff --git a/compiler/testData/diagnostics/tests/ShiftFunctionTypes.jet b/compiler/testData/diagnostics/tests/ShiftFunctionTypes.jet index 346943c5f13..0337823529e 100644 --- a/compiler/testData/diagnostics/tests/ShiftFunctionTypes.jet +++ b/compiler/testData/diagnostics/tests/ShiftFunctionTypes.jet @@ -8,7 +8,7 @@ package n // FILE: f.kt abstract class XXX() { abstract val a : Int - abstract val a1 : package.Int + abstract val a1 : package.Int abstract val a2 : n.B abstract val a3 : (A) abstract val a31 : (n.B) @@ -50,4 +50,4 @@ abstract class YYY() { abstract val a17 : ((a : Int) -> Int).(a : Int) -> Int abstract val a18 : (a : Int) -> ((a : Int) -> Int) abstract val a19 : (b : (a : Int) -> Int) -> Int -} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/ImportFromCurrentWithDifferentName.jet b/compiler/testData/diagnostics/tests/scopes/ImportFromCurrentWithDifferentName.jet index 31fac95ce4c..d531078860e 100644 --- a/compiler/testData/diagnostics/tests/scopes/ImportFromCurrentWithDifferentName.jet +++ b/compiler/testData/diagnostics/tests/scopes/ImportFromCurrentWithDifferentName.jet @@ -1,5 +1,5 @@ package a -import A as ER +import a.A as ER class A() diff --git a/compiler/testData/diagnostics/tests/scopes/Imports.jet b/compiler/testData/diagnostics/tests/scopes/Imports.jet index 192c751f12f..5ef08d7bb8f 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.C.* object C { fun f() { @@ -85,8 +85,8 @@ fun foo() { //FILE:d.kt package d -import A.B -import A.C +import d.A.B +import d.A.C val b : B = B() val c : B = C diff --git a/compiler/testData/diagnostics/tests/scopes/ImportsUselessSimpleImport.jet b/compiler/testData/diagnostics/tests/scopes/ImportsUselessSimpleImport.jet index e0457aed5cb..3d3ca073d89 100644 --- a/compiler/testData/diagnostics/tests/scopes/ImportsUselessSimpleImport.jet +++ b/compiler/testData/diagnostics/tests/scopes/ImportsUselessSimpleImport.jet @@ -1,5 +1,5 @@ package a -import B +import a object B {} diff --git a/compiler/testData/diagnostics/tests/scopes/kt1579.jet b/compiler/testData/diagnostics/tests/scopes/kt1579.jet index f5ca40c278a..f85aa639504 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt1579.jet +++ b/compiler/testData/diagnostics/tests/scopes/kt1579.jet @@ -1,3 +1,4 @@ +//KT-1579 Can't import nested class/trait //FILE:a.kt package lib trait WithInner { diff --git a/compiler/testData/diagnostics/tests/scopes/kt1579_map_entry.jet b/compiler/testData/diagnostics/tests/scopes/kt1579_map_entry.jet index 50e727fa6c0..4632e875dee 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt1579_map_entry.jet +++ b/compiler/testData/diagnostics/tests/scopes/kt1579_map_entry.jet @@ -4,9 +4,17 @@ 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 + +//FILE:c.kt +//+JDK +package c + +import java.util.Map +fun fff(b: Map.Entry) = b \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/kt900-1.jet b/compiler/testData/diagnostics/tests/scopes/kt900-1.jet index 4ed42574658..abd2dab3cd9 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt900-1.jet +++ b/compiler/testData/diagnostics/tests/scopes/kt900-1.jet @@ -1,8 +1,8 @@ // import all members from class object package c -import A.* -import M.* +import c.A.* +import c.M.* fun foo() { val b: B = B() diff --git a/compiler/testData/diagnostics/tests/scopes/kt900-2.jet b/compiler/testData/diagnostics/tests/scopes/kt900-2.jet index 12f3aa2afcf..ae879a33cc0 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt900-2.jet +++ b/compiler/testData/diagnostics/tests/scopes/kt900-2.jet @@ -2,11 +2,11 @@ package d //import from objects before properties resolve -import A.* -import M.R -import M.R.bar -import M.T -import M.Y +import d.A.* +import d.M.R +import d.M.R.bar +import d.M.T +import d.M.Y var r: T = T() val y: T = Y diff --git a/compiler/testData/diagnostics/tests/scopes/kt900.jet b/compiler/testData/diagnostics/tests/scopes/kt900.jet index f9461d0ff6f..79f5364bc5e 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt900.jet +++ b/compiler/testData/diagnostics/tests/scopes/kt900.jet @@ -35,8 +35,8 @@ object N { //FILE:b.kt package b -import N.M -import A.P +import b.N.M +import b.A.P import b.A.B fun foo() { diff --git a/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java b/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java index 04ba86fcf75..82aa49eedde 100644 --- a/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java +++ b/compiler/tests/org/jetbrains/jet/di/InjectorForTests.java @@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; import com.intellij.openapi.project.Project; import org.jetbrains.jet.lang.resolve.AnnotationResolver; +import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver; import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; @@ -48,6 +49,7 @@ public class InjectorForTests { this.jetStandardLibrary = JetStandardLibrary.getInstance(); this.project = project; AnnotationResolver annotationResolver = new AnnotationResolver(); + QualifiedExpressionResolver qualifiedExpressionResolver = new QualifiedExpressionResolver(); OverloadingConflictResolver overloadingConflictResolver = new OverloadingConflictResolver(); this.descriptorResolver.setAnnotationResolver(annotationResolver); @@ -61,6 +63,7 @@ public class InjectorForTests { this.typeResolver.setAnnotationResolver(annotationResolver); this.typeResolver.setDescriptorResolver(descriptorResolver); + this.typeResolver.setQualifiedExpressionResolver(qualifiedExpressionResolver); this.callResolver.setDescriptorResolver(descriptorResolver); this.callResolver.setExpressionTypingServices(expressionTypingServices); diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java index 0f73ae28653..ae82d8af193 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java @@ -175,7 +175,7 @@ public class JetShortNamesCache extends PsiShortNamesCache { FqName functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(method); if (functionFQN != null) { JetImportDirective importDirective = JetPsiFactory.createImportDirective(project, new ImportPath(functionFQN, false)); - Collection declarationDescriptors = ImportsResolver.analyseImportReference(importDirective, jetScope, new BindingTraceContext()); + Collection declarationDescriptors = new QualifiedExpressionResolver().analyseImportReference(importDirective, jetScope, new BindingTraceContext()); for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { if (declarationDescriptor instanceof FunctionDescriptor) { result.add((FunctionDescriptor) declarationDescriptor); diff --git a/idea/testData/checker/ResolveToJava.jet b/idea/testData/checker/ResolveToJava.jet index 3f880191b70..25910cc8caa 100644 --- a/idea/testData/checker/ResolveToJava.jet +++ b/idea/testData/checker/ResolveToJava.jet @@ -12,7 +12,7 @@ fun test(l : java.util.List) { val y : java.util.List val b : java.lang.Object val a : util.List - val z : java.utils.List + val z : java.utils.List val f : java.io.File? = null diff --git a/idea/testData/completion/basic/InEmptyImport.kt b/idea/testData/completion/basic/InEmptyImport.kt index 3d140369fed..258a362f416 100644 --- a/idea/testData/completion/basic/InEmptyImport.kt +++ b/idea/testData/completion/basic/InEmptyImport.kt @@ -2,5 +2,5 @@ package Test import -// EXIST: java, javax, reflect +// EXIST: java, javax // ABSENT: Array, Integer \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java b/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java index 11eebf75275..4b21adffec3 100644 --- a/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java +++ b/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java @@ -135,8 +135,7 @@ public final class AnalyzerFacadeForJS { } @Override - public void addDefaultImports(@NotNull WritableScope rootScope, - @NotNull Collection directives) { + public void addDefaultImports(@NotNull Collection directives) { directives.add(JetPsiFactory.createImportDirective(project, new ImportPath("js.*"))); directives.add(JetPsiFactory.createImportDirective(project, new ImportPath(JetStandardClasses.STANDARD_CLASSES_FQNAME, true))); }