[go: nahoru, domu]

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)