Introduce @FirIncompatiblePluginApi

This commit is contained in:
Leonid Startsev
2022-07-22 20:29:46 +02:00
committed by Space
parent 467ff30aac
commit 89329a0e1b
15 changed files with 62 additions and 98 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.backend package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
@@ -39,15 +40,17 @@ class Fir2IrPluginContext(private val components: Fir2IrComponents) : IrPluginCo
} }
@ObsoleteDescriptorBasedAPI @ObsoleteDescriptorBasedAPI
@FirIncompatiblePluginAPI
override val moduleDescriptor: ModuleDescriptor override val moduleDescriptor: ModuleDescriptor
get() = error(ERROR_MESSAGE) get() = error(ERROR_MESSAGE)
@Suppress("OVERRIDE_DEPRECATION")
@ObsoleteDescriptorBasedAPI @ObsoleteDescriptorBasedAPI
@FirIncompatiblePluginAPI
override val bindingContext: BindingContext override val bindingContext: BindingContext
get() = error(ERROR_MESSAGE) get() = error(ERROR_MESSAGE)
@ObsoleteDescriptorBasedAPI @ObsoleteDescriptorBasedAPI
@FirIncompatiblePluginAPI
override val typeTranslator: TypeTranslator override val typeTranslator: TypeTranslator
get() = error(ERROR_MESSAGE) get() = error(ERROR_MESSAGE)
@@ -139,26 +142,27 @@ class Fir2IrPluginContext(private val components: Fir2IrComponents) : IrPluginCo
} }
@Deprecated("Use classId overload instead") @FirIncompatiblePluginAPI
override fun referenceClass(fqName: FqName): IrClassSymbol? { override fun referenceClass(fqName: FqName): IrClassSymbol? {
error(ERROR_MESSAGE) error(ERROR_MESSAGE)
} }
@FirIncompatiblePluginAPI
override fun referenceTypeAlias(fqName: FqName): IrTypeAliasSymbol? { override fun referenceTypeAlias(fqName: FqName): IrTypeAliasSymbol? {
error(ERROR_MESSAGE) error(ERROR_MESSAGE)
} }
@Deprecated("Use classId overload instead") @FirIncompatiblePluginAPI
override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> { override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> {
error(ERROR_MESSAGE) error(ERROR_MESSAGE)
} }
@Deprecated("Use callableId overload instead") @FirIncompatiblePluginAPI
override fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> { override fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> {
error(ERROR_MESSAGE) error(ERROR_MESSAGE)
} }
@Deprecated("Use callableId overload instead") @FirIncompatiblePluginAPI
override fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> { override fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> {
error(ERROR_MESSAGE) error(ERROR_MESSAGE)
} }
@@ -22,6 +22,15 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
/**
* Indicates methods and properties that are not available in backend after FIR
*
* Invocation of such methods in IR plugins if frontend was a FIR results in compiler crash.
* It's still possible to use them in IR plugins with old frontend.
*/
@RequiresOptIn("This API is not available after FIR")
annotation class FirIncompatiblePluginAPI(val hint: String = "")
interface IrPluginContext : IrGeneratorContext { interface IrPluginContext : IrGeneratorContext {
val languageVersionSettings: LanguageVersionSettings val languageVersionSettings: LanguageVersionSettings
@@ -29,13 +38,13 @@ interface IrPluginContext : IrGeneratorContext {
val moduleDescriptor: ModuleDescriptor val moduleDescriptor: ModuleDescriptor
@ObsoleteDescriptorBasedAPI @ObsoleteDescriptorBasedAPI
@Deprecated("", level = DeprecationLevel.ERROR) @FirIncompatiblePluginAPI
val bindingContext: BindingContext val bindingContext: BindingContext
val symbolTable: ReferenceSymbolTable val symbolTable: ReferenceSymbolTable
@ObsoleteDescriptorBasedAPI @ObsoleteDescriptorBasedAPI
// @Deprecated("", level = DeprecationLevel.ERROR) @FirIncompatiblePluginAPI
val typeTranslator: TypeTranslator val typeTranslator: TypeTranslator
val symbols: BuiltinSymbolsBase val symbols: BuiltinSymbolsBase
@@ -51,14 +60,15 @@ interface IrPluginContext : IrGeneratorContext {
fun createDiagnosticReporter(pluginId: String): IrMessageLogger fun createDiagnosticReporter(pluginId: String): IrMessageLogger
// The following API is experimental // The following API is experimental
@Deprecated("Use classId overload instead") @FirIncompatiblePluginAPI("Use classId overload instead")
fun referenceClass(fqName: FqName): IrClassSymbol? fun referenceClass(fqName: FqName): IrClassSymbol?
@FirIncompatiblePluginAPI("Use classId overload instead")
fun referenceTypeAlias(fqName: FqName): IrTypeAliasSymbol? fun referenceTypeAlias(fqName: FqName): IrTypeAliasSymbol?
@Deprecated("Use classId overload instead") @FirIncompatiblePluginAPI("Use classId overload instead")
fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol>
@Deprecated("Use callableId overload instead") @FirIncompatiblePluginAPI("Use callableId overload instead")
fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol>
@Deprecated("Use callableId overload instead") @FirIncompatiblePluginAPI("Use callableId overload instead")
fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol>
// This one is experimental too // This one is experimental too
@@ -30,11 +30,11 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
open class IrPluginContextImpl constructor( open class IrPluginContextImpl constructor(
private val module: ModuleDescriptor, private val module: ModuleDescriptor,
@Deprecated("", level = DeprecationLevel.ERROR) @Deprecated("", level = DeprecationLevel.ERROR)
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class, FirIncompatiblePluginAPI::class)
override val bindingContext: BindingContext, override val bindingContext: BindingContext,
override val languageVersionSettings: LanguageVersionSettings, override val languageVersionSettings: LanguageVersionSettings,
private val st: ReferenceSymbolTable, private val st: ReferenceSymbolTable,
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class, FirIncompatiblePluginAPI::class)
override val typeTranslator: TypeTranslator, override val typeTranslator: TypeTranslator,
override val irBuiltIns: IrBuiltIns, override val irBuiltIns: IrBuiltIns,
val linker: IrDeserializer, val linker: IrDeserializer,
@@ -98,8 +98,7 @@ open class IrPluginContextImpl constructor(
return symbols return symbols
} }
@Deprecated("Use classId overload instead") @OptIn(ObsoleteDescriptorBasedAPI::class, FirIncompatiblePluginAPI::class)
@OptIn(ObsoleteDescriptorBasedAPI::class)
override fun referenceClass(fqName: FqName): IrClassSymbol? { override fun referenceClass(fqName: FqName): IrClassSymbol? {
assert(!fqName.isRoot) assert(!fqName.isRoot)
return resolveSymbol(fqName.parent()) { scope -> return resolveSymbol(fqName.parent()) { scope ->
@@ -110,7 +109,7 @@ open class IrPluginContextImpl constructor(
} }
} }
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class, FirIncompatiblePluginAPI::class)
override fun referenceTypeAlias(fqName: FqName): IrTypeAliasSymbol? { override fun referenceTypeAlias(fqName: FqName): IrTypeAliasSymbol? {
assert(!fqName.isRoot) assert(!fqName.isRoot)
return resolveSymbol(fqName.parent()) { scope -> return resolveSymbol(fqName.parent()) { scope ->
@@ -121,15 +120,14 @@ open class IrPluginContextImpl constructor(
} }
} }
@Deprecated("Use classId overload instead") @OptIn(FirIncompatiblePluginAPI::class)
override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> { override fun referenceConstructors(classFqn: FqName): Collection<IrConstructorSymbol> {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
val classSymbol = referenceClass(classFqn) ?: error("Cannot find class $classFqn") val classSymbol = referenceClass(classFqn) ?: error("Cannot find class $classFqn")
return classSymbol.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol } return classSymbol.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol }
} }
@Deprecated("Use callableId overload instead") @OptIn(ObsoleteDescriptorBasedAPI::class, FirIncompatiblePluginAPI::class)
@OptIn(ObsoleteDescriptorBasedAPI::class)
override fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> { override fun referenceFunctions(fqName: FqName): Collection<IrSimpleFunctionSymbol> {
assert(!fqName.isRoot) assert(!fqName.isRoot)
return resolveSymbolCollection(fqName.parent()) { scope -> return resolveSymbolCollection(fqName.parent()) { scope ->
@@ -138,8 +136,7 @@ open class IrPluginContextImpl constructor(
} }
} }
@Deprecated("Use callableId overload instead") @OptIn(ObsoleteDescriptorBasedAPI::class, FirIncompatiblePluginAPI::class)
@OptIn(ObsoleteDescriptorBasedAPI::class)
override fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> { override fun referenceProperties(fqName: FqName): Collection<IrPropertySymbol> {
assert(!fqName.isRoot) assert(!fqName.isRoot)
return resolveSymbolCollection(fqName.parent()) { scope -> return resolveSymbolCollection(fqName.parent()) { scope ->
@@ -149,7 +146,6 @@ open class IrPluginContextImpl constructor(
} }
override fun referenceClass(classId: ClassId): IrClassSymbol? { override fun referenceClass(classId: ClassId): IrClassSymbol? {
@Suppress("DEPRECATION")
return referenceClass(classId.asSingleFqName()) return referenceClass(classId.asSingleFqName())
} }
@@ -158,17 +154,14 @@ open class IrPluginContextImpl constructor(
} }
override fun referenceConstructors(classId: ClassId): Collection<IrConstructorSymbol> { override fun referenceConstructors(classId: ClassId): Collection<IrConstructorSymbol> {
@Suppress("DEPRECATION")
return referenceConstructors(classId.asSingleFqName()) return referenceConstructors(classId.asSingleFqName())
} }
override fun referenceFunctions(callableId: CallableId): Collection<IrSimpleFunctionSymbol> { override fun referenceFunctions(callableId: CallableId): Collection<IrSimpleFunctionSymbol> {
@Suppress("DEPRECATION")
return referenceFunctions(callableId.asSingleFqName()) return referenceFunctions(callableId.asSingleFqName())
} }
override fun referenceProperties(callableId: CallableId): Collection<IrPropertySymbol> { override fun referenceProperties(callableId: CallableId): Collection<IrPropertySymbol> {
@Suppress("DEPRECATION")
return referenceProperties(callableId.asSingleFqName()) return referenceProperties(callableId.asSingleFqName())
} }
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.android.synthetic.descriptors.ContainerOptionsProxy
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticFunction import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticFunction
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.addDispatchReceiver import org.jetbrains.kotlin.backend.common.ir.addDispatchReceiver
@@ -120,7 +121,7 @@ private class AndroidIrTransformer(val extension: AndroidIrExtension, val plugin
} }
// NOTE: sparse array version intentionally not implemented; this plugin is deprecated // NOTE: sparse array version intentionally not implemented; this plugin is deprecated
@Suppress("DEPRECATION") // TODO: check that it still works with FIR @OptIn(FirIncompatiblePluginAPI::class) // TODO: check that it still works with FIR
private val mapFactory = pluginContext.referenceFunctions(FqName("kotlin.collections.mutableMapOf")) private val mapFactory = pluginContext.referenceFunctions(FqName("kotlin.collections.mutableMapOf"))
.single { it.owner.valueParameters.isEmpty() } .single { it.owner.valueParameters.isEmpty() }
private val mapGet = pluginContext.irBuiltIns.mapClass.owner.functions private val mapGet = pluginContext.irBuiltIns.mapClass.owner.functions
@@ -22,12 +22,10 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotat
import org.jetbrains.kotlinx.serialization.compiler.resolve.isKSerializer import org.jetbrains.kotlinx.serialization.compiler.resolve.isKSerializer
import org.jetbrains.kotlinx.serialization.compiler.resolve.toClassDescriptor import org.jetbrains.kotlinx.serialization.compiler.resolve.toClassDescriptor
const val K2_ERR_MESSAGE = "K2 not supported yet.\nBindingContext is null, meaning this function is used from the K2 compiler. Please report to devs so we can support this feature."
abstract class AbstractSerialGenerator(val bindingContext: BindingContext?, val currentDeclaration: ClassDescriptor) { abstract class AbstractSerialGenerator(val bindingContext: BindingContext?, val currentDeclaration: ClassDescriptor) {
private fun getKClassListFromFileAnnotation(annotationFqName: FqName, declarationInFile: DeclarationDescriptor): List<KotlinType> { private fun getKClassListFromFileAnnotation(annotationFqName: FqName, declarationInFile: DeclarationDescriptor): List<KotlinType> {
if (bindingContext == null) return emptyList()// TODO if (bindingContext == null) return emptyList() // TODO: support @UseSerializers in FIR
val annotation = AnnotationsUtils val annotation = AnnotationsUtils
.getContainingFileAnnotations(bindingContext, declarationInFile) .getContainingFileAnnotations(bindingContext, declarationInFile)
.find { it.fqName == annotationFqName } .find { it.fqName == annotationFqName }
@@ -16,7 +16,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
abstract class SerializableCodegen( abstract class SerializableCodegen(
protected val serializableDescriptor: ClassDescriptor, protected val serializableDescriptor: ClassDescriptor,
bindingContext: BindingContext? bindingContext: BindingContext
) : AbstractSerialGenerator(bindingContext, serializableDescriptor) { ) : AbstractSerialGenerator(bindingContext, serializableDescriptor) {
protected val properties = bindingContext.serializablePropertiesFor(serializableDescriptor) protected val properties = bindingContext.serializablePropertiesFor(serializableDescriptor)
@@ -16,7 +16,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
abstract class SerializerCodegen( abstract class SerializerCodegen(
protected val serializerDescriptor: ClassDescriptor, protected val serializerDescriptor: ClassDescriptor,
bindingContext: BindingContext?, bindingContext: BindingContext,
metadataPlugin: SerializationDescriptorSerializerPlugin? metadataPlugin: SerializationDescriptorSerializerPlugin?
) : AbstractSerialGenerator(bindingContext, serializerDescriptor) { ) : AbstractSerialGenerator(bindingContext, serializerDescriptor) {
val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorBySerializer(serializerDescriptor)!! val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorBySerializer(serializerDescriptor)!!
@@ -5,6 +5,7 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.ir.deepCopyWithVariables import org.jetbrains.kotlin.ir.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.backend.common.lower.irIfThen
@@ -24,7 +25,6 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.CallableId
@@ -33,22 +33,17 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.jvm.isJvm import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.psi import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext.typeConstructor
import org.jetbrains.kotlin.types.model.dependsOnTypeConstructor
import org.jetbrains.kotlin.types.typeUtil.* import org.jetbrains.kotlin.types.typeUtil.*
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlinx.serialization.compiler.backend.common.* import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.* import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.*
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.FUNCTION0_FQ
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_FQ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_FQ
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_FUNC_FQ
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_MODE_FQ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_MODE_FQ
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_PUBLICATION_MODE_NAME import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationDependencies.LAZY_PUBLICATION_MODE_NAME
@@ -320,23 +315,13 @@ interface IrBuilderExtension {
result result
) )
@Deprecated("", level = DeprecationLevel.ERROR) @FirIncompatiblePluginAPI
fun KotlinType.toIrType() = compilerContext.typeTranslator.translateType(this) fun KotlinType.toIrType() = compilerContext.typeTranslator.translateType(this)
// note: this method should be used only for properties from current module. Fields from other modules are private and inaccessible. // note: this method should be used only for properties from current module. Fields from other modules are private and inaccessible.
val IrSerializableProperty.irField: IrField? val IrSerializableProperty.irField: IrField?
get() = this.descriptor.backingField get() = this.descriptor.backingField
fun IrClass.searchForProperty(descriptor: PropertyDescriptor): IrProperty {
// this API is used to reference both current module descriptors and external ones (because serializable class can be in any of them),
// so we use descriptor api for current module because it is not possible to obtain FQname for e.g. local classes.
return searchForDeclaration(descriptor) ?: if (descriptor.module == compilerContext.moduleDescriptor) {
compilerContext.symbolTable.referenceProperty(descriptor).owner
} else {
@Suppress("DEPRECATION")
compilerContext.referenceProperties(descriptor.fqNameSafe).single().owner
}
}
@@ -347,8 +332,7 @@ interface IrBuilderExtension {
fun IrBuilderWithScope.createPropertyByParamReplacer( fun IrBuilderWithScope.createPropertyByParamReplacer(
irClass: IrClass, irClass: IrClass,
serialProperties: List<IrSerializableProperty>, serialProperties: List<IrSerializableProperty>,
instance: IrValueParameter, instance: IrValueParameter
bindingContext: BindingContext?
): (ValueParameterDescriptor) -> IrExpression? { ): (ValueParameterDescriptor) -> IrExpression? {
fun IrSerializableProperty.irGet(): IrExpression { fun IrSerializableProperty.irGet(): IrExpression {
val ownerType = instance.symbol.owner.type val ownerType = instance.symbol.owner.type
@@ -532,7 +516,7 @@ interface IrBuilderExtension {
val field = with(propertyDescriptor) { val field = with(propertyDescriptor) {
// TODO: type parameters // TODO: type parameters
@Suppress("DEPRECATION_ERROR") // should be called only with old FE @OptIn(FirIncompatiblePluginAPI::class)// should be called only with old FE
originProperty.factory.createField( originProperty.factory.createField(
originProperty.startOffset, originProperty.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrFieldSymbolImpl(propertyDescriptor), name, type.toIrType(), originProperty.startOffset, originProperty.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrFieldSymbolImpl(propertyDescriptor), name, type.toIrType(),
visibility, !isVar, isEffectivelyExternal(), dispatchReceiverParameter == null visibility, !isVar, isEffectivelyExternal(), dispatchReceiverParameter == null
@@ -558,7 +542,7 @@ interface IrBuilderExtension {
false -> searchForDeclaration<IrProperty>(propertyDescriptor)?.setter false -> searchForDeclaration<IrProperty>(propertyDescriptor)?.setter
} ?: run { } ?: run {
with(descriptor) { with(descriptor) {
@Suppress("DEPRECATION_ERROR") // should never be called after FIR frontend @OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
property.factory.createFunction( property.factory.createFunction(
fieldSymbol.owner.startOffset, fieldSymbol.owner.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrSimpleFunctionSymbolImpl(descriptor), fieldSymbol.owner.startOffset, fieldSymbol.owner.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrSimpleFunctionSymbolImpl(descriptor),
name, visibility, modality, returnType!!.toIrType(), name, visibility, modality, returnType!!.toIrType(),
@@ -567,7 +551,7 @@ interface IrBuilderExtension {
}.also { f -> }.also { f ->
generateOverriddenFunctionSymbols(f, compilerContext.symbolTable) generateOverriddenFunctionSymbols(f, compilerContext.symbolTable)
f.createParameterDeclarations(descriptor) f.createParameterDeclarations(descriptor)
@Suppress("DEPRECATION_ERROR") // should never be called after FIR frontend @OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
f.returnType = descriptor.returnType!!.toIrType() f.returnType = descriptor.returnType!!.toIrType()
f.correspondingPropertySymbol = fieldSymbol.owner.correspondingPropertySymbol f.correspondingPropertySymbol = fieldSymbol.owner.correspondingPropertySymbol
} }
@@ -662,7 +646,7 @@ interface IrBuilderExtension {
) { ) {
val function = this val function = this
fun irValueParameter(descriptor: ParameterDescriptor): IrValueParameter = with(descriptor) { fun irValueParameter(descriptor: ParameterDescriptor): IrValueParameter = with(descriptor) {
@Suppress("DEPRECATION_ERROR") // should never be called after FIR frontend @OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
factory.createValueParameter( factory.createValueParameter(
function.startOffset, function.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrValueParameterSymbolImpl(this), function.startOffset, function.endOffset, SERIALIZABLE_PLUGIN_ORIGIN, IrValueParameterSymbolImpl(this),
name, indexOrMinusOne, type.toIrType(), varargElementType?.toIrType(), isCrossinline, isNoinline, name, indexOrMinusOne, type.toIrType(), varargElementType?.toIrType(), isCrossinline, isNoinline,
@@ -697,7 +681,7 @@ interface IrBuilderExtension {
typeParameter.parent = this typeParameter.parent = this
} }
} }
@Suppress("DEPRECATION_ERROR") // should never be called after FIR frontend @OptIn(FirIncompatiblePluginAPI::class) // should never be called after FIR frontend
newTypeParameters.forEach { typeParameter -> newTypeParameters.forEach { typeParameter ->
typeParameter.superTypes = typeParameter.descriptor.upperBounds.map { it.toIrType() } typeParameter.superTypes = typeParameter.descriptor.upperBounds.map { it.toIrType() }
} }
@@ -867,13 +851,6 @@ interface IrBuilderExtension {
expression expression
} }
// private fun IrBuilderWithScope.wrapWithNullableSerializerIfNeeded(
// type: KotlinType,
// expression: IrExpression,
// nullableProp: IrPropertySymbol
// ): IrExpression = wrapWithNullableSerializerIfNeeded(type.toIrType(), expression, nullableProp)
fun wrapIrTypeIntoKSerializerIrType( fun wrapIrTypeIntoKSerializerIrType(
type: IrType, type: IrType,
variance: Variance = Variance.INVARIANT variance: Variance = Variance.INVARIANT
@@ -5,6 +5,7 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.ir package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
import org.jetbrains.kotlin.backend.common.ir.addExtensionReceiver import org.jetbrains.kotlin.backend.common.ir.addExtensionReceiver
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -55,7 +56,7 @@ class SerialInfoImplJvmIrGenerator(
fun getImplClass(serialInfoAnnotationClass: IrClass): IrClass = fun getImplClass(serialInfoAnnotationClass: IrClass): IrClass =
annotationToImpl.getOrPut(serialInfoAnnotationClass) { annotationToImpl.getOrPut(serialInfoAnnotationClass) {
@Suppress("DEPRECATION") // TODO @OptIn(FirIncompatiblePluginAPI::class) // TODO
val implClassSymbol = context.referenceClass(serialInfoAnnotationClass.kotlinFqName.child(SerialEntityNames.IMPL_NAME)) val implClassSymbol = context.referenceClass(serialInfoAnnotationClass.kotlinFqName.child(SerialEntityNames.IMPL_NAME))
implClassSymbol!!.owner.apply(this::generate) implClassSymbol!!.owner.apply(this::generate)
} }
@@ -36,10 +36,10 @@ class SerializableCompanionIrGenerator(
override val compilerContext: SerializationPluginContext, override val compilerContext: SerializationPluginContext,
) : SerializableCompanionCodegen(irClass.descriptor, null), IrBuilderExtension { ) : SerializableCompanionCodegen(irClass.descriptor, null), IrBuilderExtension {
override fun getSerializerGetterDescriptor(): FunctionDescriptor { // todo: remove .toKotlinType() override fun getSerializerGetterDescriptor(): FunctionDescriptor {
return irClass.findDeclaration<IrSimpleFunction> { return irClass.findDeclaration<IrSimpleFunction> {
(it.valueParameters.size == serializableDescriptor.declaredTypeParameters.size (it.valueParameters.size == serializableDescriptor.declaredTypeParameters.size
&& it.valueParameters.all { p -> isKSerializer(p.type.toKotlinType()) }) && isKSerializer(it.returnType.toKotlinType()) && it.valueParameters.all { p -> isKSerializer(p.type) }) && isKSerializer(it.returnType)
}?.descriptor ?: throw IllegalStateException( }?.descriptor ?: throw IllegalStateException(
"Can't find synthesized 'Companion.serializer()' function to generate, " + "Can't find synthesized 'Companion.serializer()' function to generate, " +
"probably clash with user-defined function has occurred" "probably clash with user-defined function has occurred"
@@ -8,7 +8,6 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir
import org.jetbrains.kotlin.backend.common.lower.irThrow import org.jetbrains.kotlin.backend.common.lower.irThrow
import org.jetbrains.kotlin.codegen.CompilationException import org.jetbrains.kotlin.codegen.CompilationException
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -22,13 +21,7 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.util.collectionUtils.filterIsInstanceAnd
import org.jetbrains.kotlin.utils.getOrPutNullable import org.jetbrains.kotlin.utils.getOrPutNullable
import org.jetbrains.kotlinx.serialization.compiler.backend.common.* import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
import org.jetbrains.kotlinx.serialization.compiler.backend.common.isStaticSerializable import org.jetbrains.kotlinx.serialization.compiler.backend.common.isStaticSerializable
@@ -75,7 +68,7 @@ class SerializableIrGenerator(
val serialDescs = serializableProperties.map { it.descriptor }.toSet() val serialDescs = serializableProperties.map { it.descriptor }.toSet()
val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? =
createPropertyByParamReplacer(irClass, serializableProperties, thiz, bindingContext) createPropertyByParamReplacer(irClass, serializableProperties, thiz)
val initializerAdapter: (IrExpressionBody) -> IrExpression = createInitializerAdapter(irClass, propertyByParamReplacer) val initializerAdapter: (IrExpressionBody) -> IrExpression = createInitializerAdapter(irClass, propertyByParamReplacer)
@@ -196,9 +189,6 @@ class SerializableIrGenerator(
private fun IrBlockBodyBuilder.getStaticSerialDescriptorExpr(): IrExpression { private fun IrBlockBodyBuilder.getStaticSerialDescriptorExpr(): IrExpression {
val serializerIrClass = irClass.classSerializer(compilerContext)!!.owner val serializerIrClass = irClass.classSerializer(compilerContext)!!.owner
// internally generated serializer always declared inside serializable class // internally generated serializer always declared inside serializable class
// val serializerIrClass = irClass.declarations
// .filterIsInstanceAnd<IrClass> { it.name == serializer.name }
// .singleOrNull() ?: throw Exception("No class with name ${serializer.fqNameSafe}")
val serialDescriptorGetter = val serialDescriptorGetter =
serializerIrClass.getPropertyGetter(SERIAL_DESC_FIELD)!! serializerIrClass.getPropertyGetter(SERIAL_DESC_FIELD)!!
@@ -282,7 +272,7 @@ class SerializableIrGenerator(
): Int { ): Int {
check(superClass.isInternalSerializable) check(superClass.isInternalSerializable)
val superCtorRef = serializableSyntheticConstructor(superClass)!! val superCtorRef = serializableSyntheticConstructor(superClass)!!
val superProperties = bindingContext.serializablePropertiesFor(superClass.descriptor).serializableProperties val superProperties = bindingContext.serializablePropertiesForIrBackend(superClass).serializableProperties
val superSlots = superProperties.bitMaskSlotCount() val superSlots = superProperties.bitMaskSlotCount()
val arguments = allValueParameters.subList(0, superSlots) + val arguments = allValueParameters.subList(0, superSlots) +
allValueParameters.subList(propertiesStart, propertiesStart + superProperties.size) + allValueParameters.subList(propertiesStart, propertiesStart + superProperties.size) +
@@ -308,7 +298,7 @@ class SerializableIrGenerator(
val kOutputClass = compilerContext.getClassFromRuntime(SerialEntityNames.STRUCTURE_ENCODER_CLASS) val kOutputClass = compilerContext.getClassFromRuntime(SerialEntityNames.STRUCTURE_ENCODER_CLASS)
val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? =
createPropertyByParamReplacer(irClass, serializableProperties, objectToSerialize, bindingContext) createPropertyByParamReplacer(irClass, serializableProperties, objectToSerialize)
// Since writeSelf is a static method, we have to replace all references to this in property initializers // Since writeSelf is a static method, we have to replace all references to this in property initializers
val thisSymbol = irClass.thisReceiver!!.symbol val thisSymbol = irClass.thisReceiver!!.symbol
@@ -319,7 +309,7 @@ class SerializableIrGenerator(
var ignoreIndexTo = -1 var ignoreIndexTo = -1
val superClass = irClass.getSuperClassOrAny() val superClass = irClass.getSuperClassOrAny()
if (superClass.descriptor.isInternalSerializable) { if (superClass.descriptor.isInternalSerializable) {
ignoreIndexTo = bindingContext.serializablePropertiesFor(superClass.descriptor).size ignoreIndexTo = bindingContext.serializablePropertiesForIrBackend(superClass).serializableProperties.size
// call super.writeSelf // call super.writeSelf
var superWriteSelfF = superClass.findWriteSelfMethod() var superWriteSelfF = superClass.findWriteSelfMethod()
@@ -293,7 +293,7 @@ open class SerializerIrGenerator(
+irInvoke(null, writeSelfFunction.symbol, typeArgs, args) +irInvoke(null, writeSelfFunction.symbol, typeArgs, args)
} else { } else {
val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? =
createPropertyByParamReplacer(serializableIrClass, serializableProperties, objectToSerialize, bindingContext) createPropertyByParamReplacer(serializableIrClass, serializableProperties, objectToSerialize)
val thisSymbol = serializableIrClass.thisReceiver!!.symbol val thisSymbol = serializableIrClass.thisReceiver!!.symbol
val initializerAdapter: (IrExpressionBody) -> IrExpression = val initializerAdapter: (IrExpressionBody) -> IrExpression =
@@ -143,7 +143,7 @@ class SerializableJsTranslator(
): Int { ): Int {
val constrDesc = superClass.constructors.single(ClassConstructorDescriptor::isSerializationCtor) val constrDesc = superClass.constructors.single(ClassConstructorDescriptor::isSerializationCtor)
val constrRef = context.getInnerNameForDescriptor(constrDesc).makeRef() val constrRef = context.getInnerNameForDescriptor(constrDesc).makeRef()
val superProperties = bindingContext.serializablePropertiesFor(superClass).serializableProperties val superProperties = bindingContext!!.serializablePropertiesFor(superClass).serializableProperties
val superSlots = superProperties.bitMaskSlotCount() val superSlots = superProperties.bitMaskSlotCount()
val arguments = parameters.subList(0, superSlots) + val arguments = parameters.subList(0, superSlots) +
parameters.subList(propertiesStart, propertiesStart + superProperties.size) + parameters.subList(propertiesStart, propertiesStart + superProperties.size) +
@@ -93,7 +93,7 @@ class SerializableCodegenImpl(
val superClass = serializableDescriptor.getSuperClassOrAny() val superClass = serializableDescriptor.getSuperClassOrAny()
val myPropsStart: Int val myPropsStart: Int
if (superClass.isInternalSerializable) { if (superClass.isInternalSerializable) {
myPropsStart = bindingContext.serializablePropertiesFor(superClass).serializableProperties.size myPropsStart = bindingContext!!.serializablePropertiesFor(superClass).serializableProperties.size
val superTypeArguments = val superTypeArguments =
serializableDescriptor.typeConstructor.supertypes.single { it.toClassDescriptor?.isInternalSerializable == true }.arguments serializableDescriptor.typeConstructor.supertypes.single { it.toClassDescriptor?.isInternalSerializable == true }.arguments
//super.writeSelf(output, serialDesc) //super.writeSelf(output, serialDesc)
@@ -293,7 +293,7 @@ class SerializableCodegenImpl(
invokespecial(superType, "<init>", desc, false) invokespecial(superType, "<init>", desc, false)
return 0 to propStartVar return 0 to propStartVar
} else { } else {
val superProps = bindingContext.serializablePropertiesFor(superClass).serializableProperties val superProps = bindingContext!!.serializablePropertiesFor(superClass).serializableProperties
val creator = buildInternalConstructorDesc(propStartVar, maskVar, classCodegen, superProps) val creator = buildInternalConstructorDesc(propStartVar, maskVar, classCodegen, superProps)
invokespecial(superType, "<init>", creator, false) invokespecial(superType, "<init>", creator, false)
return superProps.size to propStartVar + superProps.sumOf { it.asmType.size } return superProps.size to propStartVar + superProps.sumOf { it.asmType.size }
@@ -42,7 +42,7 @@ interface ISerializableProperties<D, T, S : ISerializableProperty<D, T>> {
val serializableStandaloneProperties: List<S> val serializableStandaloneProperties: List<S>
} }
class SerializableProperties(private val serializableClass: ClassDescriptor, val bindingContext: BindingContext?) : class SerializableProperties(private val serializableClass: ClassDescriptor, val bindingContext: BindingContext) :
ISerializableProperties<PropertyDescriptor, KotlinType, SerializableProperty> { ISerializableProperties<PropertyDescriptor, KotlinType, SerializableProperty> {
private val primaryConstructorParameters: List<ValueParameterDescriptor> = private val primaryConstructorParameters: List<ValueParameterDescriptor> =
serializableClass.unsubstitutedPrimaryConstructor?.valueParameters ?: emptyList() serializableClass.unsubstitutedPrimaryConstructor?.valueParameters ?: emptyList()
@@ -55,15 +55,9 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
val descriptorsSequence = serializableClass.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.VARIABLES) val descriptorsSequence = serializableClass.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.VARIABLES)
.asSequence() .asSequence()
// call to any BindingContext.get should be only AFTER MemberScope.getContributedDescriptors // call to any BindingContext.get should be only AFTER MemberScope.getContributedDescriptors
// TODO: fix binding context shit
primaryConstructorProperties = primaryConstructorProperties =
primaryConstructorParameters.asSequence() primaryConstructorParameters.asSequence()
.map { parameter -> .map { parameter -> bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter] to parameter.declaresDefaultValue() }
bindingContext?.get(
BindingContext.VALUE_PARAMETER_AS_PROPERTY,
parameter
) to parameter.declaresDefaultValue()
}
.mapNotNull { (a, b) -> if (a == null) null else a to b } .mapNotNull { (a, b) -> if (a == null) null else a to b }
.toMap() .toMap()
@@ -84,8 +78,7 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
prop.hasBackingField(bindingContext) || (prop is DeserializedPropertyDescriptor && prop.backingField != null) // workaround for TODO in .hasBackingField prop.hasBackingField(bindingContext) || (prop is DeserializedPropertyDescriptor && prop.backingField != null) // workaround for TODO in .hasBackingField
// workaround for overridden getter (val) and getter+setter (var) - in this case hasBackingField returning false // workaround for overridden getter (val) and getter+setter (var) - in this case hasBackingField returning false
// but initializer presents only for property with backing field // but initializer presents only for property with backing field
|| declaresDefaultValue || declaresDefaultValue,
|| prop.backingField != null, // todo: find out what happens next
declaresDefaultValue declaresDefaultValue
) )
} }
@@ -172,11 +165,8 @@ internal val ISerializableProperties<*, *, *>.goldenMaskList: List<Int>
internal fun List<ISerializableProperty<*, *>>.bitMaskSlotCount() = size / 32 + 1 internal fun List<ISerializableProperty<*, *>>.bitMaskSlotCount() = size / 32 + 1
internal fun bitMaskSlotAt(propertyIndex: Int) = propertyIndex / 32 internal fun bitMaskSlotAt(propertyIndex: Int) = propertyIndex / 32
internal fun BindingContext?.serializablePropertiesFor( internal fun BindingContext.serializablePropertiesFor(classDescriptor: ClassDescriptor, serializationDescriptorSerializer: SerializationDescriptorSerializerPlugin? = null): SerializableProperties {
classDescriptor: ClassDescriptor, val props = this.get(SERIALIZABLE_PROPERTIES, classDescriptor) ?: SerializableProperties(classDescriptor, this)
serializationDescriptorSerializer: SerializationDescriptorSerializerPlugin? = null
): SerializableProperties {
val props = this?.get(SERIALIZABLE_PROPERTIES, classDescriptor) ?: SerializableProperties(classDescriptor, this)
serializationDescriptorSerializer?.putIfNeeded(classDescriptor, props) serializationDescriptorSerializer?.putIfNeeded(classDescriptor, props)
return props return props
} }