Home | History | Annotate | Download | only in info
      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.optimize.info;
     22 
     23 import proguard.classfile.*;
     24 import proguard.classfile.constant.*;
     25 import proguard.classfile.constant.visitor.ConstantVisitor;
     26 import proguard.classfile.util.SimplifiedVisitor;
     27 import proguard.classfile.visitor.*;
     28 
     29 /**
     30  * This ClassVisitor marks all class members that can not be made private in the
     31  * classes that it visits, and in the classes to which they refer.
     32  *
     33  * @author Eric Lafortune
     34  */
     35 public class NonPrivateMemberMarker
     36 extends      SimplifiedVisitor
     37 implements   ClassVisitor,
     38              ConstantVisitor,
     39              MemberVisitor
     40 {
     41     private final MethodImplementationFilter filteredMethodMarker = new MethodImplementationFilter(this);
     42 
     43 
     44     // Implementations for ClassVisitor.
     45 
     46     public void visitProgramClass(ProgramClass programClass)
     47     {
     48         // Mark all referenced class members in different classes.
     49         programClass.constantPoolEntriesAccept(this);
     50 
     51         // Explicitly mark the <clinit> method.
     52         programClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT,
     53                                   ClassConstants.METHOD_TYPE_CLINIT,
     54                                   this);
     55 
     56         // Explicitly mark the parameterless <init> method.
     57         programClass.methodAccept(ClassConstants.METHOD_NAME_INIT,
     58                                   ClassConstants.METHOD_TYPE_INIT,
     59                                   this);
     60 
     61         // Mark all methods that may have implementations.
     62         programClass.methodsAccept(filteredMethodMarker);
     63     }
     64 
     65 
     66     public void visitLibraryClass(LibraryClass libraryClass)
     67     {
     68         // Go over all methods.
     69         libraryClass.methodsAccept(this);
     70     }
     71 
     72 
     73     // Implementations for ConstantVisitor.
     74 
     75     public void visitAnyConstant(Clazz clazz, Constant constant) {}
     76 
     77 
     78     public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
     79     {
     80         // The referenced class member, if any, can never be made private,
     81         // even if it's in the same class.
     82         stringConstant.referencedMemberAccept(this);
     83     }
     84 
     85 
     86     public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
     87     {
     88         Clazz referencedClass = refConstant.referencedClass;
     89 
     90         // Is it referring to a class member in another class?
     91         // The class member might be in another class, or
     92         // it may be referenced through another class.
     93         if (referencedClass != null &&
     94             !referencedClass.equals(clazz) ||
     95             !refConstant.getClassName(clazz).equals(clazz.getName()))
     96         {
     97             // The referenced class member can never be made private.
     98             refConstant.referencedMemberAccept(this);
     99         }
    100     }
    101 
    102 
    103     // Implementations for MemberVisitor.
    104 
    105     public void visitProgramField(ProgramClass programClass, ProgramField programField)
    106     {
    107         markCanNotBeMadePrivate(programField);
    108     }
    109 
    110 
    111     public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
    112     {
    113         markCanNotBeMadePrivate(libraryField);
    114     }
    115 
    116 
    117     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
    118     {
    119         markCanNotBeMadePrivate(programMethod);
    120     }
    121 
    122 
    123     public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
    124     {
    125         markCanNotBeMadePrivate(libraryMethod);
    126     }
    127 
    128 
    129     // Small utility methods.
    130 
    131     private static void markCanNotBeMadePrivate(Field field)
    132     {
    133         FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
    134         if (info != null)
    135         {
    136             info.setCanNotBeMadePrivate();
    137         }
    138     }
    139 
    140 
    141     /**
    142      * Returns whether the given field can be made private.
    143      */
    144     public static boolean canBeMadePrivate(Field field)
    145     {
    146         FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
    147         return info != null &&
    148                info.canBeMadePrivate();
    149     }
    150 
    151 
    152     private static void markCanNotBeMadePrivate(Method method)
    153     {
    154         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
    155         if (info != null)
    156         {
    157             info.setCanNotBeMadePrivate();
    158         }
    159     }
    160 
    161 
    162     /**
    163      * Returns whether the given method can be made private.
    164      */
    165     public static boolean canBeMadePrivate(Method method)
    166     {
    167         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
    168         return info != null &&
    169                info.canBeMadePrivate();
    170     }
    171 }
    172