Fixing a new bug: Considering parameters with Type and Type array, e.g., T and T[].
[jpf-core.git] / src / peers / gov / nasa / jpf / vm / JPF_java_lang_reflect_Method.java
index 299fb619fe13f7e8286ff9bc6e89ce2d86b0136e..05c049fa7a9138614cf748bc4777fd5f3598ba28 100644 (file)
@@ -128,7 +128,12 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
 
     // Get field information and fill out the fields
     String clsSig = Types.getArrayClassName(signature);
-    int paramTypeRef = getParameterizedTypeImplObj(clsSig, env, objRef, mi);
+    int paramTypeRef;
+    if (Types.isParameterWithType(clsSig)) {
+      paramTypeRef = getTypeVariableImplObject(env, objRef, clsSig);
+    } else {
+      paramTypeRef = getParameterizedTypeImplObj(clsSig, env, objRef, mi);
+    }
     ei.setReferenceField("genericComponentType", paramTypeRef);
 
     return genArrRef;
@@ -158,10 +163,13 @@ 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);
       } else {
         ClassInfo pci = cli.getResolvedClassInfo(parameterizedTypes[j]);
         if (!pci.isRegistered()) {
@@ -192,29 +200,51 @@ 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);
+        uRef = env.newObjectArray("Ljava/lang/reflect/Type;", 0);
+      }
+    } 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);
@@ -241,6 +271,8 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
     String[] argTypeNames = mi.getArgumentGenericTypeNames();
     int[] ar = new int[argTypeNames.length];
 
+    String classGenericSig = mi.getClassInfo().getGenericSignature();
+    String methodGenericSig = mi.getGenericSignature();
     for (int i = 0; i < argTypeNames.length; i++) {
       // Change this into just the generic class type if it is a generic class
       if (Types.isGenericSignature(argTypeNames[i])) {
@@ -250,6 +282,14 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
         } else {
           ar[i] = getParameterizedTypeImplObj(argTypeNames[i], env, objRef, mi);
         }
+      } else if (Types.isTypeParameter(argTypeNames[i], methodGenericSig) ||
+                 Types.isTypeParameter(argTypeNames[i], classGenericSig)) {
+        if (Types.isArraySignature(argTypeNames[i])) {
+          // Generic array
+          ar[i] = getGenericArrayTypeImplObj(argTypeNames[i], env, objRef, mi);
+        } else {
+          ar[i] = getTypeVariableImplObject(env, objRef, argTypeNames[i]);
+        }
       } else {
         ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(argTypeNames[i]);
         if (!ci.isRegistered()) {
@@ -262,7 +302,6 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
     for (int i = 0; i < argTypeNames.length; i++) {
       env.setReferenceArrayElement(aRef, i, ar[i]);
     }
-
     return aRef;
   }
 
@@ -276,9 +315,26 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
     MethodInfo mi = getMethodInfo(env, objRef);
     ThreadInfo ti = env.getThreadInfo();
 
+    String genRetType = mi.getGenericReturnTypeName();
+    String classGenericSig = mi.getClassInfo().getGenericSignature();
+    String methodGenericSig = mi.getGenericSignature();
     int retRef;
-    if (Types.isGenericSignature(mi.getGenericReturnTypeName())) {
-      retRef = getParameterizedTypeImplObj(mi.getGenericReturnTypeName(), env, objRef, mi);
+
+    if (Types.isGenericSignature(genRetType)) {
+      if (Types.isArraySignature(genRetType)) {
+        // Generic array
+        retRef = getGenericArrayTypeImplObj(genRetType, env, objRef, mi);
+      } else {
+        retRef = getParameterizedTypeImplObj(genRetType, env, objRef, mi);
+      }
+    } else if (Types.isTypeParameter(genRetType, methodGenericSig) ||
+               Types.isTypeParameter(genRetType, classGenericSig)) {
+      if (Types.isArraySignature(genRetType)) {
+        // Generic array
+        retRef = getGenericArrayTypeImplObj(genRetType, env, objRef, mi);
+      } else {
+        retRef = getTypeVariableImplObject(env, objRef, genRetType);
+      }
     } else {
       ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(mi.getReturnTypeName());
       if (!ci.isRegistered()) {
@@ -290,7 +346,6 @@ public class JPF_java_lang_reflect_Method extends NativePeer {
     return retRef;
   }
   // TODO: Fix for Groovy's model-checking
-  // TODO: We have been able to only register the generic class and not yet the parameterized types
 
   int getExceptionTypes(MJIEnv env, MethodInfo mi) {
     ThreadInfo ti = env.getThreadInfo();