diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt index 9f86903e566..aefe755b595 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/scopes/receivers/Qualifier.kt @@ -30,7 +30,6 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.Printer -import java.util.* interface Qualifier : QualifierReceiver { val referenceExpression: KtSimpleNameExpression @@ -72,17 +71,13 @@ class ClassQualifier( } override val staticScope: MemberScope - get() { - val scopes = ArrayList(2) - - scopes.add(descriptor.staticScope) - - if (descriptor.kind != ClassKind.ENUM_ENTRY) { - scopes.add(descriptor.unsubstitutedInnerClassesScope) - } - - return ChainedMemberScope("Static scope for ${descriptor.name} as class or object", scopes) - } + get() = + if (descriptor.kind == ClassKind.ENUM_ENTRY) descriptor.staticScope + else ChainedMemberScope.create( + "Static scope for ${descriptor.name} as class or object", + descriptor.staticScope, + descriptor.unsubstitutedInnerClassesScope + ) override fun toString() = "Class{$descriptor}" } @@ -100,9 +95,10 @@ class TypeAliasQualifier( override val staticScope: MemberScope get() = when { DescriptorUtils.isEnumClass(classDescriptor) -> - ChainedMemberScope( + ChainedMemberScope.create( "Static scope for typealias ${descriptor.name}", - listOf(classDescriptor.staticScope, EnumEntriesScope()) + classDescriptor.staticScope, + EnumEntriesScope() ) else -> classDescriptor.staticScope diff --git a/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt b/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt index 3795ab8f534..243a47f4b16 100644 --- a/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt +++ b/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt @@ -198,7 +198,7 @@ abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdir() { val list = ArrayList(packageScopes.size + 1) list.add(ScopeWithClassifiers(classes)) list.addAll(packageScopes) - scope = ChainedMemberScope("synthetic package view for test", list) + scope = ChainedMemberScope.create("synthetic package view for test", list) } override val fqName: FqName diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/ChainedMemberScope.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/ChainedMemberScope.kt index 50cd3e5841e..1e5e5aa97fa 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/ChainedMemberScope.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/ChainedMemberScope.kt @@ -24,26 +24,28 @@ import org.jetbrains.kotlin.name.Name 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.SmartList -class ChainedMemberScope( - internal val debugName: String, - private val scopes: List +class ChainedMemberScope private constructor( + private val debugName: String, + private val scopes: Array ) : MemberScope { - override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? - = getFirstClassifierDiscriminateHeaders(scopes) { it.getContributedClassifier(name, location) } - override fun getContributedVariables(name: Name, location: LookupLocation): Collection - = getFromAllScopes(scopes) { it.getContributedVariables(name, location) } + override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = + getFirstClassifierDiscriminateHeaders(scopes) { it.getContributedClassifier(name, location) } - override fun getContributedFunctions(name: Name, location: LookupLocation): Collection - = getFromAllScopes(scopes) { it.getContributedFunctions(name, location) } + override fun getContributedVariables(name: Name, location: LookupLocation): Collection = + getFromAllScopes(scopes) { it.getContributedVariables(name, location) } - override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) - = getFromAllScopes(scopes) { it.getContributedDescriptors(kindFilter, nameFilter) } + override fun getContributedFunctions(name: Name, location: LookupLocation): Collection = + getFromAllScopes(scopes) { it.getContributedFunctions(name, location) } + + override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = + getFromAllScopes(scopes) { it.getContributedDescriptors(kindFilter, nameFilter) } override fun getFunctionNames() = scopes.flatMapTo(mutableSetOf()) { it.getFunctionNames() } override fun getVariableNames() = scopes.flatMapTo(mutableSetOf()) { it.getVariableNames() } - override fun getClassifierNames(): Set? = scopes.flatMapClassifierNamesOrNull() + override fun getClassifierNames(): Set? = scopes.asIterable().flatMapClassifierNamesOrNull() override fun recordLookup(name: Name, location: LookupLocation) { scopes.forEach { it.recordLookup(name, location) } @@ -64,12 +66,25 @@ class ChainedMemberScope( } companion object { - fun create(debugName: String, scopes: List): MemberScope { - return when (scopes.size) { - 0 -> MemberScope.Empty - 1 -> scopes.single() - else -> ChainedMemberScope(debugName, scopes) + fun create(debugName: String, vararg scopes: MemberScope): MemberScope = create(debugName, scopes.asIterable()) + + fun create(debugName: String, scopes: Iterable): MemberScope { + val flattenedNonEmptyScopes = SmartList() + for (scope in scopes) { + when { + scope === MemberScope.Empty -> {} + scope is ChainedMemberScope -> flattenedNonEmptyScopes.addAll(scope.scopes) + else -> flattenedNonEmptyScopes.add(scope) + } } + return createOrSingle(debugName, flattenedNonEmptyScopes) } + + internal fun createOrSingle(debugName: String, scopes: List): MemberScope = + when (scopes.size) { + 0 -> MemberScope.Empty + 1 -> scopes[0] + else -> ChainedMemberScope(debugName, scopes.toTypedArray()) + } } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/TypeIntersectionScope.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/TypeIntersectionScope.kt index 1b432c15306..9e3b737306f 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/TypeIntersectionScope.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/TypeIntersectionScope.kt @@ -22,9 +22,10 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.selectMostSpecificInEachOverridableGroup import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.util.collectionUtils.listOfNonEmptyScopes import org.jetbrains.kotlin.utils.Printer -class TypeIntersectionScope private constructor(override val workerScope: ChainedMemberScope) : AbstractScopeAdapter() { +class TypeIntersectionScope private constructor(private val debugName: String, override val workerScope: MemberScope) : AbstractScopeAdapter() { override fun getContributedFunctions(name: Name, location: LookupLocation) = super.getContributedFunctions(name, location).selectMostSpecificInEachOverridableGroup { this } @@ -39,17 +40,19 @@ class TypeIntersectionScope private constructor(override val workerScope: Chaine } override fun printScopeStructure(p: Printer) { - p.print("TypeIntersectionScope for: " + workerScope.debugName) + p.print("TypeIntersectionScope for: " + debugName) super.printScopeStructure(p) } companion object { @JvmStatic fun create(message: String, types: Collection): MemberScope { - val chainedScope = ChainedMemberScope(message, types.map { it.memberScope }) - if (types.size <= 1) return chainedScope + val nonEmptyScopes = listOfNonEmptyScopes(types.map { it.memberScope }) + val chainedOrSingle = ChainedMemberScope.createOrSingle(message, nonEmptyScopes) - return TypeIntersectionScope(chainedScope) + if (nonEmptyScopes.size <= 1) return chainedOrSingle + + return TypeIntersectionScope(message, chainedOrSingle) } } } diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/kdoc/resolveKDocLink.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/kdoc/resolveKDocLink.kt index d7b34ef244c..6d79ab5ee2f 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/kdoc/resolveKDocLink.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/kdoc/resolveKDocLink.kt @@ -212,7 +212,7 @@ fun getKDocLinkMemberScope(descriptor: DeclarationDescriptor, contextScope: Lexi is PackageViewDescriptor -> descriptor.memberScope is ClassDescriptor -> { - ChainedMemberScope( + ChainedMemberScope.create( "Member scope for KDoc resolve", listOfNotNull( descriptor.unsubstitutedMemberScope, descriptor.staticScope, diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentCompiler.kt b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentCompiler.kt index 656709c2ae8..ed809639b90 100644 --- a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentCompiler.kt +++ b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentCompiler.kt @@ -284,7 +284,7 @@ private class EvaluatorModuleDescriptor( MemberScope.Empty } else { val scopes = fragments.map { it.getMemberScope() } + SubpackagesScope(module, fqName) - ChainedMemberScope("package view scope for $fqName in ${module.name}", scopes) + ChainedMemberScope.create("package view scope for $fqName in ${module.name}", scopes) } }