Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JDK-8265376: Prepare for javac change to do the member translation as described in SoV #387

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/java.base/share/classes/java/lang/Class.java
Original file line number Diff line number Diff line change
@@ -605,6 +605,7 @@ public Optional<Class<?>> valueType() {
public Optional<Class<?>> referenceType() {
if (isPrimitive()) return Optional.empty();
if (isInterface() || isArray()) return Optional.of(this);
if (!isPrimitiveClass()) return Optional.of(this);

Class<?>[] valRefTypes = getPrimitiveTypes();
return valRefTypes.length == 2 ? Optional.of(valRefTypes[1]) : Optional.empty();
4 changes: 3 additions & 1 deletion test/jdk/valhalla/valuetypes/QTypeDescriptorTest.java
Original file line number Diff line number Diff line change
@@ -139,7 +139,9 @@ static Object[][] descriptors() {
@Test(dataProvider = "descriptors")
public static void testDescriptors(Class<?> defc, String name, Class<?>[] params, boolean found) throws Exception {
try {
defc.getDeclaredMethod(name, params);
// TODO: methods are in the reference projection
Class<?> declaringClass = defc /* defc.referenceType().get() */;
declaringClass.getDeclaredMethod(name, params);
if (!found) throw new AssertionError("Expected NoSuchMethodException");
} catch (NoSuchMethodException e) {
if (found) throw e;
121 changes: 104 additions & 17 deletions test/jdk/valhalla/valuetypes/Reflection.java
Original file line number Diff line number Diff line change
@@ -29,10 +29,12 @@
* @run testng/othervm --enable-preview Reflection
*/

import java.lang.constant.ClassDesc;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.testng.annotations.Test;
import static org.testng.Assert.*;
@@ -52,27 +54,30 @@ public static void testPointClass() throws Exception {
test.newInstance();
test.constructor();
test.accessFieldX(o.x);
test.staticField();
test.checkStaticField("STATIC_FIELD", Object.class);
// TODO: static field is in the reference projection
Class<?> declaringClass = Point.class;
test.testSetAccessible(declaringClass.getDeclaredField("STATIC_FIELD"));
}

@Test
public static void testLineClass() throws Exception {
Line l = Line.makeLine(10, 20, 30, 40);
Reflection test = new Reflection(Line.class, "Line", l);
test.checkField("public final Point Line.p1", "p1", Point.class);
test.checkField("public final Point Line.p2", "p2", Point.class);
test.checkMethod("public Point Line.p1()", "p1", Point.class);
test.checkMethod("public Point Line.p2()", "p2", Point.class);
test.checkInstanceField("p1", Point.class);
test.checkInstanceField("p2", Point.class);
test.checkInstanceMethod("p1", Point.class);
test.checkInstanceMethod("p2", Point.class);
}

@Test
public static void testNonFlattenValue() throws Exception {
NonFlattenValue nfv = NonFlattenValue.make(10, 20);
Reflection test = new Reflection(NonFlattenValue.class, "NonFlattenValue", nfv);
test.checkField("final Point$ref NonFlattenValue.nfp", "nfp", Point.ref.class);
test.checkMethod("public Point NonFlattenValue.pointValue()", "pointValue", Point.class);
test.checkMethod("public Point$ref NonFlattenValue.point()", "point", Point.ref.class);
test.checkMethod("public boolean NonFlattenValue.has(Point,Point$ref)", "has", boolean.class, Point.class, Point.ref.class);
test.checkInstanceField("nfp", Point.ref.class);
test.checkInstanceMethod("pointValue", Point.class);
test.checkInstanceMethod("point", Point.ref.class);
test.checkInstanceMethod("has", boolean.class, Point.class, Point.ref.class);
}

/*
@@ -198,20 +203,102 @@ void constructor() throws Exception {
assertEquals(o.getClass(), c);
}

void staticField() throws Exception {
Field f = c.getDeclaredField("STATIC_FIELD");
void testSetAccessible(Field f) throws Exception {
f.trySetAccessible();
assertTrue(f.isAccessible());
}

void checkField(String source, String name, Class<?> type) throws Exception {
/*
* Fields are in the value projection
*/
void checkInstanceField(String name, Class<?> type) throws Exception {
Field f = c.getDeclaredField(name);
assertEquals(f.getType(), type);
assertEquals(f.toString(), source);
assertTrue(f.getType() == type);
checkToString(f);
}

/*
* Static members are in the reference projection
*/
void checkStaticField(String name, Class<?> type) throws Exception {
Class<?> declaringClass = c;
// TODO: methods are in the reference projection
// Class<?> declaringClass = c.referenceType().get();
Field f = declaringClass.getDeclaredField(name);
assertTrue(f.getType() == type);
checkToString(f);
}

/*
* Methods are in the reference projection
*/
void checkInstanceMethod(String name, Class<?> returnType, Class<?>... params) throws Exception {
Class<?> declaringClass = c;
// TODO: methods are in the reference projection
// Class<?> declaringClass = c.referenceType().get();
Method m = declaringClass.getDeclaredMethod(name, params);
assertTrue(m.getReturnType() == returnType);
checkToString(m);
}

void checkToString(Field f) {
StringBuilder sb = new StringBuilder();
int mods = f.getModifiers();
if (Modifier.isPublic(mods)) {
sb.append("public").append(" ");
}
if (Modifier.isStatic(mods)) {
sb.append("static").append(" ");
}
if (Modifier.isFinal(mods)) {
sb.append("final").append(" ");
}
// instance fields are in the value projection
// whereas static fields are in the reference projection
Class<?> declaringClass = c;
// TODO: static members are in the reference projection
// if (Modifier.isStatic(mods)) {
// declaringClass = c.referenceType().get();
// }
sb.append(displayName(f.getType())).append(" ");
sb.append(declaringClass.getName()).append(".").append(f.getName());
assertEquals(f.toString(), sb.toString());
}

void checkMethod(String source, String name, Class<?> returnType, Class<?>... params) throws Exception {
Method m = c.getDeclaredMethod(name, params);
assertEquals(m.toString(), source);
void checkToString(Method m) {
StringBuilder sb = new StringBuilder();
int mods = m.getModifiers();
if (Modifier.isPublic(mods)) {
sb.append("public").append(" ");
}
if (Modifier.isStatic(mods)) {
sb.append("static").append(" ");
}
if (Modifier.isFinal(mods)) {
sb.append("final").append(" ");
}
sb.append(displayName(m.getReturnType())).append(" ");
// TODO: methods are in the reference projection
// Class<?> declaringClass = c.referenceType().get();
Class<?> declaringClass = c;
sb.append(declaringClass.getName()).append(".").append(m.getName());
sb.append("(");
int count = m.getParameterCount();
for (Class<?> ptype : m.getParameterTypes()) {
sb.append(displayName(ptype));
if (--count > 0) {
sb.append(",");
}
}
sb.append(")");
assertEquals(m.toString(), sb.toString());
}

static String displayName(Class<?> type) {
if (type.isPrimitive()) {
ClassDesc classDesc = type.describeConstable().get();
return classDesc.displayName();
}
return type.getName();
}
}