From 9cc13c8324f723d71cfe9e0fe882a70ada839add Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 28 May 2020 18:01:11 +0300 Subject: [PATCH] [FIR-PLUGIN] Add dummy implementation for nested class generator extension --- .../fir/plugin/AllOpenMemberGenerator.kt | 4 +- .../fir/plugin/AllOpenNestedClassGenerator.kt | 102 ++++++++++++++++++ .../plugin/FirAllOpenComponentRegistrar.kt | 1 + .../org/jetbrains/kotlin/fir/plugin/utils.kt | 10 ++ .../testData/memberGen/nestedClass.kt | 20 ++++ .../testData/memberGen/nestedClass.txt | 37 +++++++ .../FirAllOpenDiagnosticTestGenerated.java | 5 + 7 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenNestedClassGenerator.kt create mode 100644 plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/utils.kt create mode 100644 plugins/fir/fir-plugin-prototype/testData/memberGen/nestedClass.kt create mode 100644 plugins/fir/fir-plugin-prototype/testData/memberGen/nestedClass.txt 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/AllOpenMemberGenerator.kt index ff5a579b9a0..8fbcdbb3656 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/AllOpenMemberGenerator.kt @@ -54,6 +54,4 @@ class AllOpenMemberGenerator(session: FirSession) : FirExistingClassModification override val key: FirPluginKey get() = AllOpenPluginKey -} - -private fun String.fqn(): FqName = FqName("org.jetbrains.kotlin.fir.plugin.$this") \ No newline at end of file +} \ No newline at end of file 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/AllOpenNestedClassGenerator.kt new file mode 100644 index 00000000000..f8f558e1c4a --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenNestedClassGenerator.kt @@ -0,0 +1,102 @@ +/* + * 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 + +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.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.predicate.DeclarationPredicate +import org.jetbrains.kotlin.fir.extensions.predicate.has +import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedNestedClass +import org.jetbrains.kotlin.fir.symbols.CallableId +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.Name + +class AllOpenNestedClassGenerator(session: FirSession) : FirExistingClassModificationExtension(session) { + override fun generateNestedClasses( + annotatedDeclaration: FirDeclaration, + owners: List + ): List> { + val owner = annotatedDeclaration as? FirRegularClass ?: return emptyList() + val newClass = buildRegularClass { + session = this@AllOpenNestedClassGenerator.session + resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES + origin = FirDeclarationOrigin.Plugin(key) + status = FirResolvedDeclarationStatusImpl( + Visibilities.PRIVATE, + FirEffectiveVisibilityImpl.Private, + Modality.FINAL + ).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 generateMembersForNestedClasses(generatedNestedClass: GeneratedNestedClass): List { + val klass = generatedNestedClass.nestedClass + + val classId = klass.symbol.classId + val constructor = buildConstructor { + session = klass.session + resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES + origin = FirDeclarationOrigin.Plugin(key) + returnTypeRef = buildResolvedTypeRef { + type = ConeClassLikeTypeImpl(ConeClassLikeLookupTagImpl(classId), emptyArray(), isNullable = false) + } + status = FirResolvedDeclarationStatusImpl( + Visibilities.PUBLIC, + FirEffectiveVisibilityImpl.Public, + Modality.FINAL + ) + symbol = FirConstructorSymbol(CallableId(classId, classId.shortClassName)) + } + + 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(classId, name), isFakeOverride = false) + } + 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 +} \ 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 89ebb9d4d6e..95e5aec28be 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 @@ -11,6 +11,7 @@ class FirAllOpenComponentRegistrar : FirExtensionRegistrar() { override fun ExtensionRegistrarContext.configurePlugin() { +::AllOpenStatusTransformer +::AllOpenMemberGenerator + +::AllOpenNestedClassGenerator +::AllOpenAdditionalCheckers } } \ No newline at end of file diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/utils.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/utils.kt new file mode 100644 index 00000000000..0127cda97cd --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/utils.kt @@ -0,0 +1,10 @@ +/* + * 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 + +import org.jetbrains.kotlin.name.FqName + +fun String.fqn(): FqName = FqName("org.jetbrains.kotlin.fir.plugin.$this") \ No newline at end of file diff --git a/plugins/fir/fir-plugin-prototype/testData/memberGen/nestedClass.kt b/plugins/fir/fir-plugin-prototype/testData/memberGen/nestedClass.kt new file mode 100644 index 00000000000..c5f6372f827 --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/testData/memberGen/nestedClass.kt @@ -0,0 +1,20 @@ +import org.jetbrains.kotlin.fir.plugin.WithNestedFoo + +fun T.also(block: (T) -> Unit): T = this + +@WithNestedFoo +class A { + private fun test(): Foo { + return Foo().also { + it.hello() // should be OK + } + } +} + +class B { + private fun test(): Foo { + return Foo().also { + it.hello() // should be an error + } + } +} diff --git a/plugins/fir/fir-plugin-prototype/testData/memberGen/nestedClass.txt b/plugins/fir/fir-plugin-prototype/testData/memberGen/nestedClass.txt new file mode 100644 index 00000000000..1833bb70ef3 --- /dev/null +++ b/plugins/fir/fir-plugin-prototype/testData/memberGen/nestedClass.txt @@ -0,0 +1,37 @@ +FILE: nestedClass.kt + public final fun R|T|.also(block: R|(T) -> kotlin/Unit|): R|T| { + ^also this@R|/also| + } + @R|org/jetbrains/kotlin/fir/plugin/WithNestedFoo|() public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + private final fun test(): R|A.Foo| { + ^test R|/A.Foo.Foo|().R|/also|( = also@fun (it: R|A.Foo|): R|kotlin/Unit| { + ^ R|/it|.R|/A.Foo.hello|() + } + ) + } + + private final inner class Foo { + public constructor(): R|A.Foo| + + public final fun hello(): R|kotlin/Int| + + } + + } + public final class B : R|kotlin/Any| { + public constructor(): R|B| { + super() + } + + private final fun test(): R|ERROR CLASS: Symbol not found, for `Foo`| { + ^test #().#( = also@fun (): R|ERROR CLASS: Unresolved name: hello| { + ^ #.#() + } + ) + } + + } 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 b13cf59d09c..2d76150feae 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 @@ -62,6 +62,11 @@ public class FirAllOpenDiagnosticTestGenerated extends AbstractFirAllOpenDiagnos public void testFunctionForProperty() throws Exception { runTest("plugins/fir/fir-plugin-prototype/testData/memberGen/functionForProperty.kt"); } + + @TestMetadata("nestedClass.kt") + public void testNestedClass() throws Exception { + runTest("plugins/fir/fir-plugin-prototype/testData/memberGen/nestedClass.kt"); + } } @TestMetadata("plugins/fir/fir-plugin-prototype/testData/status")