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.classfile.util; 22 23 import proguard.classfile.*; 24 import proguard.classfile.visitor.*; 25 26 /** 27 * This MemberVisitor lets a given parameter visitor visit all the parameters 28 * of the methods that it visits. The parameters do not include or count the 29 * 'this' parameter or the return value. 30 * 31 * @author Eric Lafortune 32 */ 33 public class AllParameterVisitor 34 implements MemberVisitor 35 { 36 private final ParameterVisitor parameterVisitor; 37 38 39 /** 40 * Creates a new AllParameterVisitor for the given parameter 41 * visitor. 42 */ AllParameterVisitor(ParameterVisitor parameterVisitor)43 public AllParameterVisitor(ParameterVisitor parameterVisitor) 44 { 45 this.parameterVisitor = parameterVisitor; 46 } 47 48 49 // Implementations for MemberVisitor. 50 visitProgramField(ProgramClass programClass, ProgramField programField)51 public void visitProgramField(ProgramClass programClass, ProgramField programField) 52 { 53 visitFieldType(programClass, 54 programField, 55 programField.referencedClass); 56 } 57 58 visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)59 public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) 60 { 61 visitFieldType(libraryClass, 62 libraryField, 63 libraryField.referencedClass); 64 } 65 66 visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)67 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 68 { 69 visitParameters(programClass, 70 programMethod, 71 programMethod.referencedClasses); 72 } 73 74 visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)75 public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) 76 { 77 visitParameters(libraryClass, 78 libraryMethod, 79 libraryMethod.referencedClasses); 80 } 81 82 83 // Small utility methods. 84 85 /** 86 * Lets the parameter visitor visit the type of the given field. 87 */ visitFieldType(Clazz clazz, Field field, Clazz referencedClass)88 private void visitFieldType(Clazz clazz, 89 Field field, 90 Clazz referencedClass) 91 { 92 String descriptor = field.getDescriptor(clazz); 93 parameterVisitor.visitParameter(clazz, 94 field, 95 0, 96 1, 97 0, 98 ClassUtil.internalTypeSize(descriptor), 99 descriptor, 100 referencedClass); 101 } 102 103 104 /** 105 * Lets the parameter visitor visit the parameters of the given method. 106 */ visitParameters(Clazz clazz, Method method, Clazz[] referencedClasses)107 private void visitParameters(Clazz clazz, 108 Method method, 109 Clazz[] referencedClasses) 110 { 111 String descriptor = method.getDescriptor(clazz); 112 113 // Count the number of parameters and their total size. 114 int parameterCount = 0; 115 int parameterSize = 0; 116 117 int index = 1; 118 119 loop: while (true) 120 { 121 char c = descriptor.charAt(index++); 122 switch (c) 123 { 124 case ClassConstants.TYPE_LONG: 125 case ClassConstants.TYPE_DOUBLE: 126 { 127 // Long and double primitive types. 128 parameterSize++; 129 break; 130 } 131 default: 132 { 133 // All other primitive types. 134 break; 135 } 136 case ClassConstants.TYPE_CLASS_START: 137 { 138 // Class types. 139 // Skip the class name. 140 index = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1; 141 break; 142 } 143 case ClassConstants.TYPE_ARRAY: 144 { 145 // Array types. 146 // Skip all array characters. 147 while ((c = descriptor.charAt(index++)) == ClassConstants.TYPE_ARRAY) {} 148 149 if (c == ClassConstants.TYPE_CLASS_START) 150 { 151 // Skip the class type. 152 index = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1; 153 } 154 break; 155 } 156 case ClassConstants.METHOD_ARGUMENTS_CLOSE: 157 { 158 break loop; 159 } 160 } 161 162 parameterCount++; 163 parameterSize++; 164 } 165 166 // Visit the parameters. 167 int parameterIndex = 0; 168 int parameterOffset = 0; 169 int referenceClassIndex = 0; 170 171 index = 1; 172 173 while (true) 174 { 175 int newIndex = index + 1; 176 int thisParameterSize = 1; 177 Clazz referencedClass = null; 178 179 char c = descriptor.charAt(index); 180 switch (c) 181 { 182 case ClassConstants.TYPE_LONG: 183 case ClassConstants.TYPE_DOUBLE: 184 { 185 // Long and double primitive types. 186 thisParameterSize = 2; 187 break; 188 } 189 default: 190 { 191 // All other primitive types. 192 break; 193 } 194 case ClassConstants.TYPE_CLASS_START: 195 { 196 // Class types. 197 // Skip the class name. 198 newIndex = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, newIndex) + 1; 199 referencedClass = referencedClasses == null ? null : 200 referencedClasses[referenceClassIndex++]; 201 break; 202 } 203 case ClassConstants.TYPE_ARRAY: 204 { 205 // Array types. 206 // Skip all array characters. 207 while ((c = descriptor.charAt(newIndex++)) == ClassConstants.TYPE_ARRAY) {} 208 209 if (c == ClassConstants.TYPE_CLASS_START) 210 { 211 // Skip the class type. 212 newIndex = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, newIndex) + 1; 213 referencedClass = referencedClasses == null ? null : 214 referencedClasses[referenceClassIndex++]; 215 } 216 break; 217 } 218 case ClassConstants.METHOD_ARGUMENTS_CLOSE: 219 { 220 // End of the method parameters. 221 return; 222 } 223 } 224 225 parameterVisitor.visitParameter(clazz, 226 method, 227 parameterIndex++, 228 parameterCount, 229 parameterOffset, 230 parameterSize, 231 descriptor.substring(index, newIndex), 232 referencedClass); 233 234 // Continue with the next parameter. 235 index = newIndex; 236 parameterOffset += thisParameterSize; 237 } 238 } 239 } 240