blob: 30021c110acecde203b8709a1deaa4b275def967 [file] [log] [blame]
// Copyright (c) 2017, 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.shaking;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import java.nio.charset.StandardCharsets;
class UsagePrinter {
private static final String INDENT = " ";
static final UsagePrinter DONT_PRINT = new NoOpUsagePrinter();
private final StringBuilder writer;
private DexProgramClass enclosingClazz = null;
private boolean clazzPrefixPrinted = false;
UsagePrinter() {
writer = new StringBuilder();
}
String toStringContent() {
return writer.toString();
}
byte[] toByteArray() {
return writer.toString().getBytes(StandardCharsets.UTF_8);
}
void printUnusedClass(DexProgramClass clazz) {
writer.append(clazz.toSourceString());
writer.append('\n');
}
// Visiting methods and fields of the given clazz.
void visiting(DexProgramClass clazz) {
assert enclosingClazz == null;
enclosingClazz = clazz;
}
// Visited methods and fields of the top at the clazz stack.
void visited() {
enclosingClazz = null;
clazzPrefixPrinted = false;
}
private void printClazzPrefixIfNecessary() {
assert enclosingClazz != null;
if (!clazzPrefixPrinted) {
writer.append(enclosingClazz.toSourceString());
writer.append('\n');
clazzPrefixPrinted = true;
}
}
void printUnusedMethod(DexEncodedMethod method) {
printClazzPrefixIfNecessary();
writer.append(INDENT);
String accessFlags = method.accessFlags.toString();
if (!accessFlags.isEmpty()) {
writer.append(accessFlags).append(' ');
}
writer.append(method.method.proto.returnType.toSourceString()).append(' ');
writer.append(method.method.name.toSourceString());
writer.append('(');
for (int i = 0; i < method.method.proto.parameters.values.length; i++) {
if (i != 0) {
writer.append(',');
}
writer.append(method.method.proto.parameters.values[i].toSourceString());
}
writer.append(')');
writer.append('\n');
}
void printUnusedField(DexEncodedField field) {
printClazzPrefixIfNecessary();
writer.append(INDENT);
String accessFlags = field.accessFlags.toString();
if (!accessFlags.isEmpty()) {
writer.append(accessFlags).append(' ');
}
writer.append(field.field.type.toSourceString()).append(" ");
writer.append(field.field.name.toSourceString());
writer.append('\n');
}
// Empty implementation to silently ignore printing dead code.
private static class NoOpUsagePrinter extends UsagePrinter {
@Override
byte[] toByteArray() {
return null;
}
@Override
void printUnusedClass(DexProgramClass clazz) {
// Intentionally left empty.
}
@Override
void visiting(DexProgramClass clazz) {
// Intentionally left empty.
}
@Override
void visited() {
// Intentionally left empty.
}
@Override
void printUnusedMethod(DexEncodedMethod method) {
// Intentionally left empty.
}
@Override
void printUnusedField(DexEncodedField field) {
// Intentionally left empty.
}
}
}