Synthesize @Metadata signature of constructor and (extension) functions.

With that, when synthesizing @Metdata for constructor and (extension)
functions, we don't need original @Metadata anymore.

Bug: 70169921
Change-Id: I2965d78494c78ae6e8213c65a71b1f0d8c812aa3
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 06f579c..779e3cc 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -14,7 +14,6 @@
 import com.google.common.base.MoreObjects;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Iterators;
 import com.google.common.collect.Sets;
@@ -24,12 +23,10 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
-import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
-import kotlinx.metadata.KmConstructor;
 import kotlinx.metadata.KmFunction;
 import kotlinx.metadata.KmProperty;
 
@@ -214,24 +211,10 @@
     return Arrays.asList(virtualMethods);
   }
 
-  public Map<DexEncodedMethod, KmConstructor> kotlinConstructors(
-      List<KmConstructor> constructors, AppView<?> appView) {
-    ImmutableMap.Builder<DexEncodedMethod, KmConstructor> builder = ImmutableMap.builder();
-    for (DexEncodedMethod method : directMethods) {
-      if (method.isInstanceInitializer()) {
-        KmConstructor constructor = method.findCompatibleKotlinConstructor(constructors, appView);
-        if (constructor != null) {
-          // Found a compatible constructor that is likely asked to keep.
-          builder.put(method, constructor);
-        }
-      }
-    }
-    return builder.build();
-  }
-
-  public Map<DexEncodedMethod, KmFunction> kotlinExtensions(
+  // TODO(b/70169921): mark/propagate extension function as a method metadata.
+  public List<DexEncodedMethod> kotlinExtensions(
       List<KmFunction> extensions, AppView<?> appView) {
-    ImmutableMap.Builder<DexEncodedMethod, KmFunction> builder = ImmutableMap.builder();
+    ImmutableList.Builder<DexEncodedMethod> builder = ImmutableList.builder();
     for (DexEncodedMethod method : directMethods) {
       if (method.isInitializer()) {
         continue;
@@ -239,7 +222,7 @@
       KmFunction extension = method.findCompatibleKotlinExtension(extensions, appView);
       if (extension != null) {
         // Found a compatible extension that is likely asked to keep.
-        builder.put(method, extension);
+        builder.add(method);
       }
     }
     return builder.build();
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 2ecc549..39f8eeb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -74,7 +74,6 @@
 import java.util.Map;
 import java.util.function.Consumer;
 import java.util.function.IntPredicate;
-import kotlinx.metadata.KmConstructor;
 import kotlinx.metadata.KmFunction;
 import kotlinx.metadata.KmProperty;
 import org.objectweb.asm.Opcodes;
@@ -395,20 +394,6 @@
   }
 
   // TODO(b/70169921): Handling JVM extensions as well.
-  KmConstructor findCompatibleKotlinConstructor(
-      List<KmConstructor> constructors, AppView<?> appView) {
-    if (!isInstanceInitializer()) {
-      return null;
-    }
-    for (KmConstructor constructor : constructors) {
-      if (KotlinMetadataSynthesizer.isCompatibleConstructor(constructor, this, appView)) {
-        return constructor;
-      }
-    }
-    return null;
-  }
-
-  // TODO(b/70169921): Handling JVM extensions as well.
   KmFunction findCompatibleKotlinExtension(List<KmFunction> extensions, AppView<?> appView) {
     if (!isStaticMember()) {
       return null;
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
index ff97c60..5f31c51 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
@@ -15,9 +15,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import kotlinx.metadata.KmClass;
 import kotlinx.metadata.KmConstructor;
 import kotlinx.metadata.KmType;
@@ -70,12 +68,12 @@
       return;
     }
     List<KmConstructor> constructors = kmClass.getConstructors();
-    List<KmConstructor> originalConstructors = new ArrayList<>(constructors);
     constructors.clear();
-    for (Map.Entry<DexEncodedMethod, KmConstructor> entry :
-        clazz.kotlinConstructors(originalConstructors, appView).entrySet()) {
-      KmConstructor constructor =
-          toRenamedKmConstructor(entry.getKey(), entry.getValue(), appView, lens);
+    for (DexEncodedMethod method : clazz.directMethods()) {
+      if (!method.isInstanceInitializer()) {
+        continue;
+      }
+      KmConstructor constructor = toRenamedKmConstructor(method, appView, lens);
       if (constructor != null) {
         constructors.add(constructor);
       }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
index 9cd71c3..548d2e2 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
@@ -14,7 +14,6 @@
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.List;
-import java.util.Map;
 import java.util.stream.Collectors;
 import kotlinx.metadata.KmDeclarationContainer;
 import kotlinx.metadata.KmFunction;
@@ -118,15 +117,13 @@
 
     List<KmProperty> properties = kmDeclarationContainer.getProperties();
     for (DexEncodedMethod method : clazz.kotlinFunctions(originalFunctions, properties, appView)) {
-      KmFunction function = toRenamedKmFunction(method, null, appView, lens);
+      KmFunction function = toRenamedKmFunction(method, appView, lens);
       if (function != null) {
         functions.add(function);
       }
     }
-    for (Map.Entry<DexEncodedMethod, KmFunction> entry :
-        clazz.kotlinExtensions(originalExtensions, appView).entrySet()) {
-      KmFunction extension =
-          toRenamedKmFunctionAsExtension(entry.getKey(), entry.getValue(), appView, lens);
+    for (DexEncodedMethod method : clazz.kotlinExtensions(originalExtensions, appView)) {
+      KmFunction extension = toRenamedKmFunctionAsExtension(method, appView, lens);
       if (extension != null) {
         functions.add(extension);
       }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataJvmExtensionUtils.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataJvmExtensionUtils.java
index 85e3540..e0ae783 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataJvmExtensionUtils.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataJvmExtensionUtils.java
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.kotlin;
 
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
 import com.google.common.collect.ImmutableList;
 import java.util.Arrays;
 import java.util.List;
@@ -24,6 +26,17 @@
 
 class KotlinMetadataJvmExtensionUtils {
 
+  static JvmMethodSignature toJvmMethodSignature(DexMethod method) {
+    StringBuilder descBuilder = new StringBuilder();
+    descBuilder.append("(");
+    for (DexType argType : method.proto.parameters.values) {
+      descBuilder.append(argType.toDescriptorString());
+    }
+    descBuilder.append(")");
+    descBuilder.append(method.proto.returnType.toDescriptorString());
+    return new JvmMethodSignature(method.name.toString(), descBuilder.toString());
+  }
+
   private static boolean isValidJvmMethodSignature(String desc) {
     return desc != null
         && !desc.isEmpty()
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
index 51b04d9..b3491a5 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
@@ -6,6 +6,7 @@
 import static com.android.tools.r8.kotlin.Kotlin.addKotlinPrefix;
 import static com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.parameterTypesFromJvmMethodSignature;
 import static com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.returnTypeFromJvmMethodSignature;
+import static com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.toJvmMethodSignature;
 import static com.android.tools.r8.utils.DescriptorUtils.descriptorToInternalName;
 import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromKmType;
 import static kotlinx.metadata.FlagsKt.flagsOf;
@@ -16,7 +17,6 @@
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.KmConstructorProcessor;
 import com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.KmFunctionProcessor;
 import com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.KmPropertyProcessor;
 import com.android.tools.r8.naming.NamingLens;
@@ -28,6 +28,7 @@
 import kotlinx.metadata.KmType;
 import kotlinx.metadata.KmValueParameter;
 import kotlinx.metadata.jvm.JvmMethodSignature;
+import kotlinx.metadata.jvm.JvmExtensionsKt;
 
 public class KotlinMetadataSynthesizer {
 
@@ -254,7 +255,6 @@
 
   static KmConstructor toRenamedKmConstructor(
       DexEncodedMethod method,
-      KmConstructor original,
       AppView<AppInfoWithLiveness> appView,
       NamingLens lens) {
     // Make sure it is an instance initializer and live.
@@ -262,17 +262,9 @@
         || !appView.appInfo().liveMethods.contains(method.method)) {
       return null;
     }
-    // TODO(b/70169921): {@link KmConstructor.extensions} is private, i.e., no way to alter!
-    //   Thus, we rely on original metadata for now.
-    KmConstructorProcessor kmConstructorProcessor = new KmConstructorProcessor(original);
-    JvmMethodSignature jvmMethodSignature = kmConstructorProcessor.signature();
-    KmConstructor kmConstructor =
-        jvmMethodSignature != null
-            ? original
-            // TODO(b/70169921): Consult kotlinx.metadata.Flag.Constructor to set IS_PRIMARY.
-            : new KmConstructor(method.accessFlags.getAsKotlinFlags());
+    KmConstructor kmConstructor = new KmConstructor(method.accessFlags.getAsKotlinFlags());
+    JvmExtensionsKt.setSignature(kmConstructor, toJvmMethodSignature(method.method));
     List<KmValueParameter> parameters = kmConstructor.getValueParameters();
-    parameters.clear();
     if (!populateKmValueParameters(parameters, method, appView, lens, false)) {
       return null;
     }
@@ -281,23 +273,20 @@
 
   static KmFunction toRenamedKmFunction(
       DexEncodedMethod method,
-      KmFunction original,
       AppView<AppInfoWithLiveness> appView,
       NamingLens lens) {
-    return toRenamedKmFunctionHelper(method, original, appView, lens, false);
+    return toRenamedKmFunctionHelper(method, appView, lens, false);
   }
 
   static KmFunction toRenamedKmFunctionAsExtension(
       DexEncodedMethod method,
-      KmFunction original,
       AppView<AppInfoWithLiveness> appView,
       NamingLens lens) {
-    return toRenamedKmFunctionHelper(method, original, appView, lens, true);
+    return toRenamedKmFunctionHelper(method, appView, lens, true);
   }
 
   private static KmFunction toRenamedKmFunctionHelper(
       DexEncodedMethod method,
-      KmFunction original,
       AppView<AppInfoWithLiveness> appView,
       NamingLens lens,
       boolean isExtension) {
@@ -311,14 +300,9 @@
     // For a library method override, we should not have renamed it.
     assert !method.isLibraryMethodOverride().isTrue() || renamedMethod == method.method
         : method.toSourceString() + " -> " + renamedMethod.toSourceString();
-    // TODO(b/70169921): {@link KmFunction.extensions} is private, i.e., no way to alter!
-    //   Thus, we rely on original metadata for now.
-    assert !isExtension || original != null;
     KmFunction kmFunction =
-        isExtension
-            ? original
-            // TODO(b/70169921): Consult kotlinx.metadata.Flag.Function for kind (e.g., suspend).
-            : new KmFunction(method.accessFlags.getAsKotlinFlags(), renamedMethod.name.toString());
+        new KmFunction(method.accessFlags.getAsKotlinFlags(), renamedMethod.name.toString());
+    JvmExtensionsKt.setSignature(kmFunction, toJvmMethodSignature(method.method));
     KmType kmReturnType = toRenamedKmType(method.method.proto.returnType, appView, lens);
     if (kmReturnType == null) {
       return null;
@@ -334,7 +318,6 @@
       kmFunction.setReceiverParameterType(kmReceiverType);
     }
     List<KmValueParameter> parameters = kmFunction.getValueParameters();
-    parameters.clear();
     if (!populateKmValueParameters(parameters, method, appView, lens, isExtension)) {
       return null;
     }