| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.maven.shared.dependency.analyzer.asm; |
| |
| import java.util.Arrays; |
| |
| import org.objectweb.asm.AnnotationVisitor; |
| import org.objectweb.asm.Handle; |
| import org.objectweb.asm.Label; |
| import org.objectweb.asm.MethodVisitor; |
| import org.objectweb.asm.Opcodes; |
| import org.objectweb.asm.Type; |
| import org.objectweb.asm.TypePath; |
| import org.objectweb.asm.signature.SignatureReader; |
| import org.objectweb.asm.signature.SignatureVisitor; |
| |
| /** |
| * Computes the set of classes referenced by visited code. |
| * Inspired by <code>org.objectweb.asm.depend.DependencyVisitor</code> in the ASM dependencies example. |
| * |
| * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a> |
| */ |
| public class DefaultMethodVisitor extends MethodVisitor { |
| private final AnnotationVisitor annotationVisitor; |
| |
| private final SignatureVisitor signatureVisitor; |
| |
| private final ResultCollector resultCollector; |
| |
| /** |
| * <p>Constructor for DefaultMethodVisitor.</p> |
| * |
| * @param annotationVisitor a {@link org.objectweb.asm.AnnotationVisitor} object. |
| * @param signatureVisitor a {@link org.objectweb.asm.signature.SignatureVisitor} object. |
| * @param resultCollector a {@link org.apache.maven.shared.dependency.analyzer.asm.ResultCollector} object. |
| */ |
| public DefaultMethodVisitor( |
| AnnotationVisitor annotationVisitor, SignatureVisitor signatureVisitor, ResultCollector resultCollector) { |
| super(Opcodes.ASM9); |
| this.annotationVisitor = annotationVisitor; |
| this.signatureVisitor = signatureVisitor; |
| this.resultCollector = resultCollector; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { |
| resultCollector.addDesc(desc); |
| |
| return annotationVisitor; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { |
| resultCollector.addDesc(desc); |
| |
| return annotationVisitor; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible) { |
| resultCollector.addDesc(desc); |
| |
| return annotationVisitor; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public AnnotationVisitor visitLocalVariableAnnotation( |
| int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) { |
| resultCollector.addDesc(desc); |
| |
| return annotationVisitor; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void visitTypeInsn(final int opcode, final String desc) { |
| if (desc.charAt(0) == '[') { |
| resultCollector.addDesc(desc); |
| } else { |
| resultCollector.addName(desc); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) { |
| resultCollector.addName(owner); |
| /* |
| * NOTE: Merely accessing a field does not impose a direct dependency on its type. For example, the code line |
| * <code>java.lang.Object var = bean.field;</code> does not directly depend on the type of the field. A direct |
| * dependency is only introduced when the code explicitly references the field's type by means of a variable |
| * declaration or a type check/cast. Those cases are handled by other visitor callbacks. |
| */ |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { |
| resultCollector.addName(owner); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void visitLdcInsn(final Object cst) { |
| if (cst instanceof Type) { |
| resultCollector.addType((Type) cst); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void visitMultiANewArrayInsn(final String desc, final int dims) { |
| resultCollector.addDesc(desc); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) { |
| resultCollector.addName(type); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void visitLocalVariable( |
| final String name, |
| final String desc, |
| final String signature, |
| final Label start, |
| final Label end, |
| final int index) { |
| if (signature == null) { |
| resultCollector.addDesc(desc); |
| } else { |
| addTypeSignature(signature); |
| } |
| } |
| |
| private void addTypeSignature(final String signature) { |
| if (signature != null) { |
| new SignatureReader(signature).acceptType(signatureVisitor); |
| } |
| } |
| |
| @Override |
| public void visitInvokeDynamicInsn( |
| String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) { |
| Arrays.stream(bootstrapMethodArguments) |
| .filter(Type.class::isInstance) |
| .map(Type.class::cast) |
| .map(Type::getDescriptor) |
| .forEach(resultCollector::addMethodDesc); |
| } |
| } |