From 860951748f1fa64ec111df6672d2073ba8f371cf Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 16 Aug 2017 15:49:02 +0700 Subject: [PATCH] Filter out inapplicable member scopes in resolution --- .../kotlin/resolve/calls/tower/TowerLevels.kt | 4 ++++ .../kotlin/resolve/calls/tower/TowerResolver.kt | 10 ++++++++-- .../kotlin/load/java/lazy/descriptors/LazyJavaScope.kt | 5 +++++ .../descriptors/DeserializedMemberScope.kt | 5 +++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt index cee2f639914..f3bab33812d 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt @@ -87,6 +87,10 @@ internal class MemberScopeTowerLevel( private val syntheticScopes = scopeTower.syntheticScopes + fun definitelyDoesNotContainName(name: Name) = + (dispatchReceiver.possibleTypes + dispatchReceiver.receiverValue.type) + .all { !it.isDynamic() && it.memberScope.definitelyDoesNotContainName(name, location) } + private fun collectMembers( getMembers: ResolutionScope.(KotlinType?) -> Collection ): Collection { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt index a9c24775fc4..043f7029f8e 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerResolver.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.scopes.ResolutionScope import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.yieldIfNotNull import java.util.* import kotlin.coroutines.experimental.buildSequence @@ -99,7 +100,7 @@ class TowerResolver { } getImplicitReceiver(scope)?.let { - yield(MemberScopeTowerLevel(this@createNonLocalLevels, it)) + yieldIfNotNull(MemberScopeTowerLevel(this@createNonLocalLevels, it).takeIf { it.mayFitForName(name) }) } } else if (scope.mayFitForName(name, location)) { @@ -156,7 +157,9 @@ class TowerResolver { } // members of implicit receiver or member extension for explicit receiver - TowerData.TowerLevel(MemberScopeTowerLevel(this, implicitReceiver)).process()?.let { return it } + MemberScopeTowerLevel(this, implicitReceiver).takeIf { it.mayFitForName(name) }?.let { + TowerData.TowerLevel(it).process()?.let { return it } + } // synthetic properties TowerData.BothTowerLevelAndImplicitReceiver(syntheticLevel, implicitReceiver).process()?.let { return it } @@ -193,6 +196,9 @@ class TowerResolver { return resultCollector.getFinalCandidates() } + private fun MemberScopeTowerLevel.mayFitForName(name: Name) = + !definitelyDoesNotContainName(name) || !definitelyDoesNotContainName(OperatorNameConventions.INVOKE) + private fun ResolutionScope.mayFitForName(name: Name, location: LookupLocation) = !definitelyDoesNotContainName(name, location) || !definitelyDoesNotContainName(OperatorNameConventions.INVOKE, location) diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt index 434f28ad9ed..d7834eab324 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt @@ -218,6 +218,11 @@ abstract class LazyJavaScope(protected val c: LazyJavaResolverContext) : MemberS override fun getVariableNames() = propertyNamesLazy override fun getClassifierNames() = classNamesLazy + override fun definitelyDoesNotContainName(name: Name, location: LookupLocation): Boolean { + recordLookup(name, location) + return name !in functionNamesLazy && name !in propertyNamesLazy && name !in classNamesLazy + } + override fun getContributedFunctions(name: Name, location: LookupLocation): Collection { if (name !in getFunctionNames()) return emptyList() return functions(name) diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedMemberScope.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedMemberScope.kt index 83cb57b6a1a..3145304b9a6 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedMemberScope.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedMemberScope.kt @@ -78,6 +78,11 @@ abstract class DeserializedMemberScope protected constructor( override fun getVariableNames() = variableNamesLazy override fun getClassifierNames(): Set? = classNames + typeAliasNames + override fun definitelyDoesNotContainName(name: Name, location: LookupLocation): Boolean { + recordLookup(name, location) + return name !in functionNamesLazy && name !in variableNamesLazy && name !in classNames && name !in typeAliasNames + } + private inline fun Collection.groupByName( getNameIndex: (M) -> Int ) = groupBy { c.nameResolver.getName(getNameIndex(it)) }