Add initial support for printing kotlin metadata in AssemblyWriter
Bug: 148581822
Change-Id: I04612b531ee08a4af1e9c8dd2e80e3d807cef36e
diff --git a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
index 74735f4..4eb9a85 100644
--- a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
+++ b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
@@ -7,6 +7,9 @@
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.conversion.OneTimeMethodProcessor;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
+import com.android.tools.r8.kotlin.Kotlin;
+import com.android.tools.r8.kotlin.KotlinClassMetadataReader;
+import com.android.tools.r8.kotlin.KotlinInfo;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.utils.CfgPrinter;
@@ -21,6 +24,7 @@
private final boolean writeAnnotations;
private final boolean writeIR;
private final AppInfoWithSubtyping appInfo;
+ private final Kotlin kotlin;
private final Timing timing = new Timing("AssemblyWriter");
public AssemblyWriter(
@@ -41,6 +45,7 @@
} else {
this.appInfo = null;
}
+ kotlin = new Kotlin(application.dexItemFactory);
}
@Override
@@ -59,7 +64,7 @@
ps.println("# Bytecode for");
ps.println("# Class: '" + clazzName + "'");
if (writeAllClassInfo) {
- writeAnnotations(clazz.annotations(), ps);
+ writeAnnotations(clazz, clazz.annotations(), ps);
ps.println("# Flags: '" + clazz.accessFlags + "'");
if (clazz.superType != application.dexItemFactory.objectType) {
ps.println("# Extends: '" + clazz.superType.toSourceString() + "'");
@@ -87,7 +92,7 @@
FieldSignature fieldSignature = naming != null
? naming.originalSignatureOf(field.field)
: FieldSignature.fromDexField(field.field);
- writeAnnotations(field.annotations(), ps);
+ writeAnnotations(null, field.annotations(), ps);
ps.print(field.accessFlags + " ");
ps.print(fieldSignature);
if (field.isStatic() && field.hasExplicitStaticValue()) {
@@ -110,7 +115,7 @@
: method.method.name.toString();
ps.println("#");
ps.println("# Method: '" + methodName + "':");
- writeAnnotations(method.annotations(), ps);
+ writeAnnotations(null, method.annotations(), ps);
ps.println("# " + method.accessFlags);
ps.println("#");
ps.println();
@@ -134,16 +139,17 @@
ps.println(printer.toString());
}
- private void writeAnnotations(DexAnnotationSet annotations, PrintStream ps) {
+ private void writeAnnotations(
+ DexProgramClass clazz, DexAnnotationSet annotations, PrintStream ps) {
if (writeAnnotations) {
if (!annotations.isEmpty()) {
ps.println("# Annotations:");
for (DexAnnotation annotation : annotations.annotations) {
- ps.print("# ");
- if (annotation.annotation.type
- == application.dexItemFactory.createType("Lkotlin/Metadata;")) {
- ps.println("<kotlin metadata>");
+ if (annotation.annotation.type == kotlin.metadata.kotlinMetadataType) {
+ assert clazz != null : "Kotlin metadata is a class annotation";
+ writeKotlinMetadata(clazz, annotation, ps);
} else {
+ ps.print("# ");
ps.println(annotation);
}
}
@@ -151,6 +157,14 @@
}
}
+ private void writeKotlinMetadata(
+ DexProgramClass clazz, DexAnnotation annotation, PrintStream ps) {
+ assert annotation.annotation.type == kotlin.metadata.kotlinMetadataType;
+ KotlinInfo kotlinInfo =
+ KotlinClassMetadataReader.createKotlinInfo(kotlin, clazz, annotation.annotation);
+ ps.println(kotlinInfo.toString("# "));
+ }
+
@Override
void writeClassFooter(DexProgramClass clazz, PrintStream ps) {
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 a37a42b..136947b 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClass.java
@@ -22,6 +22,7 @@
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.StringUtils;
import java.util.List;
import kotlinx.metadata.KmClass;
import kotlinx.metadata.KmConstructor;
@@ -187,7 +188,13 @@
}
@Override
- public String toString() {
- return clazz.toString() + ": " + kmClass.toString();
+ public String toString(String indent) {
+ StringBuilder sb = new StringBuilder(indent);
+ sb.append("Metadata.Class {");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ sb.append(kmDeclarationContainerToString(indent + INDENT));
+ sb.append(indent);
+ sb.append("}");
+ return sb.toString();
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassFacade.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassFacade.java
index cc1cd14..627ac9d 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassFacade.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassFacade.java
@@ -81,8 +81,7 @@
}
@Override
- public String toString() {
- return clazz.toString()
- + ": MultiFileClassFacade(" + StringUtils.join(partClassNames, ", ") + ")";
+ public String toString(String indent) {
+ return indent + "MultiFileClassFacade(" + StringUtils.join(partClassNames, ", ") + ")";
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
index 5a3e469..e49d99d 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
@@ -18,7 +18,7 @@
import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
-final class KotlinClassMetadataReader {
+public final class KotlinClassMetadataReader {
static KotlinInfo getKotlinInfo(
Kotlin kotlin,
@@ -72,7 +72,7 @@
return KotlinClassMetadata.read(header);
}
- private static KotlinInfo createKotlinInfo(
+ public static KotlinInfo createKotlinInfo(
Kotlin kotlin, DexClass clazz, DexEncodedAnnotation metadataAnnotation) {
KotlinClassMetadata kMetadata = toKotlinClassMetadata(kotlin, metadataAnnotation);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassPart.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassPart.java
index 16223bb..e67cd05 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassPart.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassPart.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
import kotlinx.metadata.KmPackage;
import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
@@ -82,8 +83,14 @@
}
@Override
- public String toString() {
- return clazz.toString() + ": " + kmPackage.toString()
- + ": MultiFileClassPart(" + facadeClassName + ")";
+ public String toString(String indent) {
+ StringBuilder sb = new StringBuilder(indent);
+ sb.append("Metadata.MultiFileClassPart {");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ sb.append(kmDeclarationContainerToString(indent + INDENT));
+ appendKeyValue(indent + INDENT, "facadeClassName", facadeClassName, sb);
+ sb.append(indent);
+ sb.append("}");
+ return sb.toString();
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinFile.java b/src/main/java/com/android/tools/r8/kotlin/KotlinFile.java
index 27c9230..08fc8ef 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinFile.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinFile.java
@@ -64,7 +64,13 @@
}
@Override
- public String toString() {
- return clazz.toString() + ": " + kmPackage.toString();
+ public String toString(String indent) {
+ StringBuilder sb = new StringBuilder(indent);
+ sb.append("Metadata.MultiFileClassPart {\n");
+ sb.append(kmDeclarationContainerToString(indent + INDENT));
+ appendKeyValue(indent + INDENT, "package", kmPackage.toString(), sb);
+ sb.append(indent);
+ sb.append("}");
+ return sb.toString();
}
}
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 7c53cba..3727146 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
@@ -15,13 +15,18 @@
import com.android.tools.r8.kotlin.KotlinMetadataSynthesizer.KmPropertyGroup;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.BiFunction;
import java.util.function.Predicate;
import kotlinx.metadata.KmDeclarationContainer;
import kotlinx.metadata.KmFunction;
import kotlinx.metadata.KmProperty;
+import kotlinx.metadata.KmType;
+import kotlinx.metadata.KmTypeAlias;
import kotlinx.metadata.jvm.KotlinClassHeader;
import kotlinx.metadata.jvm.KotlinClassMetadata;
@@ -202,4 +207,100 @@
}
}
}
+
+ public abstract String toString(String indent);
+
+ String kmDeclarationContainerToString(String indent) {
+ StringBuilder sb = new StringBuilder();
+ KmDeclarationContainer declarations = getDeclarations();
+ appendKmSection(indent, "functions", declarations.getFunctions(), this::kmFunctionToString, sb);
+ appendKmSection(
+ indent, "properties", declarations.getProperties(), this::kmPropertyToString, sb);
+ appendKmSection(
+ indent, "typeAliases", declarations.getTypeAliases(), this::kmTypeAliasToString, sb);
+ return sb.toString();
+ }
+
+ final String INDENT = " ";
+
+ private <T> void appendKmSection(
+ String indent,
+ String header,
+ List<T> items,
+ BiFunction<String, T, String> stringify,
+ StringBuilder sb) {
+ if (items.size() > 0) {
+ sb.append(indent);
+ sb.append(header);
+ sb.append(": [");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ }
+ for (T item : items) {
+ sb.append(stringify.apply(indent + INDENT, item));
+ sb.append(",");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ }
+ if (items.size() > 0) {
+ sb.append(indent);
+ sb.append("]");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ }
+ }
+
+ private String kmFunctionToString(String indent, KmFunction function) {
+ assert function != null;
+ StringBuilder sb = new StringBuilder();
+ sb.append(indent);
+ sb.append("KmFunction {");
+ sb.append(StringUtils.LINE_SEPARATOR);
+ String newIndent = indent + INDENT;
+ KmType receiverParameterType = function.getReceiverParameterType();
+ appendKeyValue(
+ newIndent,
+ "receiverParameterType",
+ receiverParameterType == null ? "null" : kmTypeToString(receiverParameterType),
+ sb);
+ appendKeyValue(newIndent, "returnType", kmTypeToString(function.returnType), sb);
+ appendKeyValue(newIndent, "name", function.getName(), sb);
+ // TODO(b/148581822): Print flags, generic signature etc.
+ sb.append(indent);
+ sb.append("}");
+ return sb.toString();
+ }
+
+ private String kmPropertyToString(String indent, KmProperty property) {
+ // TODO(b/148581822): Add information.
+ return indent + "KmProperty { " + property + "}";
+ }
+
+ private String kmTypeAliasToString(String indent, KmTypeAlias alias) {
+ assert alias != null;
+ StringBuilder sb = new StringBuilder(indent);
+ sb.append("KmAlias {");
+ 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);
+ sb.append(indent);
+ sb.append("}");
+ return sb.toString();
+ }
+
+ void appendKeyValue(String indent, String key, String value, StringBuilder sb) {
+ sb.append(indent);
+ sb.append(key);
+ sb.append(": ");
+ sb.append(value);
+ sb.append(StringUtils.LINE_SEPARATOR);
+ }
+
+ private String kmTypeToString(KmType type) {
+ return DescriptorUtils.getDescriptorFromKmType(type);
+ }
+
+ @Override
+ public String toString() {
+ return toString("");
+ }
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClass.java b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClass.java
index 1bb17ea..8c4ccaf 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClass.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinSyntheticClass.java
@@ -119,7 +119,7 @@
}
@Override
- public String toString() {
- return clazz.toString() + ": " + metadata.toString();
+ public String toString(String indent) {
+ return indent + "Metadata.SyntheticClass { function: " + metadata.toString() + "}";
}
}