Adding tests for Type parameter, wild card, and class types for generic classes.
authorrtrimana <rtrimana@uci.edu>
Tue, 25 Jun 2019 00:18:33 +0000 (17:18 -0700)
committerrtrimana <rtrimana@uci.edu>
Tue, 25 Jun 2019 00:18:33 +0000 (17:18 -0700)
examples/Reflection.java
src/main/gov/nasa/jpf/vm/Types.java
src/peers/gov/nasa/jpf/vm/JPF_java_lang_reflect_Method.java

index b32715832912b6b30b60dc1e25510a89f5c6cb26..788ef585547341268ab7aee8a4bafa5df9a03d9c 100644 (file)
@@ -63,7 +63,10 @@ public class Reflection {
       for (int i = 0; i < parameters.length; i++) {
          System.out.println(parameters[i]);
       }
-      System.out.println();*/
+      System.out.println();
+      Type returnType = method.getGenericReturnType();
+      System.out.println(returnType);*/
+      
       /*Type superCls = Generic.class.getGenericSuperclass();
       //Type superCls = String.class.getGenericSuperclass();
       System.out.println(superCls);
@@ -73,12 +76,13 @@ public class Reflection {
             System.out.println(interfaces[i]);
         }*/
       
+      
          Method[] methods = Class.class.getMethods();
          Method method = null;
       for(Method mth : methods) {
-        //if (mth.getName().equals("getConstructor")) {
+        if (mth.getName().equals("getConstructor")) {
         //if (mth.getName().equals("isAssignableFrom")) {
-        if (mth.getName().equals("getTypeParameters")) {
+        //if (mth.getName().equals("getSuperclass")) {
            method = mth;
         }
       }
@@ -88,6 +92,10 @@ public class Reflection {
          System.out.println(parameters[i]);
       }
       System.out.println();
+      Type returnType = method.getGenericReturnType();
+      System.out.println(returnType);
+         
+
       /*Class[] parameterTypes = methods[0].getParameterTypes();
       for(Class parameterType: parameterTypes){
          System.out.println(parameterType.getName());   
@@ -107,9 +115,7 @@ public class Reflection {
           System.out.println(bound);
       }
       System.out.println();*/
-      Type returnType = method.getGenericReturnType();
-      System.out.println(returnType);
-         
+  
    }
 }
 
index f9723a6689c36f5c95e27d7c6f5b2ab9586bef8b..fcc8ec24b49bc5e9dce3886d60b4c7c661cda6d5 100644 (file)
@@ -1288,7 +1288,11 @@ public class Types {
   }
 
   public static boolean isWildcardType(String signature) {
-    return (signature.startsWith("+L") || signature.startsWith("-L") || signature.equals("*"));
+    return (signature.startsWith("+L") ||
+            signature.startsWith("-L") ||
+            signature.startsWith("+")  ||
+            signature.startsWith("-")  ||
+            signature.equals("*"));
   }
 
   public static String getWildcardType(String signature) {
@@ -1297,5 +1301,32 @@ public class Types {
     }
     return signature.replaceAll("\\+L|-L", "");
   }
+
+  public static String getTypeParameter(String signature) {
+    if (signature == null || signature.equals(""))
+      return signature;
+
+    if (signature.equals("*")) {
+      return signature;
+    }
+
+    String cleanSig = signature.replaceAll("\\+|-", "");
+    // This kind of signature should be a repetition of its class' type parameter, e.g., TT for Class<T>
+    if (cleanSig.length()%2 != 0) {
+      // This is probably a class, e.g., +java.lang.Class
+      return signature;
+    }
+
+    // Check that the first and the second halves are the same, e.g., TT for Class<T>
+    int halfPos = cleanSig.length()/2;
+    String firstHalf = cleanSig.substring(0, halfPos);
+    String secondHalf = cleanSig.substring(halfPos, cleanSig.length());
+    if (firstHalf.equals(secondHalf)) {
+      return firstHalf;
+    } else {
+      // This is probably a class, e.g., +java.lang.Class
+      return signature;
+    }
+  }
   // TODO: Fix for Groovy's model-checking
 }
index 4fcf1d93487eb201c3ebcb903415787616f279c4..5a890dfc714e784991edb0c9862ac08ae7550313 100644 (file)
@@ -158,10 +158,10 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
     String methodGenericSig = mi.getGenericSignature();
     for(int j = 0; j < parameterizedTypes.length; j++) {
       if (Types.isTypeParameter(parameterizedTypes[j], methodGenericSig) ||
-              Types.isTypeParameter(parameterizedTypes[j], classGenericSig)) {
+          Types.isTypeParameter(parameterizedTypes[j], classGenericSig)) {
         types[j] = getTypeVariableImplObject(env, objRef, parameterizedTypes[j]);
       } else if (Types.isWildcardType(parameterizedTypes[j])) {
-        types[j] = getWildcardTypeImplObject(env, objRef, parameterizedTypes[j]);
+        types[j] = getWildcardTypeImplObject(env, objRef, parameterizedTypes[j], mi);
       } else if (Types.isParameterizedType(parameterizedTypes[j])) {
         // Recursion!
         types[j] = getParameterizedTypeImplObj(parameterizedTypes[j], env, objRef, mi);
@@ -195,29 +195,50 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
     return paramTypeRef;
   }
 
-  private static int getWildcardTypeImplObject(MJIEnv env, int objRef, String wildcardType) {
+  private static int getWildcardTypeImplObject(MJIEnv env, int objRef, String wildcardType, MethodInfo mi) {
     ThreadInfo ti = env.getThreadInfo();
     ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
     ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.WildcardTypeImpl");
 
     int wildcardRef = env.newObject(ci);
     ElementInfo ei = env.getModifiableElementInfo(wildcardRef);
-    String actualType = Types.getWildcardType(wildcardType);
-    ClassInfo uci = cli.getResolvedClassInfo(actualType);
-    if (!uci.isRegistered()) {
-      uci.registerClass(ti);
-    }
+    // Type parameter test
+    // TODO: This test could probably be made cleaner
+    String classGenericSig = mi.getClassInfo().getGenericSignature();
+    String methodGenericSig = mi.getGenericSignature();
+    String typeParameter = Types.getTypeParameter(wildcardType);
     int uRef = MJIEnv.NULL;
     int lRef = MJIEnv.NULL;
-    if (wildcardType.startsWith("+L") || wildcardType.equals("*")) {
-      // Set upperBounds
-      uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
-      env.setReferenceArrayElement(uRef, 0, uci.getClassObjectRef());
-      lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
-    } else { // wildcardType.startsWith("-L")
-      // Set lowerBounds
-      lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
-      env.setReferenceArrayElement(lRef, 0, uci.getClassObjectRef());
+    if (Types.isTypeParameter(typeParameter, methodGenericSig) ||
+        Types.isTypeParameter(typeParameter, classGenericSig)) {
+      int tpRef = getTypeVariableImplObject(env, objRef, typeParameter);
+      if (wildcardType.startsWith("+")) {
+        // Set upperBounds
+        uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
+        env.setReferenceArrayElement(uRef, 0, tpRef);
+        lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
+      } else { // wildcardType.startsWith("-")
+        // Set lowerBounds
+        lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
+        env.setReferenceArrayElement(lRef, 0, tpRef);
+      }
+    } else {
+
+      String actualType = Types.getWildcardType(wildcardType);
+      ClassInfo uci = cli.getResolvedClassInfo(actualType);
+      if (!uci.isRegistered()) {
+        uci.registerClass(ti);
+      }
+      if (wildcardType.startsWith("+L") || wildcardType.equals("*")) {
+        // Set upperBounds
+        uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
+        env.setReferenceArrayElement(uRef, 0, uci.getClassObjectRef());
+        lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
+      } else { // wildcardType.startsWith("-L")
+        // Set lowerBounds
+        lRef = env.newObjectArray("Ljava/lang/reflect/Type;", 1);
+        env.setReferenceArrayElement(lRef, 0, uci.getClassObjectRef());
+      }
     }
     ei.setReferenceField("upperBounds", uRef);
     ei.setReferenceField("lowerBounds", lRef);