[Retrace] Change RetraceTypeResult to follow the same result pattern

Change-Id: I705da867fc8088ff727ae9ffff48602cdd275a3b
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceTypeElement.java b/src/main/java/com/android/tools/r8/retrace/RetraceTypeElement.java
new file mode 100644
index 0000000..2df0a4c
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceTypeElement.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import com.android.tools.r8.Keep;
+
+@Keep
+public interface RetraceTypeElement extends RetraceElement<RetraceTypeResult> {
+
+  RetracedTypeReference getType();
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceTypeResult.java b/src/main/java/com/android/tools/r8/retrace/RetraceTypeResult.java
index 30a4c5c..7925ff6 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceTypeResult.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceTypeResult.java
@@ -5,21 +5,6 @@
 package com.android.tools.r8.retrace;
 
 import com.android.tools.r8.Keep;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
 
 @Keep
-public interface RetraceTypeResult {
-
-  Stream<Element> stream();
-
-  RetraceTypeResult forEach(Consumer<Element> resultConsumer);
-
-  boolean isAmbiguous();
-
-  @Keep
-  interface Element {
-
-    RetracedTypeReference getType();
-  }
-}
+public interface RetraceTypeResult extends RetraceResult<RetraceTypeElement> {}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceTypeResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceTypeResultImpl.java
index 6242c3b..d1ee952 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceTypeResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceTypeResultImpl.java
@@ -4,61 +4,94 @@
 
 package com.android.tools.r8.retrace.internal;
 
+import com.android.tools.r8.references.Reference;
 import com.android.tools.r8.references.TypeReference;
+import com.android.tools.r8.retrace.RetraceTypeElement;
 import com.android.tools.r8.retrace.RetraceTypeResult;
 import com.android.tools.r8.retrace.RetracedTypeReference;
 import com.android.tools.r8.retrace.Retracer;
+import com.android.tools.r8.utils.ListUtils;
+import java.util.Collections;
+import java.util.List;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 public class RetraceTypeResultImpl implements RetraceTypeResult {
 
   private final TypeReference obfuscatedType;
+  private final List<RetracedTypeReference> retracedTypeReferences;
   private final Retracer retracer;
 
-  private RetraceTypeResultImpl(TypeReference obfuscatedType, Retracer retracer) {
+  private RetraceTypeResultImpl(
+      TypeReference obfuscatedType,
+      List<RetracedTypeReference> retracedTypeReferences,
+      Retracer retracer) {
     this.obfuscatedType = obfuscatedType;
+    this.retracedTypeReferences = retracedTypeReferences;
     this.retracer = retracer;
   }
 
   static RetraceTypeResultImpl create(TypeReference obfuscatedType, Retracer retracer) {
-    return new RetraceTypeResultImpl(obfuscatedType, retracer);
+    // Handle void and primitive types as single element results.
+    return new RetraceTypeResultImpl(
+        obfuscatedType, retraceTypeReference(obfuscatedType, retracer), retracer);
+  }
+
+  private static List<RetracedTypeReference> retraceTypeReference(
+      TypeReference obfuscatedType, Retracer retracer) {
+    if (obfuscatedType == null) {
+      return Collections.emptyList();
+    } else if (obfuscatedType.isPrimitive()) {
+      return Collections.singletonList(RetracedTypeReferenceImpl.create(obfuscatedType));
+    } else if (obfuscatedType.isArray()) {
+      int dimensions = obfuscatedType.asArray().getDimensions();
+      List<RetracedTypeReference> baseTypeRetraceResult =
+          retraceTypeReference(obfuscatedType.asArray().getBaseType(), retracer);
+      return ListUtils.map(
+          baseTypeRetraceResult,
+          retraceTypeReference ->
+              RetracedTypeReferenceImpl.create(
+                  Reference.array(retraceTypeReference.getTypeReference(), dimensions)));
+    } else {
+      assert obfuscatedType.isClass();
+      return retracer.retraceClass(obfuscatedType.asClass()).stream()
+          .map(clazz -> clazz.getRetracedClass().getRetracedType())
+          .collect(Collectors.toList());
+    }
   }
 
   @Override
-  public Stream<Element> stream() {
-    // Handle void and primitive types as single element results.
-    if (obfuscatedType == null || obfuscatedType.isPrimitive()) {
-      return Stream.of(new ElementImpl(RetracedTypeReferenceImpl.create(obfuscatedType)));
-    }
-    if (obfuscatedType.isArray()) {
-      int dimensions = obfuscatedType.asArray().getDimensions();
-      return retracer.retraceType(obfuscatedType.asArray().getBaseType()).stream()
-          .map(
-              baseElement ->
-                  new ElementImpl(
-                      RetracedTypeReferenceImpl.create(baseElement.getType().toArray(dimensions))));
-    }
-    return retracer.retraceClass(obfuscatedType.asClass()).stream()
-        .map(classElement -> new ElementImpl(classElement.getRetracedClass().getRetracedType()));
+  public Stream<RetraceTypeElement> stream() {
+    List<RetraceTypeElement> map =
+        ListUtils.map(
+            retracedTypeReferences,
+            retracedTypeReference -> new ElementImpl(this, retracedTypeReference));
+    return map.stream();
   }
 
   @Override
   public boolean isAmbiguous() {
-    return false;
+    return retracedTypeReferences.size() > 1;
   }
 
   @Override
-  public RetraceTypeResultImpl forEach(Consumer<Element> resultConsumer) {
+  public void forEach(Consumer<RetraceTypeElement> resultConsumer) {
     stream().forEach(resultConsumer);
-    return this;
   }
 
-  public static class ElementImpl implements RetraceTypeResult.Element {
+  @Override
+  public boolean isEmpty() {
+    return retracedTypeReferences.size() == 0;
+  }
 
+  public static class ElementImpl implements RetraceTypeElement {
+
+    private final RetraceTypeResult typeResult;
     private final RetracedTypeReference retracedType;
 
-    public ElementImpl(RetracedTypeReference retracedType) {
+    private ElementImpl(RetraceTypeResult typeResult, RetracedTypeReference retracedType) {
+      this.typeResult = typeResult;
       this.retracedType = retracedType;
     }
 
@@ -66,5 +99,15 @@
     public RetracedTypeReference getType() {
       return retracedType;
     }
+
+    @Override
+    public RetraceTypeResult getParentResult() {
+      return typeResult;
+    }
+
+    @Override
+    public boolean isCompilerSynthesized() {
+      return false;
+    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java
index a8b5e71..c907105 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/StackTraceElementProxyRetracerImpl.java
@@ -15,8 +15,8 @@
 import com.android.tools.r8.retrace.RetraceStackTraceElementProxy;
 import com.android.tools.r8.retrace.RetraceStackTraceElementProxyResult;
 import com.android.tools.r8.retrace.RetraceThrownExceptionElement;
+import com.android.tools.r8.retrace.RetraceTypeElement;
 import com.android.tools.r8.retrace.RetraceTypeResult;
-import com.android.tools.r8.retrace.RetraceTypeResult.Element;
 import com.android.tools.r8.retrace.RetracedClassReference;
 import com.android.tools.r8.retrace.RetracedFieldReference;
 import com.android.tools.r8.retrace.RetracedMethodReference;
@@ -272,7 +272,8 @@
     } else {
       TypeReference typeReference = Reference.typeFromTypeName(elementOrReturnType);
       RetraceTypeResult retraceTypeResult = retracer.retraceType(typeReference);
-      List<Element> retracedElements = retraceTypeResult.stream().collect(Collectors.toList());
+      List<RetraceTypeElement> retracedElements =
+          retraceTypeResult.stream().collect(Collectors.toList());
       return resultBuilder
           .setResultStream(
               currentResult.stream()
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiTestCollection.java b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiTestCollection.java
index c233d49..e665c12 100644
--- a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiTestCollection.java
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiTestCollection.java
@@ -41,7 +41,8 @@
           RetracePartitionRoundTripTest.ApiTest.class,
           RetracePartitionJoinNoMetadataTest.ApiTest.class,
           RetracePartitionSerializedObfuscatedKeyTest.ApiTest.class,
-          RetracePartitionRoundTripInlineTest.ApiTest.class);
+          RetracePartitionRoundTripInlineTest.ApiTest.class,
+          RetraceApiTypeResultTest.ApiTest.class);
 
   public static List<Class<? extends RetraceApiBinaryTest>> CLASSES_PENDING_BINARY_COMPATIBILITY =
       ImmutableList.of(RetraceApiResidualSignatureTest.ApiTest.class);
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiTypeResultTest.java b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiTypeResultTest.java
new file mode 100644
index 0000000..4d76e2c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiTypeResultTest.java
@@ -0,0 +1,67 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.api;
+
+import static junit.framework.TestCase.assertEquals;
+
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.references.TypeReference;
+import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.RetraceTypeElement;
+import com.android.tools.r8.retrace.Retracer;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class RetraceApiTypeResultTest extends RetraceApiTestBase {
+
+  public RetraceApiTypeResultTest(TestParameters parameters) {
+    super(parameters);
+  }
+
+  @Override
+  protected Class<? extends RetraceApiBinaryTest> binaryTestClass() {
+    return ApiTest.class;
+  }
+
+  public static class ApiTest implements RetraceApiBinaryTest {
+
+    private final TypeReference minifiedName = Reference.typeFromTypeName("a[]");
+    private final TypeReference original = Reference.typeFromTypeName("some.Class[]");
+
+    private static final String mapping =
+        "# { id: 'com.android.tools.r8.mapping', version: '1.0' }\nsome.Class -> a:\n";
+
+    @Test
+    public void testRetraceClassArray() {
+      List<RetraceTypeElement> collect =
+          Retracer.createDefault(
+                  ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {})
+              .retraceType(minifiedName)
+              .stream()
+              .collect(Collectors.toList());
+      assertEquals(1, collect.size());
+      assertEquals(original, collect.get(0).getType().getTypeReference());
+    }
+
+    @Test
+    public void testRetracePrimitiveArray() {
+      TypeReference intArr = Reference.typeFromTypeName("int[][]");
+      List<RetraceTypeElement> collect =
+          Retracer.createDefault(
+                  ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {})
+              .retraceType(intArr)
+              .stream()
+              .collect(Collectors.toList());
+      assertEquals(1, collect.size());
+      assertEquals(intArr, collect.get(0).getType().getTypeReference());
+    }
+  }
+}
diff --git a/third_party/retrace/binary_compatibility.tar.gz.sha1 b/third_party/retrace/binary_compatibility.tar.gz.sha1
index 023f1c9..e86ba01 100644
--- a/third_party/retrace/binary_compatibility.tar.gz.sha1
+++ b/third_party/retrace/binary_compatibility.tar.gz.sha1
@@ -1 +1 @@
-ec4f1b68e126b5b5e8a53078c74c79c65e190cf2
\ No newline at end of file
+8eea4fa493bb7cb63d11e8d2a0ac34775726825e
\ No newline at end of file