From 257b8f31e7fc8049c7575c78117ba52c4166bfe8 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Wed, 13 May 2015 21:21:40 +0300 Subject: [PATCH] Change import resolution algorithm The new algorithm: move from right to left, trying to find package, (new code) when found go right resolving descriptors (uses old code) This allows to avoid unnecessary computations (matters in IDE moslty) for resolving root packages This changes semantics of imports resolution: when package clashes with any declaration package is preffered --- .../resolve/ImportDirectiveProcessor.kt | 106 +++++++++++++++--- .../resolve/QualifiedExpressionResolver.java | 2 +- 2 files changed, 89 insertions(+), 19 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ImportDirectiveProcessor.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ImportDirectiveProcessor.kt index 4bb150ae26e..0d9d0052ab5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ImportDirectiveProcessor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ImportDirectiveProcessor.kt @@ -21,11 +21,10 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageViewDescriptor import org.jetbrains.kotlin.diagnostics.Errors -import org.jetbrains.kotlin.psi.JetImportDirective -import org.jetbrains.kotlin.psi.JetPsiUtil -import org.jetbrains.kotlin.psi.JetQualifiedExpression -import org.jetbrains.kotlin.psi.JetSimpleNameExpression +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.scopes.JetScope +import java.util.ArrayList import kotlin.platform.platformStatic public class ImportDirectiveProcessor( @@ -44,20 +43,11 @@ public class ImportDirectiveProcessor( } val importedReference = importDirective.getImportedReference() ?: return JetScope.Empty - - val scope = JetModuleUtil.getImportsResolutionScope(moduleDescriptor, allowClassesFromDefaultPackage) - val descriptors = if (importedReference is JetQualifiedExpression) { - //store result only when we find all descriptors, not only classes on the second phase - qualifiedExpressionResolver.lookupDescriptorsForQualifiedExpression( - importedReference, scope, moduleDescriptor, trace, lookupMode, lookupMode.isEverything() - ) - } - else { - assert(importedReference is JetSimpleNameExpression) - qualifiedExpressionResolver.lookupDescriptorsForSimpleNameReference( - importedReference as JetSimpleNameExpression, scope, moduleDescriptor, trace, lookupMode, true, lookupMode.isEverything() - ) - } + val importPath = importDirective.getImportPath() ?: return JetScope.Empty + val (packageViewDescriptor, selectorsToLookUp) = tryResolvePackagesFromRightToLeft( + moduleDescriptor, trace, importPath.fqnPart(), importedReference + ) + val descriptors = lookUpMembersFromLeftToRight(moduleDescriptor, trace, packageViewDescriptor, selectorsToLookUp, lookupMode) val referenceExpression = JetPsiUtil.getLastReference(importedReference) if (importDirective.isAllUnder()) { @@ -82,6 +72,86 @@ public class ImportDirectiveProcessor( } } + private fun tryResolvePackagesFromRightToLeft( + moduleDescriptor: ModuleDescriptor, + trace: BindingTrace, + fqName: FqName, + jetExpression: JetExpression? + ): Pair> { + val selectorsToLookUp = ArrayList() + + fun recTryResolvePackagesFromRightToLeft( + fqName: FqName, + jetExpression: JetExpression? + ): PackageViewDescriptor { + val packageView = moduleDescriptor.getPackage(fqName) + if (jetExpression == null) { + assert(fqName.isRoot()) + return packageView.sure { "Root package does not exist in module $moduleDescriptor" } + } + return when { + packageView != null -> { + recordPackageViews(jetExpression, packageView, trace) + packageView + } + else -> { + assert(!fqName.isRoot()) + val (expressionRest, selector) = jetExpression.getReceiverAndSelector() + if (selector != null) { + selectorsToLookUp.add(selector) + } + recTryResolvePackagesFromRightToLeft(fqName.parent(), expressionRest) + } + } + } + + val packageView = recTryResolvePackagesFromRightToLeft(fqName, jetExpression) + return Pair(packageView, selectorsToLookUp.reverse()) + } + + private fun recordPackageViews(jetExpression: JetExpression, packageView: PackageViewDescriptor, trace: BindingTrace) { + trace.record(BindingContext.REFERENCE_TARGET, JetPsiUtil.getLastReference(jetExpression), packageView) + val containingView = packageView.getContainingDeclaration() + val (receiver, _) = jetExpression.getReceiverAndSelector() + if (containingView != null && receiver != null) { + recordPackageViews(receiver, containingView, trace) + } + } + + private fun lookUpMembersFromLeftToRight( + moduleDescriptor: ModuleDescriptor, + trace: BindingTrace, + packageView: PackageViewDescriptor, + selectorsToLookUp: List, + lookupMode: QualifiedExpressionResolver.LookupMode + ): Collection { + var currentDescriptors: Collection = listOf(packageView) + for ((i, selector) in selectorsToLookUp.withIndex()) { + currentDescriptors = qualifiedExpressionResolver.lookupSelectorDescriptors( + selector, currentDescriptors, trace, moduleDescriptor, lookupMode, lookupMode.isEverything() + ) + val isLastReference = i == selectorsToLookUp.size() - 1 + if (!isLastReference && !canImportMembersFrom(currentDescriptors, selector, trace, lookupMode)) { + return emptyList() + } + } + return currentDescriptors + } + + private fun JetExpression.getReceiverAndSelector(): Pair { + when (this) { + is JetDotQualifiedExpression -> { + return Pair(this.getReceiverExpression(), this.getSelectorExpression() as? JetSimpleNameExpression) + } + is JetSimpleNameExpression -> { + return Pair(null, this) + } + else -> { + throw AssertionError("Invalid expression in import $this of class ${this.javaClass}") + } + } + } + public companion object { public fun canAllUnderImportFrom(descriptors: Collection): Boolean { if (descriptors.isEmpty()) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.java index 0fb4317ef69..1719ac39464 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.java @@ -171,7 +171,7 @@ public class QualifiedExpressionResolver { } @NotNull - private Collection lookupSelectorDescriptors( + public Collection lookupSelectorDescriptors( @NotNull JetSimpleNameExpression selector, @NotNull Collection declarationDescriptors, @NotNull BindingTrace trace,