Discriminate header classes in member scope.

We made it because of non-stable name resolution when project is multi platform. For such projects in platform module we have two classifiers with the same name, but impl class or type alias should win!
This commit is contained in:
Stanislav Erokhin
2016-12-17 16:55:10 +03:00
parent 5f124e9781
commit 04fddc7139
4 changed files with 21 additions and 10 deletions
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.utils.takeSnapshot import org.jetbrains.kotlin.resolve.scopes.utils.takeSnapshot
import org.jetbrains.kotlin.util.collectionUtils.getFirstMatch import org.jetbrains.kotlin.util.collectionUtils.getFirstClassifierDiscriminateHeaders
import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
@@ -40,7 +40,7 @@ class LexicalChainedScope @JvmOverloads constructor(
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= getFromAllScopes(memberScopes) { it.getContributedDescriptors() } = getFromAllScopes(memberScopes) { it.getContributedDescriptors() }
override fun getContributedClassifier(name: Name, location: LookupLocation) = getFirstMatch(memberScopes) { it.getContributedClassifier(name, location) } override fun getContributedClassifier(name: Name, location: LookupLocation) = getFirstClassifierDiscriminateHeaders(memberScopes) { it.getContributedClassifier(name, location) }
override fun getContributedVariables(name: Name, location: LookupLocation) = getFromAllScopes(memberScopes) { it.getContributedVariables(name, location) } override fun getContributedVariables(name: Name, location: LookupLocation) = getFromAllScopes(memberScopes) { it.getContributedVariables(name, location) }
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.util.collectionUtils.getFirstMatch import org.jetbrains.kotlin.util.collectionUtils.getFirstClassifierDiscriminateHeaders
import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.toReadOnlyList import org.jetbrains.kotlin.utils.toReadOnlyList
@@ -52,7 +52,7 @@ class JvmPackageScope(
val javaClassifier = javaScope.getContributedClassifier(name, location) val javaClassifier = javaScope.getContributedClassifier(name, location)
if (javaClassifier != null) return javaClassifier if (javaClassifier != null) return javaClassifier
return getFirstMatch(kotlinScopes) { it.getContributedClassifier(name, location) } return getFirstClassifierDiscriminateHeaders(kotlinScopes) { it.getContributedClassifier(name, location) }
} }
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> { override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.collectionUtils.getFirstMatch import org.jetbrains.kotlin.util.collectionUtils.getFirstClassifierDiscriminateHeaders
import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
@@ -30,7 +30,7 @@ class ChainedMemberScope(
private val scopes: List<MemberScope> private val scopes: List<MemberScope>
) : MemberScope { ) : MemberScope {
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor?
= getFirstMatch(scopes) { it.getContributedClassifier(name, location) } = getFirstClassifierDiscriminateHeaders(scopes) { it.getContributedClassifier(name, location) }
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor>
= getFromAllScopes(scopes) { it.getContributedVariables(name, location) } = getFromAllScopes(scopes) { it.getContributedVariables(name, location) }
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.util.collectionUtils package org.jetbrains.kotlin.util.collectionUtils
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import java.util.* import java.util.*
/** /**
@@ -70,11 +72,20 @@ inline fun <Scope, T> getFromAllScopes(firstScope: Scope, restScopes: List<Scope
return result ?: emptySet() return result ?: emptySet()
} }
inline fun <Scope, T : Any> getFirstMatch(scopes: List<Scope>, callback: (Scope) -> T?): T? { inline fun <Scope, T : ClassifierDescriptor> getFirstClassifierDiscriminateHeaders(scopes: List<Scope>, callback: (Scope) -> T?): T? {
// NOTE: This is performance-sensitive; please don't replace with map().firstOrNull() // NOTE: This is performance-sensitive; please don't replace with map().firstOrNull()
var result: T? = null
for (scope in scopes) { for (scope in scopes) {
val result = callback(scope) val newResult = callback(scope)
if (result != null) return result if (newResult != null) {
if (newResult is ClassifierDescriptorWithTypeParameters && newResult.isHeader) {
if (result == null) result = newResult
}
// this class is Impl or usual class
else {
return newResult
}
}
} }
return null return result
} }