1
/* $Id: ShortestUsagePrinter.java,v 1.3 2005/06/11 13:21:35 eric Exp $
3
* ProGuard -- shrinking, optimization, and obfuscation of Java class files.
5
* Copyright (c) 2002-2005 Eric Lafortune (eric@graphics.cornell.edu)
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)
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
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
21
package proguard.shrink;
23
import proguard.classfile.*;
24
import proguard.classfile.util.*;
25
import proguard.classfile.visitor.*;
31
* This ClassFileVisitor and MemberInfoVisitor prints out the reasons why
32
* class files and class members have been marked as being used.
36
* @author Eric Lafortune
38
public class ShortestUsagePrinter
39
implements ClassFileVisitor,
42
private ShortestUsageMarker shortestUsageMarker;
43
private boolean verbose;
44
private PrintStream ps;
48
* Creates a new UsagePrinter that prints verbosely to <code>System.out</code>.
49
* @param shortestUsageMarker the usage marker that was used to mark the
50
* classes and class members.
52
public ShortestUsagePrinter(ShortestUsageMarker shortestUsageMarker)
54
this(shortestUsageMarker, true);
59
* Creates a new UsagePrinter that prints to the given stream.
60
* @param shortestUsageMarker the usage marker that was used to mark the
61
* classes and class members.
62
* @param verbose specifies whether the output should be verbose.
64
public ShortestUsagePrinter(ShortestUsageMarker shortestUsageMarker,
67
this(shortestUsageMarker, verbose, System.out);
71
* Creates a new UsagePrinter that prints to the given stream.
72
* @param shortestUsageMarker the usage marker that was used to mark the
73
* classes and class members.
74
* @param verbose specifies whether the output should be verbose.
75
* @param printStream the stream to which to print.
77
public ShortestUsagePrinter(ShortestUsageMarker shortestUsageMarker,
79
PrintStream printStream)
81
this.shortestUsageMarker = shortestUsageMarker;
82
this.verbose = verbose;
83
this.ps = printStream;
87
// Implementations for ClassFileVisitor.
89
public void visitProgramClassFile(ProgramClassFile programClassFile)
91
// Print the name of this class file.
92
ps.println(ClassUtil.externalClassName(programClassFile.getName()));
94
// Print the reason for keeping this class file.
95
printReason(programClassFile);
99
public void visitLibraryClassFile(LibraryClassFile libraryClassFile)
101
// Print the name of this class file.
102
ps.println(ClassUtil.externalClassName(libraryClassFile.getName()));
104
// Print the reason for keeping this class file.
105
ps.println(" is a library class.\n");
109
// Implementations for MemberInfoVisitor.
111
public void visitProgramFieldInfo(ProgramClassFile programClassFile, ProgramFieldInfo programFieldInfo)
113
// Print the name of this field.
114
String name = programFieldInfo.getName(programClassFile);
115
String type = programFieldInfo.getDescriptor(programClassFile);
117
ps.println(ClassUtil.externalClassName(programClassFile.getName()) +
119
": " + ClassUtil.externalFullFieldDescription(0, name, type):
121
lineNumberRange(programClassFile, programFieldInfo));
123
// Print the reason for keeping this method.
124
printReason(programFieldInfo);
128
public void visitProgramMethodInfo(ProgramClassFile programClassFile, ProgramMethodInfo programMethodInfo)
130
// Print the name of this method.
131
String name = programMethodInfo.getName(programClassFile);
132
String type = programMethodInfo.getDescriptor(programClassFile);
134
ps.println(ClassUtil.externalClassName(programClassFile.getName()) +
136
": " + ClassUtil.externalFullMethodDescription(programClassFile.getName(), 0, name, type):
138
lineNumberRange(programClassFile, programMethodInfo));
140
// Print the reason for keeping this method.
141
printReason(programMethodInfo);
145
public void visitLibraryFieldInfo(LibraryClassFile libraryClassFile, LibraryFieldInfo libraryFieldInfo)
147
// Print the name of this field.
148
String name = libraryFieldInfo.getName(libraryClassFile);
149
String type = libraryFieldInfo.getDescriptor(libraryClassFile);
151
ps.println(ClassUtil.externalClassName(libraryClassFile.getName()) +
153
": " + ClassUtil.externalFullFieldDescription(0, name, type):
156
// Print the reason for keeping this field.
157
ps.println(" is a library field.\n");
161
public void visitLibraryMethodInfo(LibraryClassFile libraryClassFile, LibraryMethodInfo libraryMethodInfo)
163
// Print the name of this method.
164
String name = libraryMethodInfo.getName(libraryClassFile);
165
String type = libraryMethodInfo.getDescriptor(libraryClassFile);
167
ps.println(ClassUtil.externalClassName(libraryClassFile.getName()) +
169
": " + ClassUtil.externalFullMethodDescription(libraryClassFile.getName(), 0, name, type):
172
// Print the reason for keeping this method.
173
ps.println(" is a library method.\n");
177
// Small utility methods.
179
private void printReason(VisitorAccepter visitorAccepter)
181
if (shortestUsageMarker.isUsed(visitorAccepter))
183
ShortestUsageMark shortestUsageMark = shortestUsageMarker.getShortestUsageMark(visitorAccepter);
185
// Print the reason for keeping this class file.
186
ps.print(" " + shortestUsageMark.getReason());
188
// Print the class or method that is responsible, with its reasons.
189
shortestUsageMark.acceptClassFileVisitor(this);
190
shortestUsageMark.acceptMethodInfoVisitor(this);
194
ps.println(" is not being kept.\n");
200
* Returns the line number range of the given class member, followed by a
201
* colon, or just an empty String if no range is available.
203
private static String lineNumberRange(ProgramClassFile programClassFile, ProgramMemberInfo programMemberInfo)
205
String range = programMemberInfo.getLineNumberRange(programClassFile);
206
return range != null ?
207
(" (" + range + ")") :