| /* |
| * ProGuard -- shrinking, optimization, obfuscation, and preverification |
| * of Java bytecode. |
| * |
| * Copyright (c) 2002-2017 Eric Lafortune @ GuardSquare |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by the Free |
| * Software Foundation; either version 2 of the License, or (at your option) |
| * any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with this program; if not, write to the Free Software Foundation, Inc., |
| * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| package proguard.shrink; |
| |
| import proguard.classfile.*; |
| import proguard.classfile.attribute.*; |
| import proguard.classfile.attribute.visitor.AttributeVisitor; |
| import proguard.classfile.util.*; |
| import proguard.classfile.visitor.*; |
| |
| import java.io.PrintStream; |
| |
| |
| /** |
| * This ClassVisitor prints out the classes and class members that have been |
| * marked as being used (or not used). |
| * |
| * @see UsageMarker |
| * |
| * @author Eric Lafortune |
| */ |
| public class UsagePrinter |
| extends SimplifiedVisitor |
| implements ClassVisitor, |
| MemberVisitor, |
| AttributeVisitor |
| { |
| private final UsageMarker usageMarker; |
| private final boolean printUnusedItems; |
| private final PrintStream ps; |
| |
| // A field to remember the class name, if a header is needed for class members. |
| private String className; |
| |
| |
| /** |
| * Creates a new UsagePrinter that prints to <code>System.out</code>. |
| * @param usageMarker the usage marker that was used to mark the |
| * classes and class members. |
| * @param printUnusedItems a flag that indicates whether only unused items |
| * should be printed, or alternatively, only used |
| * items. |
| */ |
| public UsagePrinter(UsageMarker usageMarker, |
| boolean printUnusedItems) |
| { |
| this(usageMarker, printUnusedItems, System.out); |
| } |
| |
| |
| /** |
| * Creates a new UsagePrinter that prints to the given stream. |
| * @param usageMarker the usage marker that was used to mark the |
| * classes and class members. |
| * @param printUnusedItems a flag that indicates whether only unused items |
| * should be printed, or alternatively, only used |
| * items. |
| * @param printStream the stream to which to print. |
| */ |
| public UsagePrinter(UsageMarker usageMarker, |
| boolean printUnusedItems, |
| PrintStream printStream) |
| { |
| this.usageMarker = usageMarker; |
| this.printUnusedItems = printUnusedItems; |
| this.ps = printStream; |
| } |
| |
| |
| // Implementations for ClassVisitor. |
| |
| public void visitProgramClass(ProgramClass programClass) |
| { |
| if (usageMarker.isUsed(programClass)) |
| { |
| if (printUnusedItems) |
| { |
| className = programClass.getName(); |
| |
| programClass.fieldsAccept(this); |
| programClass.methodsAccept(this); |
| |
| className = null; |
| } |
| else |
| { |
| ps.println(ClassUtil.externalClassName(programClass.getName())); |
| } |
| } |
| else |
| { |
| if (printUnusedItems) |
| { |
| ps.println(ClassUtil.externalClassName(programClass.getName())); |
| } |
| } |
| } |
| |
| |
| // Implementations for MemberVisitor. |
| |
| public void visitProgramField(ProgramClass programClass, ProgramField programField) |
| { |
| if (usageMarker.isUsed(programField) ^ printUnusedItems) |
| { |
| printClassNameHeader(); |
| |
| ps.println(" " + |
| ClassUtil.externalFullFieldDescription( |
| programField.getAccessFlags(), |
| programField.getName(programClass), |
| programField.getDescriptor(programClass))); |
| } |
| } |
| |
| |
| public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) |
| { |
| if (usageMarker.isUsed(programMethod) ^ printUnusedItems) |
| { |
| printClassNameHeader(); |
| |
| ps.print(" "); |
| programMethod.attributesAccept(programClass, this); |
| ps.println(ClassUtil.externalFullMethodDescription( |
| programClass.getName(), |
| programMethod.getAccessFlags(), |
| programMethod.getName(programClass), |
| programMethod.getDescriptor(programClass))); |
| } |
| } |
| |
| |
| // Implementations for AttributeVisitor. |
| |
| public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} |
| |
| |
| public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) |
| { |
| codeAttribute.attributesAccept(clazz, method, this); |
| } |
| |
| |
| public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) |
| { |
| ps.print(lineNumberTableAttribute.getLowestLineNumber() + ":" + |
| lineNumberTableAttribute.getHighestLineNumber() + ":"); |
| } |
| |
| |
| // Small utility methods. |
| |
| /** |
| * Prints the class name field. The field is then cleared, so it is not |
| * printed again. |
| */ |
| private void printClassNameHeader() |
| { |
| if (className != null) |
| { |
| ps.println(ClassUtil.externalClassName(className) + ":"); |
| className = null; |
| } |
| } |
| } |