• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the Free
9  * Software Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 package proguard.shrink;
22 
23 import proguard.classfile.*;
24 import proguard.classfile.attribute.*;
25 import proguard.classfile.attribute.visitor.AttributeVisitor;
26 import proguard.classfile.util.*;
27 import proguard.classfile.visitor.*;
28 
29 import java.io.PrintStream;
30 
31 
32 /**
33  * This ClassVisitor prints out the classes and class members that have been
34  * marked as being used (or not used).
35  *
36  * @see UsageMarker
37  *
38  * @author Eric Lafortune
39  */
40 public class UsagePrinter
41 extends      SimplifiedVisitor
42 implements   ClassVisitor,
43              MemberVisitor,
44              AttributeVisitor
45 {
46     private final UsageMarker usageMarker;
47     private final boolean     printUnusedItems;
48     private final PrintStream ps;
49 
50     // A field to remember the class name, if a header is needed for class members.
51     private String      className;
52 
53 
54     /**
55      * Creates a new UsagePrinter that prints to <code>System.out</code>.
56      * @param usageMarker      the usage marker that was used to mark the
57      *                         classes and class members.
58      * @param printUnusedItems a flag that indicates whether only unused items
59      *                         should be printed, or alternatively, only used
60      *                         items.
61      */
UsagePrinter(UsageMarker usageMarker, boolean printUnusedItems)62     public UsagePrinter(UsageMarker usageMarker,
63                         boolean     printUnusedItems)
64     {
65         this(usageMarker, printUnusedItems, System.out);
66     }
67 
68 
69     /**
70      * Creates a new UsagePrinter that prints to the given stream.
71      * @param usageMarker      the usage marker that was used to mark the
72      *                         classes and class members.
73      * @param printUnusedItems a flag that indicates whether only unused items
74      *                         should be printed, or alternatively, only used
75      *                         items.
76      * @param printStream      the stream to which to print.
77      */
UsagePrinter(UsageMarker usageMarker, boolean printUnusedItems, PrintStream printStream)78     public UsagePrinter(UsageMarker usageMarker,
79                         boolean     printUnusedItems,
80                         PrintStream printStream)
81     {
82         this.usageMarker      = usageMarker;
83         this.printUnusedItems = printUnusedItems;
84         this.ps               = printStream;
85     }
86 
87 
88     // Implementations for ClassVisitor.
89 
visitProgramClass(ProgramClass programClass)90     public void visitProgramClass(ProgramClass programClass)
91     {
92         if (usageMarker.isUsed(programClass))
93         {
94             if (printUnusedItems)
95             {
96                 className = programClass.getName();
97 
98                 programClass.fieldsAccept(this);
99                 programClass.methodsAccept(this);
100 
101                 className = null;
102             }
103             else
104             {
105                 ps.println(ClassUtil.externalClassName(programClass.getName()));
106             }
107         }
108         else
109         {
110             if (printUnusedItems)
111             {
112                 ps.println(ClassUtil.externalClassName(programClass.getName()));
113             }
114         }
115     }
116 
117 
118     // Implementations for MemberVisitor.
119 
visitProgramField(ProgramClass programClass, ProgramField programField)120     public void visitProgramField(ProgramClass programClass, ProgramField programField)
121     {
122         if (usageMarker.isUsed(programField) ^ printUnusedItems)
123         {
124             printClassNameHeader();
125 
126             ps.println("    " +
127                        ClassUtil.externalFullFieldDescription(
128                            programField.getAccessFlags(),
129                            programField.getName(programClass),
130                            programField.getDescriptor(programClass)));
131         }
132     }
133 
134 
visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)135     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
136     {
137         if (usageMarker.isUsed(programMethod) ^ printUnusedItems)
138         {
139             printClassNameHeader();
140 
141             ps.print("    ");
142             programMethod.attributesAccept(programClass, this);
143             ps.println(ClassUtil.externalFullMethodDescription(
144                            programClass.getName(),
145                            programMethod.getAccessFlags(),
146                            programMethod.getName(programClass),
147                            programMethod.getDescriptor(programClass)));
148         }
149     }
150 
151 
152     // Implementations for AttributeVisitor.
153 
visitAnyAttribute(Clazz clazz, Attribute attribute)154     public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
155 
156 
visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)157     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
158     {
159         codeAttribute.attributesAccept(clazz, method, this);
160     }
161 
162 
visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)163     public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
164     {
165         ps.print(lineNumberTableAttribute.getLowestLineNumber() + ":" +
166                  lineNumberTableAttribute.getHighestLineNumber() + ":");
167     }
168 
169 
170     // Small utility methods.
171 
172     /**
173      * Prints the class name field. The field is then cleared, so it is not
174      * printed again.
175      */
printClassNameHeader()176     private void printClassNameHeader()
177     {
178         if (className != null)
179         {
180             ps.println(ClassUtil.externalClassName(className) + ":");
181             className = null;
182         }
183     }
184 }
185