
net.bytebuddy.description.method.ParameterList Maven / Gradle / Ivy
package net.bytebuddy.description.method;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeList;
import net.bytebuddy.implementation.bytecode.StackSize;
import net.bytebuddy.matcher.FilterableList;
import net.bytebuddy.utility.JavaMethod;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Represents a list of parameters of a method or a constructor.
*/
public interface ParameterList extends FilterableList {
/**
* Transforms the list of parameters into a list of type descriptions.
*
* @return A list of type descriptions.
*/
TypeList asTypeList();
/**
* Checks if all parameters in this list define both an explicit name and an explicit modifier.
*
* @return {@code true} if all parameters in this list define both an explicit name and an explicit modifier.
*/
boolean hasExplicitMetaData();
/**
* An base implementation for a {@link ParameterList}.
*/
abstract class AbstractBase extends FilterableList.AbstractBase implements ParameterList {
@Override
public boolean hasExplicitMetaData() {
for (ParameterDescription parameterDescription : this) {
if (!parameterDescription.isNamed() || !parameterDescription.hasModifiers()) {
return false;
}
}
return true;
}
}
/**
* Represents a list of parameters for an executable, i.e. a {@link java.lang.reflect.Method} or
* {@link java.lang.reflect.Constructor}.
*/
class ForLoadedExecutable extends AbstractBase {
/**
* Represents the {@code java.lang.reflect.Executable}'s {@code getParameters} method.
*/
private static final JavaMethod GET_PARAMETERS;
/*
* Initializes the {@link net.bytebuddy.utility.JavaMethod} instances of this class dependant on
* whether they are available.
*/
static {
JavaMethod getParameters;
try {
Class> executableType = Class.forName("java.lang.reflect.Executable");
getParameters = new JavaMethod.ForLoadedMethod(executableType.getDeclaredMethod("getParameters"));
} catch (Exception ignored) {
getParameters = JavaMethod.ForUnavailableMethod.INSTANCE;
}
GET_PARAMETERS = getParameters;
}
/**
* An array of the represented {@code java.lang.reflect.Parameter} instances.
*/
private final Object[] parameter;
/**
* Creates a list representing a method's or a constructor's parameters.
*
* @param parameter The {@code java.lang.reflect.Parameter}-typed parameters to represent.
*/
protected ForLoadedExecutable(Object[] parameter) {
this.parameter = parameter;
}
/**
* Creates a parameter list for a loaded method.
*
* @param method The method to represent.
* @return A list of parameters for this method.
*/
public static ParameterList of(Method method) {
return GET_PARAMETERS.isInvokable()
? new ForLoadedExecutable((Object[]) GET_PARAMETERS.invoke(method))
: new OfLegacyVmMethod(method);
}
/**
* Creates a parameter list for a loaded constructor.
*
* @param constructor The constructor to represent.
* @return A list of parameters for this constructor.
*/
public static ParameterList of(Constructor> constructor) {
return GET_PARAMETERS.isInvokable()
? new ForLoadedExecutable((Object[]) GET_PARAMETERS.invoke(constructor))
: new OfLegacyVmConstructor(constructor);
}
@Override
public ParameterDescription get(int index) {
return new ParameterDescription.ForLoadedParameter(parameter[index], index);
}
@Override
public int size() {
return parameter.length;
}
@Override
public TypeList asTypeList() {
List typeDescriptions = new ArrayList(parameter.length);
for (Object aParameter : parameter) {
Class> type = (Class>) ParameterDescription.ForLoadedParameter.GET_TYPE.invoke(aParameter);
typeDescriptions.add(new TypeDescription.ForLoadedType(type));
}
return new TypeList.Explicit(typeDescriptions);
}
@Override
protected ParameterList wrap(List values) {
return new Explicit(values);
}
/**
* Represents a list of method parameters on virtual machines where the {@code java.lang.reflect.Parameter}
* type is not available.
*/
protected static class OfLegacyVmMethod extends ParameterList.AbstractBase {
/**
* The represented method.
*/
private final Method method;
/**
* An array of this method's parameter types.
*/
private final Class>[] parameterType;
/**
* An array of all parameter annotations of the represented method.
*/
private final Annotation[][] parameterAnnotation;
/**
* Creates a legacy representation of a method's parameters.
*
* @param method The method to represent.
*/
protected OfLegacyVmMethod(Method method) {
this.method = method;
this.parameterType = method.getParameterTypes();
this.parameterAnnotation = method.getParameterAnnotations();
}
@Override
protected ParameterList wrap(List values) {
return new Explicit(values);
}
@Override
public ParameterDescription get(int index) {
return new ParameterDescription.ForLoadedParameter.OfLegacyVmMethod(method, index, parameterType[index], parameterAnnotation[index]);
}
@Override
public int size() {
return parameterType.length;
}
@Override
public TypeList asTypeList() {
return new TypeList.ForLoadedType(parameterType);
}
}
/**
* Represents a list of constructor parameters on virtual machines where the {@code java.lang.reflect.Parameter}
* type is not available.
*/
protected static class OfLegacyVmConstructor extends ParameterList.AbstractBase {
/**
* The represented constructor.
*/
private final Constructor> constructor;
/**
* An array of this method's parameter types.
*/
private final Class>[] parameterType;
/**
* An array of all parameter annotations of the represented method.
*/
private final Annotation[][] parameterAnnotation;
/**
* Creates a legacy representation of a constructor's parameters.
*
* @param constructor The constructor to represent.
*/
public OfLegacyVmConstructor(Constructor> constructor) {
this.constructor = constructor;
this.parameterType = constructor.getParameterTypes();
this.parameterAnnotation = constructor.getParameterAnnotations();
}
@Override
protected ParameterList wrap(List values) {
return new Explicit(values);
}
@Override
public ParameterDescription get(int index) {
return new ParameterDescription.ForLoadedParameter.OfLegacyVmConstructor(constructor, index, parameterType[index], parameterAnnotation[index]);
}
@Override
public int size() {
return parameterType.length;
}
@Override
public TypeList asTypeList() {
return new TypeList.ForLoadedType(parameterType);
}
}
}
/**
* A list of explicitly provided parameter descriptions.
*/
class Explicit extends AbstractBase {
/**
* The list of parameter descriptions that are represented by this list.
*/
private final List extends ParameterDescription> parameterDescriptions;
/**
* Creates a new list of explicit parameter descriptions.
*
* @param parameterDescriptions The list of parameter descriptions that are represented by this list.
*/
public Explicit(List extends ParameterDescription> parameterDescriptions) {
this.parameterDescriptions = Collections.unmodifiableList(parameterDescriptions);
}
/**
* Creates a list of method parameters from a list of type descriptions.
*
* @param declaringMethod The method for which this latent list should be created.
* @param parameterTypes A list of the parameter types.
* @return A list describing these parameters.
*/
public static ParameterList latent(MethodDescription declaringMethod, List extends TypeDescription> parameterTypes) {
List parameterDescriptions = new ArrayList(parameterTypes.size());
int index = 0, offset = declaringMethod.isStatic()
? StackSize.ZERO.getSize()
: StackSize.SINGLE.getSize();
for (TypeDescription parameterType : parameterTypes) {
parameterDescriptions.add(new ParameterDescription.Latent(declaringMethod,
parameterType,
index++,
offset));
offset += parameterType.getStackSize().getSize();
}
return new Explicit(parameterDescriptions);
}
@Override
public ParameterDescription get(int index) {
return parameterDescriptions.get(index);
}
@Override
public int size() {
return parameterDescriptions.size();
}
@Override
public TypeList asTypeList() {
List typeDescriptions = new ArrayList(parameterDescriptions.size());
for (ParameterDescription parameterDescription : parameterDescriptions) {
typeDescriptions.add(parameterDescription.getTypeDescription());
}
return new TypeList.Explicit(typeDescriptions);
}
@Override
protected ParameterList wrap(List values) {
return new Explicit(values);
}
}
/**
* An empty list of parameters.
*/
class Empty extends FilterableList.Empty implements ParameterList {
@Override
public boolean hasExplicitMetaData() {
return true;
}
@Override
public TypeList asTypeList() {
return new TypeList.Empty();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy