FIR: Serialize members originated from delegation

This commit is contained in:
Denis.Zharkov
2021-03-30 11:02:09 +03:00
parent a130b110f1
commit 4d3825a824
12 changed files with 117 additions and 16 deletions
@@ -11,8 +11,7 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirAnnotationContainer
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.deserialization.CONTINUATION_INTERFACE_CLASS_ID
@@ -23,18 +22,19 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall
import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.varargElementType
import org.jetbrains.kotlin.fir.resolve.symbolProvider
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
import org.jetbrains.kotlin.fir.resolve.inference.suspendFunctionTypeToFunctionTypeWithContinuation
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.processAllFunctions
import org.jetbrains.kotlin.fir.scopes.processAllProperties
import org.jetbrains.kotlin.fir.serialization.constant.EnumValue
import org.jetbrains.kotlin.fir.serialization.constant.IntValue
import org.jetbrains.kotlin.fir.serialization.constant.StringValue
import org.jetbrains.kotlin.fir.serialization.constant.toConstantValue
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitNullableAnyTypeRef
@@ -55,6 +55,7 @@ import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
class FirElementSerializer private constructor(
private val session: FirSession,
private val scopeSession: ScopeSession,
private val containingDeclaration: FirDeclaration?,
private val typeParameters: Interner<FirTypeParameter>,
private val extension: FirSerializerExtension,
@@ -139,7 +140,7 @@ class FirElementSerializer private constructor(
val callableMembers =
extension.customClassMembersProducer?.getCallableMembers(klass)
?: klass.declarations.filterIsInstance<FirCallableMemberDeclaration<*>>()
?: klass.declarations()
.sortedWith(FirCallableMemberDeclarationComparator)
for (declaration in callableMembers) {
@@ -197,6 +198,32 @@ class FirElementSerializer private constructor(
return builder
}
@OptIn(ExperimentalStdlibApi::class)
private fun FirClass<*>.declarations(): List<FirCallableMemberDeclaration<*>> = buildList {
val memberScope =
defaultType().scope(session, scopeSession, FakeOverrideTypeCalculator.DoNothing)
?: error("Null scope for $this")
fun addDeclarationIfNeeded(symbol: FirCallableSymbol<*>) {
val declaration = symbol.fir as? FirCallableMemberDeclaration<*> ?: return
if (declaration.isSubstitutionOrIntersectionOverride) return
// non-intersection or substitution fake override
if (!declaration.isStatic && declaration.dispatchReceiverClassOrNull() != this@declarations.symbol.toLookupTag()) return
add(declaration)
}
memberScope.processAllFunctions(::addDeclarationIfNeeded)
memberScope.processAllProperties(::addDeclarationIfNeeded)
for (declaration in declarations) {
if (declaration is FirCallableMemberDeclaration<*> && declaration.isStatic) {
add(declaration)
}
}
}
private fun FirPropertyAccessor.nonSourceAnnotations(session: FirSession, property: FirProperty): List<FirAnnotationCall> =
(this as FirAnnotationContainer).nonSourceAnnotations(session) + property.nonSourceAnnotations(session).filter {
val useSiteTarget = it.useSiteTarget
@@ -747,7 +774,7 @@ class FirElementSerializer private constructor(
private fun createChildSerializer(declaration: FirDeclaration): FirElementSerializer =
FirElementSerializer(
session, declaration, Interner(typeParameters), extension,
session, scopeSession, declaration, Interner(typeParameters), extension,
typeTable, versionRequirementTable, serializeTypeTableToFunction = false,
typeApproximator
)
@@ -876,11 +903,12 @@ class FirElementSerializer private constructor(
@JvmStatic
fun createTopLevel(
session: FirSession,
scopeSession: ScopeSession,
extension: FirSerializerExtension,
typeApproximator: AbstractTypeApproximator,
): FirElementSerializer =
FirElementSerializer(
session, null,
session, scopeSession, null,
Interner(), extension, MutableTypeTable(), MutableVersionRequirementTable(),
serializeTypeTableToFunction = false,
typeApproximator
@@ -889,11 +917,12 @@ class FirElementSerializer private constructor(
@JvmStatic
fun createForLambda(
session: FirSession,
scopeSession: ScopeSession,
extension: FirSerializerExtension,
typeApproximator: AbstractTypeApproximator,
): FirElementSerializer =
FirElementSerializer(
session, null,
session, scopeSession, null,
Interner(), extension, MutableTypeTable(),
versionRequirementTable = null, serializeTypeTableToFunction = true,
typeApproximator
@@ -901,6 +930,7 @@ class FirElementSerializer private constructor(
@JvmStatic
fun create(
scopeSession: ScopeSession,
klass: FirClass<*>,
extension: FirSerializerExtension,
parentSerializer: FirElementSerializer?,
@@ -909,9 +939,9 @@ class FirElementSerializer private constructor(
val parentClassId = klass.symbol.classId.outerClassId
val parent = if (parentClassId != null && !parentClassId.isLocal) {
val parentClass = klass.session.symbolProvider.getClassLikeSymbolByFqName(parentClassId)!!.fir as FirRegularClass
parentSerializer ?: create(parentClass, extension, null, typeApproximator)
parentSerializer ?: create(scopeSession, parentClass, extension, null, typeApproximator)
} else {
createTopLevel(klass.session, extension, typeApproximator)
createTopLevel(klass.session, scopeSession, extension, typeApproximator)
}
// Calculate type parameter ids for the outer class beforehand, as it would've had happened if we were always
@@ -919,6 +949,7 @@ class FirElementSerializer private constructor(
// Otherwise our interner can get wrong ids because we may serialize classes in any order.
val serializer = FirElementSerializer(
klass.session,
scopeSession,
klass,
Interner(parent.typeParameters),
extension,
@@ -45,7 +45,7 @@ class FirJvmSerializerExtension(
private val localDelegatedProperties: List<FirProperty>,
private val approximator: AbstractTypeApproximator,
typeMapper: IrTypeMapper,
components: Fir2IrComponents
private val components: Fir2IrComponents
) : FirSerializerExtension() {
private val globalBindings = state.globalSerializationBindings
override val stringTable = FirJvmElementAwareStringTable(typeMapper, components)
@@ -137,7 +137,7 @@ class FirJvmSerializerExtension(
extension: GeneratedMessageLite.GeneratedExtension<MessageType, List<ProtoBuf.Property>>
) {
for (localVariable in localDelegatedProperties) {
val serializer = FirElementSerializer.createForLambda(session, this, approximator)
val serializer = FirElementSerializer.createForLambda(session, components.scopeSession,this, approximator)
proto.addExtension(extension, serializer.propertyProto(localVariable)?.build() ?: continue)
}
}
@@ -154,10 +154,21 @@ class FirMetadataSerializer(
private val serializer: FirElementSerializer? =
when (val metadata = irClass.metadata) {
is FirMetadataSource.Class -> FirElementSerializer.create(
components.scopeSession,
metadata.fir, serializerExtension, (parent as? FirMetadataSerializer)?.serializer, approximator
)
is FirMetadataSource.File -> FirElementSerializer.createTopLevel(metadata.session, serializerExtension, approximator)
is FirMetadataSource.Function -> FirElementSerializer.createForLambda(metadata.session, serializerExtension, approximator)
is FirMetadataSource.File -> FirElementSerializer.createTopLevel(
metadata.session,
components.scopeSession,
serializerExtension,
approximator
)
is FirMetadataSource.Function -> FirElementSerializer.createForLambda(
metadata.session,
components.scopeSession,
serializerExtension,
approximator
)
else -> null
}
@@ -13320,6 +13320,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/delegation/delegationAndInheritanceFromJava.kt");
}
@Test
@TestMetadata("delegationDifferentModule.kt")
public void testDelegationDifferentModule() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationDifferentModule.kt");
}
@Test
@TestMetadata("delegationToMap.kt")
public void testDelegationToMap() throws Exception {
@@ -0,0 +1,16 @@
// MODULE: lib
// FILE: lib.kt
interface A {
fun foo(): String
}
abstract class B(a: A) : A by a
// MODULE: main(lib)
// FILE: main.kt
class AImpl : A {
override fun foo(): String = "OK"
}
class C : B(AImpl())
fun box(): String = C().foo()
@@ -13320,6 +13320,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/delegation/delegationAndInheritanceFromJava.kt");
}
@Test
@TestMetadata("delegationDifferentModule.kt")
public void testDelegationDifferentModule() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationDifferentModule.kt");
}
@Test
@TestMetadata("delegationToMap.kt")
public void testDelegationToMap() throws Exception {
@@ -13320,6 +13320,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/delegation/delegationAndInheritanceFromJava.kt");
}
@Test
@TestMetadata("delegationDifferentModule.kt")
public void testDelegationDifferentModule() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationDifferentModule.kt");
}
@Test
@TestMetadata("delegationToMap.kt")
public void testDelegationToMap() throws Exception {
@@ -10848,6 +10848,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/delegation/delegationAndInheritanceFromJava.kt");
}
@TestMetadata("delegationDifferentModule.kt")
public void testDelegationDifferentModule() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationDifferentModule.kt");
}
@TestMetadata("delegationToMap.kt")
public void testDelegationToMap() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationToMap.kt");
@@ -9717,6 +9717,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/delegation"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
@TestMetadata("delegationDifferentModule.kt")
public void testDelegationDifferentModule() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationDifferentModule.kt");
}
@TestMetadata("delegationWithPrivateConstructor.kt")
public void testDelegationWithPrivateConstructor() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
@@ -9138,6 +9138,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/delegation"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@TestMetadata("delegationDifferentModule.kt")
public void testDelegationDifferentModule() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationDifferentModule.kt");
}
@TestMetadata("delegationWithPrivateConstructor.kt")
public void testDelegationWithPrivateConstructor() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
@@ -9138,6 +9138,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/delegation"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@TestMetadata("delegationDifferentModule.kt")
public void testDelegationDifferentModule() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationDifferentModule.kt");
}
@TestMetadata("delegationWithPrivateConstructor.kt")
public void testDelegationWithPrivateConstructor() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
@@ -4282,6 +4282,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/delegation"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@TestMetadata("delegationDifferentModule.kt")
public void testDelegationDifferentModule() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationDifferentModule.kt");
}
@TestMetadata("delegationWithPrivateConstructor.kt")
public void testDelegationWithPrivateConstructor() throws Exception {
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");