Home | History | Annotate | Download | only in shrink
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2014 Eric Lafortune (eric (at) 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      */
     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      */
     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 
     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 
    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 
    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 
    154     public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
    155 
    156 
    157     public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
    158     {
    159         codeAttribute.attributesAccept(clazz, method, this);
    160     }
    161 
    162 
    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      */
    176     private void printClassNameHeader()
    177     {
    178         if (className != null)
    179         {
    180             ps.println(ClassUtil.externalClassName(className) + ":");
    181             className = null;
    182         }
    183     }
    184 }
    185