blob: 0fdeebcf47f97af2782c89fa645bcd77030bb0ef [file] [log] [blame]
// Copyright (c) 2016, 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.naming;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
public class MinifiedNameMapPrinter {
private static final String NEW_LINE = "\n";
private final DexApplication application;
private final NamingLens namingLens;
private final Set<DexType> seenTypes = Sets.newIdentityHashSet();
public MinifiedNameMapPrinter(DexApplication application, NamingLens namingLens) {
this.application = application;
this.namingLens = namingLens;
}
private <T> T[] sortedCopy(T[] source, Comparator<? super T> comparator) {
T copy[] = Arrays.copyOf(source, source.length);
Arrays.sort(copy, comparator);
return copy;
}
private <T> List<T> sortedCopy(List<T> source, Comparator<? super T> comparator) {
List<T> copy = new ArrayList<>(source);
Collections.sort(copy, comparator);
return copy;
}
private void writeClass(DexProgramClass clazz, StringBuilder out) {
seenTypes.add(clazz.type);
DexString descriptor = namingLens.lookupDescriptor(clazz.type);
out.append(DescriptorUtils.descriptorToJavaType(clazz.type.descriptor.toSourceString()));
out.append(" -> ");
out.append(DescriptorUtils.descriptorToJavaType(descriptor.toSourceString()));
out.append(":").append(NEW_LINE);
writeFields(sortedCopy(
clazz.instanceFields(), Comparator.comparing(DexEncodedField::toSourceString)), out);
writeFields(sortedCopy(
clazz.staticFields(), Comparator.comparing(DexEncodedField::toSourceString)), out);
writeMethods(sortedCopy(
clazz.directMethods(), Comparator.comparing(DexEncodedMethod::toSourceString)), out);
writeMethods(sortedCopy(
clazz.virtualMethods(), Comparator.comparing(DexEncodedMethod::toSourceString)), out);
}
private void writeType(DexType type, StringBuilder out) {
if (type.isClassType() && seenTypes.add(type)) {
DexString descriptor = namingLens.lookupDescriptor(type);
out.append(DescriptorUtils.descriptorToJavaType(type.descriptor.toSourceString()));
out.append(" -> ");
out.append(DescriptorUtils.descriptorToJavaType(descriptor.toSourceString()));
out.append(":").append(NEW_LINE);
}
}
private void writeFields(List<DexEncodedField> fields, StringBuilder out) {
for (DexEncodedField encodedField : fields) {
DexField field = encodedField.field;
DexString renamed = namingLens.lookupName(field);
if (renamed != field.name) {
out.append(" ");
out.append(field.type.toSourceString());
out.append(" ");
out.append(field.name.toSourceString());
out.append(" -> ");
out.append(renamed.toSourceString()).append(NEW_LINE);
}
}
}
private void writeMethod(MethodSignature signature, String renamed, StringBuilder out) {
out.append(" ");
out.append(signature.toString());
out.append(" -> ");
out.append(renamed).append(NEW_LINE);
}
private void writeMethods(List<DexEncodedMethod> methods, StringBuilder out) {
for (DexEncodedMethod encodedMethod : methods) {
DexMethod method = encodedMethod.method;
DexString renamed = namingLens.lookupName(method);
if (renamed != method.name) {
MethodSignature signature = MethodSignature.fromDexMethod(method);
String renamedSourceString = renamed.toSourceString();
writeMethod(signature, renamedSourceString, out);
}
}
}
public void write(StringBuilder out) {
// First write out all classes that have been renamed.
List<DexProgramClass> classes = new ArrayList<>(application.classes());
classes.sort(Comparator.comparing(DexProgramClass::toSourceString));
classes.forEach(clazz -> writeClass(clazz, out));
// Now write out all types only mentioned in descriptors that have been renamed.
namingLens.forAllRenamedTypes(type -> writeType(type, out));
}
}