proguard.classfile.visitor.ReferencedClassVisitor Maven / Gradle / Ivy
Show all versions of proguard-core Show documentation
/*
* 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.visitor;
import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.annotation.*;
import proguard.classfile.attribute.annotation.visitor.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.kotlin.*;
import proguard.classfile.kotlin.visitor.*;
/**
* This {@link ClassVisitor}, {@link MemberVisitor}, {@link ConstantVisitor}, {@link
* AttributeVisitor}, etc. lets a given {@link ClassVisitor} visit all the referenced classes of the
* elements that it visits. Only downstream elements are considered (in order to avoid loops and
* repeated visits)
*
* It also considers references in the Kotlin metadata of this class, if includeKotlinMetadata =
* true. So that, for example, a Kotlin function referencing a type alias will execute the delegate
* class visitor for the referencedClass of the alias.
*
* @author Eric Lafortune
* @author James Hamilton
*/
public class ReferencedClassVisitor
implements ClassVisitor,
MemberVisitor,
ConstantVisitor,
AttributeVisitor,
LocalVariableInfoVisitor,
LocalVariableTypeInfoVisitor,
AnnotationVisitor,
ElementValueVisitor {
private final ClassVisitor classVisitor;
private final KotlinReferencedClassVisitor kotlinReferencedClassVisitor;
public ReferencedClassVisitor(ClassVisitor classVisitor) {
this(false, classVisitor);
}
public ReferencedClassVisitor(boolean includeKotlinMetadata, ClassVisitor classVisitor) {
this.classVisitor = classVisitor;
this.kotlinReferencedClassVisitor =
includeKotlinMetadata ? new KotlinReferencedClassVisitor() : null;
}
// Implementations for ClassVisitor.
@Override
public void visitAnyClass(Clazz clazz) {
throw new UnsupportedOperationException(
this.getClass().getName() + " does not support " + clazz.getClass().getName());
}
@Override
public void visitProgramClass(ProgramClass programClass) {
// Visit the constant pool entries.
programClass.constantPoolEntriesAccept(this);
// Visit the fields and methods.
programClass.fieldsAccept(this);
programClass.methodsAccept(this);
// Visit the attributes.
programClass.attributesAccept(this);
if (kotlinReferencedClassVisitor != null) {
programClass.kotlinMetadataAccept(kotlinReferencedClassVisitor);
}
}
@Override
public void visitLibraryClass(LibraryClass libraryClass) {
// Visit the superclass and interfaces.
libraryClass.superClassAccept(classVisitor);
libraryClass.interfacesAccept(classVisitor);
// Visit the fields and methods.
libraryClass.fieldsAccept(this);
libraryClass.methodsAccept(this);
if (kotlinReferencedClassVisitor != null) {
libraryClass.kotlinMetadataAccept(kotlinReferencedClassVisitor);
}
}
// Implementations for MemberVisitor.
@Override
public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) {
// Let the visitor visit the classes referenced in the descriptor string.
programMember.referencedClassesAccept(classVisitor);
// Visit the attributes.
programMember.attributesAccept(programClass, this);
}
@Override
public void visitLibraryMember(LibraryClass programClass, LibraryMember libraryMember) {
// Let the visitor visit the classes referenced in the descriptor string.
libraryMember.referencedClassesAccept(classVisitor);
}
// Implementations for ConstantVisitor.
@Override
public void visitAnyConstant(Clazz clazz, Constant constant) {}
@Override
public void visitStringConstant(Clazz clazz, StringConstant stringConstant) {
// Let the visitor visit the class referenced in the string constant.
stringConstant.referencedClassAccept(classVisitor);
}
@Override
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) {
// Let the visitor visit the class referenced in the reference constant.
refConstant.referencedClassAccept(classVisitor);
}
@Override
public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) {
// Let the visitor visit the class referenced in the reference constant.
invokeDynamicConstant.referencedClassesAccept(classVisitor);
}
@Override
public void visitClassConstant(Clazz clazz, ClassConstant classConstant) {
// Let the visitor visit the class referenced in the class constant.
classConstant.referencedClassAccept(classVisitor);
}
@Override
public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) {
// Let the visitor visit the classes referenced in the method type constant.
methodTypeConstant.referencedClassesAccept(classVisitor);
}
// Implementations for AttributeVisitor.
@Override
public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
@Override
public void visitEnclosingMethodAttribute(
Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) {
// Let the visitor visit the class of the enclosing method.
enclosingMethodAttribute.referencedClassAccept(classVisitor);
}
@Override
public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) {
// Visit the attributes of the code attribute.
codeAttribute.attributesAccept(clazz, method, this);
}
@Override
public void visitLocalVariableTableAttribute(
Clazz clazz,
Method method,
CodeAttribute codeAttribute,
LocalVariableTableAttribute localVariableTableAttribute) {
// Visit the local variables.
localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
}
@Override
public void visitLocalVariableTypeTableAttribute(
Clazz clazz,
Method method,
CodeAttribute codeAttribute,
LocalVariableTypeTableAttribute localVariableTypeTableAttribute) {
// Visit the local variable types.
localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
}
@Override
public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) {
// Let the visitor visit the classes referenced in the signature string.
signatureAttribute.referencedClassesAccept(classVisitor);
}
@Override
public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) {
// Visit the annotations.
annotationsAttribute.annotationsAccept(clazz, this);
}
@Override
public void visitAnyParameterAnnotationsAttribute(
Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) {
// Visit the parameter annotations.
parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
}
@Override
public void visitAnnotationDefaultAttribute(
Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) {
// Visit the default element value.
annotationDefaultAttribute.defaultValueAccept(clazz, this);
}
// Implementations for LocalVariableInfoVisitor.
@Override
public void visitLocalVariableInfo(
Clazz clazz,
Method method,
CodeAttribute codeAttribute,
LocalVariableInfo localVariableInfo) {
// Let the visitor visit the class referenced in the local variable.
localVariableInfo.referencedClassAccept(classVisitor);
}
// Implementations for LocalVariableTypeInfoVisitor.
@Override
public void visitLocalVariableTypeInfo(
Clazz clazz,
Method method,
CodeAttribute codeAttribute,
LocalVariableTypeInfo localVariableTypeInfo) {
// Let the visitor visit the classes referenced in the local variable type.
localVariableTypeInfo.referencedClassesAccept(classVisitor);
}
// Implementations for AnnotationVisitor.
@Override
public void visitAnnotation(Clazz clazz, Annotation annotation) {
// Let the visitor visit the classes referenced in the annotation.
annotation.referencedClassesAccept(classVisitor);
// Visit the element values.
annotation.elementValuesAccept(clazz, this);
}
// Implementations for ElementValueVisitor.
@Override
public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) {}
@Override
public void visitEnumConstantElementValue(
Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) {
// Let the visitor visit the classes referenced in the constant element value.
enumConstantElementValue.referencedClassesAccept(classVisitor);
}
@Override
public void visitClassElementValue(
Clazz clazz, Annotation annotation, ClassElementValue classElementValue) {
// Let the visitor visit the classes referenced in the class element value.
classElementValue.referencedClassesAccept(classVisitor);
}
@Override
public void visitAnnotationElementValue(
Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) {
// Visit the contained annotation.
annotationElementValue.annotationAccept(clazz, this);
}
@Override
public void visitArrayElementValue(
Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) {
// Visit the element values.
arrayElementValue.elementValuesAccept(clazz, annotation, this);
}
private class KotlinReferencedClassVisitor
implements KotlinMetadataVisitor,
KotlinTypeVisitor,
KotlinTypeAliasVisitor,
KotlinFunctionVisitor,
KotlinTypeParameterVisitor,
KotlinValueParameterVisitor,
KotlinPropertyVisitor,
KotlinAnnotationVisitor,
KotlinAnnotationArgumentVisitor {
// Implementations for KotlinTypeVisitor.
@Override
public void visitAnyType(Clazz clazz, KotlinTypeMetadata kotlinTypeMetadata) {
kotlinTypeMetadata.referencedClassAccept(classVisitor);
kotlinTypeMetadata.typeArgumentsAccept(clazz, this);
kotlinTypeMetadata.annotationsAccept(clazz, this);
}
// Implementations for KotlinMetadataVisitor.
@Override
public void visitAnyKotlinMetadata(Clazz clazz, KotlinMetadata kotlinMetadata) {}
@Override
public void visitKotlinClassMetadata(
Clazz clazz, KotlinClassKindMetadata kotlinClassKindMetadata) {
kotlinClassKindMetadata.contextReceiverTypesAccept(clazz, this);
visitKotlinDeclarationContainerMetadata(clazz, kotlinClassKindMetadata);
}
@Override
public void visitKotlinDeclarationContainerMetadata(
Clazz clazz, KotlinDeclarationContainerMetadata kotlinDeclarationContainerMetadata) {
kotlinDeclarationContainerMetadata.typeAliasesAccept(clazz, this);
kotlinDeclarationContainerMetadata.functionsAccept(clazz, this);
kotlinDeclarationContainerMetadata.propertiesAccept(clazz, this);
kotlinDeclarationContainerMetadata.delegatedPropertiesAccept(clazz, this);
}
@Override
public void visitKotlinSyntheticClassMetadata(
Clazz clazz, KotlinSyntheticClassKindMetadata kotlinSyntheticClassKindMetadata) {
kotlinSyntheticClassKindMetadata.functionsAccept(clazz, this);
}
// Implementations for KotlinTypeAliasVisitor.
@Override
public void visitTypeAlias(
Clazz clazz,
KotlinDeclarationContainerMetadata kotlinDeclarationContainerMetadata,
KotlinTypeAliasMetadata kotlinTypeAliasMetadata) {
kotlinTypeAliasMetadata.annotationsAccept(clazz, this);
kotlinTypeAliasMetadata.typeParametersAccept(clazz, kotlinDeclarationContainerMetadata, this);
kotlinTypeAliasMetadata.expandedTypeAccept(clazz, kotlinDeclarationContainerMetadata, this);
kotlinTypeAliasMetadata.underlyingTypeAccept(clazz, kotlinDeclarationContainerMetadata, this);
}
// Implementations for KotlinFunctionVisitor.
@Override
public void visitAnyFunction(
Clazz clazz, KotlinMetadata kotlinMetadata, KotlinFunctionMetadata kotlinFunctionMetadata) {
kotlinFunctionMetadata.receiverTypeAccept(clazz, kotlinMetadata, this);
kotlinFunctionMetadata.contextReceiverTypesAccept(clazz, kotlinMetadata, this);
kotlinFunctionMetadata.returnTypeAccept(clazz, kotlinMetadata, this);
kotlinFunctionMetadata.typeParametersAccept(clazz, kotlinMetadata, this);
kotlinFunctionMetadata.valueParametersAccept(clazz, kotlinMetadata, this);
}
// Implementations for KotlinTypeParameterVisitor.
@Override
public void visitAnyTypeParameter(
Clazz clazz, KotlinTypeParameterMetadata kotlinTypeParameterMetadata) {
kotlinTypeParameterMetadata.annotationsAccept(clazz, this);
kotlinTypeParameterMetadata.upperBoundsAccept(clazz, this);
}
// Implementations for KotlinValueParameterVisitor.
@Override
public void visitAnyValueParameter(
Clazz clazz, KotlinValueParameterMetadata kotlinValueParameterMetadata) {}
@Override
public void visitConstructorValParameter(
Clazz clazz,
KotlinClassKindMetadata kotlinClassKindMetadata,
KotlinConstructorMetadata kotlinConstructorMetadata,
KotlinValueParameterMetadata kotlinValueParameterMetadata) {
kotlinValueParameterMetadata.typeAccept(
clazz, kotlinClassKindMetadata, kotlinConstructorMetadata, this);
}
@Override
public void visitFunctionValParameter(
Clazz clazz,
KotlinMetadata kotlinMetadata,
KotlinFunctionMetadata kotlinFunctionMetadata,
KotlinValueParameterMetadata kotlinValueParameterMetadata) {
kotlinValueParameterMetadata.typeAccept(clazz, kotlinMetadata, kotlinFunctionMetadata, this);
}
@Override
public void visitPropertyValParameter(
Clazz clazz,
KotlinDeclarationContainerMetadata kotlinDeclarationContainerMetadata,
KotlinPropertyMetadata kotlinPropertyMetadata,
KotlinValueParameterMetadata kotlinValueParameterMetadata) {
kotlinValueParameterMetadata.typeAccept(
clazz, kotlinDeclarationContainerMetadata, kotlinPropertyMetadata, this);
}
// Implementations for KotlinPropertyVisitor.
@Override
public void visitAnyProperty(
Clazz clazz,
KotlinDeclarationContainerMetadata kotlinDeclarationContainerMetadata,
KotlinPropertyMetadata kotlinPropertyMetadata) {
kotlinPropertyMetadata.receiverTypeAccept(clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.contextReceiverTypesAccept(
clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.typeAccept(clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.setterParametersAccept(
clazz, kotlinDeclarationContainerMetadata, this);
kotlinPropertyMetadata.typeParametersAccept(clazz, kotlinDeclarationContainerMetadata, this);
if (kotlinPropertyMetadata.referencedSyntheticMethodClass != null) {
kotlinPropertyMetadata.referencedSyntheticMethodClass.accept(classVisitor);
}
if (kotlinPropertyMetadata.referencedBackingFieldClass != null) {
kotlinPropertyMetadata.referencedBackingFieldClass.accept(classVisitor);
}
if (kotlinPropertyMetadata.referencedSyntheticMethodForDelegateClass != null) {
kotlinPropertyMetadata.referencedSyntheticMethodForDelegateClass.accept(classVisitor);
}
}
// Implementations for KotlinAnnotationVisitor.
@Override
public void visitAnyAnnotation(
Clazz clazz, KotlinAnnotatable annotatable, KotlinAnnotation annotation) {
annotation.referencedClassAccept(classVisitor);
annotation.argumentsAccept(clazz, annotatable, this);
}
// Implementations for KotlinAnnotationArgumentVisitor
@Override
public void visitAnyArgument(
Clazz clazz,
KotlinAnnotatable annotatable,
KotlinAnnotation annotation,
KotlinAnnotationArgument argument,
KotlinAnnotationArgument.Value value) {
argument.referencedMethodAccept(new ReferencedClassVisitor(classVisitor));
}
@Override
public void visitClassArgument(
Clazz clazz,
KotlinAnnotatable annotatable,
KotlinAnnotation annotation,
KotlinAnnotationArgument argument,
KotlinAnnotationArgument.ClassValue value) {
this.visitAnyArgument(clazz, annotatable, annotation, argument, value);
value.referencedClassAccept(classVisitor);
}
@Override
public void visitEnumArgument(
Clazz clazz,
KotlinAnnotatable annotatable,
KotlinAnnotation annotation,
KotlinAnnotationArgument argument,
KotlinAnnotationArgument.EnumValue value) {
this.visitAnyArgument(clazz, annotatable, annotation, argument, value);
value.referencedClassAccept(classVisitor);
}
@Override
public void visitArrayArgument(
Clazz clazz,
KotlinAnnotatable annotatable,
KotlinAnnotation annotation,
KotlinAnnotationArgument argument,
KotlinAnnotationArgument.ArrayValue value) {
this.visitAnyArgument(clazz, annotatable, annotation, argument, value);
value.elementsAccept(clazz, annotatable, annotation, argument, this);
}
}
}