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.name.Name
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.utils.Printer
@@ -40,7 +40,7 @@ class LexicalChainedScope @JvmOverloads constructor(
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean)
= 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) }
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
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.utils.Printer
import org.jetbrains.kotlin.utils.toReadOnlyList
@@ -52,7 +52,7 @@ class JvmPackageScope(
val javaClassifier = javaScope.getContributedClassifier(name, location)
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> {
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
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.utils.Printer
@@ -30,7 +30,7 @@ class ChainedMemberScope(
private val scopes: List<MemberScope>
) : MemberScope {
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>
= getFromAllScopes(scopes) { it.getContributedVariables(name, location) }
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.util.collectionUtils
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import java.util.*
/**
@@ -70,11 +72,20 @@ inline fun <Scope, T> getFromAllScopes(firstScope: Scope, restScopes: List<Scope
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()
var result: T? = null
for (scope in scopes) {
val result = callback(scope)
if (result != null) return result
val newResult = callback(scope)
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
}