Optimize data handling inside scopes

This commit is contained in:
Ilya Chernikov
2020-06-02 23:11:24 +02:00
parent c720fa5793
commit bf97323301
12 changed files with 170 additions and 97 deletions
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.findCorrespondingSupertype import org.jetbrains.kotlin.types.checker.findCorrespondingSupertype
import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.utils.addIfNotNull
import kotlin.properties.Delegates import kotlin.properties.Delegates
interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor, FunctionInterfaceAdapterExtensionFunctionDescriptor { interface SamAdapterExtensionFunctionDescriptor : FunctionDescriptor, FunctionInterfaceAdapterExtensionFunctionDescriptor {
@@ -244,14 +245,15 @@ class SamAdapterFunctionsScope(
} }
} }
private fun getAllSamConstructors(classifier: ClassifierDescriptor): List<FunctionDescriptor> { private fun getAllSamConstructors(classifier: ClassifierDescriptor): List<FunctionDescriptor> =
return getSamAdaptersFromConstructors(classifier) + listOfNotNull(getSamConstructor(classifier)) getSamAdaptersFromConstructors(classifier).also {
} it.addIfNotNull(getSamConstructor(classifier))
}
private fun getSamAdaptersFromConstructors(classifier: ClassifierDescriptor): List<FunctionDescriptor> { private fun getSamAdaptersFromConstructors(classifier: ClassifierDescriptor): MutableList<FunctionDescriptor> {
if (!shouldGenerateAdditionalSamCandidate || classifier !is JavaClassDescriptor) return emptyList() if (!shouldGenerateAdditionalSamCandidate || classifier !is JavaClassDescriptor) return SmartList()
return arrayListOf<FunctionDescriptor>().apply { return SmartList<FunctionDescriptor>().apply {
for (constructor in classifier.constructors) { for (constructor in classifier.constructors) {
val samConstructor = getSyntheticConstructor(constructor) ?: continue val samConstructor = getSyntheticConstructor(constructor) ?: continue
add(samConstructor) add(samConstructor)
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.resolve.scopes.BaseImportingScope
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.resolve.scopes.computeAllNames import org.jetbrains.kotlin.resolve.scopes.computeAllNames
import org.jetbrains.kotlin.util.collectionUtils.flatMapScopes
import org.jetbrains.kotlin.util.collectionUtils.listOfNonEmptyScopes
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.flatMapToNullable import org.jetbrains.kotlin.utils.addToStdlib.flatMapToNullable
@@ -32,13 +34,13 @@ class AllUnderImportScope(
excludedImportNames: Collection<FqName> excludedImportNames: Collection<FqName>
) : BaseImportingScope(null) { ) : BaseImportingScope(null) {
private val scopes: List<MemberScope> = if (descriptor is ClassDescriptor) { private val scopes: Array<MemberScope> = if (descriptor is ClassDescriptor) {
listOf(descriptor.staticScope, descriptor.unsubstitutedInnerClassesScope) listOfNonEmptyScopes(descriptor.staticScope, descriptor.unsubstitutedInnerClassesScope).toTypedArray()
} else { } else {
assert(descriptor is PackageViewDescriptor) { assert(descriptor is PackageViewDescriptor) {
"Must be class or package view descriptor: $descriptor" "Must be class or package view descriptor: $descriptor"
} }
listOf((descriptor as PackageViewDescriptor).memberScope) listOfNonEmptyScopes((descriptor as PackageViewDescriptor).memberScope).toTypedArray()
} }
private val excludedNames: Set<Name> = if (excludedImportNames.isEmpty()) { // optimization private val excludedNames: Set<Name> = if (excludedImportNames.isEmpty()) { // optimization
@@ -49,7 +51,11 @@ class AllUnderImportScope(
excludedImportNames.mapNotNull { if (it.parent() == fqName) it.shortName() else null }.toSet() excludedImportNames.mapNotNull { if (it.parent() == fqName) it.shortName() else null }.toSet()
} }
override fun computeImportedNames(): Set<Name>? = scopes.flatMapToNullable(hashSetOf(), MemberScope::computeAllNames) override fun computeImportedNames(): Set<Name>? = when (scopes.size) {
0 -> null
1 -> scopes[0].computeAllNames()
else -> scopes.asIterable().flatMapToNullable(hashSetOf(), MemberScope::computeAllNames)
}
override fun getContributedDescriptors( override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter, kindFilter: DescriptorKindFilter,
@@ -64,23 +70,29 @@ class AllUnderImportScope(
val noPackagesKindFilter = kindFilter.withoutKinds(DescriptorKindFilter.PACKAGES_MASK) val noPackagesKindFilter = kindFilter.withoutKinds(DescriptorKindFilter.PACKAGES_MASK)
return scopes return scopes
.flatMap { it.getContributedDescriptors(noPackagesKindFilter, nameFilterToUse) } .flatMapScopes { it.getContributedDescriptors(noPackagesKindFilter, nameFilterToUse) }
.filter { it !is PackageViewDescriptor } // subpackages are not imported .filter { it !is PackageViewDescriptor } // subpackages are not imported
} }
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? { override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
if (name in excludedNames) return null if (name in excludedNames) return null
return scopes.asSequence().mapNotNull { it.getContributedClassifier(name, location) }.singleOrNull() var single: ClassifierDescriptor? = null
for (scope in scopes) {
val res = scope.getContributedClassifier(name, location) ?: continue
if (single == null) single = res
else return null
}
return single
} }
override fun getContributedVariables(name: Name, location: LookupLocation): List<VariableDescriptor> { override fun getContributedVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
if (name in excludedNames) return emptyList() if (name in excludedNames) return emptyList()
return scopes.flatMap { it.getContributedVariables(name, location) } return scopes.flatMapScopes { it.getContributedVariables(name, location) }
} }
override fun getContributedFunctions(name: Name, location: LookupLocation): List<FunctionDescriptor> { override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
if (name in excludedNames) return emptyList() if (name in excludedNames) return emptyList()
return scopes.flatMap { it.getContributedFunctions(name, location) } return scopes.flatMapScopes { it.getContributedFunctions(name, location) }
} }
override fun recordLookup(name: Name, location: LookupLocation) { override fun recordLookup(name: Name, location: LookupLocation) {
@@ -92,3 +104,4 @@ class AllUnderImportScope(
} }
} }
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtImportInfo import org.jetbrains.kotlin.psi.KtImportInfo
import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.ImportPath import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
import org.jetbrains.kotlin.resolve.extensions.ExtraImportsProviderExtension import org.jetbrains.kotlin.resolve.extensions.ExtraImportsProviderExtension
import org.jetbrains.kotlin.resolve.scopes.* import org.jetbrains.kotlin.resolve.scopes.*
@@ -85,20 +85,20 @@ class FileScopeFactory(
} }
val explicit = createDefaultImportResolver( val explicit = createDefaultImportResolver(
ExplicitImportsIndexed(defaultImportsFiltered), makeExplicitImportsIndexed(defaultImportsFiltered, components.storageManager),
tempTrace, tempTrace,
packageFragment = null, packageFragment = null,
aliasImportNames = aliasImportNames aliasImportNames = aliasImportNames
) )
val allUnder = createDefaultImportResolver( val allUnder = createDefaultImportResolver(
AllUnderImportsIndexed(defaultImportsFiltered), makeAllUnderImportsIndexed(defaultImportsFiltered),
tempTrace, tempTrace,
packageFragment = null, packageFragment = null,
aliasImportNames = aliasImportNames, aliasImportNames = aliasImportNames,
excludedImports = analyzerServices.excludedImports excludedImports = analyzerServices.excludedImports
) )
val lowPriority = createDefaultImportResolver( val lowPriority = createDefaultImportResolver(
AllUnderImportsIndexed(defaultLowPriorityImports.also { imports -> makeAllUnderImportsIndexed(defaultLowPriorityImports.also { imports ->
assert(imports.all { it.isAllUnder }) { "All low priority imports must be all-under: $imports" } assert(imports.all { it.isAllUnder }) { "All low priority imports must be all-under: $imports" }
}), }),
tempTrace, tempTrace,
@@ -142,9 +142,13 @@ class FileScopeFactory(
val imports = file.importDirectives val imports = file.importDirectives
val aliasImportNames = imports.mapNotNull { if (it.aliasName != null) it.importedFqName else null } val aliasImportNames = imports.mapNotNull { if (it.aliasName != null) it.importedFqName else null }
val explicitImportResolver = createImportResolver(ExplicitImportsIndexed(imports), bindingTrace, aliasImportNames, packageFragment) val explicitImportResolver =
createImportResolver(
makeExplicitImportsIndexed(imports, components.storageManager),
bindingTrace, aliasImportNames, packageFragment
)
val allUnderImportResolver = createImportResolver( val allUnderImportResolver = createImportResolver(
AllUnderImportsIndexed(imports), makeAllUnderImportsIndexed(imports),
bindingTrace, bindingTrace,
aliasImportNames, aliasImportNames,
packageFragment packageFragment
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.ImportingScope import org.jetbrains.kotlin.resolve.scopes.ImportingScope
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.storage.NotNullLazyValue import org.jetbrains.kotlin.storage.NotNullLazyValue
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.expressions.OperatorConventions
@@ -47,20 +48,20 @@ import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.flatMapToNullable import org.jetbrains.kotlin.utils.addToStdlib.flatMapToNullable
import org.jetbrains.kotlin.utils.ifEmpty import org.jetbrains.kotlin.utils.ifEmpty
interface IndexedImports<I : KtImportInfo> { open class IndexedImports<I : KtImportInfo>(val imports: Array<I>) {
val imports: List<I> open fun importsForName(name: Name): Iterable<I> = imports.asIterable()
fun importsForName(name: Name): Collection<I>
} }
class AllUnderImportsIndexed<I : KtImportInfo>(allImports: Collection<I>) : IndexedImports<I> { inline fun <reified I : KtImportInfo> makeAllUnderImportsIndexed(imports: Collection<I>) : IndexedImports<I> =
override val imports = allImports.filter { it.isAllUnder } IndexedImports(imports.filter { it.isAllUnder }.toTypedArray())
override fun importsForName(name: Name) = imports
}
class ExplicitImportsIndexed<I : KtImportInfo>(allImports: Collection<I>) : IndexedImports<I> {
override val imports = allImports.filter { !it.isAllUnder }
private val nameToDirectives: ListMultimap<Name, I> by lazy { class ExplicitImportsIndexed<I : KtImportInfo>(
imports: Array<I>,
storageManager: StorageManager
) : IndexedImports<I>(imports) {
private val nameToDirectives: NotNullLazyValue<ListMultimap<Name, I>> = storageManager.createLazyValue {
val builder = ImmutableListMultimap.builder<Name, I>() val builder = ImmutableListMultimap.builder<Name, I>()
for (directive in imports) { for (directive in imports) {
@@ -71,9 +72,15 @@ class ExplicitImportsIndexed<I : KtImportInfo>(allImports: Collection<I>) : Inde
builder.build() builder.build()
} }
override fun importsForName(name: Name) = nameToDirectives.get(name) override fun importsForName(name: Name) = nameToDirectives().get(name)
} }
inline fun <reified I : KtImportInfo> makeExplicitImportsIndexed(
imports: Collection<I>,
storageManager: StorageManager
) : IndexedImports<I> =
ExplicitImportsIndexed(imports.filter { !it.isAllUnder }.toTypedArray(), storageManager)
interface ImportForceResolver { interface ImportForceResolver {
fun forceResolveNonDefaultImports() fun forceResolveNonDefaultImports()
fun forceResolveImport(importDirective: KtImportDirective) fun forceResolveImport(importDirective: KtImportDirective)
@@ -119,15 +126,18 @@ open class LazyImportResolver<I : KtImportInfo>(
} }
val allNames: Set<Name>? by lazy(LazyThreadSafetyMode.PUBLICATION) { val allNames: Set<Name>? by lazy(LazyThreadSafetyMode.PUBLICATION) {
indexedImports.imports.flatMapToNullable(THashSet()) { getImportScope(it).computeImportedNames() } indexedImports.imports.asIterable().flatMapToNullable(THashSet()) { getImportScope(it).computeImportedNames() }
} }
fun definitelyDoesNotContainName(name: Name) = allNames?.let { name !in it } == true fun definitelyDoesNotContainName(name: Name) = allNames?.let { name !in it } == true
fun recordLookup(name: Name, location: LookupLocation) { fun recordLookup(name: Name, location: LookupLocation) {
if (allNames == null) return if (allNames == null) return
indexedImports.importsForName(name).forEach { for (it in indexedImports.importsForName(name)) {
getImportScope(it).recordLookup(name, location) val scope = getImportScope(it)
if (scope !== ImportingScope.Empty) {
scope.recordLookup(name, location)
}
} }
} }
} }
@@ -58,25 +58,22 @@ open class LazyClassMemberScope(
c, declarationProvider, thisClass, trace, scopeForDeclaredMembers c, declarationProvider, thisClass, trace, scopeForDeclaredMembers
) { ) {
private val descriptorsFromDeclaredElements = storageManager.createLazyValue { private val allDescriptors = storageManager.createLazyValue {
computeDescriptorsFromDeclaredElements( val result = LinkedHashSet(
DescriptorKindFilter.ALL, computeDescriptorsFromDeclaredElements(
MemberScope.ALL_NAME_FILTER, DescriptorKindFilter.ALL,
NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS MemberScope.ALL_NAME_FILTER,
NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS
)
) )
} result.addAll(computeExtraDescriptors(NoLookupLocation.FOR_ALREADY_TRACKED))
private val extraDescriptors: NotNullLazyValue<Collection<DeclarationDescriptor>> = storageManager.createLazyValue { result
computeExtraDescriptors(NoLookupLocation.FOR_ALREADY_TRACKED)
} }
override fun getContributedDescriptors( override fun getContributedDescriptors(
kindFilter: DescriptorKindFilter, kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean nameFilter: (Name) -> Boolean
): Collection<DeclarationDescriptor> { ): Collection<DeclarationDescriptor> = allDescriptors()
val result = LinkedHashSet(descriptorsFromDeclaredElements())
result.addAll(extraDescriptors())
return result
}
protected open fun computeExtraDescriptors(location: LookupLocation): Collection<DeclarationDescriptor> { protected open fun computeExtraDescriptors(location: LookupLocation): Collection<DeclarationDescriptor> {
val result = ArrayList<DeclarationDescriptor>() val result = ArrayList<DeclarationDescriptor>()
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.scopes.flatMapClassifierNamesOrNull
import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.util.collectionUtils.getFirstClassifierDiscriminateHeaders 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.util.collectionUtils.listOfNonEmptyScopes
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
class JvmPackageScope( class JvmPackageScope(
@@ -41,9 +42,11 @@ class JvmPackageScope(
internal val javaScope = LazyJavaPackageScope(c, jPackage, packageFragment) internal val javaScope = LazyJavaPackageScope(c, jPackage, packageFragment)
private val kotlinScopes by c.storageManager.createLazyValue { private val kotlinScopes by c.storageManager.createLazyValue {
packageFragment.binaryClasses.values.mapNotNull { partClass -> listOfNonEmptyScopes(
c.components.deserializedDescriptorResolver.createKotlinPackagePartScope(packageFragment, partClass) packageFragment.binaryClasses.values.mapNotNull { partClass ->
}.toList() c.components.deserializedDescriptorResolver.createKotlinPackagePartScope(packageFragment, partClass)
}
).toTypedArray()
} }
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? { override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
@@ -78,7 +81,7 @@ class JvmPackageScope(
addAll(javaScope.getVariableNames()) addAll(javaScope.getVariableNames())
} }
override fun getClassifierNames(): Set<Name>? = kotlinScopes.flatMapClassifierNamesOrNull()?.apply { override fun getClassifierNames(): Set<Name>? = kotlinScopes.asIterable().flatMapClassifierNamesOrNull()?.apply {
addAll(javaScope.getClassifierNames()) addAll(javaScope.getClassifierNames())
} }
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy
import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.compact import org.jetbrains.kotlin.utils.compact
import java.util.* import java.util.*
@@ -47,11 +48,11 @@ abstract class GivenFunctionsMemberScope(
} }
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> { override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> {
return allDescriptors.filterIsInstance<SimpleFunctionDescriptor>().filter { it.name == name } return allDescriptors.filterIsInstanceAnd { it.name == name }
} }
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> { override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
return allDescriptors.filterIsInstance<PropertyDescriptor>().filter { it.name == name } return allDescriptors.filterIsInstanceAnd { it.name == name }
} }
private fun createFakeOverrides(functionsFromCurrent: List<FunctionDescriptor>): List<DeclarationDescriptor> { private fun createFakeOverrides(functionsFromCurrent: List<FunctionDescriptor>): List<DeclarationDescriptor> {
@@ -58,9 +58,14 @@ interface MemberScope : ResolutionScope {
} }
} }
fun MemberScope.computeAllNames() = getClassifierNames()?.let { getFunctionNames() + getVariableNames() + it } fun MemberScope.computeAllNames() = getClassifierNames()?.let { classifierNames ->
getFunctionNames().toMutableSet().also {
it.addAll(getVariableNames())
it.addAll(classifierNames)
}
}
fun Collection<MemberScope>.flatMapClassifierNamesOrNull(): MutableSet<Name>? = fun Iterable<MemberScope>.flatMapClassifierNamesOrNull(): MutableSet<Name>? =
flatMapToNullable(hashSetOf(), MemberScope::getClassifierNames) flatMapToNullable(hashSetOf(), MemberScope::getClassifierNames)
/** /**
@@ -167,7 +172,6 @@ class DescriptorKindFilter(
val filter = field.get(null) as? DescriptorKindFilter val filter = field.get(null) as? DescriptorKindFilter
if (filter != null) MaskToName(filter.kindMask, field.name) else null if (filter != null) MaskToName(filter.kindMask, field.name) else null
} }
.toList()
private val DEBUG_MASK_BIT_NAMES = staticFields<DescriptorKindFilter>() private val DEBUG_MASK_BIT_NAMES = staticFields<DescriptorKindFilter>()
.filter { it.type == Integer.TYPE } .filter { it.type == Integer.TYPE }
@@ -176,7 +180,6 @@ class DescriptorKindFilter(
val isOneBitMask = mask == (mask and (-mask)) val isOneBitMask = mask == (mask and (-mask))
if (isOneBitMask) MaskToName(mask, field.name) else null if (isOneBitMask) MaskToName(mask, field.name) else null
} }
.toList()
private inline fun <reified T : Any> staticFields() = T::class.java.fields.filter { Modifier.isStatic(it.modifiers) } private inline fun <reified T : Any> staticFields() = T::class.java.fields.filter { Modifier.isStatic(it.modifiers) }
} }
@@ -16,9 +16,13 @@
package org.jetbrains.kotlin.resolve.scopes package org.jetbrains.kotlin.resolve.scopes
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
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.filterIsInstanceMapTo
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.alwaysTrue import org.jetbrains.kotlin.utils.alwaysTrue
@@ -35,14 +39,14 @@ abstract class MemberScopeImpl : MemberScope {
nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> = emptyList() nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> = emptyList()
override fun getFunctionNames(): Set<Name> = override fun getFunctionNames(): Set<Name> =
getContributedDescriptors( getContributedDescriptors(
DescriptorKindFilter.FUNCTIONS, alwaysTrue() DescriptorKindFilter.FUNCTIONS, alwaysTrue()
).filterIsInstance<SimpleFunctionDescriptor>().mapTo(mutableSetOf()) { it.name } ).filterIsInstanceMapTo<SimpleFunctionDescriptor, Name, MutableSet<Name>>(mutableSetOf()) { it.name }
override fun getVariableNames(): Set<Name> = override fun getVariableNames(): Set<Name> =
getContributedDescriptors( getContributedDescriptors(
DescriptorKindFilter.VARIABLES, alwaysTrue() DescriptorKindFilter.VARIABLES, alwaysTrue()
).filterIsInstance<VariableDescriptor>().mapTo(mutableSetOf()) { it.name } ).filterIsInstanceMapTo<SimpleFunctionDescriptor, Name, MutableSet<Name>>(mutableSetOf()) { it.name }
override fun getClassifierNames(): Set<Name>? = null override fun getClassifierNames(): Set<Name>? = null
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.resolve.DescriptorFactory.createEnumValuesMethod
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
import java.util.* import org.jetbrains.kotlin.utils.SmartList
// We don't need to track lookups here since this scope used only for introduce special Enum class members // We don't need to track lookups here since this scope used only for introduce special Enum class members
class StaticScopeForKotlinEnum( class StaticScopeForKotlinEnum(
@@ -46,7 +46,7 @@ class StaticScopeForKotlinEnum(
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = functions override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = functions
override fun getContributedFunctions(name: Name, location: LookupLocation) = override fun getContributedFunctions(name: Name, location: LookupLocation) =
functions.filterTo(ArrayList<SimpleFunctionDescriptor>(1)) { it.name == name } functions.filterTo(SmartList()) { it.name == name }
override fun printScopeStructure(p: Printer) { override fun printScopeStructure(p: Printer) {
p.println("Static scope for $containingClass") p.println("Static scope for $containingClass")
@@ -5,7 +5,10 @@
package org.jetbrains.kotlin.resolve.scopes.synthetic package org.jetbrains.kotlin.resolve.scopes.synthetic
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.record import org.jetbrains.kotlin.incremental.record
@@ -16,6 +19,7 @@ import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceMapNotNull
class FunInterfaceConstructorsScopeProvider( class FunInterfaceConstructorsScopeProvider(
storageManager: StorageManager, storageManager: StorageManager,
@@ -47,11 +51,9 @@ class FunInterfaceConstructorsSyntheticScope(
return listOfNotNull(getSamConstructor(classifier)) return listOfNotNull(getSamConstructor(classifier))
} }
override fun getSyntheticConstructors(scope: ResolutionScope): Collection<FunctionDescriptor> { override fun getSyntheticConstructors(scope: ResolutionScope): Collection<FunctionDescriptor> =
val classifiers = scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS).filterIsInstance<ClassifierDescriptor>() scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)
.filterIsInstanceMapNotNull<ClassifierDescriptor, FunctionDescriptor> { getSamConstructor(it) }
return classifiers.mapNotNull { getSamConstructor(it) }
}
private fun getSamConstructor(classifier: ClassifierDescriptor): SamConstructorDescriptor? { private fun getSamConstructor(classifier: ClassifierDescriptor): SamConstructorDescriptor? {
if (classifier is TypeAliasDescriptor) { if (classifier is TypeAliasDescriptor) {
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.util.collectionUtils
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.utils.SmartList
import java.util.* import java.util.*
/** /**
@@ -41,30 +43,20 @@ fun <T> Collection<T>?.concat(collection: Collection<T>): Collection<T>? {
return result return result
} }
fun <T> concatInOrder(c1: Collection<T>?, c2: Collection<T>?): Collection<T> { inline fun <Scope, T> getFromAllScopes(scopes: Array<Scope>, callback: (Scope) -> Collection<T>): Collection<T> =
val result = if (c1 == null || c1.isEmpty()) when (scopes.size) {
c2 0 -> emptyList()
else if (c2 == null || c2.isEmpty()) 1 -> callback(scopes[0])
c1 else -> {
else { var result: Collection<T>? = null
val result = LinkedHashSet<T>() for (scope in scopes) {
result.addAll(c1) result = result.concat(callback(scope))
result.addAll(c2) }
result result ?: emptySet()
}
} }
return result ?: emptySet()
}
inline fun <Scope, T> getFromAllScopes(scopes: List<Scope>, callback: (Scope) -> Collection<T>): Collection<T> { inline fun <Scope, T> getFromAllScopes(firstScope: Scope, restScopes: Array<Scope>, callback: (Scope) -> Collection<T>): Collection<T> {
if (scopes.isEmpty()) return emptySet()
var result: Collection<T>? = null
for (scope in scopes) {
result = result.concat(callback(scope))
}
return result ?: emptySet()
}
inline fun <Scope, T> getFromAllScopes(firstScope: Scope, restScopes: List<Scope>, callback: (Scope) -> Collection<T>): Collection<T> {
var result: Collection<T>? = callback(firstScope) var result: Collection<T>? = callback(firstScope)
for (scope in restScopes) { for (scope in restScopes) {
result = result.concat(callback(scope)) result = result.concat(callback(scope))
@@ -72,7 +64,20 @@ inline fun <Scope, T> getFromAllScopes(firstScope: Scope, restScopes: List<Scope
return result ?: emptySet() return result ?: emptySet()
} }
inline fun <Scope, T : ClassifierDescriptor> getFirstClassifierDiscriminateHeaders(scopes: List<Scope>, callback: (Scope) -> T?): T? { inline fun <Scope, R> Array<out Scope>.flatMapScopes(transform: (Scope) -> Collection<R>): Collection<R> =
when (size) {
0 -> emptyList()
1 -> transform(get(0))
else -> flatMapTo(ArrayList<R>(), transform)
}
fun listOfNonEmptyScopes(vararg scopes: MemberScope?): SmartList<MemberScope> =
scopes.filterTo(SmartList<MemberScope>()) { it != null && it !== MemberScope.Empty }
fun listOfNonEmptyScopes(scopes: Iterable<MemberScope?>): SmartList<MemberScope> =
scopes.filterTo(SmartList<MemberScope>()) { it != null && it !== MemberScope.Empty }
inline fun <Scope, T : ClassifierDescriptor> getFirstClassifierDiscriminateHeaders(scopes: Array<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 var result: T? = null
for (scope in scopes) { for (scope in scopes) {
@@ -89,3 +94,32 @@ inline fun <Scope, T : ClassifierDescriptor> getFirstClassifierDiscriminateHeade
} }
return result return result
} }
inline fun <reified R> Iterable<*>.filterIsInstanceAnd(predicate: (R) -> Boolean): Collection<R> =
filterIsInstanceAndTo(SmartList(), predicate)
inline fun <reified R, C : MutableCollection<in R>> Iterable<*>.filterIsInstanceAndTo(destination: C, predicate: (R) -> Boolean): C {
for (element in this) if (element is R && predicate(element)) destination.add(element)
return destination
}
inline fun <reified T, reified R, C : MutableCollection<in R>> Iterable<*>.filterIsInstanceMapTo(destination: C, transform: (T) -> R): C {
for (element in this) if (element is T) {
destination.add(transform(element))
}
return destination
}
inline fun <reified T, reified R> Iterable<*>.filterIsInstanceMapNotNull(transform: (T) -> R?): Collection<R> =
filterIsInstanceMapNotNullTo(SmartList(), transform)
inline fun <reified T, reified R, C : MutableCollection<in R>> Iterable<*>.filterIsInstanceMapNotNullTo(destination: C, transform: (T) -> R?): C {
for (element in this) if (element is T) {
val result = transform(element)
if (result != null) {
destination.add(result)
}
}
return destination
}