Write classifier and type arguments for typealiases

Bug: 148581822
Change-Id: I4886c7b0004230f202378a827f47112a8330ccf0
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 3727146..967cf05 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
@@ -22,11 +22,13 @@
 import java.util.Map;
 import java.util.function.BiFunction;
 import java.util.function.Predicate;
+import java.util.stream.Collectors;
 import kotlinx.metadata.KmDeclarationContainer;
 import kotlinx.metadata.KmFunction;
 import kotlinx.metadata.KmProperty;
 import kotlinx.metadata.KmType;
 import kotlinx.metadata.KmTypeAlias;
+import kotlinx.metadata.KmTypeParameter;
 import kotlinx.metadata.jvm.KotlinClassHeader;
 import kotlinx.metadata.jvm.KotlinClassMetadata;
 
@@ -276,17 +278,48 @@
   private String kmTypeAliasToString(String indent, KmTypeAlias alias) {
     assert alias != null;
     StringBuilder sb = new StringBuilder(indent);
-    sb.append("KmAlias {");
+    sb.append("KmTypeAlias {");
     sb.append(StringUtils.LINE_SEPARATOR);
     String newIndent = indent + INDENT;
     appendKeyValue(newIndent, "name", alias.getName(), sb);
-    appendKeyValue(newIndent, "underlyingType", kmTypeToString(alias.underlyingType), sb);
-    appendKeyValue(newIndent, "expandedType", kmTypeToString(alias.expandedType), sb);
+    if (!alias.getTypeParameters().isEmpty()) {
+      appendKeyValue(
+          newIndent,
+          "typeParameters",
+          alias.getTypeParameters().stream()
+              .map(KmTypeParameter::getName)
+              .collect(Collectors.joining(",")),
+          sb);
+    }
+    appendType(newIndent, "underlyingType", alias.underlyingType, sb);
+    appendType(newIndent, "expandedType", alias.expandedType, sb);
+    // TODO(b/151783973): Extend with annotations.
     sb.append(indent);
     sb.append("}");
     return sb.toString();
   }
 
+  void appendType(String indent, String key, KmType kmType, StringBuilder sb) {
+    sb.append(indent);
+    sb.append(key);
+    sb.append(" {");
+    sb.append(StringUtils.LINE_SEPARATOR);
+    String newIndent = indent + INDENT;
+    appendKeyValue(newIndent, "classifier", kmType.classifier.toString(), sb);
+    if (!kmType.getArguments().isEmpty()) {
+      appendKeyValue(
+          newIndent,
+          "arguments",
+          kmType.getArguments().stream()
+              .map(arg -> arg.getType().classifier.toString())
+              .collect(Collectors.joining(",")),
+          sb);
+    }
+    sb.append(indent);
+    sb.append("}");
+    sb.append(StringUtils.LINE_SEPARATOR);
+  }
+
   void appendKeyValue(String indent, String key, String value, StringBuilder sb) {
     sb.append(indent);
     sb.append(key);
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib.kt
index 5f4de47..15771dd 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib.kt
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib.kt
@@ -3,12 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.kotlin.metadata.typealias_lib
 
-// TypeAlias {
-//   name: "Jude"
+// KmTypeAlias {
+//   name: Jude
 //   underlyingType {
-//     classifier: "kotlin/Long"
+//     classifier: Class(name=kotlin/Long)
 //   }
-// }
+//   expandedType {
+//     classifier: Class(name=kotlin/Long)
+//   }
+// },
 typealias Jude = Long
 
 interface Itf {
@@ -16,38 +19,42 @@
   fun hey() : Jude
 }
 
-// TypeAlias {
-//   name: "API"
+// KmTypeAlias {
+//   name: API
 //   underlyingType {
-//     classifier: ".../Itf"
-//   }
-// }
-typealias API = Itf
-
-// TypeAlias {
-//   typeParameters { KmTypeParameter { name = "T" ... } }
-//   name: "myAliasedList"
-//   underlyingType {
-//     classifier: "kotlin/Array"
-//   }
-//   expandedType == underlyingType
-// }
-typealias myAliasedArray<T> = Array<T>
-
-// TypeAlias {
-//   underlyingType {
-//     classifier: ".../myAliasedArray"
-//     arguments {
-//       KmTypeProjection { ... type = ".../API" }
-//     }
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Itf)
 //   }
 //   expandedType {
-//     classifier: "kotlin/Array"
-//     arguments {
-//       KmTypeProjection { ... type = ".../Itf" }
-//     }
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Itf)
 //   }
-// }
+// },
+typealias API = Itf
+
+// KmTypeAlias {
+//   name: myAliasedArray
+//   typeParameters: T
+//   underlyingType {
+//     classifier: Class(name=kotlin/Array)
+//     arguments: TypeParameter(id=0)
+//   }
+//   expandedType {
+//     classifier: Class(name=kotlin/Array)
+//     arguments: TypeParameter(id=0)
+//   }
+// },
+typealias myAliasedArray<T> = Array<T>
+
+// KmTypeAlias {
+//   name: APIs
+//   underlyingType {
+//     classifier: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/myAliasedArray)
+//     arguments: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/API)
+//   }
+//   expandedType {
+//     classifier: Class(name=kotlin/Array)
+//     arguments: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Itf)
+//   }
+// },
 typealias APIs = myAliasedArray<API>
 
 open class Impl : API {
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt
index 397da26..ba63667 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/typealias_lib/lib_ext.kt
@@ -7,19 +7,28 @@
 
 open class LibraryClass { }
 
-//  KmAlias {
-//    name: Unused
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/LibraryClass;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/LibraryClass;
-//  },
+// KmTypeAlias {
+//   name: Unused
+//   underlyingType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/LibraryClass)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/LibraryClass)
+//   }
+// },
 typealias Unused = LibraryClass
 
 // Will give a warning, but is is not an error to have an unused argument.
-//  KmAlias {
-//    name: UnusedTypeArgument
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Unused;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/LibraryClass;
-//  },
+// KmTypeAlias {
+//   name: UnusedTypeArgument
+//   typeParameters: T
+//   underlyingType {
+//     classifier: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Unused)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/LibraryClass)
+//   }
+// },
 typealias UnusedTypeArgument<T> = Unused
 
 // Expansion to simple class
@@ -28,11 +37,15 @@
   val y : Int = 42;
 }
 
-//  KmAlias {
-//    name: AlphaNaming
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/SimpleClass;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/SimpleClass;
-//  },
+// KmTypeAlias {
+//   name: AlphaNaming
+//   underlyingType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/SimpleClass)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/SimpleClass)
+//   }
+// },
 typealias AlphaNaming = SimpleClass
 
 class SimpleClassTester {
@@ -61,11 +74,15 @@
   }
 }
 
-//  KmAlias {
-//    name: ApiAlias
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Api;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Api;
-//  },
+// KmTypeAlias {
+//   name: ApiAlias
+//   underlyingType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Api)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Api)
+//   }
+// },
 typealias ApiAlias = Api
 
 class VerticalClassMergingTester {
@@ -86,18 +103,32 @@
 
 class Arr<K>(val x : K)
 
-//  KmAlias {
-//    name: Arr1D
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Arr;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Arr;
-//    },
+// KmTypeAlias {
+//   name: Arr1D
+//   typeParameters: K
+//   underlyingType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr)
+//     arguments: TypeParameter(id=0)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr)
+//     arguments: TypeParameter(id=0)
+//   }
+// },
 typealias Arr1D<K> = Arr<K>
 
-//  KmAlias {
-//    name: Arr2D
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Arr;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Arr;
-//  },
+// KmTypeAlias {
+//   name: Arr2D
+//   typeParameters: K
+//   underlyingType {
+//     classifier: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr1D)
+//     arguments: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr1D)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr)
+//     arguments: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Arr)
+//   }
+// },
 typealias Arr2D<K> = Arr1D<Arr1D<K>>
 
 class Arr2DTester {
@@ -121,25 +152,44 @@
   fun f()
 }
 
-//  KmAlias {
-//    name: MyI
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/I;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/I;
-//  },
+// KmTypeAlias {
+//   name: MyI
+//   underlyingType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/I)
+//     arguments: Class(name=kotlin/Int)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/I)
+//     arguments: Class(name=kotlin/Int)
+//   }
+// },
 typealias MyI = I<Int>
 
-//  KmAlias {
-//    name: IntSet
-//    underlyingType: Lkotlin/collections/Set;
-//    expandedType: Lkotlin/collections/Set;
-//  },
+// KmTypeAlias {
+//   name: IntSet
+//   underlyingType {
+//     classifier: Class(name=kotlin/collections/Set)
+//     arguments: Class(name=kotlin/Int)
+//   }
+//   expandedType {
+//     classifier: Class(name=kotlin/collections/Set)
+//     arguments: Class(name=kotlin/Int)
+//   }
+// },
 typealias IntSet = Set<Int>
 
-//  KmAlias {
-//    name: MyMapToSetOfInt
-//    underlyingType: Lkotlin/collections/Map;
-//    expandedType: Lkotlin/collections/Map;
-//  },
+// KmTypeAlias {
+//   name: MyMapToSetOfInt
+//   typeParameters: K
+//   underlyingType {
+//     classifier: Class(name=kotlin/collections/MutableMap)
+//     arguments: TypeParameter(id=0),TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/IntSet)
+//   }
+//   expandedType {
+//     classifier: Class(name=kotlin/collections/MutableMap)
+//     arguments: TypeParameter(id=0),Class(name=kotlin/collections/Set)
+//   }
+// },
 typealias MyMapToSetOfInt<K> = MutableMap<K, IntSet>
 
 class InterfaceTester {
@@ -166,18 +216,31 @@
 
 // Expansion to function types
 
-//  KmAlias {
-//    name: MyHandler
-//    underlyingType: Lkotlin/Function2;
-//    expandedType: Lkotlin/Function2;
-//  },
+// KmTypeAlias {
+//   name: MyHandler
+//   underlyingType {
+//     classifier: Class(name=kotlin/Function2)
+//     arguments: Class(name=kotlin/Int),Class(name=kotlin/Any),Class(name=kotlin/Unit)
+//   }
+//   expandedType {
+//     classifier: Class(name=kotlin/Function2)
+//     arguments: Class(name=kotlin/Int),Class(name=kotlin/Any),Class(name=kotlin/Unit)
+//   }
+// },
 typealias MyHandler = (Int, Any) -> Unit
 
-//  KmAlias {
-//    name: MyGenericPredicate
-//    underlyingType: Lkotlin/Function1;
-//    expandedType: Lkotlin/Function1;
-//  },
+// KmTypeAlias {
+//   name: MyGenericPredicate
+//   typeParameters: T
+//   underlyingType {
+//     classifier: Class(name=kotlin/Function1)
+//     arguments: TypeParameter(id=0),Class(name=kotlin/Boolean)
+//   }
+//   expandedType {
+//     classifier: Class(name=kotlin/Function1)
+//     arguments: TypeParameter(id=0),Class(name=kotlin/Boolean)
+//   }
+// },
 typealias MyGenericPredicate<T> = (T) -> Boolean
 
 class FunctionTester {
@@ -212,18 +275,26 @@
   }
 }
 
-//  KmAlias {
-//    name: OuterNested
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Outer$Nested;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Outer$Nested;
-//  },
+// KmTypeAlias {
+//   name: OuterNested
+//   underlyingType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested)
+//   }
+// },
 typealias OuterNested = Outer.Nested
 
-//  KmAlias {
-//    name: OuterNestedInner
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Outer$Nested$Inner;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/Outer$Nested$Inner;
-//  },
+// KmTypeAlias {
+//   name: OuterNestedInner
+//   underlyingType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested.Inner)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested.Inner)
+//   }
+// },
 typealias OuterNestedInner = Outer.Nested.Inner
 
 class OuterTester {
@@ -251,11 +322,15 @@
   }
 }
 
-//  KmAlias {
-//    name: ClassWithCompanionC
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/ClassWithCompanion$Companion;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/ClassWithCompanion$Companion;
-//  },
+// KmTypeAlias {
+//   name: ClassWithCompanionC
+//   underlyingType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/ClassWithCompanion.Companion)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/ClassWithCompanion.Companion)
+//   }
+// },
 typealias ClassWithCompanionC = ClassWithCompanion.Companion
 
 // Expansion to constructor
@@ -265,11 +340,15 @@
   private constructor() : this(0)
 }
 
-//  KmAlias {
-//    name: CWithConstructor
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/C;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/C;
-//  },
+// KmTypeAlias {
+//   name: CWithConstructor
+//   underlyingType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/C)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/C)
+//   }
+// },
 typealias CWithConstructor = C
 
 class CWithConstructorTester {
@@ -288,18 +367,28 @@
 
 // Underlying type having type alias
 
-//  KmAlias {
-//    name: StillCWithConstructor
-//    underlyingType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/CWithConstructor;
-//    expandedType: Lcom/android/tools/r8/kotlin/metadata/typealias_lib/C;
-//  },
+// KmTypeAlias {
+//   name: StillCWithConstructor
+//   underlyingType {
+//     classifier: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/CWithConstructor)
+//   }
+//   expandedType {
+//     classifier: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/C)
+//   }
+// },
 typealias StillCWithConstructor = CWithConstructor
 
-//  KmAlias {
-//    name: MyAdvancedMap
-//    underlyingType: Lkotlin/collections/Map;
-//    expandedType: Lkotlin/collections/Map;
-//  },
+// KmTypeAlias {
+//   name: MyAdvancedMap
+//   underlyingType {
+//     classifier: Class(name=kotlin/collections/MutableMap)
+//     arguments: TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/OuterNested),TypeAlias(name=com/android/tools/r8/kotlin/metadata/typealias_lib/OuterNestedInner)
+//   }
+//   expandedType {
+//     classifier: Class(name=kotlin/collections/MutableMap)
+//     arguments: Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested),Class(name=com/android/tools/r8/kotlin/metadata/typealias_lib/Outer.Nested.Inner)
+//   }
+// },
 typealias MyAdvancedMap = MutableMap<OuterNested, OuterNestedInner>
 
 class UnderlyingTypeTest {