|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package java.lang.constant; |
|
|
|
import java.lang.invoke.MethodHandles; |
|
import java.lang.invoke.MethodType; |
|
import java.security.AccessController; |
|
import java.security.PrivilegedAction; |
|
import java.util.Arrays; |
|
import java.util.List; |
|
|
|
import static java.util.Objects.requireNonNull; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
final class MethodTypeDescImpl implements MethodTypeDesc { |
|
private final ClassDesc returnType; |
|
private final ClassDesc[] argTypes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
MethodTypeDescImpl(ClassDesc returnType, ClassDesc[] argTypes) { |
|
this.returnType = requireNonNull(returnType); |
|
this.argTypes = requireNonNull(argTypes); |
|
|
|
for (ClassDesc cr : argTypes) |
|
if (cr.isPrimitive() && cr.descriptorString().equals("V")) |
|
throw new IllegalArgumentException("Void parameters not permitted"); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
static MethodTypeDescImpl ofDescriptor(String descriptor) { |
|
requireNonNull(descriptor); |
|
List<String> types = ConstantUtils.parseMethodDescriptor(descriptor); |
|
ClassDesc[] paramTypes = types.stream().skip(1).map(ClassDesc::ofDescriptor).toArray(ClassDesc[]::new); |
|
return new MethodTypeDescImpl(ClassDesc.ofDescriptor(types.get(0)), paramTypes); |
|
} |
|
|
|
@Override |
|
public ClassDesc returnType() { |
|
return returnType; |
|
} |
|
|
|
@Override |
|
public int parameterCount() { |
|
return argTypes.length; |
|
} |
|
|
|
@Override |
|
public ClassDesc parameterType(int index) { |
|
return argTypes[index]; |
|
} |
|
|
|
@Override |
|
public List<ClassDesc> parameterList() { |
|
return List.of(argTypes); |
|
} |
|
|
|
@Override |
|
public ClassDesc[] parameterArray() { |
|
return argTypes.clone(); |
|
} |
|
|
|
@Override |
|
public MethodTypeDesc changeReturnType(ClassDesc returnType) { |
|
return MethodTypeDesc.of(returnType, argTypes); |
|
} |
|
|
|
@Override |
|
public MethodTypeDesc changeParameterType(int index, ClassDesc paramType) { |
|
ClassDesc[] newArgs = argTypes.clone(); |
|
newArgs[index] = paramType; |
|
return MethodTypeDesc.of(returnType, newArgs); |
|
} |
|
|
|
@Override |
|
public MethodTypeDesc dropParameterTypes(int start, int end) { |
|
if (start < 0 || start >= argTypes.length || end < 0 || end > argTypes.length || start > end) |
|
throw new IndexOutOfBoundsException(); |
|
ClassDesc[] newArgs = new ClassDesc[argTypes.length - (end - start)]; |
|
System.arraycopy(argTypes, 0, newArgs, 0, start); |
|
System.arraycopy(argTypes, end, newArgs, start, argTypes.length - end); |
|
return MethodTypeDesc.of(returnType, newArgs); |
|
} |
|
|
|
@Override |
|
public MethodTypeDesc insertParameterTypes(int pos, ClassDesc... paramTypes) { |
|
if (pos < 0 || pos > argTypes.length) |
|
throw new IndexOutOfBoundsException(pos); |
|
ClassDesc[] newArgs = new ClassDesc[argTypes.length + paramTypes.length]; |
|
System.arraycopy(argTypes, 0, newArgs, 0, pos); |
|
System.arraycopy(paramTypes, 0, newArgs, pos, paramTypes.length); |
|
System.arraycopy(argTypes, pos, newArgs, pos+paramTypes.length, argTypes.length - pos); |
|
return MethodTypeDesc.of(returnType, newArgs); |
|
} |
|
|
|
@Override |
|
public MethodType resolveConstantDesc(MethodHandles.Lookup lookup) throws ReflectiveOperationException { |
|
@SuppressWarnings("removal") |
|
MethodType mtype = AccessController.doPrivileged(new PrivilegedAction<>() { |
|
@Override |
|
public MethodType run() { |
|
return MethodType.fromMethodDescriptorString(descriptorString(), |
|
lookup.lookupClass().getClassLoader()); |
|
} |
|
}); |
|
|
|
|
|
lookup.accessClass(mtype.returnType()); |
|
for (Class<?> paramType: mtype.parameterArray()) { |
|
lookup.accessClass(paramType); |
|
} |
|
return mtype; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public boolean equals(Object o) { |
|
if (this == o) return true; |
|
if (o == null || getClass() != o.getClass()) return false; |
|
|
|
MethodTypeDescImpl constant = (MethodTypeDescImpl) o; |
|
|
|
return returnType.equals(constant.returnType) |
|
&& Arrays.equals(argTypes, constant.argTypes); |
|
} |
|
|
|
@Override |
|
public int hashCode() { |
|
int result = returnType.hashCode(); |
|
result = 31 * result + Arrays.hashCode(argTypes); |
|
return result; |
|
} |
|
|
|
@Override |
|
public String toString() { |
|
return String.format("MethodTypeDesc[%s]", displayDescriptor()); |
|
} |
|
} |