8306698: Add overloads to MethodTypeDesc::of

Reviewed-by: mchung
This commit is contained in:
Chen Liang 2023-05-23 21:26:25 +00:00 committed by Mandy Chung
parent 6b27dad76e
commit 8ffa264cf0
3 changed files with 53 additions and 38 deletions

View file

@ -36,6 +36,7 @@ import static java.util.Objects.requireNonNull;
class ConstantUtils { class ConstantUtils {
/** an empty constant descriptor */ /** an empty constant descriptor */
public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0]; public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0];
static final ClassDesc[] EMPTY_CLASSDESC = new ClassDesc[0];
static final Constable[] EMPTY_CONSTABLE = new Constable[0]; static final Constable[] EMPTY_CONSTABLE = new Constable[0];
static final int MAX_ARRAY_TYPE_DESC_DIMENSIONS = 255; static final int MAX_ARRAY_TYPE_DESC_DIMENSIONS = 255;

View file

@ -55,6 +55,34 @@ public sealed interface MethodTypeDesc
return MethodTypeDescImpl.ofDescriptor(descriptor); return MethodTypeDescImpl.ofDescriptor(descriptor);
} }
/**
* {@return a {@linkplain MethodTypeDesc} with the given return type and no
* parameter types}
*
* @param returnDesc a {@linkplain ClassDesc} describing the return type
* @throws NullPointerException if {@code returnDesc} is {@code null}
* @since 21
*/
static MethodTypeDesc of(ClassDesc returnDesc) {
return new MethodTypeDescImpl(returnDesc, ConstantUtils.EMPTY_CLASSDESC);
}
/**
* {@return a {@linkplain MethodTypeDesc} given the return type and a list of
* parameter types}
*
* @param returnDesc a {@linkplain ClassDesc} describing the return type
* @param paramDescs a {@linkplain List} of {@linkplain ClassDesc}s
* describing the parameter types
* @throws NullPointerException if any argument or its contents are {@code null}
* @throws IllegalArgumentException if any element of {@code paramDescs} is a
* {@link ClassDesc} for {@code void}
* @since 21
*/
static MethodTypeDesc of(ClassDesc returnDesc, List<ClassDesc> paramDescs) {
return of(returnDesc, paramDescs.toArray(ConstantUtils.EMPTY_CLASSDESC));
}
/** /**
* Returns a {@linkplain MethodTypeDesc} given the return type and parameter * Returns a {@linkplain MethodTypeDesc} given the return type and parameter
* types. * types.

View file

@ -25,6 +25,7 @@ import java.lang.invoke.MethodType;
import java.lang.constant.ClassDesc; import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc; import java.lang.constant.MethodTypeDesc;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -36,6 +37,7 @@ import static java.lang.constant.ConstantDescs.CD_void;
import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.fail; import static org.testng.Assert.fail;
/** /**
@ -52,6 +54,9 @@ public class MethodTypeDescTest extends SymbolicDescTest {
// Tests accessors (rType, pType, pCount, pList, pArray, descriptorString), // Tests accessors (rType, pType, pCount, pList, pArray, descriptorString),
// factories (ofDescriptor, of), equals // factories (ofDescriptor, of), equals
if (r.parameterCount() == 0) {
assertEquals(r, MethodTypeDesc.of(r.returnType()));
}
assertEquals(r, MethodTypeDesc.ofDescriptor(r.descriptorString())); assertEquals(r, MethodTypeDesc.ofDescriptor(r.descriptorString()));
assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterArray())); assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterArray()));
assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterList().toArray(new ClassDesc[0]))); assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterList().toArray(new ClassDesc[0])));
@ -59,6 +64,12 @@ public class MethodTypeDescTest extends SymbolicDescTest {
assertEquals(r, MethodTypeDesc.of(r.returnType(), IntStream.range(0, r.parameterCount()) assertEquals(r, MethodTypeDesc.of(r.returnType(), IntStream.range(0, r.parameterCount())
.mapToObj(r::parameterType) .mapToObj(r::parameterType)
.toArray(ClassDesc[]::new))); .toArray(ClassDesc[]::new)));
assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterList()));
assertEquals(r, MethodTypeDesc.of(r.returnType(), List.copyOf(r.parameterList())));
assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterList().stream().toList()));
assertEquals(r, MethodTypeDesc.of(r.returnType(), IntStream.range(0, r.parameterCount())
.mapToObj(r::parameterType)
.toList()));
} }
private void testMethodTypeDesc(MethodTypeDesc r, MethodType mt) throws ReflectiveOperationException { private void testMethodTypeDesc(MethodTypeDesc r, MethodType mt) throws ReflectiveOperationException {
@ -255,54 +266,29 @@ public class MethodTypeDescTest extends SymbolicDescTest {
} }
public void testBadMethodTypeRefs() { public void testBadMethodTypeRefs() {
// ofDescriptor
List<String> badDescriptors = List.of("()II", "()I;", "(I;)", "(I)", "()L", "(V)V", List<String> badDescriptors = List.of("()II", "()I;", "(I;)", "(I)", "()L", "(V)V",
"(java.lang.String)V", "()[]", "(Ljava/lang/String)V", "(java.lang.String)V", "()[]", "(Ljava/lang/String)V",
"(Ljava.lang.String;)V", "(java/lang/String)V"); "(Ljava.lang.String;)V", "(java/lang/String)V");
for (String d : badDescriptors) { for (String d : badDescriptors) {
try { assertThrows(IllegalArgumentException.class, () -> MethodTypeDesc.ofDescriptor(d));
MethodTypeDesc r = MethodTypeDesc.ofDescriptor(d);
fail(d);
}
catch (IllegalArgumentException e) {
// good
}
} }
assertThrows(NullPointerException.class, () -> MethodTypeDesc.ofDescriptor(null));
// try with null argument // of(ClassDesc)
try { assertThrows(NullPointerException.class, () -> MethodTypeDesc.of(null));
MethodTypeDesc r = MethodTypeDesc.ofDescriptor(null);
fail("should fail with NPE");
} catch (NullPointerException ex) {
// good
}
// of(ClassDesc, ClassDesc...)
assertThrows(NullPointerException.class, () -> MethodTypeDesc.of(CD_int, (ClassDesc[]) null));
assertThrows(NullPointerException.class, () -> MethodTypeDesc.of(CD_int, new ClassDesc[] {null}));
// try with void arguments, this will stress another code path in particular // try with void arguments, this will stress another code path in particular
// ConstantMethodTypeDesc::init // ConstantMethodTypeDesc::init
try { assertThrows(IllegalArgumentException.class, () -> MethodTypeDesc.of(CD_int, CD_void));
MethodTypeDesc r = MethodTypeDesc.of(CD_int, CD_void);
fail("can't reach here");
}
catch (IllegalArgumentException e) {
// good
}
try { // of(ClassDesc, List<ClassDesc>)
MethodTypeDesc r = MethodTypeDesc.of(CD_int, null); assertThrows(NullPointerException.class, () -> MethodTypeDesc.of(CD_int, (List<ClassDesc>) null));
fail("ClassDesc array should not be null"); assertThrows(NullPointerException.class, () -> MethodTypeDesc.of(CD_int, Collections.singletonList(null)));
} assertThrows(IllegalArgumentException.class, () -> MethodTypeDesc.of(CD_int, List.of(CD_void)));
catch (NullPointerException e) {
// good
}
try {
ClassDesc[] paramDescs = new ClassDesc[1];
paramDescs[0] = null;
MethodTypeDesc r = MethodTypeDesc.of(CD_int, paramDescs);
fail("ClassDesc should not be null");
}
catch (NullPointerException e) {
// good
}
} }
} }