Update parameter metadata for companion classes

Extend the MethodParameters attribute and the parameter annotations
when moving the default method to the static companion class.

Bug: 189743726
Change-Id: I2e43dfc2d8ba9b16aaceeda649bf658b37eedec8
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
index e1a64b1..651a484 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
@@ -7,6 +7,9 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.dex.MixedSectionCollection;
+import com.android.tools.r8.graph.DexValue.DexValueArray;
+import com.android.tools.r8.graph.DexValue.DexValueInt;
+import com.android.tools.r8.graph.DexValue.DexValueString;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.utils.ArrayUtils;
 import com.android.tools.r8.utils.structural.StructuralItem;
@@ -199,6 +202,43 @@
     return new DexAnnotationSet(rewritten);
   }
 
+  public DexAnnotationSet methodParametersWithFakeThisArguments(DexItemFactory factory) {
+    DexAnnotation[] newAnnotations = null;
+    for (int i = 0; i < annotations.length; i++) {
+      DexAnnotation annotation = annotations[i];
+      if (annotation.annotation.type == factory.annotationMethodParameters) {
+        assert annotation.visibility == DexAnnotation.VISIBILITY_SYSTEM;
+        assert annotation.annotation.elements.length == 2;
+        assert annotation.annotation.elements[0].name.toString().equals("names");
+        assert annotation.annotation.elements[1].name.toString().equals("accessFlags");
+        DexValueArray names = annotation.annotation.elements[0].value.asDexValueArray();
+        DexValueArray accessFlags = annotation.annotation.elements[1].value.asDexValueArray();
+        assert names != null && accessFlags != null;
+        assert names.getValues().length == accessFlags.getValues().length;
+        if (newAnnotations == null) {
+          newAnnotations = new DexAnnotation[annotations.length];
+          System.arraycopy(annotations, 0, newAnnotations, 0, i);
+        }
+        DexValue[] newNames = new DexValue[names.getValues().length + 1];
+        newNames[0] =
+            new DexValueString(
+                factory.createString(DexCode.FAKE_THIS_PREFIX + DexCode.FAKE_THIS_SUFFIX));
+        System.arraycopy(names.getValues(), 0, newNames, 1, names.getValues().length);
+        DexValue[] newAccessFlags = new DexValue[accessFlags.getValues().length + 1];
+        newAccessFlags[0] = DexValueInt.create(0);
+        System.arraycopy(
+            accessFlags.getValues(), 0, newAccessFlags, 1, accessFlags.getValues().length);
+        newAnnotations[i] =
+            DexAnnotation.createMethodParametersAnnotation(newNames, newAccessFlags, factory);
+      } else {
+        if (newAnnotations != null) {
+          newAnnotations[i] = annotation;
+        }
+      }
+    }
+    return newAnnotations == null ? this : new DexAnnotationSet(newAnnotations);
+  }
+
   @Override
   public String toString() {
     return Arrays.toString(annotations);
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index e4f7973..be89c66 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -38,8 +38,8 @@
 // DexCode corresponds to code item in dalvik/dex-format.html
 public class DexCode extends Code implements StructuralItem<DexCode> {
 
-  static final String FAKE_THIS_PREFIX = "_";
-  static final String FAKE_THIS_SUFFIX = "this";
+  public static final String FAKE_THIS_PREFIX = "_";
+  public static final String FAKE_THIS_SUFFIX = "this";
 
   public final int registerSize;
   public final int incomingRegisterSize;
diff --git a/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java b/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
index 7628702..dee2c8d 100644
--- a/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
+++ b/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
@@ -187,6 +187,17 @@
     return new ParameterAnnotationsList(values, parameterCount - values.length);
   }
 
+  public ParameterAnnotationsList withFakeThisParameter() {
+    // If there are no parameter annotations there is no need to add one for the this parameter.
+    if (isEmpty()) {
+      return this;
+    }
+    DexAnnotationSet[] newValues = new DexAnnotationSet[size() + 1];
+    System.arraycopy(values, 0, newValues, 1, size());
+    newValues[0] = DexAnnotationSet.empty();
+    return new ParameterAnnotationsList(newValues, 0);
+  }
+
   /**
    * Return a new ParameterAnnotationsList that keeps only the annotations matched by {@code
    * filter}.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
index 2174002..0eebbdb 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
@@ -256,8 +256,12 @@
                 methodBuilder
                     .setAccessFlags(newFlags)
                     .setGenericSignature(MethodTypeSignature.noSignature())
-                    .setAnnotations(virtual.annotations())
-                    .setParameterAnnotationsList(virtual.getParameterAnnotations())
+                    .setAnnotations(
+                        virtual
+                            .annotations()
+                            .methodParametersWithFakeThisArguments(appView.dexItemFactory()))
+                    .setParameterAnnotationsList(
+                        virtual.getParameterAnnotations().withFakeThisParameter())
                     .setCode(ignored -> virtual.getCode())
                     .setOnBuildConsumer(
                         implMethod -> {
diff --git a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/MethodParametersTest.java b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/MethodParametersTest.java
index 27dcc8c..43373b9 100644
--- a/src/test/java/com/android/tools/r8/desugaring/interfacemethods/MethodParametersTest.java
+++ b/src/test/java/com/android/tools/r8/desugaring/interfacemethods/MethodParametersTest.java
@@ -5,12 +5,9 @@
 
 import static com.android.tools.r8.TestRuntime.getCheckedInJdk;
 import static com.android.tools.r8.TestRuntime.getCheckedInJdk11;
-import static org.hamcrest.CoreMatchers.anyOf;
-import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestCompileResult;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.ToolHelper;
@@ -57,6 +54,22 @@
   private final String EXPECTED =
       StringUtils.lines(
           "0", "1", "a: 1", "2", "a: 1", "b: 2", "0", "1", "a: 1", "2", "a: 1", "b: 2");
+  private final String EXPECTED_DESUGARED =
+      StringUtils.lines(
+          "1",
+          "2",
+          "_this: 0",
+          "a: 1",
+          "3",
+          "_this: 0",
+          "a: 1",
+          "b: 2",
+          "0",
+          "1",
+          "a: 1",
+          "2",
+          "a: 1",
+          "b: 2");
 
   @Test
   public void testJvm() throws Exception {
@@ -86,17 +99,6 @@
             .addProgramFiles(interfaceDesugared)
             .setMinApi(parameters.getApiLevel())
             .compile()
-            // TODO(b/189743726): These warnings should not be there.
-            .applyIf(
-                parameters.canUseDefaultAndStaticInterfaceMethodsWhenDesugaring(),
-                TestCompileResult::assertNoInfoMessages,
-                r ->
-                    r.assertAtLeastOneInfoMessage()
-                        .assertAllInfoMessagesMatch(
-                            anyOf(
-                                containsString(
-                                    "Invalid parameter counts in MethodParameter attributes"),
-                                containsString("Methods with invalid MethodParameter attributes"))))
             .writeToZip();
 
     Path programDesugared =
@@ -112,26 +114,11 @@
         .addProgramFiles(programDesugared)
         .setMinApi(parameters.getApiLevel())
         .compile()
-        // TODO(b/189743726): These warnings should not be there.
-        .applyIf(
-            parameters.canUseDefaultAndStaticInterfaceMethodsWhenDesugaring(),
-            TestCompileResult::assertNoInfoMessages,
-            r ->
-                r.assertAtLeastOneInfoMessage()
-                    .assertAllInfoMessagesMatch(
-                        anyOf(
-                            containsString(
-                                "Invalid parameter counts in MethodParameter attributes"),
-                            containsString("Methods with invalid MethodParameter attributes"))))
         .run(parameters.getRuntime(), TestRunner.class)
         .applyIf(
             parameters.canUseDefaultAndStaticInterfaceMethodsWhenDesugaring(),
             r -> r.assertSuccessWithOutput(EXPECTED),
-            // TODO(b/189743726): Should not fail at runtime (but will have different parameter
-            // count for non-static methods when desugared).
-            r ->
-                r.assertFailureWithErrorThatMatches(
-                    containsString("Wrong number of parameters in MethodParameters attribute")));
+            r -> r.assertSuccessWithOutput(EXPECTED_DESUGARED));
   }
 
   static class A implements I {}