Make references public to enable use and creation from retrace

Bug: 144151634
Change-Id: Ia97d91714ac59bbb9d67d9243138edc1c1c9afbf
diff --git a/src/main/java/com/android/tools/r8/references/ArrayReference.java b/src/main/java/com/android/tools/r8/references/ArrayReference.java
index 96cb926..f95a60c 100644
--- a/src/main/java/com/android/tools/r8/references/ArrayReference.java
+++ b/src/main/java/com/android/tools/r8/references/ArrayReference.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.Keep;
 import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.utils.DescriptorUtils;
 
 /** Reference to an array type. */
 @Keep
@@ -34,6 +35,13 @@
     throw new Unreachable("Invalid array type descriptor: " + descriptor);
   }
 
+  static ArrayReference fromBaseType(TypeReference baseType, int dimensions) {
+    return new ArrayReference(
+        dimensions,
+        baseType,
+        DescriptorUtils.toArrayDescriptor(dimensions, baseType.getDescriptor()));
+  }
+
   public int getDimensions() {
     return dimensions;
   }
diff --git a/src/main/java/com/android/tools/r8/references/ClassReference.java b/src/main/java/com/android/tools/r8/references/ClassReference.java
index 1159ec3..9c0f479 100644
--- a/src/main/java/com/android/tools/r8/references/ClassReference.java
+++ b/src/main/java/com/android/tools/r8/references/ClassReference.java
@@ -30,6 +30,11 @@
   }
 
   @Override
+  public ClassReference asClass() {
+    return this;
+  }
+
+  @Override
   public String getDescriptor() {
     return descriptor;
   }
diff --git a/src/main/java/com/android/tools/r8/references/PrimitiveReference.java b/src/main/java/com/android/tools/r8/references/PrimitiveReference.java
index 66c1ae7..eb4ae72 100644
--- a/src/main/java/com/android/tools/r8/references/PrimitiveReference.java
+++ b/src/main/java/com/android/tools/r8/references/PrimitiveReference.java
@@ -105,6 +105,11 @@
   }
 
   @Override
+  public PrimitiveReference asPrimitive() {
+    return this;
+  }
+
+  @Override
   public abstract String getDescriptor();
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/references/Reference.java b/src/main/java/com/android/tools/r8/references/Reference.java
index 8a3d278..94d4ea0 100644
--- a/src/main/java/com/android/tools/r8/references/Reference.java
+++ b/src/main/java/com/android/tools/r8/references/Reference.java
@@ -118,6 +118,16 @@
     return getInstance().arrays.computeIfAbsent(descriptor, ArrayReference::fromDescriptor);
   }
 
+  /** Get an array reference from a base type and dimensions. */
+  public static ArrayReference array(TypeReference baseType, int dimensions) {
+    String arrayDescriptor =
+        DescriptorUtils.toArrayDescriptor(dimensions, baseType.getDescriptor());
+    return getInstance()
+        .arrays
+        .computeIfAbsent(
+            arrayDescriptor, descriptor -> ArrayReference.fromBaseType(baseType, dimensions));
+  }
+
   /** Get a method reference from its full reference specification. */
   public static MethodReference method(
       ClassReference holderClass,
diff --git a/src/main/java/com/android/tools/r8/references/TypeReference.java b/src/main/java/com/android/tools/r8/references/TypeReference.java
index 44fb54a..bfef3f6 100644
--- a/src/main/java/com/android/tools/r8/references/TypeReference.java
+++ b/src/main/java/com/android/tools/r8/references/TypeReference.java
@@ -31,6 +31,33 @@
     return false;
   }
 
+  /**
+   * Return a non-null ClassTypeReference if this type is ClassTypeReference
+   *
+   * @return this with static type of ClassTypeReference
+   */
+  default ClassReference asClass() {
+    return null;
+  }
+
+  /**
+   * Return a non-null ArrayReference if this type is ArrayReference
+   *
+   * @return this with static type of ArrayReference
+   */
+  default ArrayReference asArray() {
+    return null;
+  }
+
+  /**
+   * Return a non-null PrimitiveReference if this type is PrimitiveReference
+   *
+   * @return this with static type of PrimitiveReference
+   */
+  default PrimitiveReference asPrimitive() {
+    return null;
+  }
+
   default String getTypeName() {
     return DescriptorUtils.descriptorToJavaType(getDescriptor());
   }
diff --git a/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java b/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java
index 59c3169..c3916cb 100644
--- a/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/DescriptorUtils.java
@@ -96,6 +96,23 @@
   }
 
   /**
+   * Produces an array descriptor having the number of dimensions specified and the
+   * baseTypeDescriptor as base.
+   *
+   * @param dimensions number of dimensions
+   * @param baseTypeDescriptor the base type
+   * @return the descriptor string
+   */
+  public static String toArrayDescriptor(int dimensions, String baseTypeDescriptor) {
+    StringBuilder sb = new StringBuilder();
+    for (int i = 0; i < dimensions; i++) {
+      sb.append('[');
+    }
+    sb.append(baseTypeDescriptor);
+    return sb.toString();
+  }
+
+  /**
    * Determine the given {@param typeName} is a valid jvms binary name or not (jvms 4.2.1).
    *
    * @param typeName the jvms binary name