[FIR] Add ability to generate members and nested classifiers for existing classes
This commit is contained in:
committed by
TeamCityServer
parent
9bfa6c54b8
commit
26fa772846
@@ -41,10 +41,13 @@ abstract class AbstractArrayMapOwner<K : Any, V : Any> : Iterable<V> {
|
||||
|
||||
class ArrayMapAccessor<K : Any, V : Any, T : V>(
|
||||
key: KClass<out K>,
|
||||
id: Int
|
||||
id: Int,
|
||||
val default: T? = null
|
||||
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(key, id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V> {
|
||||
override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T {
|
||||
return extractValue(thisRef) ?: error("No '$key'($id) in array owner: $thisRef")
|
||||
return extractValue(thisRef)
|
||||
?: default
|
||||
?: error("No '$key'($id) in array owner: $thisRef")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,8 +65,8 @@ abstract class TypeRegistry<K : Any, V : Any> {
|
||||
private val idCounter = AtomicInteger(0)
|
||||
|
||||
|
||||
fun <T : V, KK : K> generateAccessor(kClass: KClass<KK>): ArrayMapAccessor<K, V, T> {
|
||||
return ArrayMapAccessor(kClass, getId(kClass))
|
||||
fun <T : V, KK : K> generateAccessor(kClass: KClass<KK>, default: T? = null): ArrayMapAccessor<K, V, T> {
|
||||
return ArrayMapAccessor(kClass, getId(kClass), default)
|
||||
}
|
||||
|
||||
fun <T : V, KK : K> generateNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, T> {
|
||||
|
||||
+2
-2
@@ -38,8 +38,8 @@ abstract class FirDeclarationGenerationExtension(session: FirSession) : FirPredi
|
||||
// Can be called on IMPORTS stage
|
||||
open fun hasPackage(packageFqName: FqName): Boolean = false
|
||||
|
||||
open fun getCallableNamesForGeneratedClass(classSymbol: FirClassSymbol<*>): Set<Name> = emptySet()
|
||||
open fun getNestedClassifiersNamesForGeneratedClass(classSymbol: FirClassSymbol<*>): Set<Name> = emptySet()
|
||||
open fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>): Set<Name> = emptySet()
|
||||
open fun getNestedClassifiersNames(classSymbol: FirClassSymbol<*>): Set<Name> = emptySet()
|
||||
|
||||
fun interface Factory : FirExtension.Factory<FirDeclarationGenerationExtension>
|
||||
}
|
||||
|
||||
@@ -20,11 +20,13 @@ annotation class PluginServicesInitialization
|
||||
class FirExtensionService(val session: FirSession) : ComponentArrayOwner<FirExtension, List<FirExtension>>(), FirSessionComponent {
|
||||
companion object : TypeRegistry<FirExtension, List<FirExtension>>() {
|
||||
inline fun <reified P : FirExtension, V : List<P>> registeredExtensions(): ArrayMapAccessor<FirExtension, List<FirExtension>, V> {
|
||||
return generateAccessor(P::class)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return generateAccessor(P::class, default = emptyList<P>() as V)
|
||||
}
|
||||
|
||||
fun <P : FirExtension, V : List<P>> registeredExtensions(kClass: KClass<P>): ArrayMapAccessor<FirExtension, List<FirExtension>, V> {
|
||||
return generateAccessor(kClass)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return generateAccessor(kClass, default = emptyList<P>() as V)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
-12
@@ -12,16 +12,20 @@ import org.jetbrains.kotlin.fir.caches.FirCache
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.caches.getValue
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.extensions.declarationGenerators
|
||||
import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.declaredMemberScopeProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@ThreadSafeMutableState
|
||||
class FirDeclaredMemberScopeProvider(val useSiteSession: FirSession) : FirSessionComponent {
|
||||
private val declaredMemberCache: FirCache<FirClass, FirClassDeclaredMemberScope, DeclaredMemberScopeContext> =
|
||||
private val declaredMemberCache: FirCache<FirClass, FirContainingNamesAwareScope, DeclaredMemberScopeContext> =
|
||||
useSiteSession.firCachesFactory.createCache { klass, context ->
|
||||
createDeclaredMemberScope(klass, context.useLazyNestedClassifierScope, context.existingNames, context.symbolProvider)
|
||||
}
|
||||
@@ -29,12 +33,14 @@ class FirDeclaredMemberScopeProvider(val useSiteSession: FirSession) : FirSessio
|
||||
private val nestedClassifierCache: FirCache<FirClass, FirNestedClassifierScope?, Nothing?> =
|
||||
useSiteSession.firCachesFactory.createCache { klass, _ -> createNestedClassifierScope(klass) }
|
||||
|
||||
private val extensions by lazy(LazyThreadSafetyMode.PUBLICATION) { useSiteSession.extensionService.declarationGenerators }
|
||||
|
||||
fun declaredMemberScope(
|
||||
klass: FirClass,
|
||||
useLazyNestedClassifierScope: Boolean,
|
||||
existingNames: List<Name>?,
|
||||
symbolProvider: FirSymbolProvider?
|
||||
): FirClassDeclaredMemberScope {
|
||||
): FirContainingNamesAwareScope {
|
||||
return declaredMemberCache.getValue(klass, DeclaredMemberScopeContext(useLazyNestedClassifierScope, existingNames, symbolProvider))
|
||||
}
|
||||
|
||||
@@ -49,11 +55,27 @@ class FirDeclaredMemberScopeProvider(val useSiteSession: FirSession) : FirSessio
|
||||
useLazyNestedClassifierScope: Boolean,
|
||||
existingNames: List<Name>?,
|
||||
symbolProvider: FirSymbolProvider?
|
||||
): FirClassDeclaredMemberScope {
|
||||
return if (klass.origin.generated) {
|
||||
FirGeneratedClassDeclaredMemberScope(useSiteSession, klass)
|
||||
} else {
|
||||
FirClassDeclaredMemberScopeImpl(useSiteSession, klass, useLazyNestedClassifierScope, existingNames, symbolProvider)
|
||||
): FirContainingNamesAwareScope {
|
||||
return when {
|
||||
klass.origin.generated -> {
|
||||
FirGeneratedClassDeclaredMemberScope(useSiteSession, klass, needNestedClassifierScope = true)
|
||||
}
|
||||
else -> {
|
||||
val baseScope = FirClassDeclaredMemberScopeImpl(
|
||||
useSiteSession,
|
||||
klass,
|
||||
useLazyNestedClassifierScope,
|
||||
existingNames,
|
||||
symbolProvider
|
||||
)
|
||||
if (extensions.any { useSiteSession.predicateBasedProvider.matches(it.predicate, klass) }) {
|
||||
FirCompositeScope(
|
||||
listOf(baseScope, FirGeneratedClassDeclaredMemberScope(useSiteSession, klass, needNestedClassifierScope = false))
|
||||
)
|
||||
} else {
|
||||
baseScope
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,17 +87,26 @@ class FirDeclaredMemberScopeProvider(val useSiteSession: FirSession) : FirSessio
|
||||
return if (klass.origin.generated) {
|
||||
FirGeneratedClassNestedClassifierScope(klass, useSiteSession)
|
||||
} else {
|
||||
FirNestedClassifierScopeImpl(klass, useSiteSession)
|
||||
val baseScope = FirNestedClassifierScopeImpl(klass, useSiteSession)
|
||||
if (extensions.any { useSiteSession.predicateBasedProvider.matches(it.predicate, klass) }) {
|
||||
FirCompositeNestedClassifierScope(
|
||||
listOf(baseScope, FirGeneratedClassNestedClassifierScope(klass, useSiteSession)),
|
||||
klass,
|
||||
useSiteSession
|
||||
)
|
||||
} else {
|
||||
baseScope
|
||||
}
|
||||
}.takeUnless { it.isEmpty() }
|
||||
}
|
||||
}
|
||||
|
||||
fun FirSession.declaredMemberScope(klass: FirClass): FirClassDeclaredMemberScope {
|
||||
fun FirSession.declaredMemberScope(klass: FirClass): FirContainingNamesAwareScope {
|
||||
return declaredMemberScopeProvider
|
||||
.declaredMemberScope(klass, useLazyNestedClassifierScope = false, existingNames = null, symbolProvider = null)
|
||||
}
|
||||
|
||||
fun FirSession.declaredMemberScope(klass: FirClassSymbol<*>): FirClassDeclaredMemberScope {
|
||||
fun FirSession.declaredMemberScope(klass: FirClassSymbol<*>): FirContainingNamesAwareScope {
|
||||
return declaredMemberScope(klass.fir)
|
||||
}
|
||||
|
||||
@@ -83,7 +114,7 @@ fun FirSession.declaredMemberScopeWithLazyNestedScope(
|
||||
klass: FirClass,
|
||||
existingNames: List<Name>,
|
||||
symbolProvider: FirSymbolProvider
|
||||
): FirScope {
|
||||
): FirContainingNamesAwareScope {
|
||||
return declaredMemberScopeProvider
|
||||
.declaredMemberScope(klass, useLazyNestedClassifierScope = true, existingNames = existingNames, symbolProvider = symbolProvider)
|
||||
}
|
||||
|
||||
+23
-17
@@ -16,19 +16,23 @@ import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||
import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
|
||||
import org.jetbrains.kotlin.fir.extensions.declarationGenerators
|
||||
import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
|
||||
class FirGeneratedClassDeclaredMemberScope(
|
||||
val useSiteSession: FirSession,
|
||||
val firClass: FirClass
|
||||
val firClass: FirClass,
|
||||
needNestedClassifierScope: Boolean
|
||||
) : FirClassDeclaredMemberScope() {
|
||||
private val extension: FirDeclarationGenerationExtension = firClass.findGeneratedExtension(useSiteSession)
|
||||
private val nestedClassifierScope: FirNestedClassifierScope? = useSiteSession.nestedClassifierScope(firClass)
|
||||
private val extensions: List<FirDeclarationGenerationExtension> = firClass.findGeneratedExtensions(useSiteSession)
|
||||
private val nestedClassifierScope: FirNestedClassifierScope? = runIf(needNestedClassifierScope) {
|
||||
useSiteSession.nestedClassifierScope(firClass)
|
||||
}
|
||||
|
||||
private val firCachesFactory = useSiteSession.firCachesFactory
|
||||
|
||||
@@ -47,17 +51,17 @@ class FirGeneratedClassDeclaredMemberScope(
|
||||
}
|
||||
|
||||
private val callableNamesCache: FirLazyValue<Set<Name>, Nothing?> = firCachesFactory.createLazyValue {
|
||||
extension.getCallableNamesForGeneratedClass(firClass.symbol)
|
||||
extensions.flatMapTo(mutableSetOf()) { it.getCallableNamesForClass(firClass.symbol) }
|
||||
}
|
||||
|
||||
// ------------------------------------------ generators ------------------------------------------
|
||||
|
||||
private fun generateMemberFunctions(name: Name): List<FirNamedFunctionSymbol> {
|
||||
return extension.generateFunctions(CallableId(firClass.classId, name), firClass.symbol)
|
||||
return extensions.flatMap { it.generateFunctions(CallableId(firClass.classId, name), firClass.symbol) }
|
||||
}
|
||||
|
||||
private fun generateMemberProperties(name: Name): List<FirPropertySymbol> {
|
||||
return extension.generateProperties(CallableId(firClass.classId, name), firClass.symbol)
|
||||
return extensions.flatMap { it.generateProperties(CallableId(firClass.classId, name), firClass.symbol) }
|
||||
}
|
||||
|
||||
private fun generateConstructors(): List<FirConstructorSymbol> {
|
||||
@@ -67,7 +71,7 @@ class FirGeneratedClassDeclaredMemberScope(
|
||||
} else {
|
||||
CallableId(classId.asSingleFqName().parent(), classId.shortClassName)
|
||||
}
|
||||
return extension.generateConstructors(callableId)
|
||||
return extensions.flatMap { it.generateConstructors(callableId) }
|
||||
}
|
||||
|
||||
// ------------------------------------------ scope methods ------------------------------------------
|
||||
@@ -109,7 +113,7 @@ class FirGeneratedClassNestedClassifierScope(
|
||||
klass: FirClass,
|
||||
useSiteSession: FirSession
|
||||
) : FirNestedClassifierScope(klass, useSiteSession) {
|
||||
private val extension = klass.findGeneratedExtension(useSiteSession)
|
||||
private val extensions = klass.findGeneratedExtensions(useSiteSession)
|
||||
|
||||
private val nestedClassifierCache: FirCache<Name, FirRegularClassSymbol?, Nothing?> =
|
||||
useSiteSession.firCachesFactory.createCache { name, _ ->
|
||||
@@ -118,7 +122,7 @@ class FirGeneratedClassNestedClassifierScope(
|
||||
|
||||
private val nestedClassifiersNames: FirLazyValue<Set<Name>, Nothing?> =
|
||||
useSiteSession.firCachesFactory.createLazyValue {
|
||||
extension.getNestedClassifiersNamesForGeneratedClass(klass.symbol)
|
||||
extensions.flatMapTo(mutableSetOf()) { it.getNestedClassifiersNames(klass.symbol) }
|
||||
}
|
||||
|
||||
private fun generateNestedClassifier(name: Name): FirRegularClassSymbol? {
|
||||
@@ -142,13 +146,15 @@ class FirGeneratedClassNestedClassifierScope(
|
||||
}
|
||||
|
||||
|
||||
private fun FirClass.findGeneratedExtension(useSiteSession: FirSession): FirDeclarationGenerationExtension {
|
||||
private fun FirClass.findGeneratedExtensions(useSiteSession: FirSession): List<FirDeclarationGenerationExtension> {
|
||||
val origin = origin
|
||||
require(origin is FirDeclarationOrigin.Plugin) {
|
||||
"GeneratedClassDeclaredMemberScope can not be created for non-generated class: ${this.render()}"
|
||||
val declarationGenerators = useSiteSession.extensionService.declarationGenerators
|
||||
return if (origin is FirDeclarationOrigin.Plugin) {
|
||||
declarationGenerators.filter { it.key == origin.key }.also {
|
||||
require(it.isNotEmpty()) { "Extension for ${origin.key} not found" }
|
||||
}
|
||||
} else {
|
||||
val predicateBasedProvider = useSiteSession.predicateBasedProvider
|
||||
declarationGenerators.filter { predicateBasedProvider.matches(it.predicate, this) }
|
||||
}
|
||||
|
||||
return useSiteSession.extensionService.declarationGenerators.firstOrNull {
|
||||
it.key == origin.key
|
||||
} ?: error("Extension for ${origin.key} not found")
|
||||
}
|
||||
|
||||
+22
@@ -59,6 +59,28 @@ class FirNestedClassifierScopeImpl(klass: FirClass, useSiteSession: FirSession)
|
||||
override fun getClassifierNames(): Set<Name> = classIndex.keys
|
||||
}
|
||||
|
||||
class FirCompositeNestedClassifierScope(
|
||||
val scopes: List<FirNestedClassifierScope>,
|
||||
klass: FirClass,
|
||||
useSiteSession: FirSession
|
||||
) : FirNestedClassifierScope(klass, useSiteSession) {
|
||||
override fun getNestedClassSymbol(name: Name): FirRegularClassSymbol? {
|
||||
error("Should not be called")
|
||||
}
|
||||
|
||||
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
|
||||
scopes.forEach { it.processClassifiersByNameWithSubstitution(name, processor) }
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean {
|
||||
return scopes.all { it.isEmpty() }
|
||||
}
|
||||
|
||||
override fun getClassifierNames(): Set<Name> {
|
||||
return scopes.flatMapTo(mutableSetOf()) { it.getClassifierNames() }
|
||||
}
|
||||
}
|
||||
|
||||
fun FirTypeParameterRef.toConeType(): ConeKotlinType = symbol.toConeType()
|
||||
|
||||
fun FirTypeParameterSymbol.toConeType(): ConeKotlinType = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(this), isNullable = false)
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.scopes
|
||||
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -37,6 +38,20 @@ class FirCompositeScope(val scopes: Iterable<FirScope>) : FirContainingNamesAwar
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <T> processComposite(
|
||||
process: FirScope.((T) -> Unit) -> Unit,
|
||||
noinline processor: (T) -> Unit
|
||||
) {
|
||||
val unique = mutableSetOf<T>()
|
||||
for (scope in scopes) {
|
||||
scope.process {
|
||||
if (unique.add(it)) {
|
||||
processor(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||
return processComposite(FirScope::processFunctionsByName, name, processor)
|
||||
}
|
||||
@@ -45,6 +60,10 @@ class FirCompositeScope(val scopes: Iterable<FirScope>) : FirContainingNamesAwar
|
||||
return processComposite(FirScope::processPropertiesByName, name, processor)
|
||||
}
|
||||
|
||||
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
||||
processComposite(FirScope::processDeclaredConstructors, processor)
|
||||
}
|
||||
|
||||
override fun getCallableNames(): Set<Name> {
|
||||
return scopes.flatMapTo(hashSetOf()) { it.getContainingCallableNamesIfPresent() }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user