From 0c18cb054d95ea96e7976f61769158094bb76dcd Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Mon, 1 Jun 2020 18:52:16 +0300 Subject: [PATCH] [FIR-PLUGIN] Add tests for generating declarations from plugin --- .../kotlin/fir/plugin/annotations.kt | 10 ++- .../plugin/FirAllOpenComponentRegistrar.kt | 6 ++ .../AllOpenMemberGenerator.kt | 15 ++-- .../AllOpenNestedClassGenerator.kt | 16 ++-- .../AllOpenRecursiveNestedClassGenerator.kt | 84 +++++++++++++++++++ .../AllOpenTopLevelDeclarationsGenerator.kt | 84 +++++++++++++++++++ .../memberGen/recursiveNestedClasses.kt | 8 ++ .../memberGen/recursiveNestedClasses.txt | 19 +++++ .../testData/memberGen/topLevelClass.kt | 8 ++ .../testData/memberGen/topLevelClass.txt | 14 ++++ .../FirAllOpenDiagnosticTestGenerated.java | 10 +++ 11 files changed, 259 insertions(+), 15 deletions(-) rename plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/{ => generators}/AllOpenMemberGenerator.kt (82%) rename plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/{ => generators}/AllOpenNestedClassGenerator.kt (88%) create mode 100644 plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenRecursiveNestedClassGenerator.kt create mode 100644 plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenTopLevelDeclarationsGenerator.kt create mode 100644 plugins/fir/fir-plugin-prototype/testData/memberGen/recursiveNestedClasses.kt create mode 100644 plugins/fir/fir-plugin-prototype/testData/memberGen/recursiveNestedClasses.txt create mode 100644 plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelClass.kt create mode 100644 plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelClass.txt diff --git a/plugins/fir/fir-plugin-prototype/plugin-annotations/src/org/jetbrains/kotlin/fir/plugin/annotations.kt b/plugins/fir/fir-plugin-prototype/plugin-annotations/src/org/jetbrains/kotlin/fir/plugin/annotations.kt index aa204f7eb0c..7c686a6ccd0 100644 --- a/plugins/fir/fir-plugin-prototype/plugin-annotations/src/org/jetbrains/kotlin/fir/plugin/annotations.kt +++ b/plugins/fir/fir-plugin-prototype/plugin-annotations/src/org/jetbrains/kotlin/fir/plugin/annotations.kt @@ -8,4 +8,12 @@ package org.jetbrains.kotlin.fir.plugin annotation class AllOpen annotation class WithGenerated annotation class WithHello -annotation class WithNestedFoo \ No newline at end of file +annotation class WithNestedFoo + +annotation class A +annotation class B +annotation class C +annotation class D +annotation class E +annotation class F +annotation class G \ No newline at end of file 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 95e5aec28be..5c776f5affd 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 @@ -6,6 +6,10 @@ package org.jetbrains.kotlin.fir.plugin import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar +import org.jetbrains.kotlin.fir.plugin.generators.AllOpenMemberGenerator +import org.jetbrains.kotlin.fir.plugin.generators.AllOpenNestedClassGenerator +import org.jetbrains.kotlin.fir.plugin.generators.AllOpenRecursiveNestedClassGenerator +import org.jetbrains.kotlin.fir.plugin.generators.AllOpenTopLevelDeclarationsGenerator class FirAllOpenComponentRegistrar : FirExtensionRegistrar() { override fun ExtensionRegistrarContext.configurePlugin() { @@ -13,5 +17,7 @@ class FirAllOpenComponentRegistrar : FirExtensionRegistrar() { +::AllOpenMemberGenerator +::AllOpenNestedClassGenerator +::AllOpenAdditionalCheckers + +::AllOpenTopLevelDeclarationsGenerator + +::AllOpenRecursiveNestedClassGenerator } } \ No newline at end of file diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenMemberGenerator.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenMemberGenerator.kt similarity index 82% rename from plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenMemberGenerator.kt rename to plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenMemberGenerator.kt index 8fbcdbb3656..d4bdd0059d8 100644 --- a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenMemberGenerator.kt +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenMemberGenerator.kt @@ -3,31 +3,32 @@ * 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 +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.extensions.FirExistingClassModificationExtension +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.resolve.transformers.plugin.GeneratedNestedClass +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.CallableId import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -class AllOpenMemberGenerator(session: FirSession) : FirExistingClassModificationExtension(session) { - override fun generateNestedClasses( +class AllOpenMemberGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) { + override fun generateClasses( annotatedDeclaration: FirDeclaration, owners: List ): List> { return emptyList() } - override fun generateMembersForNestedClasses(generatedNestedClass: GeneratedNestedClass): List { + override fun generateMembersForGeneratedClass(generatedClass: GeneratedClass): List { return emptyList() } diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenNestedClassGenerator.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenNestedClassGenerator.kt similarity index 88% rename from plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenNestedClassGenerator.kt rename to plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenNestedClassGenerator.kt index f8f558e1c4a..ac3dbb5e031 100644 --- a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenNestedClassGenerator.kt +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenNestedClassGenerator.kt @@ -3,7 +3,7 @@ * 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 +package org.jetbrains.kotlin.fir.plugin.generators import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality @@ -15,10 +15,12 @@ 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.FirExistingClassModificationExtension +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.resolve.transformers.plugin.GeneratedNestedClass +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.CallableId import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol @@ -28,8 +30,8 @@ import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.name.Name -class AllOpenNestedClassGenerator(session: FirSession) : FirExistingClassModificationExtension(session) { - override fun generateNestedClasses( +class AllOpenNestedClassGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) { + override fun generateClasses( annotatedDeclaration: FirDeclaration, owners: List ): List> { @@ -53,8 +55,8 @@ class AllOpenNestedClassGenerator(session: FirSession) : FirExistingClassModific return listOf(GeneratedDeclaration(newClass, owner)) } - override fun generateMembersForNestedClasses(generatedNestedClass: GeneratedNestedClass): List { - val klass = generatedNestedClass.nestedClass + override fun generateMembersForGeneratedClass(generatedClass: GeneratedClass): List { + val klass = generatedClass.klass val classId = klass.symbol.classId val constructor = buildConstructor { 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 new file mode 100644 index 00000000000..08fe49b92d3 --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenRecursiveNestedClassGenerator.kt @@ -0,0 +1,84 @@ +/* + * 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.Modality +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.FirEffectiveVisibilityImpl +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.buildAnnotationCall +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.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 { + session = this@AllOpenRecursiveNestedClassGenerator.session + resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES + origin = FirDeclarationOrigin.Plugin(key) + status = FirResolvedDeclarationStatusImpl( + Visibilities.PUBLIC, + FirEffectiveVisibilityImpl.Public, + Modality.FINAL + ) + classKind = ClassKind.CLASS + name = Name.identifier("Nested") + symbol = FirRegularClassSymbol(owner.symbol.classId.createNestedClassId(name)) + scopeProvider = owner.scopeProvider + annotations += buildAnnotationCall { + annotationTypeRef = buildResolvedTypeRef { + type = ConeClassLikeTypeImpl( + ConeClassLikeLookupTagImpl(annotationClassId), + emptyArray(), + isNullable = false + ) + } + } + } + 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() +} \ No newline at end of file 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 new file mode 100644 index 00000000000..f2f4b670196 --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/generators/AllOpenTopLevelDeclarationsGenerator.kt @@ -0,0 +1,84 @@ +/* + * 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.Modality +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.FirEffectiveVisibilityImpl +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.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.plugin.fqn +import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClass +import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +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 { + session = this@AllOpenTopLevelDeclarationsGenerator.session + resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES + origin = FirDeclarationOrigin.Plugin(key) + status = FirResolvedDeclarationStatusImpl( + Visibilities.PUBLIC, + FirEffectiveVisibilityImpl.Public, + Modality.FINAL + ) + classKind = ClassKind.OBJECT + name = Name.identifier("TopLevel${klass.name}") + symbol = FirRegularClassSymbol(ClassId(file.packageFqName, name)) + scopeProvider = klass.scopeProvider + } + return listOf(GeneratedDeclaration(newClass, file)) + } + + override fun generateMembersForGeneratedClass(generatedClass: GeneratedClass): List { + val klass = generatedClass.klass + val function = buildSimpleFunction { + session = klass.session + resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES + origin = FirDeclarationOrigin.Plugin(key) + returnTypeRef = session.builtinTypes.intType + status = FirResolvedDeclarationStatusImpl( + Visibilities.PUBLIC, + FirEffectiveVisibilityImpl.Public, + Modality.FINAL + ) + name = Name.identifier("hello") + symbol = FirNamedFunctionSymbol(CallableId(klass.symbol.classId, name), isFakeOverride = false) + } + return listOf(function) + } + + override fun generateMembers( + annotatedDeclaration: FirDeclaration, + owners: List + ): List> { + return emptyList() + } + + override val key: FirPluginKey + get() = Key + + override val predicate: DeclarationPredicate + get() = has("A".fqn()) + + private object Key : FirPluginKey() +} \ No newline at end of file diff --git a/plugins/fir/fir-plugin-prototype/testData/memberGen/recursiveNestedClasses.kt b/plugins/fir/fir-plugin-prototype/testData/memberGen/recursiveNestedClasses.kt new file mode 100644 index 00000000000..c7e6d36a56d --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/testData/memberGen/recursiveNestedClasses.kt @@ -0,0 +1,8 @@ +import org.jetbrains.kotlin.fir.plugin.B + +@B +class SomeClass + +fun test_1(x: SomeClass.Nested) {} +fun test_2(x: SomeClass.Nested.Nested) {} +fun test_3(x: SomeClass.Nested.Nested.Nested) {} \ No newline at end of file diff --git a/plugins/fir/fir-plugin-prototype/testData/memberGen/recursiveNestedClasses.txt b/plugins/fir/fir-plugin-prototype/testData/memberGen/recursiveNestedClasses.txt new file mode 100644 index 00000000000..b5463b91192 --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/testData/memberGen/recursiveNestedClasses.txt @@ -0,0 +1,19 @@ +FILE: recursiveNestedClasses.kt + @R|org/jetbrains/kotlin/fir/plugin/B|() public final class SomeClass : R|kotlin/Any| { + public constructor(): R|SomeClass| { + super() + } + + @R|org/jetbrains/kotlin/fir/plugin/B|() public final class Nested { + @R|org/jetbrains/kotlin/fir/plugin/B|() public final class Nested { + } + + } + + } + public final fun test_1(x: R|SomeClass.Nested|): R|kotlin/Unit| { + } + public final fun test_2(x: R|SomeClass.Nested.Nested|): R|kotlin/Unit| { + } + public final fun test_3(x: R|ERROR CLASS: Symbol not found, for `SomeClass.Nested.Nested.Nested`|): R|kotlin/Unit| { + } diff --git a/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelClass.kt b/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelClass.kt new file mode 100644 index 00000000000..64a200b6405 --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelClass.kt @@ -0,0 +1,8 @@ +import org.jetbrains.kotlin.fir.plugin.A + +@A +class SomeClass + +fun test() { + TopLevelSomeClass.hello() +} \ No newline at end of file diff --git a/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelClass.txt b/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelClass.txt new file mode 100644 index 00000000000..93dfee64622 --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelClass.txt @@ -0,0 +1,14 @@ +FILE: topLevelClass.kt + @R|org/jetbrains/kotlin/fir/plugin/A|() public final class SomeClass : R|kotlin/Any| { + public constructor(): R|SomeClass| { + super() + } + + } + public final fun test(): R|kotlin/Unit| { + Q|TopLevelSomeClass|.R|/TopLevelSomeClass.hello|() + } + public final object TopLevelSomeClass { + public final fun hello(): R|kotlin/Int| + + } diff --git a/plugins/fir/fir-plugin-prototype/tests/org/jetbrains/kotlin/fir/plugin/FirAllOpenDiagnosticTestGenerated.java b/plugins/fir/fir-plugin-prototype/tests/org/jetbrains/kotlin/fir/plugin/FirAllOpenDiagnosticTestGenerated.java index 2d76150feae..e2852caa92f 100644 --- a/plugins/fir/fir-plugin-prototype/tests/org/jetbrains/kotlin/fir/plugin/FirAllOpenDiagnosticTestGenerated.java +++ b/plugins/fir/fir-plugin-prototype/tests/org/jetbrains/kotlin/fir/plugin/FirAllOpenDiagnosticTestGenerated.java @@ -67,6 +67,16 @@ public class FirAllOpenDiagnosticTestGenerated extends AbstractFirAllOpenDiagnos public void testNestedClass() throws Exception { runTest("plugins/fir/fir-plugin-prototype/testData/memberGen/nestedClass.kt"); } + + @TestMetadata("recursiveNestedClasses.kt") + public void testRecursiveNestedClasses() throws Exception { + runTest("plugins/fir/fir-plugin-prototype/testData/memberGen/recursiveNestedClasses.kt"); + } + + @TestMetadata("topLevelClass.kt") + public void testTopLevelClass() throws Exception { + runTest("plugins/fir/fir-plugin-prototype/testData/memberGen/topLevelClass.kt"); + } } @TestMetadata("plugins/fir/fir-plugin-prototype/testData/status")