[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
get() = NAME
override val extensionType: KClass<out FirExtension> = FirSupertypeGenerationExtension::class
final override val extensionType: KClass<out FirExtension> = FirSupertypeGenerationExtension::class
abstract fun computeAdditionalSupertypes(
classLikeDeclaration: FirClassLikeDeclaration,
resolvedSupertypes: List<FirTypeRef>
resolvedSupertypes: List<FirResolvedTypeRef>
): List<FirResolvedTypeRef>
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.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
@@ -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<FirTypeRef>
resolvedSupertypes: List<FirResolvedTypeRef>
): List<FirResolvedTypeRef> {
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())
}
@@ -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<R|kotlin/Any|>()
}
public final class MyNested : <ERROR TYPE REF: Symbol not found for NestedClass> {
public constructor(): R|A.MyNested| {
super<<ERROR TYPE REF: Symbol not found for NestedClass>>()
}
}
@R|org/jetbrains/kotlin/fir/plugin/D|() public final class FinalClassWithOverride : R|kotlin/Any|, R|foo/MyInterface| {
public constructor(): R|foo/FinalClassWithOverride| {
super<R|kotlin/Any|>()
}
public final fun test(): R|kotlin/Unit| {
R|/A.MyNested.MyNested|().<Unresolved name: foo>#()
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<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
class A {
class MyNested : NestedClass()
import org.jetbrains.kotlin.fir.plugin.D
fun test() {
MyNested().foo()
}
}
interface MyInterface {
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()
}