diff options
Diffstat (limited to 'src/proguard/classfile/util/AllParameterVisitor.java')
-rw-r--r-- | src/proguard/classfile/util/AllParameterVisitor.java | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/src/proguard/classfile/util/AllParameterVisitor.java b/src/proguard/classfile/util/AllParameterVisitor.java new file mode 100644 index 0000000..3695dbb --- /dev/null +++ b/src/proguard/classfile/util/AllParameterVisitor.java @@ -0,0 +1,239 @@ +/* + * 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; + } + } +} |