diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/CallableDescriptorCollectors.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/CallableDescriptorCollectors.kt index b7598d8d41e..fdc51f440b5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/CallableDescriptorCollectors.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/CallableDescriptorCollectors.kt @@ -27,6 +27,9 @@ import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.descriptorUtil.hasClassObjectType import org.jetbrains.kotlin.resolve.scopes.JetScope +import org.jetbrains.kotlin.resolve.scopes.LexicalScope +import org.jetbrains.kotlin.resolve.scopes.utils.collectAllFromMeAndParent +import org.jetbrains.kotlin.resolve.scopes.utils.getLocalVariable import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.types.expressions.OperatorConventions @@ -34,6 +37,8 @@ import org.jetbrains.kotlin.utils.singletonOrEmptyList public interface CallableDescriptorCollector { + public fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection + public fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection public fun getMembersByName(receiver: JetType, name: Name, location: LookupLocation): Collection @@ -71,6 +76,17 @@ public fun CallableDescriptorCollectors.filtered(fil CallableDescriptorCollectors(this.collectors.map { it.filtered(filter) }) private object FunctionCollector : CallableDescriptorCollector { + override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection { + return lexicalScope.collectAllFromMeAndParent { + if (it.ownerDescriptor is FunctionDescriptor) { + it.getDeclaredFunctions(name, location).filter { it.extensionReceiverParameter == null } + + getConstructors(it.getDeclaredClassifier(name, location)) + } + else { + emptyList() + } + } + } override fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection { return scope.getFunctions(name, location).filter { it.extensionReceiverParameter == null } + getConstructors(scope, name, location) @@ -117,6 +133,13 @@ private object FunctionCollector : CallableDescriptorCollector Boolean = { true } ): Collection { val classifier = scope.getClassifier(name, location) + return getConstructors(classifier, filterClassPredicate) + } + + private fun getConstructors( + classifier: ClassifierDescriptor?, + filterClassPredicate: (ClassDescriptor) -> Boolean = { true } + ): Collection { if (classifier !is ClassDescriptor || ErrorUtils.isError(classifier) || !filterClassPredicate(classifier) // Constructors of singletons shouldn't be callable from the code || classifier.kind.isSingleton) { @@ -129,6 +152,9 @@ private object FunctionCollector : CallableDescriptorCollector { + override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection { + return listOfNotNull(lexicalScope.getLocalVariable(name)) + } private fun getFakeDescriptorForObject(scope: JetScope, name: Name, location: LookupLocation): VariableDescriptor? { val classifier = scope.getClassifier(name, location) @@ -172,6 +198,10 @@ private object PropertyCollector : CallableDescriptorCollector) = variableDescriptors.filter { it is PropertyDescriptor } + override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection { + return filterProperties(VARIABLES_COLLECTOR.getLocalNonExtensionsByName(lexicalScope, name, location)) + } + override fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection { return filterProperties(VARIABLES_COLLECTOR.getNonExtensionsByName(scope, name, location)) } @@ -194,6 +224,10 @@ private object PropertyCollector : CallableDescriptorCollector CallableDescriptorCollector.filtered(filter: (D) -> Boolean): CallableDescriptorCollector { val delegate = this return object : CallableDescriptorCollector { + override fun getLocalNonExtensionsByName(lexicalScope: LexicalScope, name: Name, location: LookupLocation): Collection { + return delegate.getLocalNonExtensionsByName(lexicalScope, name, location).filter(filter) + } + override fun getNonExtensionsByName(scope: JetScope, name: Name, location: LookupLocation): Collection { return delegate.getNonExtensionsByName(scope, name, location).filter(filter) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/ResolutionTaskHolder.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/ResolutionTaskHolder.kt index 70e23a65651..455cad9d89a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/ResolutionTaskHolder.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/ResolutionTaskHolder.kt @@ -37,15 +37,6 @@ public class ResolutionTaskHolder( candidatesList.add(storageManager.createLazyValue { lazyCandidates().toReadOnlyList() }) } - public fun addCandidates(candidatesList: List>>) { - assertNotFinished() - for (candidates in candidatesList) { - if (candidates.isNotEmpty()) { - addCandidates { candidates } - } - } - } - private fun assertNotFinished() { assert(internalTasks == null, "Can't add candidates after the resulting tasks were computed.") } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TaskPrioritizer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TaskPrioritizer.kt index e396eb686cc..48b91512940 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TaskPrioritizer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TaskPrioritizer.kt @@ -56,22 +56,6 @@ public class TaskPrioritizer( private val smartCastManager: SmartCastManager ) { - public fun splitLexicallyLocalDescriptors( - allDescriptors: Collection>, - containerOfTheCurrentLocality: DeclarationDescriptor, - local: MutableCollection>, - nonlocal: MutableCollection> - ) { - for (resolvedCall in allDescriptors) { - if (ExpressionTypingUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) { - local.add(resolvedCall) - } - else { - nonlocal.add(resolvedCall) - } - } - } - public fun computePrioritizedTasks( context: BasicCallResolutionContext, name: Name, @@ -264,28 +248,18 @@ public class TaskPrioritizer( implicitReceivers: Collection, c: TaskPrioritizerContext ) { - val localsList = Lists.newArrayList>>() - val nonlocalsList = Lists.newArrayList>>() - for (callableDescriptorCollector in c.callableDescriptorCollectors) { - - val members = convertWithImpliedThisAndNoReceiver( - c.scope, - callableDescriptorCollector.getNonExtensionsByName(c.scope.asJetScope(), c.name, createLookupLocation(c)), - c.context.call - ) - - if (members.isNotEmpty()) { - val nonlocals = Lists.newArrayList>() - val locals = Lists.newArrayList>() - splitLexicallyLocalDescriptors(members, c.scope.ownerDescriptor, locals, nonlocals) - - localsList.add(locals) - nonlocalsList.add(nonlocals) - } - } + val lookupLocation = createLookupLocation(c) //locals - c.result.addCandidates(localsList) + c.callableDescriptorCollectors.forEach { + c.result.addCandidates { + convertWithImpliedThisAndNoReceiver( + c.scope, + it.getLocalNonExtensionsByName(c.scope, c.name, lookupLocation), + c.context.call + ) + } + } val implicitReceiversWithTypes = implicitReceivers.map { ReceiverWithTypes(it, c.context) } @@ -295,7 +269,13 @@ public class TaskPrioritizer( } //nonlocals - c.result.addCandidates(nonlocalsList) + c.callableDescriptorCollectors.forEach { + c.result.addCandidates { + val descriptors = it.getNonExtensionsByName(c.scope.asJetScope(), c.name, lookupLocation) + .filter { !ExpressionTypingUtils.isLocal(c.scope.ownerDescriptor, it) } + convertWithImpliedThisAndNoReceiver(c.scope, descriptors, c.context.call) + } + } //static (only for better error reporting) for (implicitReceiver in implicitReceiversWithTypes) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt index 6f53e0516e2..9950290a265 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/utils/ScopeUtils.kt @@ -266,7 +266,7 @@ private inline fun LexicalScope.collectFromMeAndParent( return result ?: emptyList() } -private inline fun LexicalScope.collectAllFromMeAndParent( +internal inline fun LexicalScope.collectAllFromMeAndParent( collect: (LexicalScope) -> Collection ): Collection { var result: Collection? = null diff --git a/jps-plugin/testData/incremental/lookupTracker/classifierMembers/foo.kt b/jps-plugin/testData/incremental/lookupTracker/classifierMembers/foo.kt index 964ef2290ca..a909d94a91a 100644 --- a/jps-plugin/testData/incremental/lookupTracker/classifierMembers/foo.kt +++ b/jps-plugin/testData/incremental/lookupTracker/classifierMembers/foo.kt @@ -7,20 +7,20 @@ import bar.* var b = "" val c: /*c:foo.A c:foo.A.Companion p:foo*/String - get() = /*p:foo p:bar c:foo.A c:foo.A.Companion*/b + get() = /*c:foo.A*/b var d: /*c:foo.A c:foo.A.Companion p:foo*/String = "ddd" - get() = /*p:foo p:bar c:foo.A c:foo.A.Companion*/$d - set(v) { /*p:foo p:bar c:foo.A c:foo.A.Companion*/$d = v } + get() = /*c:foo.A*/$d + set(v) { /*c:foo.A*/$d = v } fun foo() { - /*p:foo p:bar c:foo.A c:foo.A.Companion*/a - /*p:foo p:bar c:foo.A c:foo.A.Companion*/foo() + /*c:foo.A*/a + /*c:foo.A*/foo() this./*c:foo.A*/a this./*c:foo.A*/foo() - /*p:foo p:bar c:foo.A c:foo.A.Companion*/baz() - /*p:foo p:bar c:foo.A c:foo.A.Companion*/Companion./*c:foo.A.Companion*/a - /*p:foo p:bar c:foo.A c:foo.A.Companion*/O./*c:foo.A.O*/v = "OK" + /*c:foo.A c:foo.A.Companion p:foo p:bar*/baz() + /*c:foo.A c:foo.A.Companion p:foo p:bar*/Companion./*c:foo.A.Companion*/a + /*c:foo.A c:foo.A.Companion p:foo p:bar*/O./*c:foo.A.O*/v = "OK" } class B { @@ -59,10 +59,10 @@ import bar.* val a = 1 fun foo() { - /*p:foo p:bar c:foo.E*/a - /*p:foo p:bar c:foo.E*/Y./*c:foo.E*/a - /*p:foo p:bar c:foo.E*/foo() - /*p:foo p:bar c:foo.E*/X./*c:foo.E*/foo() + /*c:foo.E*/a + /*c:foo.E p:foo p:bar*/Y./*c:foo.E*/a + /*c:foo.E*/foo() + /*c:foo.E p:foo p:bar*/X./*c:foo.E*/foo() } } diff --git a/jps-plugin/testData/incremental/lookupTracker/localDeclarations/locals.kt b/jps-plugin/testData/incremental/lookupTracker/localDeclarations/locals.kt index b6c26a2dafb..534ee1d4fc3 100644 --- a/jps-plugin/testData/incremental/lookupTracker/localDeclarations/locals.kt +++ b/jps-plugin/testData/incremental/lookupTracker/localDeclarations/locals.kt @@ -8,7 +8,7 @@ import bar.* val a = 1 val b = a fun localFun() = b - fun /*p:local.declarations*/Int.localExtFun() = /*p:local.declarations p:bar*/localFun() + fun /*p:local.declarations*/Int.localExtFun() = localFun() interface LocalI { var a: /*p:local.declarations*/Int @@ -30,10 +30,10 @@ import bar.* fun foo(): LocalI = null as LocalI } - /*p:local.declarations p:bar*/localFun() + localFun() 1./*p:local.declarations p:bar*/localExtFun() - val c = /*p:local.declarations p:bar*/LocalC() + val c = LocalC() c.a c.b c.foo() diff --git a/jps-plugin/testData/incremental/lookupTracker/packageDeclarations/foo1.kt b/jps-plugin/testData/incremental/lookupTracker/packageDeclarations/foo1.kt index 530a33c0558..bc2ad02cdd9 100644 --- a/jps-plugin/testData/incremental/lookupTracker/packageDeclarations/foo1.kt +++ b/jps-plugin/testData/incremental/lookupTracker/packageDeclarations/foo1.kt @@ -12,6 +12,6 @@ import baz./*p:baz*/C } /*p:foo*/fun /*p:foo*/MyClass.extFunc(p: /**p:foo p:bar*//*p:foo*/Array, e: /*p:foo*/MyEnum, c: /**???*/C): /*p:foo*/MyInterface { - /*p:foo p:bar c:foo.MyClass*/b - return /*p:foo p:bar c:foo.MyClass*/MyClass() + /*c:foo.MyClass p:foo p:bar*/b + return /*c:foo.MyClass p:foo p:bar*/MyClass() }