Compile Compose Web with Kotlin 1.5
Changes:
- Updated ComposableSymbolRemapper to clear up mismatched descriptors (now with nulls instead of WrappedDescriptors).
- Used ir type in ComposableParamTransformer as KotlinType transformation doesn't handle annotations correctly.
- Cleaned up some outdated elements that are no longer needed,
Change-Id: I988c19a3c2bb2ea94e8492db832e87eb5a80b921
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableSymbolRemapper.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableSymbolRemapper.kt
index 722fd6c..6974105 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableSymbolRemapper.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableSymbolRemapper.kt
@@ -16,22 +16,20 @@
package androidx.compose.compiler.plugins.kotlin.lower
-import org.jetbrains.kotlin.ir.IrElement
-import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
-import org.jetbrains.kotlin.ir.declarations.IrConstructor
-import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
-import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
-import org.jetbrains.kotlin.ir.declarations.IrValueParameter
+import androidx.compose.compiler.plugins.kotlin.hasComposableAnnotation
+import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.descriptors.ParameterDescriptor
+import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+import org.jetbrains.kotlin.ir.descriptors.IrBasedDeclarationDescriptor
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
import org.jetbrains.kotlin.ir.util.DescriptorsRemapper
-import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
-import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
+import org.jetbrains.kotlin.types.KotlinType
/**
- * This symbol remapper is aware of possible wrapped descriptor ownership change to align
+ * This symbol remapper is aware of possible descriptor signature change to align
* function signature and descriptor signature in cases of composable value parameters.
- * As wrapped descriptors are bound to IR functions inside, we need to create a new one to change
- * the function this descriptor represents as well.
+ * It removes descriptors whenever the signature changes, forcing it to be generated from IR.
*
* E.g. when function has a signature of:
* ```
@@ -43,37 +41,51 @@
* ```
* Same applies for receiver and return types.
*
- * After remapping them, the newly created descriptors are bound back using
- * [WrappedComposableDescriptorPatcher] right after IR counterparts are created
- * (see usages in [ComposerTypeRemapper])
- *
* This conversion is only required with decoys, but can be applied to the JVM as well for
* consistency.
*/
class ComposableSymbolRemapper : DeepCopySymbolRemapper(
object : DescriptorsRemapper {
+ override fun remapDeclaredConstructor(
+ descriptor: ClassConstructorDescriptor
+ ): ClassConstructorDescriptor? =
+ descriptor.takeUnless { it.isTransformed() }
+
+ override fun remapDeclaredSimpleFunction(
+ descriptor: FunctionDescriptor
+ ): FunctionDescriptor? =
+ descriptor.takeUnless { it.isTransformed() }
+
+ override fun remapDeclaredValueParameter(
+ descriptor: ParameterDescriptor
+ ): ParameterDescriptor? =
+ descriptor.takeUnless { it.isTransformed() }
+
+ override fun remapDeclaredTypeParameter(
+ descriptor: TypeParameterDescriptor
+ ): TypeParameterDescriptor? =
+ descriptor.takeUnless { it.isTransformed() }
+
+ private fun ClassConstructorDescriptor.isTransformed(): Boolean =
+ this is IrBasedDeclarationDescriptor<*> ||
+ valueParameters.any { it.type.containsComposable() }
+
+ private fun FunctionDescriptor.isTransformed(): Boolean =
+ this is IrBasedDeclarationDescriptor<*> ||
+ valueParameters.any { it.type.containsComposable() } ||
+ returnType?.containsComposable() == true
+
+ private fun ParameterDescriptor.isTransformed(): Boolean =
+ this is IrBasedDeclarationDescriptor<*> ||
+ type.containsComposable() ||
+ containingDeclaration.let { it is FunctionDescriptor && it.isTransformed() }
+
+ private fun TypeParameterDescriptor.isTransformed(): Boolean =
+ this is IrBasedDeclarationDescriptor<*> ||
+ containingDeclaration.let { it is FunctionDescriptor && it.isTransformed() }
+
+ private fun KotlinType.containsComposable() =
+ hasComposableAnnotation() ||
+ arguments.any { it.type.hasComposableAnnotation() }
}
)
-
-@OptIn(ObsoleteDescriptorBasedAPI::class)
-object WrappedComposableDescriptorPatcher : IrElementVisitorVoid {
- override fun visitElement(element: IrElement) {
- element.acceptChildrenVoid(this)
- }
-
- override fun visitConstructor(declaration: IrConstructor) {
- super.visitConstructor(declaration)
- }
-
- override fun visitSimpleFunction(declaration: IrSimpleFunction) {
- super.visitSimpleFunction(declaration)
- }
-
- override fun visitValueParameter(declaration: IrValueParameter) {
- super.visitValueParameter(declaration)
- }
-
- override fun visitTypeParameter(declaration: IrTypeParameter) {
- super.visitTypeParameter(declaration)
- }
-}
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableTypeRemapper.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableTypeRemapper.kt
index b5c9461..b465f4a 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableTypeRemapper.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableTypeRemapper.kt
@@ -91,8 +91,6 @@
override fun visitConstructor(declaration: IrConstructor): IrConstructor {
return super.visitConstructor(declaration).also {
- WrappedComposableDescriptorPatcher.visitConstructor(it)
-
it.copyMetadataFrom(declaration)
}
}
@@ -105,8 +103,6 @@
symbolRemapper.visitSimpleFunction(declaration)
}
return super.visitSimpleFunction(declaration).also {
- WrappedComposableDescriptorPatcher.visitSimpleFunction(it)
-
it.correspondingPropertySymbol = declaration.correspondingPropertySymbol
it.copyMetadataFrom(declaration)
}
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerParamTransformer.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerParamTransformer.kt
index bff6adf..72b5ecf 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerParamTransformer.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerParamTransformer.kt
@@ -600,12 +600,11 @@
return isInvoke() && dispatchReceiver?.type?.hasComposableAnnotation() == true
}
- @OptIn(ObsoleteDescriptorBasedAPI::class)
private fun IrFunction.isNonComposableInlinedLambda(): Boolean {
for (element in inlinedFunctions) {
if (element.argument.function != this)
continue
- if (!element.parameter.descriptor.type.hasComposableAnnotation())
+ if (!element.parameter.type.hasComposableAnnotation())
return true
}
return false
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyTransformBase.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyTransformBase.kt
index cd726fb..23be234 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyTransformBase.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyTransformBase.kt
@@ -21,9 +21,6 @@
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl
import org.jetbrains.kotlin.backend.common.ir.isTopLevel
import org.jetbrains.kotlin.backend.common.ir.remapTypeParameters
-import org.jetbrains.kotlin.backend.common.serialization.IrModuleDeserializer
-import org.jetbrains.kotlin.backend.common.serialization.KotlinIrLinker
-import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData.SymbolKind.FUNCTION_SYMBOL
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrElement
@@ -38,6 +35,7 @@
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.interpreter.toIrConst
import org.jetbrains.kotlin.ir.linkage.IrDeserializer
+import org.jetbrains.kotlin.ir.linkage.IrDeserializer.TopLevelSymbolKind.FUNCTION_SYMBOL
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
@@ -168,24 +166,10 @@
}
}
- // todo(KT-44100): functions generated by this plugin are not referenceable from other modules
private fun IrDeserializer.getDeclaration(
moduleDescriptor: ModuleDescriptor,
idSignature: IdSignature
- ): IrSymbol? {
- val moduleDeserializerField =
- KotlinIrLinker::class.java.getDeclaredField("deserializersForModules")
- moduleDeserializerField.isAccessible = true
-
- @Suppress("UNCHECKED_CAST")
- val moduleMap = moduleDeserializerField.get(this)
- as Map<ModuleDescriptor, IrModuleDeserializer>
- val moduleDeserializer = moduleMap[moduleDescriptor] ?: return null
-
- val symbol = moduleDeserializer.deserializeIrSymbol(idSignature, FUNCTION_SYMBOL)
- moduleDeserializer.deserializeReachableDeclarations()
- return symbol
- }
+ ): IrSymbol = resolveBySignatureInModule(idSignature, FUNCTION_SYMBOL, moduleDescriptor.name)
}
@OptIn(ObsoleteDescriptorBasedAPI::class)