From e26cd74b165e0750d0bd7bbc0f4286ca7af13983 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 30 Sep 2021 12:18:11 +0300 Subject: [PATCH] [FIR] Fix applying generated supertypes for classes without explicit supertypes --- .../FirSupertypeGenerationExtension.kt | 4 +- .../transformers/FirSupertypesResolution.kt | 3 +- .../fir/plugin/AllOpenSupertypeGenerator.kt | 14 +++-- .../testData/supertypes/simple.fir.txt | 53 +++++++++++++++---- .../testData/supertypes/simple.kt | 48 ++++++++++++++--- 5 files changed, 97 insertions(+), 25 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirSupertypeGenerationExtension.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirSupertypeGenerationExtension.kt index b14f8aaa517..444ef894292 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirSupertypeGenerationExtension.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/extensions/FirSupertypeGenerationExtension.kt @@ -19,11 +19,11 @@ abstract class FirSupertypeGenerationExtension(session: FirSession) : FirPredica final override val name: FirExtensionPointName get() = NAME - override val extensionType: KClass = FirSupertypeGenerationExtension::class + final override val extensionType: KClass = FirSupertypeGenerationExtension::class abstract fun computeAdditionalSupertypes( classLikeDeclaration: FirClassLikeDeclaration, - resolvedSupertypes: List + resolvedSupertypes: List ): List fun interface Factory : FirExtension.Factory diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt index 7f47e399d44..26f28abac79 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef +import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.fir.visitors.FirTransformer @@ -120,7 +121,7 @@ open class FirApplySupertypesTransformer( } private fun applyResolvedSupertypesToClass(firClass: FirClass) { - if (firClass.superTypeRefs.any { it !is FirResolvedTypeRef }) { + if (firClass.superTypeRefs.any { it !is FirResolvedTypeRef || it is FirImplicitBuiltinTypeRef }) { val supertypeRefs = getResolvedSupertypeRefs(firClass) // TODO: Replace with an immutable version or transformer diff --git a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenSupertypeGenerator.kt b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenSupertypeGenerator.kt index d526d755747..360b4448321 100644 --- a/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenSupertypeGenerator.kt +++ b/plugins/fir/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/AllOpenSupertypeGenerator.kt @@ -12,25 +12,29 @@ import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate import org.jetbrains.kotlin.fir.extensions.predicate.has import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.classId import org.jetbrains.kotlin.fir.types.constructClassLikeType import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +/* + * Adds MyInterface supertype for all classes annotated with @D + */ class AllOpenSupertypeGenerator(session: FirSession) : FirSupertypeGenerationExtension(session) { companion object { - private val newSupertypeClassId = ClassId(FqName("org.jetbrains.kotlin.fir.plugin"), Name.identifier("LibraryClassWithNestedClass")) + private val myInterfaceClassId = ClassId(FqName("foo"), Name.identifier("MyInterface")) } override fun computeAdditionalSupertypes( classLikeDeclaration: FirClassLikeDeclaration, - resolvedSupertypes: List + resolvedSupertypes: List ): List { + if (resolvedSupertypes.any { it.type.classId == myInterfaceClassId }) return emptyList() return listOf( buildResolvedTypeRef { - type = newSupertypeClassId.constructClassLikeType(emptyArray(), isNullable = false) + type = myInterfaceClassId.constructClassLikeType(emptyArray(), isNullable = false) } ) } @@ -38,5 +42,5 @@ class AllOpenSupertypeGenerator(session: FirSession) : FirSupertypeGenerationExt override val key: FirPluginKey get() = AllOpenPluginKey - override val predicate: DeclarationPredicate = has("C".fqn()) + override val predicate: DeclarationPredicate = has("D".fqn()) } diff --git a/plugins/fir/fir-plugin-prototype/testData/supertypes/simple.fir.txt b/plugins/fir/fir-plugin-prototype/testData/supertypes/simple.fir.txt index be657e237f7..d21361b5614 100644 --- a/plugins/fir/fir-plugin-prototype/testData/supertypes/simple.fir.txt +++ b/plugins/fir/fir-plugin-prototype/testData/supertypes/simple.fir.txt @@ -1,18 +1,53 @@ FILE: simple.kt - @R|org/jetbrains/kotlin/fir/plugin/C|() public final class A : R|kotlin/Any| { - public constructor(): R|A| { + public abstract interface MyInterface : R|kotlin/Any| { + public abstract fun foo(): R|kotlin/Unit| + + } + @R|org/jetbrains/kotlin/fir/plugin/D|() public abstract class AbstractClass : R|kotlin/Any|, R|foo/MyInterface| { + public constructor(): R|foo/AbstractClass| { super() } - public final class MyNested : { - public constructor(): R|A.MyNested| { - super<>() - } - + } + @R|org/jetbrains/kotlin/fir/plugin/D|() public final class FinalClassWithOverride : R|kotlin/Any|, R|foo/MyInterface| { + public constructor(): R|foo/FinalClassWithOverride| { + super() } - public final fun test(): R|kotlin/Unit| { - R|/A.MyNested.MyNested|().#() + public final override fun foo(): R|kotlin/Unit| { } } + @R|org/jetbrains/kotlin/fir/plugin/D|() public final class FinalClassWithoutOverride : R|kotlin/Any|, R|foo/MyInterface| { + public constructor(): R|foo/FinalClassWithoutOverride| { + super() + } + + } + public final class NotAnnotatedWithOverride : R|kotlin/Any| { + public constructor(): R|foo/NotAnnotatedWithOverride| { + super() + } + + public final override fun foo(): R|kotlin/Unit| { + } + + } + @R|org/jetbrains/kotlin/fir/plugin/D|() public final class AnnotatedClassWithExplicitInheritance : R|foo/MyInterface| { + public constructor(): R|foo/AnnotatedClassWithExplicitInheritance| { + super() + } + + public final override fun foo(): R|kotlin/Unit| { + } + + } + public final fun test_1(x: R|foo/AbstractClass|): R|kotlin/Unit| { + R|/x|.R|foo/MyInterface.foo|() + } + public final fun test_2(x: R|foo/FinalClassWithOverride|): R|kotlin/Unit| { + R|/x|.R|foo/FinalClassWithOverride.foo|() + } + public final fun test_3(x: R|foo/FinalClassWithoutOverride|): R|kotlin/Unit| { + R|/x|.R|foo/MyInterface.foo|() + } diff --git a/plugins/fir/fir-plugin-prototype/testData/supertypes/simple.kt b/plugins/fir/fir-plugin-prototype/testData/supertypes/simple.kt index ecc4a2e34a5..3f67b6154df 100644 --- a/plugins/fir/fir-plugin-prototype/testData/supertypes/simple.kt +++ b/plugins/fir/fir-plugin-prototype/testData/supertypes/simple.kt @@ -1,10 +1,42 @@ -import org.jetbrains.kotlin.fir.plugin.C +package foo -@C -class A { - class MyNested : NestedClass() +import org.jetbrains.kotlin.fir.plugin.D - fun test() { - MyNested().foo() - } -} \ No newline at end of file +interface MyInterface { + fun foo() +} + +@D +abstract class AbstractClass + +@D +class FinalClassWithOverride { + override fun foo() {} +} + +@D +class FinalClassWithoutOverride { + // should be error +} + +class NotAnnotatedWithOverride { + // should be error + override fun foo() {} +} + +@D +class AnnotatedClassWithExplicitInheritance : MyInterface { + override fun foo() {} +} + +fun test_1(x: AbstractClass) { + x.foo() +} + +fun test_2(x: FinalClassWithOverride) { + x.foo() +} + +fun test_3(x: FinalClassWithoutOverride) { + x.foo() +}