proguard.classfile.util.AllParameterVisitor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of proguard-core Show documentation
Show all versions of proguard-core Show documentation
ProGuardCORE is a free library to read, analyze, modify, and write Java class files.
/*
* ProGuardCORE -- library to process Java bytecode.
*
* Copyright (c) 2002-2020 Guardsquare NV
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package proguard.classfile.util;
import proguard.classfile.*;
import proguard.classfile.visitor.*;
/**
* This {@link MemberVisitor} lets a given parameter visitor visit all the parameters of the methods
* that it visits. The parameters optionally include the 'this' parameters of non-static methods,
* but never the return value.
*
* @author Eric Lafortune
*/
public class AllParameterVisitor implements MemberVisitor {
private final boolean includeThisParameter;
private final ParameterVisitor parameterVisitor;
/**
* Creates a new AllParameterVisitor for the given parameter visitor.
*
* @param includeThisParameter specifies whether to visit the 'this' parameters.
* @param parameterVisitor the visitor for the parameters of the visited methods.
*/
public AllParameterVisitor(boolean includeThisParameter, ParameterVisitor parameterVisitor) {
this.includeThisParameter = includeThisParameter;
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 TypeConstants.LONG:
case TypeConstants.DOUBLE:
{
// Long and double primitive types.
parameterSize++;
break;
}
default:
{
// All other primitive types.
break;
}
case TypeConstants.CLASS_START:
{
// Class types.
// Skip the class name.
index = descriptor.indexOf(TypeConstants.CLASS_END, index) + 1;
break;
}
case TypeConstants.ARRAY:
{
// Array types.
// Skip all array characters.
while ((c = descriptor.charAt(index++)) == TypeConstants.ARRAY) {}
if (c == TypeConstants.CLASS_START) {
// Skip the class type.
index = descriptor.indexOf(TypeConstants.CLASS_END, index) + 1;
}
break;
}
case TypeConstants.METHOD_ARGUMENTS_CLOSE:
{
break loop;
}
}
parameterCount++;
parameterSize++;
}
// Visit the parameters.
int parameterIndex = 0;
int parameterOffset = 0;
int referenceClassIndex = 0;
// Visit the 'this' parameter if applicable.
if (includeThisParameter && (method.getAccessFlags() & AccessConstants.STATIC) == 0) {
parameterVisitor.visitParameter(
clazz,
method,
parameterIndex++,
++parameterCount,
parameterOffset++,
++parameterSize,
ClassUtil.internalTypeFromClassName(clazz.getName()),
clazz);
}
index = 1;
while (true) {
int newIndex = index + 1;
int thisParameterSize = 1;
Clazz referencedClass = null;
char c = descriptor.charAt(index);
switch (c) {
case TypeConstants.LONG:
case TypeConstants.DOUBLE:
{
// Long and double primitive types.
thisParameterSize = 2;
break;
}
default:
{
// All other primitive types.
break;
}
case TypeConstants.CLASS_START:
{
// Class types.
// Skip the class name.
newIndex = descriptor.indexOf(TypeConstants.CLASS_END, newIndex) + 1;
referencedClass =
referencedClasses == null ? null : referencedClasses[referenceClassIndex++];
break;
}
case TypeConstants.ARRAY:
{
// Array types.
// Skip all array characters.
while ((c = descriptor.charAt(newIndex++)) == TypeConstants.ARRAY) {}
if (c == TypeConstants.CLASS_START) {
// Skip the class type.
newIndex = descriptor.indexOf(TypeConstants.CLASS_END, newIndex) + 1;
referencedClass =
referencedClasses == null ? null : referencedClasses[referenceClassIndex++];
}
break;
}
case TypeConstants.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;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy