/*
 * Copyright 2014 - 2020 Rafael Winterhalter
 *
 * 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 net.bytebuddy.description.method;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import net.bytebuddy.build.CachedReturnPlugin;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.ByteCodeElement;
import net.bytebuddy.description.ModifierReviewable;
import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.annotation.AnnotationList;
import net.bytebuddy.description.annotation.AnnotationSource;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeList;
import net.bytebuddy.implementation.bytecode.StackSize;
import net.bytebuddy.matcher.ElementMatcher;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.AbstractList;
import java.util.Collections;
import java.util.List;

Description of the parameter of a Java method or constructor.
/** * Description of the parameter of a Java method or constructor. */
public interface ParameterDescription extends AnnotationSource, NamedElement.WithRuntimeName, NamedElement.WithOptionalName, ModifierReviewable.ForParameterDescription, ByteCodeElement.TypeDependant<ParameterDescription.InDefinedShape, ParameterDescription.Token> {
The prefix for names of an unnamed parameter.
/** * The prefix for names of an unnamed parameter. */
String NAME_PREFIX = "arg";
Returns the type of this parameter.
Returns:The type of this parameter.
/** * Returns the type of this parameter. * * @return The type of this parameter. */
TypeDescription.Generic getType();
Returns the method that declares this parameter.
Returns:The method that declares this parameter.
/** * Returns the method that declares this parameter. * * @return The method that declares this parameter. */
MethodDescription getDeclaringMethod();
Returns this parameter's index.
Returns:The index of this parameter.
/** * Returns this parameter's index. * * @return The index of this parameter. */
int getIndex();
Checks if this parameter has an explicit modifier. A parameter without a modifier is simply treated as if it had a modifier of zero.
Returns:true if this parameter defines explicit modifiers.
/** * Checks if this parameter has an explicit modifier. A parameter without a modifier is simply treated as * if it had a modifier of zero. * * @return {@code true} if this parameter defines explicit modifiers. */
boolean hasModifiers();
Returns the offset to the parameter value within the local method variable.
Returns:The offset of this parameter's value.
/** * Returns the offset to the parameter value within the local method variable. * * @return The offset of this parameter's value. */
int getOffset();
Represents a parameter description in its generic shape, i.e. in the shape it is defined by a generic or raw type.
/** * Represents a parameter description in its generic shape, i.e. in the shape it is defined by a generic or raw type. */
interface InGenericShape extends ParameterDescription {
{@inheritDoc}
/** * {@inheritDoc} */
MethodDescription.InGenericShape getDeclaringMethod(); }
Represents a parameter in its defined shape, i.e. in the form it is defined by a class without its type variables being resolved.
/** * Represents a parameter in its defined shape, i.e. in the form it is defined by a class without its type variables being resolved. */
interface InDefinedShape extends ParameterDescription {
{@inheritDoc}
/** * {@inheritDoc} */
MethodDescription.InDefinedShape getDeclaringMethod();
An abstract base implementation of a parameter description in its defined shape.
/** * An abstract base implementation of a parameter description in its defined shape. */
abstract class AbstractBase extends ParameterDescription.AbstractBase implements InDefinedShape {
{@inheritDoc}
/** * {@inheritDoc} */
public InDefinedShape asDefined() { return this; } } }
A base implementation of a method parameter description.
/** * A base implementation of a method parameter description. */
abstract class AbstractBase extends ModifierReviewable.AbstractBase implements ParameterDescription {
{@inheritDoc}
/** * {@inheritDoc} */
public String getName() { return NAME_PREFIX.concat(String.valueOf(getIndex())); }
{@inheritDoc}
/** * {@inheritDoc} */
public String getInternalName() { return getName(); }
{@inheritDoc}
/** * {@inheritDoc} */
public String getActualName() { return isNamed() ? getName() : EMPTY_NAME; }
{@inheritDoc}
/** * {@inheritDoc} */
public int getModifiers() { return EMPTY_MASK; }
{@inheritDoc}
/** * {@inheritDoc} */
public int getOffset() { TypeList parameterType = getDeclaringMethod().getParameters().asTypeList().asErasures(); int offset = getDeclaringMethod().isStatic() ? StackSize.ZERO.getSize() : StackSize.SINGLE.getSize(); for (int i = 0; i < getIndex(); i++) { offset += parameterType.get(i).getStackSize().getSize(); } return offset; }
{@inheritDoc}
/** * {@inheritDoc} */
public Token asToken(ElementMatcher<? super TypeDescription> matcher) { return new Token(getType().accept(new TypeDescription.Generic.Visitor.Substitutor.ForDetachment(matcher)), getDeclaredAnnotations(), isNamed() ? getName() : Token.NO_NAME, hasModifiers() ? (Integer) getModifiers() : Token.NO_MODIFIERS); } @Override @CachedReturnPlugin.Enhance("hashCode") public int hashCode() { return getDeclaringMethod().hashCode() ^ getIndex(); } @Override public boolean equals(Object other) { if (this == other) { return true; } else if (!(other instanceof ParameterDescription)) { return false; } ParameterDescription parameterDescription = (ParameterDescription) other; return getDeclaringMethod().equals(parameterDescription.getDeclaringMethod()) && getIndex() == parameterDescription.getIndex(); } @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(Modifier.toString(getModifiers())); if (getModifiers() != EMPTY_MASK) { stringBuilder.append(' '); } stringBuilder.append(isVarArgs() ? getType().asErasure().getName().replaceFirst("\\[\\]$", "...") : getType().asErasure().getName()); return stringBuilder.append(' ').append(getName()).toString(); } }
Description of a loaded parameter with support for the information exposed by java.lang.reflect.Parameter.
Type parameters:
  • <T> – The type of the java.lang.reflect.Executable that this list represents.
/** * Description of a loaded parameter with support for the information exposed by {@code java.lang.reflect.Parameter}. * * @param <T> The type of the {@code java.lang.reflect.Executable} that this list represents. */
abstract class ForLoadedParameter<T extends AccessibleObject> extends InDefinedShape.AbstractBase {
A dispatcher for reading properties from java.lang.reflect.Executable instances.
/** * A dispatcher for reading properties from {@code java.lang.reflect.Executable} instances. */
private static final Dispatcher DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE);
The java.lang.reflect.Executable for which the parameter types are described.
/** * The {@code java.lang.reflect.Executable} for which the parameter types are described. */
protected final T executable;
The parameter's index.
/** * The parameter's index. */
protected final int index;
The parameter annotation source to query.
/** * The parameter annotation source to query. */
protected final ParameterAnnotationSource parameterAnnotationSource;
Creates a new description for a loaded parameter.
Params:
  • executable – The java.lang.reflect.Executable for which the parameter types are described.
  • index – The parameter's index.
  • parameterAnnotationSource – The parameter annotation source to query.
/** * Creates a new description for a loaded parameter. * * @param executable The {@code java.lang.reflect.Executable} for which the parameter types are described. * @param index The parameter's index. * @param parameterAnnotationSource The parameter annotation source to query. */
protected ForLoadedParameter(T executable, int index, ParameterAnnotationSource parameterAnnotationSource) { this.executable = executable; this.index = index; this.parameterAnnotationSource = parameterAnnotationSource; }
{@inheritDoc}
/** * {@inheritDoc} */
public String getName() { return DISPATCHER.getName(executable, index); }
{@inheritDoc}
/** * {@inheritDoc} */
public int getIndex() { return index; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isNamed() { return DISPATCHER.isNamePresent(executable, index); }
{@inheritDoc}
/** * {@inheritDoc} */
public int getModifiers() { return DISPATCHER.getModifiers(executable, index); }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean hasModifiers() { // Rational: If a parameter is not named despite the information being attached, // it is synthetic, i.e. it has non-default modifiers. return isNamed() || getModifiers() != EMPTY_MASK; }
A source for querying parameter annotations.
/** * A source for querying parameter annotations. */
public interface ParameterAnnotationSource {
Returns the parameter annotations represented by this source.
Returns:The parameter annotations as an array indexed by parameter index.
/** * Returns the parameter annotations represented by this source. * * @return The parameter annotations as an array indexed by parameter index. */
Annotation[][] getParameterAnnotations();
A source for a loaded constructor.
/** * A source for a loaded constructor. */
@HashCodeAndEqualsPlugin.Enhance class ForLoadedConstructor implements ParameterAnnotationSource {
The constructor to query for annotations.
/** * The constructor to query for annotations. */
private final Constructor<?> constructor;
Creates a new parameter annotation source for a constructor.
Params:
  • constructor – The constructor to query for annotations.
/** * Creates a new parameter annotation source for a constructor. * * @param constructor The constructor to query for annotations. */
public ForLoadedConstructor(Constructor<?> constructor) { this.constructor = constructor; }
{@inheritDoc}
/** * {@inheritDoc} */
public Annotation[][] getParameterAnnotations() { return constructor.getParameterAnnotations(); } }
A source for a loaded method.
/** * A source for a loaded method. */
@HashCodeAndEqualsPlugin.Enhance class ForLoadedMethod implements ParameterAnnotationSource {
The method to query for annotations.
/** * The method to query for annotations. */
private final Method method;
Creates a new parameter annpotation source for a method.
Params:
  • method – The method to query for annotations.
/** * Creates a new parameter annpotation source for a method. * * @param method The method to query for annotations. */
public ForLoadedMethod(Method method) { this.method = method; }
{@inheritDoc}
/** * {@inheritDoc} */
public Annotation[][] getParameterAnnotations() { return method.getParameterAnnotations(); } } }
A dispatcher creating parameter descriptions based on the API that is available for the current JVM.
/** * A dispatcher creating parameter descriptions based on the API that is available for the current JVM. */
protected interface Dispatcher {
Returns the given parameter's modifiers.
Params:
  • executable – The executable to introspect.
  • index – The parameter's index.
Returns:The parameter's modifiers.
/** * Returns the given parameter's modifiers. * * @param executable The executable to introspect. * @param index The parameter's index. * @return The parameter's modifiers. */
int getModifiers(AccessibleObject executable, int index);
Returns true if the given parameter has an explicit name.
Params:
  • executable – The parameter to introspect.
  • index – The parameter's index.
Returns:true if the given parameter has an explicit name.
/** * Returns {@code true} if the given parameter has an explicit name. * * @param executable The parameter to introspect. * @param index The parameter's index. * @return {@code true} if the given parameter has an explicit name. */
boolean isNamePresent(AccessibleObject executable, int index);
Returns the given parameter's implicit or explicit name.
Params:
  • executable – The parameter to introspect.
  • index – The parameter's index.
Returns:The parameter's name.
/** * Returns the given parameter's implicit or explicit name. * * @param executable The parameter to introspect. * @param index The parameter's index. * @return The parameter's name. */
String getName(AccessibleObject executable, int index);
A creation action for a dispatcher.
/** * A creation action for a dispatcher. */
enum CreationAction implements PrivilegedAction<Dispatcher> {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "Exception should not be rethrown but trigger a fallback") public Dispatcher run() { try { Class<?> executableType = Class.forName("java.lang.reflect.Executable"); Class<?> parameterType = Class.forName("java.lang.reflect.Parameter"); return new Dispatcher.ForJava8CapableVm(executableType.getMethod("getParameters"), parameterType.getMethod("getName"), parameterType.getMethod("isNamePresent"), parameterType.getMethod("getModifiers")); } catch (Exception ignored) { return Dispatcher.ForLegacyVm.INSTANCE; } } }
A dispatcher for VMs that support the java.lang.reflect.Parameter API for Java 8+.
/** * A dispatcher for VMs that support the {@code java.lang.reflect.Parameter} API for Java 8+. */
@HashCodeAndEqualsPlugin.Enhance class ForJava8CapableVm implements Dispatcher {
An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call.
/** * An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call. */
private static final Object[] NO_ARGUMENTS = new Object[0];
A reference to java.lang.reflect.Executable#getParameters.
/** * A reference to {@code java.lang.reflect.Executable#getParameters}. */
private final Method getParameters;
A reference to java.lang.reflect.Parameter#getName.
/** * A reference to {@code java.lang.reflect.Parameter#getName}. */
private final Method getName;
A reference to java.lang.reflect.Parameter#isNamePresent.
/** * A reference to {@code java.lang.reflect.Parameter#isNamePresent}. */
private final Method isNamePresent;
A reference to java.lang.reflect.Parameter#getModifiers.
/** * A reference to {@code java.lang.reflect.Parameter#getModifiers}. */
private final Method getModifiers;
Creates a new dispatcher for a modern VM.
Params:
  • getParameters – A reference to java.lang.reflect.Executable#getTypeArguments.
  • getName – A reference to java.lang.reflect.Parameter#getName.
  • isNamePresent – A reference to java.lang.reflect.Parameter#isNamePresent.
  • getModifiers – A reference to java.lang.reflect.Parameter#getModifiers.
/** * Creates a new dispatcher for a modern VM. * * @param getParameters A reference to {@code java.lang.reflect.Executable#getTypeArguments}. * @param getName A reference to {@code java.lang.reflect.Parameter#getName}. * @param isNamePresent A reference to {@code java.lang.reflect.Parameter#isNamePresent}. * @param getModifiers A reference to {@code java.lang.reflect.Parameter#getModifiers}. */
protected ForJava8CapableVm(Method getParameters, Method getName, Method isNamePresent, Method getModifiers) { this.getParameters = getParameters; this.getName = getName; this.isNamePresent = isNamePresent; this.getModifiers = getModifiers; }
{@inheritDoc}
/** * {@inheritDoc} */
public int getModifiers(AccessibleObject executable, int index) { try { return (Integer) getModifiers.invoke(getParameter(executable, index), NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.reflect.Parameter#getModifiers", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.reflect.Parameter#getModifiers", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isNamePresent(AccessibleObject executable, int index) { try { return (Boolean) isNamePresent.invoke(getParameter(executable, index), NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.reflect.Parameter#isNamePresent", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.reflect.Parameter#isNamePresent", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public String getName(AccessibleObject executable, int index) { try { return (String) getName.invoke(getParameter(executable, index), NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.reflect.Parameter#getName", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.reflect.Parameter#getName", exception.getCause()); } }
Returns the java.lang.reflect.Parameter of an executable at a given index.
Params:
  • executable – The executable for which a parameter should be read.
  • index – The index of the parameter.
Returns:The parameter for the given index.
/** * Returns the {@code java.lang.reflect.Parameter} of an executable at a given index. * * @param executable The executable for which a parameter should be read. * @param index The index of the parameter. * @return The parameter for the given index. */
private Object getParameter(AccessibleObject executable, int index) { try { return Array.get(getParameters.invoke(executable, NO_ARGUMENTS), index); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.reflect.Executable#getParameters", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.reflect.Executable#getParameters", exception.getCause()); } } }
A dispatcher for a legacy VM that does not know the java.lang.reflect.Parameter type that only throws exceptions on any property extraction.
/** * A dispatcher for a legacy VM that does not know the {@code java.lang.reflect.Parameter} type that only throws * exceptions on any property extraction. */
enum ForLegacyVm implements Dispatcher {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public int getModifiers(AccessibleObject executable, int index) { throw new UnsupportedOperationException("Cannot dispatch method for java.lang.reflect.Parameter"); }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isNamePresent(AccessibleObject executable, int index) { throw new UnsupportedOperationException("Cannot dispatch method for java.lang.reflect.Parameter"); }
{@inheritDoc}
/** * {@inheritDoc} */
public String getName(AccessibleObject executable, int index) { throw new UnsupportedOperationException("Cannot dispatch method for java.lang.reflect.Parameter"); } } }
A description of a loaded Method parameter for a modern VM.
/** * A description of a loaded {@link Method} parameter for a modern VM. */
protected static class OfMethod extends ForLoadedParameter<Method> {
Creates a new description for a loaded method.
Params:
  • method – The method for which a parameter is represented.
  • index – The index of the parameter.
  • parameterAnnotationSource – The parameter annotation source to query.
/** * Creates a new description for a loaded method. * * @param method The method for which a parameter is represented. * @param index The index of the parameter. * @param parameterAnnotationSource The parameter annotation source to query. */
protected OfMethod(Method method, int index, ParameterAnnotationSource parameterAnnotationSource) { super(method, index, parameterAnnotationSource); }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs") public MethodDescription.InDefinedShape getDeclaringMethod() { return new MethodDescription.ForLoadedMethod(executable); }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs") public TypeDescription.Generic getType() { if (TypeDescription.AbstractBase.RAW_TYPES) { return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(executable.getParameterTypes()[index]); } return new TypeDescription.Generic.LazyProjection.OfMethodParameter(executable, index, executable.getParameterTypes()); }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs") public AnnotationList getDeclaredAnnotations() { return new AnnotationList.ForLoadedAnnotations(parameterAnnotationSource.getParameterAnnotations()[index]); } }
A description of a loaded Constructor parameter for a modern VM.
/** * A description of a loaded {@link Constructor} parameter for a modern VM. */
protected static class OfConstructor extends ForLoadedParameter<Constructor<?>> {
Creates a new description for a loaded constructor.
Params:
  • constructor – The constructor for which a parameter is represented.
  • index – The index of the parameter.
  • parameterAnnotationSource – The parameter annotation source to query.
/** * Creates a new description for a loaded constructor. * * @param constructor The constructor for which a parameter is represented. * @param index The index of the parameter. * @param parameterAnnotationSource The parameter annotation source to query. */
protected OfConstructor(Constructor<?> constructor, int index, ParameterAnnotationSource parameterAnnotationSource) { super(constructor, index, parameterAnnotationSource); }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs") public MethodDescription.InDefinedShape getDeclaringMethod() { return new MethodDescription.ForLoadedConstructor(executable); }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs") public TypeDescription.Generic getType() { if (TypeDescription.AbstractBase.RAW_TYPES) { return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(executable.getParameterTypes()[index]); } return new TypeDescription.Generic.LazyProjection.OfConstructorParameter(executable, index, executable.getParameterTypes()); }
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST", justification = "The implicit field type casting is not understood by Findbugs") public AnnotationList getDeclaredAnnotations() { Annotation[][] annotation = parameterAnnotationSource.getParameterAnnotations(); MethodDescription.InDefinedShape declaringMethod = getDeclaringMethod(); if (annotation.length != declaringMethod.getParameters().size() && declaringMethod.getDeclaringType().isInnerClass()) { return index == 0 ? new AnnotationList.Empty() : new AnnotationList.ForLoadedAnnotations(annotation[index - 1]); } else { return new AnnotationList.ForLoadedAnnotations(annotation[index]); } } }
Description of a loaded method's parameter on a virtual machine where java.lang.reflect.Parameter is not available.
/** * Description of a loaded method's parameter on a virtual machine where {@code java.lang.reflect.Parameter} * is not available. */
protected static class OfLegacyVmMethod extends InDefinedShape.AbstractBase {
The method that declares this parameter.
/** * The method that declares this parameter. */
private final Method method;
The index of this parameter.
/** * The index of this parameter. */
private final int index;
The type erasures of the represented method.
/** * The type erasures of the represented method. */
private final Class<?>[] parameterType;
The parameter annotation source to query.
/** * The parameter annotation source to query. */
private final ParameterAnnotationSource parameterAnnotationSource;
Creates a legacy representation of a method's parameter.
Params:
  • method – The method that declares this parameter.
  • index – The index of this parameter.
  • parameterType – The type erasures of the represented method.
  • parameterAnnotationSource – The parameter annotation source to query.
/** * Creates a legacy representation of a method's parameter. * * @param method The method that declares this parameter. * @param index The index of this parameter. * @param parameterType The type erasures of the represented method. * @param parameterAnnotationSource The parameter annotation source to query. */
protected OfLegacyVmMethod(Method method, int index, Class<?>[] parameterType, ParameterAnnotationSource parameterAnnotationSource) { this.method = method; this.index = index; this.parameterType = parameterType; this.parameterAnnotationSource = parameterAnnotationSource; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription.Generic getType() { if (TypeDescription.AbstractBase.RAW_TYPES) { return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(parameterType[index]); } return new TypeDescription.Generic.LazyProjection.OfMethodParameter(method, index, parameterType); }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodDescription.InDefinedShape getDeclaringMethod() { return new MethodDescription.ForLoadedMethod(method); }
{@inheritDoc}
/** * {@inheritDoc} */
public int getIndex() { return index; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isNamed() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean hasModifiers() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
public AnnotationList getDeclaredAnnotations() { return new AnnotationList.ForLoadedAnnotations(parameterAnnotationSource.getParameterAnnotations()[index]); } }
Description of a loaded constructor's parameter on a virtual machine where java.lang.reflect.Parameter is not available.
/** * Description of a loaded constructor's parameter on a virtual machine where {@code java.lang.reflect.Parameter} * is not available. */
protected static class OfLegacyVmConstructor extends InDefinedShape.AbstractBase {
The method that declares this parameter.
/** * The method that declares this parameter. */
private final Constructor<?> constructor;
The index of this parameter.
/** * The index of this parameter. */
private final int index;
The type erasures of the represented method.
/** * The type erasures of the represented method. */
private final Class<?>[] parameterType;
The parameter annotation source to query.
/** * The parameter annotation source to query. */
private final ParameterAnnotationSource parameterAnnotationSource;
Creates a legacy representation of a method's parameter.
Params:
  • constructor – The constructor that declares this parameter.
  • index – The index of this parameter.
  • parameterType – The type erasures of the represented method.
  • parameterAnnotationSource – The parameter annotation source to query.
/** * Creates a legacy representation of a method's parameter. * * @param constructor The constructor that declares this parameter. * @param index The index of this parameter. * @param parameterType The type erasures of the represented method. * @param parameterAnnotationSource The parameter annotation source to query. */
protected OfLegacyVmConstructor(Constructor<?> constructor, int index, Class<?>[] parameterType, ParameterAnnotationSource parameterAnnotationSource) { this.constructor = constructor; this.index = index; this.parameterType = parameterType; this.parameterAnnotationSource = parameterAnnotationSource; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription.Generic getType() { if (TypeDescription.AbstractBase.RAW_TYPES) { return TypeDescription.Generic.OfNonGenericType.ForLoadedType.of(parameterType[index]); } return new TypeDescription.Generic.LazyProjection.OfConstructorParameter(constructor, index, parameterType); }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodDescription.InDefinedShape getDeclaringMethod() { return new MethodDescription.ForLoadedConstructor(constructor); }
{@inheritDoc}
/** * {@inheritDoc} */
public int getIndex() { return index; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isNamed() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean hasModifiers() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
public AnnotationList getDeclaredAnnotations() { MethodDescription.InDefinedShape declaringMethod = getDeclaringMethod(); Annotation[][] parameterAnnotation = parameterAnnotationSource.getParameterAnnotations(); if (parameterAnnotation.length != declaringMethod.getParameters().size() && declaringMethod.getDeclaringType().isInnerClass()) { return index == 0 ? new AnnotationList.Empty() : new AnnotationList.ForLoadedAnnotations(parameterAnnotation[index - 1]); } else { return new AnnotationList.ForLoadedAnnotations(parameterAnnotation[index]); } } } }
A latent description of a parameter that is not attached to a method or constructor.
/** * A latent description of a parameter that is not attached to a method or constructor. */
class Latent extends InDefinedShape.AbstractBase {
The method that is declaring the parameter.
/** * The method that is declaring the parameter. */
private final MethodDescription.InDefinedShape declaringMethod;
The type of the parameter.
/** * The type of the parameter. */
private final TypeDescription.Generic parameterType;
The annotations of the parameter.
/** * The annotations of the parameter. */
private final List<? extends AnnotationDescription> declaredAnnotations;
The name of the parameter or null if no name is explicitly defined.
/** * The name of the parameter or {@code null} if no name is explicitly defined. */
private final String name;
The modifiers of the parameter or null if no modifiers are explicitly defined.
/** * The modifiers of the parameter or {@code null} if no modifiers are explicitly defined. */
private final Integer modifiers;
The index of the parameter.
/** * The index of the parameter. */
private final int index;
The parameter's offset in the local method variables array.
/** * The parameter's offset in the local method variables array. */
private final int offset;
Creates a latent parameter description. All provided types are attached to this instance before they are returned.
Params:
  • declaringMethod – The method that is declaring the parameter.
  • token – The token describing the shape of the parameter.
  • index – The index of the parameter.
  • offset – The parameter's offset in the local method variables array.
/** * Creates a latent parameter description. All provided types are attached to this instance before they are returned. * * @param declaringMethod The method that is declaring the parameter. * @param token The token describing the shape of the parameter. * @param index The index of the parameter. * @param offset The parameter's offset in the local method variables array. */
public Latent(MethodDescription.InDefinedShape declaringMethod, Token token, int index, int offset) { this(declaringMethod, token.getType(), token.getAnnotations(), token.getName(), token.getModifiers(), index, offset); }
Creates a new latent parameter descriptions for a parameter without explicit meta data or annotations.
Params:
  • declaringMethod – The method declaring this parameter.
  • parameterType – The type of the parameter.
  • index – The index of the parameter.
  • offset – The offset of the parameter.
/** * Creates a new latent parameter descriptions for a parameter without explicit meta data or annotations. * * @param declaringMethod The method declaring this parameter. * @param parameterType The type of the parameter. * @param index The index of the parameter. * @param offset The offset of the parameter. */
public Latent(MethodDescription.InDefinedShape declaringMethod, TypeDescription.Generic parameterType, int index, int offset) { this(declaringMethod, parameterType, Collections.<AnnotationDescription>emptyList(), Token.NO_NAME, Token.NO_MODIFIERS, index, offset); }
Creates a latent parameter description. All provided types are attached to this instance before they are returned.
Params:
  • declaringMethod – The method that is declaring the parameter.
  • parameterType – The parameter's type.
  • declaredAnnotations – The annotations of the parameter.
  • name – The name of the parameter or null if no name is explicitly defined.
  • modifiers – The modifiers of the parameter or null if no modifiers are explicitly defined.
  • index – The index of the parameter.
  • offset – The parameter's offset in the local method variables array.
/** * Creates a latent parameter description. All provided types are attached to this instance before they are returned. * * @param declaringMethod The method that is declaring the parameter. * @param parameterType The parameter's type. * @param declaredAnnotations The annotations of the parameter. * @param name The name of the parameter or {@code null} if no name is explicitly defined. * @param modifiers The modifiers of the parameter or {@code null} if no modifiers are explicitly defined. * @param index The index of the parameter. * @param offset The parameter's offset in the local method variables array. */
public Latent(MethodDescription.InDefinedShape declaringMethod, TypeDescription.Generic parameterType, List<? extends AnnotationDescription> declaredAnnotations, String name, Integer modifiers, int index, int offset) { this.declaringMethod = declaringMethod; this.parameterType = parameterType; this.declaredAnnotations = declaredAnnotations; this.name = name; this.modifiers = modifiers; this.index = index; this.offset = offset; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription.Generic getType() { return parameterType.accept(TypeDescription.Generic.Visitor.Substitutor.ForAttachment.of(this)); }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodDescription.InDefinedShape getDeclaringMethod() { return declaringMethod; }
{@inheritDoc}
/** * {@inheritDoc} */
public int getIndex() { return index; }
{@inheritDoc}
/** * {@inheritDoc} */
public int getOffset() { return offset; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isNamed() { return name != null; }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean hasModifiers() { return modifiers != null; }
{@inheritDoc}
/** * {@inheritDoc} */
public String getName() { return isNamed() ? name : super.getName(); }
{@inheritDoc}
/** * {@inheritDoc} */
public int getModifiers() { return hasModifiers() ? modifiers : super.getModifiers(); }
{@inheritDoc}
/** * {@inheritDoc} */
public AnnotationList getDeclaredAnnotations() { return new AnnotationList.Explicit(declaredAnnotations); } }

A parameter description that represents a given parameter but with a substituted parameter type.

Note: The supplied visitor must assure to not substitute

/** * <p> * A parameter description that represents a given parameter but with a substituted parameter type. * </p> * <p> * <b>Note</b>: The supplied visitor must assure to not substitute * </p> */
class TypeSubstituting extends AbstractBase implements InGenericShape {
The method that declares this type-substituted parameter.
/** * The method that declares this type-substituted parameter. */
private final MethodDescription.InGenericShape declaringMethod;
The represented parameter.
/** * The represented parameter. */
private final ParameterDescription parameterDescription;
A visitor that is applied to the parameter type.
/** * A visitor that is applied to the parameter type. */
private final TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor;
Creates a new type substituting parameter.
Params:
  • declaringMethod – The method that declares this type-substituted parameter.
  • parameterDescription – The represented parameter.
  • visitor – A visitor that is applied to the parameter type.
/** * Creates a new type substituting parameter. * * @param declaringMethod The method that declares this type-substituted parameter. * @param parameterDescription The represented parameter. * @param visitor A visitor that is applied to the parameter type. */
public TypeSubstituting(MethodDescription.InGenericShape declaringMethod, ParameterDescription parameterDescription, TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) { this.declaringMethod = declaringMethod; this.parameterDescription = parameterDescription; this.visitor = visitor; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription.Generic getType() { return parameterDescription.getType().accept(visitor); }
{@inheritDoc}
/** * {@inheritDoc} */
public MethodDescription.InGenericShape getDeclaringMethod() { return declaringMethod; }
{@inheritDoc}
/** * {@inheritDoc} */
public int getIndex() { return parameterDescription.getIndex(); }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean isNamed() { return parameterDescription.isNamed(); }
{@inheritDoc}
/** * {@inheritDoc} */
public boolean hasModifiers() { return parameterDescription.hasModifiers(); }
{@inheritDoc}
/** * {@inheritDoc} */
public int getOffset() { return parameterDescription.getOffset(); }
{@inheritDoc}
/** * {@inheritDoc} */
public String getName() { return parameterDescription.getName(); }
{@inheritDoc}
/** * {@inheritDoc} */
public int getModifiers() { return parameterDescription.getModifiers(); }
{@inheritDoc}
/** * {@inheritDoc} */
public AnnotationList getDeclaredAnnotations() { return parameterDescription.getDeclaredAnnotations(); }
{@inheritDoc}
/** * {@inheritDoc} */
public InDefinedShape asDefined() { return parameterDescription.asDefined(); } }
A token representing a parameter's properties detached from a type.
/** * A token representing a parameter's properties detached from a type. */
class Token implements ByteCodeElement.Token<Token> {
Indicator for a method parameter without an explicit name.
/** * Indicator for a method parameter without an explicit name. */
public static final String NO_NAME = null;
Indicator for a method parameter without explicit modifiers.
/** * Indicator for a method parameter without explicit modifiers. */
public static final Integer NO_MODIFIERS = null;
The type of the represented parameter.
/** * The type of the represented parameter. */
private final TypeDescription.Generic type;
A list of parameter annotations.
/** * A list of parameter annotations. */
private final List<? extends AnnotationDescription> annotations;
The name of the parameter or null if no explicit name is defined.
/** * The name of the parameter or {@code null} if no explicit name is defined. */
private final String name;
The modifiers of the parameter or null if no explicit modifiers is defined.
/** * The modifiers of the parameter or {@code null} if no explicit modifiers is defined. */
private final Integer modifiers;
Creates a new parameter token without an explicit name, an explicit modifier or annotations. The parameter type must be represented in its detached format.
Params:
  • type – The type of the represented parameter.
/** * Creates a new parameter token without an explicit name, an explicit modifier or annotations. * The parameter type must be represented in its detached format. * * @param type The type of the represented parameter. */
public Token(TypeDescription.Generic type) { this(type, Collections.<AnnotationDescription>emptyList()); }
Creates a new parameter token without an explicit name or an explicit modifier. The parameter type must be represented in its detached format.
Params:
  • type – The type of the represented parameter.
  • annotations – The annotations of the parameter.
/** * Creates a new parameter token without an explicit name or an explicit modifier. The parameter type must be represented in its detached format. * * @param type The type of the represented parameter. * @param annotations The annotations of the parameter. */
public Token(TypeDescription.Generic type, List<? extends AnnotationDescription> annotations) { this(type, annotations, NO_NAME, NO_MODIFIERS); }
Creates a parameter token without annotations. The parameter type must be represented in its detached format.
Params:
  • type – The type of the represented parameter.
  • name – The name of the parameter or null if no explicit name is defined.
  • modifiers – The modifiers of the parameter or null if no explicit modifiers is defined.
/** * Creates a parameter token without annotations. The parameter type must be represented in its detached format. * * @param type The type of the represented parameter. * @param name The name of the parameter or {@code null} if no explicit name is defined. * @param modifiers The modifiers of the parameter or {@code null} if no explicit modifiers is defined. */
public Token(TypeDescription.Generic type, String name, Integer modifiers) { this(type, Collections.<AnnotationDescription>emptyList(), name, modifiers); }
Creates a new parameter token. The parameter type must be represented in its detached format.
Params:
  • type – The type of the represented parameter.
  • annotations – The annotations of the parameter.
  • name – The name of the parameter or null if no explicit name is defined.
  • modifiers – The modifiers of the parameter or null if no explicit modifiers is defined.
/** * Creates a new parameter token. The parameter type must be represented in its detached format. * * @param type The type of the represented parameter. * @param annotations The annotations of the parameter. * @param name The name of the parameter or {@code null} if no explicit name is defined. * @param modifiers The modifiers of the parameter or {@code null} if no explicit modifiers is defined. */
public Token(TypeDescription.Generic type, List<? extends AnnotationDescription> annotations, String name, Integer modifiers) { this.type = type; this.annotations = annotations; this.name = name; this.modifiers = modifiers; }
Returns the type of the represented method parameter.
Returns:The type of the represented method parameter.
/** * Returns the type of the represented method parameter. * * @return The type of the represented method parameter. */
public TypeDescription.Generic getType() { return type; }
Returns the annotations of the represented method parameter.
Returns:The annotations of the represented method parameter.
/** * Returns the annotations of the represented method parameter. * * @return The annotations of the represented method parameter. */
public AnnotationList getAnnotations() { return new AnnotationList.Explicit(annotations); }
Returns the name of the represented method parameter.
Returns:The name of the parameter or null if no explicit name is defined.
/** * Returns the name of the represented method parameter. * * @return The name of the parameter or {@code null} if no explicit name is defined. */
public String getName() { return name; }
Returns the modifiers of the represented method parameter.
Returns:The modifiers of the parameter or null if no explicit modifiers is defined.
/** * Returns the modifiers of the represented method parameter. * * @return The modifiers of the parameter or {@code null} if no explicit modifiers is defined. */
public Integer getModifiers() { return modifiers; }
{@inheritDoc}
/** * {@inheritDoc} */
public Token accept(TypeDescription.Generic.Visitor<? extends TypeDescription.Generic> visitor) { return new Token(type.accept(visitor), annotations, name, modifiers); } @Override @CachedReturnPlugin.Enhance("hashCode") public int hashCode() { int result = type.hashCode(); result = 31 * result + annotations.hashCode(); result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (modifiers != null ? modifiers.hashCode() : 0); return result; } @Override public boolean equals(Object other) { if (this == other) { return true; } else if (!(other instanceof Token)) { return false; } Token token = (Token) other; return type.equals(token.type) && annotations.equals(token.annotations) && (name != null ? name.equals(token.name) : token.name == null) && (modifiers != null ? modifiers.equals(token.modifiers) : token.modifiers == null); } @Override public String toString() { return "ParameterDescription.Token{" + "type=" + type + ", annotations=" + annotations + ", name='" + name + '\'' + ", modifiers=" + modifiers + '}'; }
A list of types represented as a list of parameter tokens.
/** * A list of types represented as a list of parameter tokens. */
public static class TypeList extends AbstractList<Token> {
The list of types to represent as parameter tokens.
/** * The list of types to represent as parameter tokens. */
private final List<? extends TypeDefinition> typeDescriptions;
Creates a new list of types that represent parameters.
Params:
  • typeDescriptions – The types to represent.
/** * Creates a new list of types that represent parameters. * * @param typeDescriptions The types to represent. */
public TypeList(List<? extends TypeDefinition> typeDescriptions) { this.typeDescriptions = typeDescriptions; }
{@inheritDoc}
/** * {@inheritDoc} */
public Token get(int index) { return new Token(typeDescriptions.get(index).asGenericType()); }
{@inheritDoc}
/** * {@inheritDoc} */
public int size() { return typeDescriptions.size(); } } } }