[FIR] Change scheme of generating declarations by plugins
Methods `needToGenerateAdditionalMembersInClass` and `needToGenerateNestedClassifiersInClass` are removed, now compiler uses `get...Names` and `getTopLevel...` methods to determine which extension may generate declaration with specific classId/callableId This is needed to simplify API of FirDeclarationGenerationExtension and provide guarantee that `generate...` method will be called with specific classId/callableId only if specific extensions returned name for this id from `getName...` functions
This commit is contained in:
committed by
teamcityserver
parent
40d8451698
commit
cb0705ec03
-107
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.extensions
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||
import org.jetbrains.kotlin.fir.caches.FirCachesFactory
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.caches.getValue
|
||||
import org.jetbrains.kotlin.fir.declarations.validate
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class FirExtensionDeclarationsSymbolProvider private constructor(
|
||||
session: FirSession,
|
||||
cachesFactory: FirCachesFactory,
|
||||
private val extensions: List<FirDeclarationGenerationExtension>
|
||||
) : FirSymbolProvider(session), FirSessionComponent {
|
||||
companion object {
|
||||
fun create(session: FirSession): FirExtensionDeclarationsSymbolProvider? {
|
||||
val extensions = session.extensionService.declarationGenerators
|
||||
if (extensions.isEmpty()) return null
|
||||
return FirExtensionDeclarationsSymbolProvider(session, session.firCachesFactory, extensions)
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------ caches ------------------------------------------
|
||||
|
||||
private val classCache: FirCache<ClassId, FirClassLikeSymbol<*>?, Nothing?> = cachesFactory.createCache { classId, _ ->
|
||||
generateClassLikeDeclaration(classId)
|
||||
}
|
||||
|
||||
private val functionCache: FirCache<CallableId, List<FirNamedFunctionSymbol>, Nothing?> = cachesFactory.createCache { callableId, _ ->
|
||||
generateTopLevelFunctions(callableId)
|
||||
}
|
||||
|
||||
private val propertyCache: FirCache<CallableId, List<FirPropertySymbol>, Nothing?> = cachesFactory.createCache { callableId, _ ->
|
||||
generateTopLevelProperties(callableId)
|
||||
}
|
||||
|
||||
private val packageCache: FirCache<FqName, Boolean, Nothing?> = cachesFactory.createCache { packageFqName, _ ->
|
||||
hasPackage(packageFqName)
|
||||
}
|
||||
|
||||
// ------------------------------------------ generators ------------------------------------------
|
||||
|
||||
private fun generateClassLikeDeclaration(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||
val generatedClasses = extensions.mapNotNull { it.generateClassLikeDeclaration(classId) }.onEach { it.fir.validate() }
|
||||
return when (generatedClasses.size) {
|
||||
0 -> null
|
||||
1 -> generatedClasses.first()
|
||||
else -> error("Multiple plugins generated classes with same classId $classId\n${generatedClasses.joinToString("\n") { it.fir.render() }}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateTopLevelFunctions(callableId: CallableId): List<FirNamedFunctionSymbol> {
|
||||
return extensions.flatMap { it.generateFunctions(callableId, owner = null) }.onEach { it.fir.validate() }
|
||||
}
|
||||
|
||||
private fun generateTopLevelProperties(callableId: CallableId): List<FirPropertySymbol> {
|
||||
return extensions.flatMap { it.generateProperties(callableId, owner = null) }.onEach { it.fir.validate() }
|
||||
}
|
||||
|
||||
private fun hasPackage(packageFqName: FqName): Boolean {
|
||||
return extensions.any { it.hasPackage(packageFqName) }
|
||||
}
|
||||
|
||||
// ------------------------------------------ provider methods ------------------------------------------
|
||||
|
||||
override fun getClassLikeSymbolByClassId(classId: ClassId): FirClassLikeSymbol<*>? {
|
||||
return classCache.getValue(classId)
|
||||
}
|
||||
|
||||
@FirSymbolProviderInternals
|
||||
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
||||
val callableId = CallableId(packageFqName, name)
|
||||
destination += functionCache.getValue(callableId)
|
||||
destination += propertyCache.getValue(callableId)
|
||||
}
|
||||
|
||||
@FirSymbolProviderInternals
|
||||
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
||||
destination += functionCache.getValue(CallableId(packageFqName, name))
|
||||
}
|
||||
|
||||
@FirSymbolProviderInternals
|
||||
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
|
||||
destination += propertyCache.getValue(CallableId(packageFqName, name))
|
||||
}
|
||||
|
||||
override fun getPackage(fqName: FqName): FqName? {
|
||||
return fqName.takeIf { packageCache.getValue(fqName, null) }
|
||||
}
|
||||
}
|
||||
|
||||
val FirSession.generatedDeclarationsSymbolProvider: FirExtensionDeclarationsSymbolProvider? by FirSession.nullableSessionComponentAccessor()
|
||||
+5
-1
@@ -13,7 +13,11 @@ import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
@RequiresOptIn(message = "Should be used just only in resolve processor")
|
||||
annotation class AdapterForResolveProcessor
|
||||
|
||||
sealed class FirResolveProcessor(val session: FirSession, val scopeSession: ScopeSession)
|
||||
sealed class FirResolveProcessor(val session: FirSession, val scopeSession: ScopeSession) {
|
||||
open fun beforePhase() {}
|
||||
|
||||
open fun afterPhase() {}
|
||||
}
|
||||
|
||||
abstract class FirGlobalResolveProcessor(session: FirSession, scopeSession: ScopeSession) : FirResolveProcessor(session, scopeSession) {
|
||||
abstract fun process(files: Collection<FirFile>)
|
||||
|
||||
+2
@@ -22,6 +22,7 @@ class FirTotalResolveProcessor(session: FirSession, enablePluginPhases: Boolean
|
||||
|
||||
fun process(files: List<FirFile>) {
|
||||
for (processor in processors) {
|
||||
processor.beforePhase()
|
||||
when (processor) {
|
||||
is FirTransformerBasedResolveProcessor -> {
|
||||
for (file in files) {
|
||||
@@ -32,6 +33,7 @@ class FirTotalResolveProcessor(session: FirSession, enablePluginPhases: Boolean
|
||||
processor.process(files)
|
||||
}
|
||||
}
|
||||
processor.afterPhase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-1
@@ -22,11 +22,25 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.extensions.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.fqName
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
class FirPluginAnnotationsResolveProcessor(session: FirSession, scopeSession: ScopeSession) : FirTransformerBasedResolveProcessor(session, scopeSession) {
|
||||
class FirPluginAnnotationsResolveProcessor(
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
) : FirTransformerBasedResolveProcessor(session, scopeSession) {
|
||||
override val transformer = FirPluginAnnotationsResolveTransformer(session, scopeSession)
|
||||
|
||||
@OptIn(FirSymbolProviderInternals::class)
|
||||
override fun beforePhase() {
|
||||
session.generatedDeclarationsSymbolProvider?.disable()
|
||||
}
|
||||
|
||||
@OptIn(FirSymbolProviderInternals::class)
|
||||
override fun afterPhase() {
|
||||
session.generatedDeclarationsSymbolProvider?.enable()
|
||||
}
|
||||
}
|
||||
|
||||
class FirPluginAnnotationsResolveTransformer(
|
||||
|
||||
Reference in New Issue
Block a user