| // 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 com.android.tools.r8.utils.StringUtils; |
| import java.util.function.Consumer; |
| |
| class UsagePrinter { |
| private static final String INDENT = " "; |
| |
| static final UsagePrinter DONT_PRINT = new NoOpUsagePrinter(); |
| |
| private final Consumer<String> consumer; |
| private DexProgramClass enclosingClazz = null; |
| private boolean clazzPrefixPrinted = false; |
| |
| UsagePrinter(Consumer<String> consumer) { |
| this.consumer = consumer; |
| } |
| |
| void append(String string) { |
| consumer.accept(string); |
| } |
| |
| void printUnusedClass(DexProgramClass clazz) { |
| append(clazz.toSourceString()); |
| append(StringUtils.LINE_SEPARATOR); |
| } |
| |
| // 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) { |
| append(enclosingClazz.toSourceString()); |
| append(":"); |
| append(StringUtils.LINE_SEPARATOR); |
| clazzPrefixPrinted = true; |
| } |
| } |
| |
| void printUnusedMethod(DexEncodedMethod method) { |
| printClazzPrefixIfNecessary(); |
| append(INDENT); |
| String accessFlags = method.accessFlags.toString(); |
| if (!accessFlags.isEmpty()) { |
| append(accessFlags); |
| append(" "); |
| } |
| append(method.method.proto.returnType.toSourceString()); |
| append(" "); |
| append(method.method.name.toSourceString()); |
| append("("); |
| for (int i = 0; i < method.method.proto.parameters.values.length; i++) { |
| if (i != 0) { |
| append(","); |
| } |
| append(method.method.proto.parameters.values[i].toSourceString()); |
| } |
| append(")"); |
| append(StringUtils.LINE_SEPARATOR); |
| } |
| |
| void printUnusedField(DexEncodedField field) { |
| printClazzPrefixIfNecessary(); |
| append(INDENT); |
| String accessFlags = field.accessFlags.toString(); |
| if (!accessFlags.isEmpty()) { |
| append(accessFlags); |
| append(" "); |
| } |
| append(field.field.type.toSourceString()); |
| append(" "); |
| append(field.field.name.toSourceString()); |
| append(StringUtils.LINE_SEPARATOR); |
| } |
| |
| // Empty implementation to silently ignore printing dead code. |
| private static class NoOpUsagePrinter extends UsagePrinter { |
| |
| public NoOpUsagePrinter() { |
| super(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. |
| } |
| } |
| } |