From 15abd839edd603fc58aad08da55cd66c50ade705 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 21 Sep 2021 16:51:45 +0300 Subject: [PATCH] [FIR] Rewrite algorithm of generating declarations by plugins Before there was separate global stage which asks extensions to generate new declarations. Now it is changed to provider like requests, so extensions will decide do they have declarations with specific classId/callableId or not --- .../kotlin/fir/session/FirSessionFactory.kt | 13 ++- .../FirDeclarationGenerationExtension.kt | 28 ++--- .../FirExtensionDeclarationsSymbolProvider.kt | 99 +++++++++++++++++ .../transformers/FirTotalResolveProcessor.kt | 2 - .../FirGlobalClassGenerationProcessor.kt | 70 ------------ .../FirGlobalNewMemberGenerationProcessor.kt | 67 ----------- .../fir/declarations/FirDeclarationOrigin.kt | 4 +- .../fir/declarations/FirResolvePhase.kt | 2 - .../plugin/FirAllOpenComponentRegistrar.kt | 8 +- .../generators/AllOpenMemberGenerator.kt | 60 ---------- .../generators/AllOpenNestedClassGenerator.kt | 105 ------------------ .../AllOpenRecursiveNestedClassGenerator.kt | 87 --------------- .../AllOpenTopLevelDeclarationsGenerator.kt | 82 ++++++-------- .../memberGen/topLevelCallables.fir.txt | 14 +++ .../testData/memberGen/topLevelCallables.kt | 17 +++ .../FirAllOpenDiagnosticTestGenerated.java | 6 + 16 files changed, 199 insertions(+), 465 deletions(-) create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionDeclarationsSymbolProvider.kt delete mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalClassGenerationProcessor.kt delete mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNewMemberGenerationProcessor.kt delete mode 100644 plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenMemberGenerator.kt delete mode 100644 plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenNestedClassGenerator.kt delete mode 100644 plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenRecursiveNestedClassGenerator.kt create mode 100644 plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelCallables.fir.txt create mode 100644 plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelCallables.kt diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt index 5a084d4cb4b..a76f2abdc4b 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.checkers.registerJvmCheckers import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider import org.jetbrains.kotlin.fir.extensions.BunchOfRegisteredExtensions +import org.jetbrains.kotlin.fir.extensions.FirExtensionDeclarationsSymbolProvider import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.registerExtensions import org.jetbrains.kotlin.fir.java.FirCliSession @@ -157,6 +158,12 @@ object FirSessionFactory { ) } + FirSessionConfigurator(this).apply { + registerCommonCheckers() + registerJvmCheckers() + init() + }.configure() + val dependenciesSymbolProvider = FirDependenciesSymbolProviderImpl(this) register( FirSymbolProvider::class, @@ -165,6 +172,7 @@ object FirSessionFactory { listOfNotNull( firProvider.symbolProvider, symbolProviderForBinariesFromIncrementalCompilation, + FirExtensionDeclarationsSymbolProvider.create(this), JavaSymbolProvider(this, projectEnvironment.getFirJavaFacade(this, moduleData, scope)), dependenciesSymbolProvider, ) @@ -177,11 +185,6 @@ object FirSessionFactory { ) FirJvmDefaultErrorMessages.installJvmErrorMessages() - FirSessionConfigurator(this).apply { - registerCommonCheckers() - registerJvmCheckers() - init() - }.configure() projectEnvironment.registerAsJavaElementFinder(this) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirDeclarationGenerationExtension.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirDeclarationGenerationExtension.kt index b7e93f3d89c..34b851d7b4a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirDeclarationGenerationExtension.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirDeclarationGenerationExtension.kt @@ -6,10 +6,13 @@ package org.jetbrains.kotlin.fir.extensions import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration -import org.jetbrains.kotlin.fir.declarations.FirDeclaration -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClass +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName import kotlin.reflect.KClass /* @@ -26,19 +29,10 @@ abstract class FirDeclarationGenerationExtension(session: FirSession) : FirPredi final override val extensionType: KClass = FirDeclarationGenerationExtension::class - abstract fun generateClasses( - annotatedDeclaration: FirDeclaration, - owners: List - ): List> - - abstract fun generateMembersForGeneratedClass(generatedClass: GeneratedClass): List - - abstract fun generateMembers( - annotatedDeclaration: FirDeclaration, - owners: List - ): List> - - data class GeneratedDeclaration(val newDeclaration: T, val owner: FirAnnotatedDeclaration) + open fun generateClassLikeDeclaration(classId: ClassId, owner: FirClassSymbol<*>?): FirClassLikeSymbol<*>? = null + open fun generateFunctions(callableId: CallableId, owner: FirClassSymbol<*>?): List = emptyList() + open fun generateProperties(callableId: CallableId, owner: FirClassSymbol<*>?): List = emptyList() + open fun hasPackage(packageFqName: FqName): Boolean = false fun interface Factory : FirExtension.Factory } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionDeclarationsSymbolProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionDeclarationsSymbolProvider.kt new file mode 100644 index 00000000000..0e2ac40a11f --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionDeclarationsSymbolProvider.kt @@ -0,0 +1,99 @@ +/* + * 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.caches.FirCache +import org.jetbrains.kotlin.fir.caches.FirCachesFactory +import org.jetbrains.kotlin.fir.caches.firCachesFactory +import org.jetbrains.kotlin.fir.declarations.validate +import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +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 +) : FirSymbolProvider(session) { + 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?, Nothing?> = cachesFactory.createCache { classId, _ -> + generateClassLikeDeclaration(classId) + } + + private val functionCache: FirCache, Nothing?> = cachesFactory.createCache { callableId, _ -> + generateTopLevelFunctions(callableId) + } + + private val propertyCache: FirCache, Nothing?> = cachesFactory.createCache { callableId, _ -> + generateTopLevelProperties(callableId) + } + + private val packageCache: FirCache = cachesFactory.createCache { packageFqName, _ -> + hasPackage(packageFqName) + } + + // ------------------------------------------ generators ------------------------------------------ + + private fun generateClassLikeDeclaration(classId: ClassId): FirClassLikeSymbol<*>? { + // TODO: what we should do if multiple extensions want to generate class with same classId? + return extensions.firstNotNullOfOrNull { it.generateClassLikeDeclaration(classId, owner = null) }?.also { it.fir.validate() } + } + + private fun generateTopLevelFunctions(callableId: CallableId): List { + return extensions.flatMap { it.generateFunctions(callableId, owner = null) }.onEach { it.fir.validate() } + } + + private fun generateTopLevelProperties(callableId: CallableId): List { + 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, context = null) + } + + @FirSymbolProviderInternals + override fun getTopLevelCallableSymbolsTo(destination: MutableList>, packageFqName: FqName, name: Name) { + destination += functionCache.getValue(CallableId(packageFqName, name), context = null) + destination += propertyCache.getValue(CallableId(packageFqName, name), context = null) + } + + @FirSymbolProviderInternals + override fun getTopLevelFunctionSymbolsTo(destination: MutableList, packageFqName: FqName, name: Name) { + destination += functionCache.getValue(CallableId(packageFqName, name), context = null) + } + + @FirSymbolProviderInternals + override fun getTopLevelPropertySymbolsTo(destination: MutableList, packageFqName: FqName, name: Name) { + destination += propertyCache.getValue(CallableId(packageFqName, name), context = null) + } + + override fun getPackage(fqName: FqName): FqName? { + return fqName.takeIf { packageCache.getValue(fqName, null) } + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt index 32bdc9d8331..fad95b817cc 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirTotalResolveProcessor.kt @@ -66,7 +66,6 @@ fun FirResolvePhase.createCompilerProcessorByPhase( return when (this) { RAW_FIR -> throw IllegalArgumentException("Raw FIR building phase does not have a transformer") ANNOTATIONS_FOR_PLUGINS -> FirPluginAnnotationsResolveProcessor(session, scopeSession) - CLASS_GENERATION -> FirGlobalClassGenerationProcessor(session, scopeSession) IMPORTS -> FirImportResolveProcessor(session, scopeSession) SUPER_TYPES -> FirSupertypeResolverProcessor(session, scopeSession) SEALED_CLASS_INHERITORS -> FirSealedClassInheritorsProcessor(session, scopeSession) @@ -74,7 +73,6 @@ fun FirResolvePhase.createCompilerProcessorByPhase( STATUS -> FirStatusResolveProcessor(session, scopeSession) ARGUMENTS_OF_ANNOTATIONS -> FirAnnotationArgumentsResolveProcessor(session, scopeSession) CONTRACTS -> FirContractResolveProcessor(session, scopeSession) - NEW_MEMBERS_GENERATION -> FirGlobalNewMemberGenerationProcessor(session, scopeSession) IMPLICIT_TYPES_BODY_RESOLVE -> FirImplicitTypeBodyResolveProcessor(session, scopeSession) BODY_RESOLVE -> FirBodyResolveProcessor(session, scopeSession) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalClassGenerationProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalClassGenerationProcessor.kt deleted file mode 100644 index 1476ed7e2c1..00000000000 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalClassGenerationProcessor.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2010-2020 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.resolve.transformers.plugin - -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirAnnotatedDeclaration -import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.utils.addDeclaration -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.extensions.predicateBasedProvider -import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.firProvider -import org.jetbrains.kotlin.fir.resolve.providers.FirProviderInternals -import org.jetbrains.kotlin.fir.resolve.transformers.FirGlobalResolveProcessor - -class FirGlobalClassGenerationProcessor( - session: FirSession, - scopeSession: ScopeSession -) : FirGlobalResolveProcessor(session, scopeSession) { - override fun process(files: Collection) { - val extensions = session.extensionService.declarationGenerators - if (extensions.isEmpty()) return - val provider = session.predicateBasedProvider - for (extension in extensions) { - var annotatedDeclarations = provider.getSymbolsWithOwnersByPredicate(extension.predicate) - while (annotatedDeclarations.isNotEmpty()) { - val newClasses = generateClasses(annotatedDeclarations, extension) - annotatedDeclarations = provider.getSymbolsWithOwnersByPredicate(newClasses, extension.predicate) - } - } - } - - private fun generateClasses( - declarations: List>>, - extension: FirDeclarationGenerationExtension, - ): List { - val newClasses = mutableListOf() - for ((declaration, owners) in declarations) { - generateClass(extension, declaration, owners, newClasses) - } - return newClasses - } - - @OptIn(FirProviderInternals::class) - private fun generateClass( - extension: FirDeclarationGenerationExtension, - declaration: FirAnnotatedDeclaration, - owners: List, - newClasses: MutableList - ) { - val generatedClasses = extension.generateClasses(declaration, owners) - for ((klass, owner) in generatedClasses) { - when (owner) { - is FirRegularClass -> owner.addDeclaration(klass) - is FirFile -> owner.addDeclaration(klass) - else -> {} - } - session.generatedClassIndex.registerClass(klass, owner) - session.predicateBasedProvider.registerGeneratedDeclaration(klass, owner) - session.firProvider.recordGeneratedClass(owner, klass) - newClasses += klass - } - } -} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNewMemberGenerationProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNewMemberGenerationProcessor.kt deleted file mode 100644 index 8ae89730330..00000000000 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNewMemberGenerationProcessor.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2010-2020 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.resolve.transformers.plugin - -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.utils.addDeclaration -import org.jetbrains.kotlin.fir.declarations.validate -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.extensions.predicateBasedProvider -import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.firProvider -import org.jetbrains.kotlin.fir.resolve.providers.FirProviderInternals -import org.jetbrains.kotlin.fir.resolve.transformers.FirGlobalResolveProcessor - -class FirGlobalNewMemberGenerationProcessor( - session: FirSession, - scopeSession: ScopeSession -) : FirGlobalResolveProcessor(session, scopeSession) { - private val index = session.generatedClassIndex - private val provider = session.predicateBasedProvider - - override fun process(files: Collection) { - val extensions = session.extensionService.declarationGenerators - if (extensions.isEmpty()) return - for (extension in extensions) { - generateNewMembers(extension) - fillGeneratedClasses(extension) - } - } - - @OptIn(FirProviderInternals::class) - private fun generateNewMembers(extension: FirDeclarationGenerationExtension) { - val declarations = provider.getSymbolsWithOwnersByPredicate(extension.predicate) - for ((declaration, owners) in declarations) { - val newMembers = extension.generateMembers(declaration, owners) - for ((newMember, owner) in newMembers) { - newMember.validate() - when (owner) { - is FirRegularClass -> owner.addDeclaration(newMember) - is FirFile -> owner.addDeclaration(newMember) - else -> error("Should not be here") - } - session.firProvider.recordGeneratedMember(owner, newMember) - } - } - } - - @OptIn(FirProviderInternals::class) - private fun fillGeneratedClasses(extension: FirDeclarationGenerationExtension) { - for (generatedClass in index[extension.key]) { - val klass = generatedClass.klass - val newMembers = extension.generateMembersForGeneratedClass(generatedClass) - for (newMember in newMembers) { - newMember.validate() - klass.addDeclaration(newMember) - session.firProvider.recordGeneratedMember(klass, newMember) - } - } - } -} diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt index 8980161d453..24675a1be32 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirDeclarationOrigin.kt @@ -25,4 +25,6 @@ sealed class FirDeclarationOrigin(private val displayName: String? = null, val f } } -abstract class FirPluginKey +abstract class FirPluginKey { + val origin: FirDeclarationOrigin = FirDeclarationOrigin.Plugin(this) +} diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt index 53eccd3b96b..995c26d83fc 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.declarations enum class FirResolvePhase(val pluginPhase: Boolean = false, val noProcessor: Boolean = false) { RAW_FIR(noProcessor = true), ANNOTATIONS_FOR_PLUGINS(pluginPhase = true), - CLASS_GENERATION(pluginPhase = true), IMPORTS, SUPER_TYPES, SEALED_CLASS_INHERITORS, @@ -16,7 +15,6 @@ enum class FirResolvePhase(val pluginPhase: Boolean = false, val noProcessor: Bo STATUS, ARGUMENTS_OF_ANNOTATIONS, CONTRACTS, - NEW_MEMBERS_GENERATION(pluginPhase = true), IMPLICIT_TYPES_BODY_RESOLVE, BODY_RESOLVE; diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirAllOpenComponentRegistrar.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirAllOpenComponentRegistrar.kt index da2dcde7d80..7ffb5134899 100644 --- a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirAllOpenComponentRegistrar.kt +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirAllOpenComponentRegistrar.kt @@ -15,10 +15,10 @@ class FirAllOpenComponentRegistrar : FirExtensionRegistrar() { +::AllOpenSupertypeGenerator // Declaration generators - +::AllOpenMemberGenerator - +::AllOpenNestedClassGenerator +// +::AllOpenMemberGenerator +// +::AllOpenNestedClassGenerator +::AllOpenAdditionalCheckers +::AllOpenTopLevelDeclarationsGenerator - +::AllOpenRecursiveNestedClassGenerator +// +::AllOpenRecursiveNestedClassGenerator } -} \ No newline at end of file +} diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenMemberGenerator.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenMemberGenerator.kt deleted file mode 100644 index 220456dafa5..00000000000 --- a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenMemberGenerator.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2010-2020 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.plugin.generators - -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction -import org.jetbrains.kotlin.fir.declarations.utils.classId -import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension -import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate -import org.jetbrains.kotlin.fir.extensions.predicate.and -import org.jetbrains.kotlin.fir.extensions.predicate.has -import org.jetbrains.kotlin.fir.extensions.predicate.under -import org.jetbrains.kotlin.fir.moduleData -import org.jetbrains.kotlin.fir.plugin.AllOpenPluginKey -import org.jetbrains.kotlin.fir.plugin.fqn -import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClass -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.name.CallableId -import org.jetbrains.kotlin.name.Name - -class AllOpenMemberGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) { - override fun generateClasses( - annotatedDeclaration: FirDeclaration, - owners: List - ): List> { - return emptyList() - } - - override fun generateMembersForGeneratedClass(generatedClass: GeneratedClass): List { - return emptyList() - } - - override fun generateMembers( - annotatedDeclaration: FirDeclaration, - owners: List - ): List> { - if (annotatedDeclaration !is FirProperty) return emptyList() - val owner = owners.last() as? FirRegularClass ?: return emptyList() - val propertyName = annotatedDeclaration.name.identifier - val function = buildSimpleFunction { - moduleData = session.moduleData - resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES - origin = FirDeclarationOrigin.Plugin(key) - returnTypeRef = annotatedDeclaration.returnTypeRef - status = annotatedDeclaration.status - name = Name.identifier("hello${propertyName.replaceFirstChar(Char::uppercaseChar)}") - symbol = FirNamedFunctionSymbol(CallableId(owner.classId, name)) - } - return listOf(GeneratedDeclaration(function, owner)) - } - - override val predicate: DeclarationPredicate = under("WithGenerated".fqn()) and has("WithHello".fqn()) - - override val key: FirPluginKey - get() = AllOpenPluginKey -} diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenNestedClassGenerator.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenNestedClassGenerator.kt deleted file mode 100644 index c7d41047f46..00000000000 --- a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenNestedClassGenerator.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2010-2020 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.plugin.generators - -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.EffectiveVisibility -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.builder.buildConstructor -import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass -import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction -import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl -import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension -import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate -import org.jetbrains.kotlin.fir.extensions.predicate.has -import org.jetbrains.kotlin.fir.moduleData -import org.jetbrains.kotlin.fir.plugin.AllOpenPluginKey -import org.jetbrains.kotlin.fir.plugin.fqn -import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClass -import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl -import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol -import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef -import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl -import org.jetbrains.kotlin.name.CallableId -import org.jetbrains.kotlin.name.Name - -class AllOpenNestedClassGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) { - override fun generateClasses( - annotatedDeclaration: FirDeclaration, - owners: List - ): List> { - val owner = annotatedDeclaration as? FirRegularClass ?: return emptyList() - val newClass = buildRegularClass { - moduleData = session.moduleData - resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES - origin = FirDeclarationOrigin.Plugin(key) - status = FirResolvedDeclarationStatusImpl( - Visibilities.Private, - Modality.FINAL, - EffectiveVisibility.PrivateInClass - ).apply { - isInner = true - } - classKind = ClassKind.CLASS - name = Name.identifier("Foo") - symbol = FirRegularClassSymbol(owner.symbol.classId.createNestedClassId(name)) - scopeProvider = owner.scopeProvider - } - return listOf(GeneratedDeclaration(newClass, owner)) - } - - override fun generateMembersForGeneratedClass(generatedClass: GeneratedClass): List { - val klass = generatedClass.klass - - val classId = klass.symbol.classId - val constructor = buildConstructor { - moduleData = session.moduleData - resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES - origin = FirDeclarationOrigin.Plugin(key) - returnTypeRef = buildResolvedTypeRef { - type = ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(classId), emptyArray(), isNullable = false) - } - status = FirResolvedDeclarationStatusImpl( - Visibilities.Public, - Modality.FINAL, - EffectiveVisibility.Public - ) - symbol = FirConstructorSymbol(CallableId(classId, classId.shortClassName)) - } - - val function = buildSimpleFunction { - moduleData = session.moduleData - resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES - origin = FirDeclarationOrigin.Plugin(key) - returnTypeRef = session.builtinTypes.intType - status = FirResolvedDeclarationStatusImpl( - Visibilities.Public, - Modality.FINAL, - EffectiveVisibility.Public - ) - name = Name.identifier("hello") - symbol = FirNamedFunctionSymbol(CallableId(classId, name)) - } - return listOf(constructor, function) - } - - override fun generateMembers( - annotatedDeclaration: FirDeclaration, - owners: List - ): List> { - return emptyList() - } - - override val predicate: DeclarationPredicate = has("WithNestedFoo".fqn()) - - override val key: FirPluginKey - get() = AllOpenPluginKey -} diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenRecursiveNestedClassGenerator.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenRecursiveNestedClassGenerator.kt deleted file mode 100644 index d0a10a80ea4..00000000000 --- a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenRecursiveNestedClassGenerator.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2010-2020 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.plugin.generators - -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.EffectiveVisibility -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass -import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl -import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotation -import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyAnnotationArgumentMapping -import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension -import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate -import org.jetbrains.kotlin.fir.extensions.predicate.has -import org.jetbrains.kotlin.fir.moduleData -import org.jetbrains.kotlin.fir.plugin.fqn -import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClass -import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol -import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef -import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.Name - -class AllOpenRecursiveNestedClassGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) { - override fun generateClasses( - annotatedDeclaration: FirDeclaration, - owners: List - ): List> { - if (owners.size > 2) return emptyList() - val owner = annotatedDeclaration as? FirRegularClass ?: return emptyList() - val newClass = buildRegularClass { - moduleData = session.moduleData - resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES - origin = FirDeclarationOrigin.Plugin(key) - status = FirResolvedDeclarationStatusImpl( - Visibilities.Public, - Modality.FINAL, - EffectiveVisibility.Public - ) - classKind = ClassKind.CLASS - name = Name.identifier("Nested") - symbol = FirRegularClassSymbol(owner.symbol.classId.createNestedClassId(name)) - scopeProvider = owner.scopeProvider - annotations += buildAnnotation { - annotationTypeRef = buildResolvedTypeRef { - type = ConeClassLikeTypeImpl( - ConeClassLikeLookupTagImpl(annotationClassId), - emptyArray(), - isNullable = false - ) - } - argumentMapping = FirEmptyAnnotationArgumentMapping - } - } - return listOf(GeneratedDeclaration(newClass, owner)) - } - - override fun generateMembersForGeneratedClass(generatedClass: GeneratedClass): List { - return emptyList() - } - - override fun generateMembers( - annotatedDeclaration: FirDeclaration, - owners: List - ): List> { - return emptyList() - } - - override val key: FirPluginKey - get() = Key - - override val predicate: DeclarationPredicate - get() = has("B".fqn()) - - private val annotationClassId = "B".fqn().let { - ClassId(it.parent(), it.shortName()) - } - - private object Key : FirPluginKey() -} diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenTopLevelDeclarationsGenerator.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenTopLevelDeclarationsGenerator.kt index 26f033f5f59..d52f4174c4b 100644 --- a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenTopLevelDeclarationsGenerator.kt +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenTopLevelDeclarationsGenerator.kt @@ -5,82 +5,74 @@ package org.jetbrains.kotlin.fir.plugin.generators -import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.EffectiveVisibility import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction +import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate import org.jetbrains.kotlin.fir.extensions.predicate.has +import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider import org.jetbrains.kotlin.fir.moduleData -import org.jetbrains.kotlin.fir.packageFqName +import org.jetbrains.kotlin.fir.plugin.AllOpenPluginKey import org.jetbrains.kotlin.fir.plugin.fqn -import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClass -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.* +import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.name.CallableId -import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name class AllOpenTopLevelDeclarationsGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) { - override fun generateClasses( - annotatedDeclaration: FirDeclaration, - owners: List - ): List> { - val file = owners.first() as FirFile - val klass = annotatedDeclaration as? FirRegularClass ?: return emptyList() - val newClass = buildRegularClass { - moduleData = session.moduleData - resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES - origin = FirDeclarationOrigin.Plugin(key) - status = FirResolvedDeclarationStatusImpl( - Visibilities.Public, - Modality.FINAL, - EffectiveVisibility.Public - ) - classKind = ClassKind.OBJECT - name = Name.identifier("TopLevel${klass.name}") - symbol = FirRegularClassSymbol(ClassId(file.packageFqName, name)) - scopeProvider = klass.scopeProvider - } - return listOf(GeneratedDeclaration(newClass, file)) + private val predicateBasedProvider = session.predicateBasedProvider + private val matchedClasses by lazy { + predicateBasedProvider.getSymbolsByPredicate(predicate).map { it.symbol }.filterIsInstance() } - override fun generateMembersForGeneratedClass(generatedClass: GeneratedClass): List { - val klass = generatedClass.klass + override fun generateFunctions(callableId: CallableId, owner: FirClassSymbol<*>?): List { + if (owner != null) return emptyList() + val matchedClassSymbol = findMatchedClassForFunction(callableId) ?: return emptyList() val function = buildSimpleFunction { moduleData = session.moduleData - resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES - origin = FirDeclarationOrigin.Plugin(key) - returnTypeRef = session.builtinTypes.intType + origin = key.origin status = FirResolvedDeclarationStatusImpl( Visibilities.Public, Modality.FINAL, EffectiveVisibility.Public ) - name = Name.identifier("hello") - symbol = FirNamedFunctionSymbol(CallableId(klass.symbol.classId, name)) + returnTypeRef = session.builtinTypes.stringType + valueParameters += buildValueParameter { + moduleData = session.moduleData + origin = key.origin + returnTypeRef = buildResolvedTypeRef { + type = ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(matchedClassSymbol.classId), emptyArray(), isNullable = false) + } + name = Name.identifier("value") + symbol = FirValueParameterSymbol(name) + isCrossinline = false + isNoinline = false + isVararg = false + } + symbol = FirNamedFunctionSymbol(callableId) + name = callableId.callableName } - return listOf(function) + return listOf(function.symbol) } - override fun generateMembers( - annotatedDeclaration: FirDeclaration, - owners: List - ): List> { - return emptyList() + private fun findMatchedClassForFunction(callableId: CallableId): FirRegularClassSymbol? { + // We generate only top-level functions + if (callableId.classId != null) return null + return matchedClasses + .filter { it.classId.packageFqName == callableId.packageName } + .firstOrNull { callableId.callableName.identifier == "dummy${it.classId.shortClassName.identifier}" } } - override val key: FirPluginKey - get() = Key + override val key: AllOpenPluginKey + get() = AllOpenPluginKey override val predicate: DeclarationPredicate get() = has("A".fqn()) - private object Key : FirPluginKey() } diff --git a/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelCallables.fir.txt b/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelCallables.fir.txt new file mode 100644 index 00000000000..51d324a3dd8 --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelCallables.fir.txt @@ -0,0 +1,14 @@ +FILE: topLevelCallables.kt + @R|org/jetbrains/kotlin/fir/plugin/A|() public final class MySuperClass : R|kotlin/Any| { + public constructor(): R|foo/MySuperClass| { + super() + } + + public final fun test(): R|kotlin/Unit| { + lval s: R|kotlin/String| = R|foo/dummyMySuperClass|(this@R|foo/MySuperClass|) + R|foo/takeString|(R|/s|) + } + + } + public final fun takeString(s: R|kotlin/String|): R|kotlin/Unit| { + } diff --git a/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelCallables.kt b/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelCallables.kt new file mode 100644 index 00000000000..2d5ea00a24c --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelCallables.kt @@ -0,0 +1,17 @@ +package foo + +import org.jetbrains.kotlin.fir.plugin.A + +/* + * Plugin generates `dummyClassName(value: ClassName): String` function for each class annotated with @A + */ + +@A +class MySuperClass { + fun test() { + val s = dummyMySuperClass(this) + takeString(s) + } +} + +fun takeString(s: String) {} diff --git a/plugins/fir/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/FirAllOpenDiagnosticTestGenerated.java b/plugins/fir/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/FirAllOpenDiagnosticTestGenerated.java index 074842a6892..3d3989bed8b 100644 --- a/plugins/fir/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/FirAllOpenDiagnosticTestGenerated.java +++ b/plugins/fir/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/FirAllOpenDiagnosticTestGenerated.java @@ -67,6 +67,12 @@ public class FirAllOpenDiagnosticTestGenerated extends AbstractFirAllOpenDiagnos runTest("plugins/fir/fir-plugin-prototype/testData/memberGen/recursiveNestedClasses.kt"); } + @Test + @TestMetadata("topLevelCallables.kt") + public void testTopLevelCallables() throws Exception { + runTest("plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelCallables.kt"); + } + @Test @TestMetadata("topLevelClass.kt") public void testTopLevelClass() throws Exception {