1 21 package proguard.optimize.info; 22 23 import proguard.classfile.*; 24 import proguard.classfile.util.*; 25 import proguard.classfile.visitor.*; 26 import proguard.optimize.KeepMarker; 27 28 36 public class SingleImplementationMarker 37 extends SimplifiedVisitor 38 implements ClassVisitor 39 { 40 private static final boolean DEBUG = false; 41 42 43 private boolean allowAccessModification; 44 private ClassVisitor extraClassVisitor; 45 46 47 53 public SingleImplementationMarker(boolean allowAccessModification) 54 { 55 this(allowAccessModification, null); 56 } 57 58 59 67 public SingleImplementationMarker(boolean allowAccessModification, 68 ClassVisitor extraClassVisitor) 69 { 70 this.allowAccessModification = allowAccessModification; 71 this.extraClassVisitor = extraClassVisitor; 72 } 73 74 75 77 public void visitProgramClass(ProgramClass programClass) 78 { 79 if ((programClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE) == 0 || 82 KeepMarker.isKept(programClass)) 83 { 84 return; 85 } 86 87 Clazz[] subClasses = programClass.subClasses; 89 if (subClasses == null || 90 subClasses.length != 1) 91 { 92 return; 93 } 94 95 Clazz singleImplementationClass = subClasses[0]; 97 int singleImplementationAccessFlags = singleImplementationClass.getAccessFlags(); 98 if ((singleImplementationAccessFlags & ClassConstants.INTERNAL_ACC_INTERFACE) != 0) 99 { 100 singleImplementationClass.accept(this); 101 102 singleImplementationClass = singleImplementation(singleImplementationClass); 104 if (singleImplementationClass == null) 105 { 106 return; 107 } 108 109 singleImplementationAccessFlags = singleImplementationClass.getAccessFlags(); 110 } 111 112 for (int index = 0; index < programClass.u2methodsCount; index++) 115 { 116 Method method = programClass.methods[index]; 117 if ((method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) == 0 && 118 singleImplementationClass.findMethod(method.getName(programClass), 119 method.getDescriptor(programClass)) == null) 120 { 121 return; 122 } 123 } 124 125 if (AccessUtil.accessLevel(singleImplementationAccessFlags) < 128 AccessUtil.accessLevel(programClass.getAccessFlags())) 129 { 130 if (allowAccessModification) 132 { 133 ((ProgramClass)singleImplementationClass).u2accessFlags = 135 AccessUtil.replaceAccessFlags(singleImplementationAccessFlags, 136 programClass.getAccessFlags()); 137 } 138 else 139 { 140 return; 143 } 144 } 145 146 if (DEBUG) 147 { 148 System.out.println("Single implementation of ["+programClass.getName()+"]: ["+singleImplementationClass.getName()+"]"); 149 } 150 151 markSingleImplementation(programClass, singleImplementationClass); 153 154 if (extraClassVisitor != null) 156 { 157 singleImplementationClass.accept(extraClassVisitor); 158 } 159 } 160 161 162 164 public static void markSingleImplementation(VisitorAccepter visitorAccepter, 165 Clazz singleImplementation) 166 { 167 visitorAccepter.setVisitorInfo(singleImplementation); 169 } 170 171 172 public static Clazz singleImplementation(VisitorAccepter visitorAccepter) 173 { 174 return visitorAccepter != null && 175 visitorAccepter.getVisitorInfo() instanceof Clazz ? 176 (Clazz)visitorAccepter.getVisitorInfo() : 177 null; 178 } 179 } 180 | Popular Tags |