/* * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package proguard.classfile.util; import proguard.classfile.*; import proguard.classfile.visitor.*; /** * This MemberVisitor lets a given parameter visitor visit all the parameters * of the methods that it visits. The parameters do not include or count the * 'this' parameter or the return value. * * @author Eric Lafortune */ public class AllParameterVisitor implements MemberVisitor { private final ParameterVisitor parameterVisitor; /** * Creates a new AllParameterVisitor for the given parameter * visitor. */ public AllParameterVisitor(ParameterVisitor parameterVisitor) { this.parameterVisitor = parameterVisitor; } // Implementations for MemberVisitor. public void visitProgramField(ProgramClass programClass, ProgramField programField) { visitFieldType(programClass, programField, programField.referencedClass); } public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) { visitFieldType(libraryClass, libraryField, libraryField.referencedClass); } public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { visitParameters(programClass, programMethod, programMethod.referencedClasses); } public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) { visitParameters(libraryClass, libraryMethod, libraryMethod.referencedClasses); } // Small utility methods. /** * Lets the parameter visitor visit the type of the given field. */ private void visitFieldType(Clazz clazz, Field field, Clazz referencedClass) { String descriptor = field.getDescriptor(clazz); parameterVisitor.visitParameter(clazz, field, 0, 1, 0, ClassUtil.internalTypeSize(descriptor), descriptor, referencedClass); } /** * Lets the parameter visitor visit the parameters of the given method. */ private void visitParameters(Clazz clazz, Method method, Clazz[] referencedClasses) { String descriptor = method.getDescriptor(clazz); // Count the number of parameters and their total size. int parameterCount = 0; int parameterSize = 0; int index = 1; loop: while (true) { char c = descriptor.charAt(index++); switch (c) { case ClassConstants.TYPE_LONG: case ClassConstants.TYPE_DOUBLE: { // Long and double primitive types. parameterSize++; break; } default: { // All other primitive types. break; } case ClassConstants.TYPE_CLASS_START: { // Class types. // Skip the class name. index = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1; break; } case ClassConstants.TYPE_ARRAY: { // Array types. // Skip all array characters. while ((c = descriptor.charAt(index++)) == ClassConstants.TYPE_ARRAY) {} if (c == ClassConstants.TYPE_CLASS_START) { // Skip the class type. index = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, index) + 1; } break; } case ClassConstants.METHOD_ARGUMENTS_CLOSE: { break loop; } } parameterCount++; parameterSize++; } // Visit the parameters. int parameterIndex = 0; int parameterOffset = 0; int referenceClassIndex = 0; index = 1; while (true) { int newIndex = index + 1; int thisParameterSize = 1; Clazz referencedClass = null; char c = descriptor.charAt(index); switch (c) { case ClassConstants.TYPE_LONG: case ClassConstants.TYPE_DOUBLE: { // Long and double primitive types. thisParameterSize = 2; break; } default: { // All other primitive types. break; } case ClassConstants.TYPE_CLASS_START: { // Class types. // Skip the class name. newIndex = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, newIndex) + 1; referencedClass = referencedClasses == null ? null : referencedClasses[referenceClassIndex++]; break; } case ClassConstants.TYPE_ARRAY: { // Array types. // Skip all array characters. while ((c = descriptor.charAt(newIndex++)) == ClassConstants.TYPE_ARRAY) {} if (c == ClassConstants.TYPE_CLASS_START) { // Skip the class type. newIndex = descriptor.indexOf(ClassConstants.TYPE_CLASS_END, newIndex) + 1; referencedClass = referencedClasses == null ? null : referencedClasses[referenceClassIndex++]; } break; } case ClassConstants.METHOD_ARGUMENTS_CLOSE: { // End of the method parameters. return; } } parameterVisitor.visitParameter(clazz, method, parameterIndex++, parameterCount, parameterOffset, parameterSize, descriptor.substring(index, newIndex), referencedClass); // Continue with the next parameter. index = newIndex; parameterOffset += thisParameterSize; } } }