diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirSessionCommonComponents.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirSessionCommonComponents.kt index c28295aac0a..21eb7f67c84 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirSessionCommonComponents.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirSessionCommonComponents.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir import org.jetbrains.kotlin.fir.extensions.FirExtensionService import org.jetbrains.kotlin.fir.extensions.FirPredicateBasedProvider import org.jetbrains.kotlin.fir.extensions.FirRegisteredPluginAnnotations +import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedNestedClassIndex import org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider import org.jetbrains.kotlin.fir.types.FirCorrespondingSupertypesCache @@ -18,4 +19,5 @@ fun FirSession.registerCommonComponents() { register(FirExtensionService::class, FirExtensionService(this)) register(FirRegisteredPluginAnnotations::class, FirRegisteredPluginAnnotations.create(this)) register(FirPredicateBasedProvider::class, FirPredicateBasedProvider.create(this)) + register(GeneratedNestedClassIndex::class, GeneratedNestedClassIndex.create()) } \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirClassGenerationExtension.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirClassGenerationExtension.kt deleted file mode 100644 index 3d623d559c5..00000000000 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirClassGenerationExtension.kt +++ /dev/null @@ -1,44 +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.extensions - -import org.jetbrains.kotlin.fir.FirAnnotationContainer -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirDeclaration -import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import kotlin.reflect.KClass - -/* - * TODO: - * - add registration of new files - * - check that annotations or meta-annotations is not empty - */ -abstract class FirClassGenerationExtension(session: FirSession) : FirPredicateBasedExtension(session) { - companion object { - val NAME = FirExtensionPointName("StatusTransformer") - } - - final override val name: FirExtensionPointName - get() = NAME - - final override val extensionType: KClass = FirClassGenerationExtension::class - - abstract fun generateClass( - containingFile: FirFile, - annotatedDeclaration: T - ): List where T : FirDeclaration, T : FirAnnotationContainer - - data class GeneratedClass(val klass: FirRegularClass, val container: FirDeclaration) { - init { - require(container is FirRegularClass || container is FirFile) - } - } - - fun interface Factory : FirExtension.Factory -} - -val FirExtensionService.classGenerationExtensions: List by FirExtensionService.registeredExtensions() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExistingClassModificationExtension.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExistingClassModificationExtension.kt new file mode 100644 index 00000000000..0d76ade5462 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExistingClassModificationExtension.kt @@ -0,0 +1,46 @@ +/* + * 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.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.GeneratedNestedClass +import kotlin.reflect.KClass + +/* + * TODO: + * - check that annotations or meta-annotations is not empty + */ +abstract class FirExistingClassModificationExtension(session: FirSession) : FirPredicateBasedExtension(session) { + companion object { + val NAME = FirExtensionPointName("ExistingClassModification") + } + + final override val name: FirExtensionPointName + get() = NAME + + final override val extensionType: KClass = FirExistingClassModificationExtension::class + + abstract fun generateNestedClasses( + annotatedDeclaration: FirDeclaration, + owners: List + ): List> + + abstract fun generateMembersForNestedClasses(generatedNestedClass: GeneratedNestedClass): List + + abstract fun generateMembers( + annotatedDeclaration: FirDeclaration, + owners: List + ): List> + + data class GeneratedDeclaration(val newDeclaration: T, val owner: FirRegularClass) + + fun interface Factory : FirExtension.Factory +} + +val FirExtensionService.existingClassModifiers: List by FirExtensionService.registeredExtensions() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionRegistrar.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionRegistrar.kt index e0bdff6f391..ae30a832ddb 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionRegistrar.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirExtensionRegistrar.kt @@ -16,7 +16,7 @@ abstract class FirExtensionRegistrar { ) { val AVAILABLE_EXTENSIONS = listOf( FirStatusTransformerExtension::class, - FirClassGenerationExtension::class, + FirExistingClassModificationExtension::class, AbstractFirAdditionalCheckersExtension::class ) } @@ -30,8 +30,8 @@ abstract class FirExtensionRegistrar { } @JvmName("plusClassGenerationExtension") - operator fun ((FirSession) -> FirClassGenerationExtension).unaryPlus() { - registerExtension(FirClassGenerationExtension::class, FirClassGenerationExtension.Factory { this.invoke(it) }) + operator fun ((FirSession) -> FirExistingClassModificationExtension).unaryPlus() { + registerExtension(FirExistingClassModificationExtension::class, FirExistingClassModificationExtension.Factory { this.invoke(it) }) } @JvmName("plusAdditionalCheckersExtension") diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirPredicateBasedProvider.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirPredicateBasedProvider.kt index 366a242d217..c797f62b734 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirPredicateBasedProvider.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirPredicateBasedProvider.kt @@ -25,6 +25,9 @@ abstract class FirPredicateBasedProvider : FirSessionComponent { } abstract fun getSymbolsByPredicate(predicate: DeclarationPredicate): List + abstract fun getSymbolsWithOwnersByPredicate( + predicate: DeclarationPredicate + ): List>> abstract fun registerAnnotatedDeclaration(declaration: FirAnnotatedDeclaration, owners: PersistentList) @@ -43,6 +46,10 @@ private class FirPredicateBasedProviderImpl(private val session: FirSession) : F } } + override fun getSymbolsWithOwnersByPredicate(predicate: DeclarationPredicate): List>> { + return getSymbolsByPredicate(predicate).map { it to cache.ownersForDeclaration.getValue(it) } + } + override fun registerAnnotatedDeclaration(declaration: FirAnnotatedDeclaration, owners: PersistentList) { cache.ownersForDeclaration[declaration] = owners registerOwnersDeclarations(declaration, owners) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt index a7f86c0e19c..5002065aaf3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/ResolvePhaseUtils.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.resolve.transformers +import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase.* @@ -12,9 +13,10 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveProcessor import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitTypeBodyResolveProcessor import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractResolveProcessor -import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirGlobalExtensionStatusProcessor -import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirPluginAnnotationsResolveProcessor -import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirTransformerBasedExtensionStatusProcessor +import org.jetbrains.kotlin.fir.resolve.transformers.plugin.* +import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult +import org.jetbrains.kotlin.fir.visitors.FirTransformer +import org.jetbrains.kotlin.fir.visitors.compose fun FirResolvePhase.createCompilerProcessorByPhase( session: FirSession, @@ -23,7 +25,7 @@ fun FirResolvePhase.createCompilerProcessorByPhase( return when (this) { RAW_FIR -> throw IllegalStateException("Raw FIR building phase does not have a transformer") ANNOTATIONS_FOR_PLUGINS -> FirPluginAnnotationsResolveProcessor(session, scopeSession) -// FIRST_PLUGIN_GENERATION -> FirFirstGenerationTransformer() + NESTED_CLASS_GENERATION -> FirGlobalNestedClassGenerationProcessor(session, scopeSession) IMPORTS -> FirImportResolveProcessor(session, scopeSession) SUPER_TYPES -> FirSupertypeResolverProcessor(session, scopeSession) SEALED_CLASS_INHERITORS -> FirSealedClassInheritorsProcessor(session, scopeSession) @@ -31,15 +33,20 @@ fun FirResolvePhase.createCompilerProcessorByPhase( EXTENSION_STATUS_UPDATE -> FirGlobalExtensionStatusProcessor(session, scopeSession) STATUS -> FirStatusResolveProcessor(session, scopeSession) CONTRACTS -> FirContractResolveProcessor(session, scopeSession) + NEW_MEMBERS_GENERATION -> FirGlobalNewMemberGenerationProcessor(session, scopeSession) IMPLICIT_TYPES_BODY_RESOLVE -> FirImplicitTypeBodyResolveProcessor(session, scopeSession) BODY_RESOLVE -> FirBodyResolveProcessor(session, scopeSession) } } -fun FirResolvePhase.createTransformerBasedProcessorByPhase(session: FirSession, scopeSession: ScopeSession): FirTransformerBasedResolveProcessor { +fun FirResolvePhase.createTransformerBasedProcessorByPhase( + session: FirSession, + scopeSession: ScopeSession +): FirTransformerBasedResolveProcessor { return when (this) { RAW_FIR -> throw IllegalStateException("Raw FIR building phase does not have a transformer") ANNOTATIONS_FOR_PLUGINS -> FirPluginAnnotationsResolveProcessor(session, scopeSession) + NESTED_CLASS_GENERATION -> FirDummyTransformerBasedProcessor(session, scopeSession) // TODO: remove IMPORTS -> FirImportResolveProcessor(session, scopeSession) SUPER_TYPES -> FirSupertypeResolverProcessor(session, scopeSession) SEALED_CLASS_INHERITORS -> FirSealedClassInheritorsProcessor(session, scopeSession) @@ -47,7 +54,22 @@ fun FirResolvePhase.createTransformerBasedProcessorByPhase(session: FirSession, EXTENSION_STATUS_UPDATE -> FirTransformerBasedExtensionStatusProcessor(session, scopeSession) STATUS -> FirStatusResolveProcessor(session, scopeSession) CONTRACTS -> FirContractResolveProcessor(session, scopeSession) + NEW_MEMBERS_GENERATION -> FirDummyTransformerBasedProcessor(session, scopeSession) // TODO: remove IMPLICIT_TYPES_BODY_RESOLVE -> FirImplicitTypeBodyResolveProcessor(session, scopeSession) BODY_RESOLVE -> FirBodyResolveProcessor(session, scopeSession) } } + +private class FirDummyTransformerBasedProcessor( + session: FirSession, + scopeSession: ScopeSession +) : FirTransformerBasedResolveProcessor(session, scopeSession) { + override val transformer: FirTransformer + get() = DummyTransformer + + private object DummyTransformer : FirTransformer() { + override fun transformElement(element: E, data: Nothing?): CompositeTransformResult { + return element.compose() + } + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNestedClassGenerationProcessor.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNestedClassGenerationProcessor.kt new file mode 100644 index 00000000000..48b547f2ade --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNestedClassGenerationProcessor.kt @@ -0,0 +1,38 @@ +/* + * 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.FirRegularClass +import org.jetbrains.kotlin.fir.declarations.addDeclaration +import org.jetbrains.kotlin.fir.extensions.existingClassModifiers +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.transformers.FirGlobalResolveProcessor + +class FirGlobalNestedClassGenerationProcessor( + session: FirSession, + scopeSession: ScopeSession +) : FirGlobalResolveProcessor(session, scopeSession) { + override fun process() { + val extensions = session.extensionService.existingClassModifiers + if (extensions.isEmpty()) return + val provider = session.predicateBasedProvider + val index = session.generatedNestedClassIndex + for (extension in extensions) { + val declarations = provider.getSymbolsWithOwnersByPredicate(extension.predicate) + for ((declaration, owners) in declarations) { + val nestedClasses = extension.generateNestedClasses(declaration, owners) + for ((nestedClass, owner) in nestedClasses) { + owner.addDeclaration(nestedClass) + index.registerNestedClass(nestedClass, owner) + } + } + } + } +} + 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 new file mode 100644 index 00000000000..51c3bedbb51 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/FirGlobalNewMemberGenerationProcessor.kt @@ -0,0 +1,55 @@ +/* + * 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.addDeclaration +import org.jetbrains.kotlin.fir.declarations.validate +import org.jetbrains.kotlin.fir.extensions.FirExistingClassModificationExtension +import org.jetbrains.kotlin.fir.extensions.existingClassModifiers +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.transformers.FirGlobalResolveProcessor + +class FirGlobalNewMemberGenerationProcessor( + session: FirSession, + scopeSession: ScopeSession +) : FirGlobalResolveProcessor(session, scopeSession) { + private val index = session.generatedNestedClassIndex + private val provider = session.predicateBasedProvider + + override fun process() { + val extensions = session.extensionService.existingClassModifiers + if (extensions.isEmpty()) return + for (extension in extensions) { + generateNewMembers(extension) + fillGeneratedNestedClasses(extension) + } + } + + private fun generateNewMembers(extension: FirExistingClassModificationExtension) { + val declarations = provider.getSymbolsWithOwnersByPredicate(extension.predicate) + for ((declaration, owners) in declarations) { + val newMembers = extension.generateMembers(declaration, owners) + for ((newMember, owner) in newMembers) { + newMember.validate() + owner.addDeclaration(newMember) + } + } + } + + private fun fillGeneratedNestedClasses(extension: FirExistingClassModificationExtension) { + for (generatedNestedClass in index[extension.key]) { + val nestedClass = generatedNestedClass.nestedClass + val newMembers = extension.generateMembersForNestedClasses(generatedNestedClass) + for (newMember in newMembers) { + newMember.validate() + nestedClass.addDeclaration(newMember) + } + } + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/GeneratedNestedClassIndex.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/GeneratedNestedClassIndex.kt new file mode 100644 index 00000000000..17eac2e879a --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/plugin/GeneratedNestedClassIndex.kt @@ -0,0 +1,41 @@ +/* + * 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 com.google.common.collect.ArrayListMultimap +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSessionComponent +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.FirPluginKey +import org.jetbrains.kotlin.fir.declarations.FirRegularClass + +data class GeneratedNestedClass(val nestedClass: FirRegularClass, val owner: FirRegularClass) + +abstract class GeneratedNestedClassIndex : FirSessionComponent { + companion object { + fun create(): GeneratedNestedClassIndex { + return GeneratedNestedClassIndexImpl() + } + } + + abstract fun registerNestedClass(klass: FirRegularClass, owner: FirRegularClass) + abstract operator fun get(key: FirPluginKey): List +} + +val FirSession.generatedNestedClassIndex: GeneratedNestedClassIndex by FirSession.sessionComponentAccessor() + +private class GeneratedNestedClassIndexImpl : GeneratedNestedClassIndex() { + private val index: ArrayListMultimap = ArrayListMultimap.create() + + override fun registerNestedClass(klass: FirRegularClass, owner: FirRegularClass) { + val key = (klass.origin as FirDeclarationOrigin.Plugin).key + index.put(key, GeneratedNestedClass(klass, owner)) + } + + override fun get(key: FirPluginKey): List { + return index.get(key) + } +} \ No newline at end of file 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 b02f96fabf1..92afb669193 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,7 @@ package org.jetbrains.kotlin.fir.declarations enum class FirResolvePhase { RAW_FIR, ANNOTATIONS_FOR_PLUGINS, // run only if some extensions are registered -// FIRST_PLUGIN_GENERATION, // plugin phase + NESTED_CLASS_GENERATION, // plugin phase IMPORTS, SUPER_TYPES, SEALED_CLASS_INHERITORS, @@ -16,6 +16,7 @@ enum class FirResolvePhase { EXTENSION_STATUS_UPDATE, STATUS, CONTRACTS, + NEW_MEMBERS_GENERATION, // plugin IMPLICIT_TYPES_BODY_RESOLVE, BODY_RESOLVE;