[FIR] Fix applying generated supertypes for classes without explicit supertypes

This commit is contained in:
Dmitriy Novozhilov
2021-09-30 12:18:11 +03:00
committed by TeamCityServer
parent 26fa772846
commit e26cd74b16
5 changed files with 97 additions and 25 deletions
@@ -19,11 +19,11 @@ abstract class FirSupertypeGenerationExtension(session: FirSession) : FirPredica
final override val name: FirExtensionPointName final override val name: FirExtensionPointName
get() = NAME get() = NAME
override val extensionType: KClass<out FirExtension> = FirSupertypeGenerationExtension::class final override val extensionType: KClass<out FirExtension> = FirSupertypeGenerationExtension::class
abstract fun computeAdditionalSupertypes( abstract fun computeAdditionalSupertypes(
classLikeDeclaration: FirClassLikeDeclaration, classLikeDeclaration: FirClassLikeDeclaration,
resolvedSupertypes: List<FirTypeRef> resolvedSupertypes: List<FirResolvedTypeRef>
): List<FirResolvedTypeRef> ): List<FirResolvedTypeRef>
fun interface Factory : FirExtension.Factory<FirSupertypeGenerationExtension> fun interface Factory : FirExtension.Factory<FirSupertypeGenerationExtension>
@@ -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.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef 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.FirDefaultTransformer
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
import org.jetbrains.kotlin.fir.visitors.FirTransformer import org.jetbrains.kotlin.fir.visitors.FirTransformer
@@ -120,7 +121,7 @@ open class FirApplySupertypesTransformer(
} }
private fun applyResolvedSupertypesToClass(firClass: FirClass) { 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) val supertypeRefs = getResolvedSupertypeRefs(firClass)
// TODO: Replace with an immutable version or transformer // TODO: Replace with an immutable version or transformer
@@ -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.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.has import org.jetbrains.kotlin.fir.extensions.predicate.has
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef 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.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.constructClassLikeType import org.jetbrains.kotlin.fir.types.constructClassLikeType
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
/*
* Adds MyInterface supertype for all classes annotated with @D
*/
class AllOpenSupertypeGenerator(session: FirSession) : FirSupertypeGenerationExtension(session) { class AllOpenSupertypeGenerator(session: FirSession) : FirSupertypeGenerationExtension(session) {
companion object { 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( override fun computeAdditionalSupertypes(
classLikeDeclaration: FirClassLikeDeclaration, classLikeDeclaration: FirClassLikeDeclaration,
resolvedSupertypes: List<FirTypeRef> resolvedSupertypes: List<FirResolvedTypeRef>
): List<FirResolvedTypeRef> { ): List<FirResolvedTypeRef> {
if (resolvedSupertypes.any { it.type.classId == myInterfaceClassId }) return emptyList()
return listOf( return listOf(
buildResolvedTypeRef { 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 override val key: FirPluginKey
get() = AllOpenPluginKey get() = AllOpenPluginKey
override val predicate: DeclarationPredicate = has("C".fqn()) override val predicate: DeclarationPredicate = has("D".fqn())
} }
@@ -1,18 +1,53 @@
FILE: simple.kt FILE: simple.kt
@R|org/jetbrains/kotlin/fir/plugin/C|() public final class A : R|kotlin/Any| { public abstract interface MyInterface : R|kotlin/Any| {
public constructor(): R|A| { 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<R|kotlin/Any|>() super<R|kotlin/Any|>()
} }
public final class MyNested : <ERROR TYPE REF: Symbol not found for NestedClass> { }
public constructor(): R|A.MyNested| { @R|org/jetbrains/kotlin/fir/plugin/D|() public final class FinalClassWithOverride : R|kotlin/Any|, R|foo/MyInterface| {
super<<ERROR TYPE REF: Symbol not found for NestedClass>>() public constructor(): R|foo/FinalClassWithOverride| {
} super<R|kotlin/Any|>()
} }
public final fun test(): R|kotlin/Unit| { public final override fun foo(): R|kotlin/Unit| {
R|/A.MyNested.MyNested|().<Unresolved name: foo>#()
} }
} }
@R|org/jetbrains/kotlin/fir/plugin/D|() public final class FinalClassWithoutOverride : R|kotlin/Any|, R|foo/MyInterface| {
public constructor(): R|foo/FinalClassWithoutOverride| {
super<R|kotlin/Any|>()
}
}
public final class NotAnnotatedWithOverride : R|kotlin/Any| {
public constructor(): R|foo/NotAnnotatedWithOverride| {
super<R|kotlin/Any|>()
}
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<R|kotlin/Any|>()
}
public final override fun foo(): R|kotlin/Unit| {
}
}
public final fun test_1(x: R|foo/AbstractClass|): R|kotlin/Unit| {
R|<local>/x|.R|foo/MyInterface.foo|()
}
public final fun test_2(x: R|foo/FinalClassWithOverride|): R|kotlin/Unit| {
R|<local>/x|.R|foo/FinalClassWithOverride.foo|()
}
public final fun test_3(x: R|foo/FinalClassWithoutOverride|): R|kotlin/Unit| {
R|<local>/x|.R|foo/MyInterface.foo|()
}
@@ -1,10 +1,42 @@
import org.jetbrains.kotlin.fir.plugin.C package foo
@C import org.jetbrains.kotlin.fir.plugin.D
class A {
class MyNested : NestedClass()
fun test() { interface MyInterface {
MyNested().foo() fun foo()
} }
}
@D
abstract class AbstractClass
@D
class FinalClassWithOverride {
override fun foo() {}
}
@D
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class FinalClassWithoutOverride<!> {
// should be error
}
class NotAnnotatedWithOverride {
// should be error
<!NOTHING_TO_OVERRIDE!>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()
}