A clean implementation for getTypeParameters' native method version.
authorrtrimana <rtrimana@uci.edu>
Tue, 18 Jun 2019 19:46:45 +0000 (12:46 -0700)
committerrtrimana <rtrimana@uci.edu>
Tue, 18 Jun 2019 19:46:45 +0000 (12:46 -0700)
examples/Reflection.java
src/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java
src/main/gov/nasa/jpf/vm/ClassInfo.java
src/main/gov/nasa/jpf/vm/MethodInfo.java
src/main/gov/nasa/jpf/vm/Types.java
src/peers/gov/nasa/jpf/vm/JPF_java_lang_Class.java

index 0a021b2f180d87d77e402098a5aa3c0f959b25cd..ae0e8537e9b55bc40224dae0d6d4b7039c77f490 100644 (file)
@@ -9,6 +9,9 @@ import java.util.Arrays;
 
 public class Reflection {
 
+       class GenericShort<TUVW,ABCD> {
+       }
+
        class Generic<TUVW,ABCD,KLM,NOP> {
        
        }
@@ -52,7 +55,7 @@ public class Reflection {
  
       }
       System.out.println();*/
-      TypeVariable[] typeParameters = Generic.class.getTypeParameters();
+      TypeVariable[] typeParameters = GenericShort.class.getTypeParameters();
       //TypeVariable[] typeParameters = SampleClass.class.getTypeParameters();
       for(TypeVariable typeVar: typeParameters){
          System.out.println(typeVar);   
index f845539b3c4ecf725fa90a2bdeeb58c79831b1e8..50392ca4793b2b3adba13cdd5c3d327b0e80898a 100644 (file)
@@ -25,12 +25,9 @@ import sun.reflect.generics.tree.FieldTypeSignature;
  */
 public class TypeVariableImpl<D extends GenericDeclaration>
     extends LazyReflectiveObjectGenerator implements TypeVariable<D> {
-//public class TypeVariableImpl {
+
     D genericDeclaration;
     private String name;
-    private Type[] bounds;
-    private FieldTypeSignature[] boundASTs;
-    //private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
 
     // constructor is private to enforce access through static factory
     private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs,
@@ -38,7 +35,6 @@ public class TypeVariableImpl<D extends GenericDeclaration>
         super(f);
         genericDeclaration = decl;
         name = n;
-        boundASTs = bs;
     }
 
     // Accessors
index 83b3f5b9f63e79a3d33246d341053016a5a59744..09d59ec4e1d412456e1b7d09e3dc37aeaaf1fbbf 100644 (file)
@@ -2598,6 +2598,14 @@ public class ClassInfo extends InfoObject implements Iterable<MethodInfo>, Gener
   public DirectCallStackFrame createRunStartStackFrame (ThreadInfo ti, MethodInfo miRun){
     return null;
   }
+
+  // TODO: Fix for Groovy's model-checking
+  public String[] getGenericTypeVariableNames () {
+    // To accommodate methods that do not have generic types
+    if (genericSignature == null)
+      return new String[0];
+    return Types.getGenericTypeVariableNames(genericSignature);
+  }
 }
 
 
index a5a83bb7d83f05722179c9e302668b43e0d9cad0..1a51c470a98c07c6fab0d3a3ffe4e2d920aff85f 100644 (file)
@@ -506,7 +506,7 @@ public class MethodInfo extends InfoObject implements GenericSignatureHolder  {
   // TODO: Fix for Groovy's model-checking
   public String[] getArgumentGenericTypeNames () {
     // To accommodate methods that do not have generic types
-    if (genericSignature == "")
+    if (genericSignature == null)
       return getArgumentTypeNames();
     return Types.getArgumentTypeNames(genericSignature);
   }
index c5b2f7f82d3cee8b4b4f843a4aaccd25d00687a2..873b06578d4edb16a6c34617453815a8bce44aae 100644 (file)
@@ -1176,5 +1176,30 @@ public class Types {
 
     throw new JPFException("invalid method declaration: " + methodDecl);
   }
+
+  public static String[] getGenericTypeVariableNames(String signature) {
+    int pos = 0;
+    int opening = 0;
+    ArrayList<String> typeVarNames = new ArrayList<>();
+
+    while (pos < signature.length()) {
+      if (pos > 0) {
+        // Start from ';' if this is not the first type variable name
+        opening = signature.indexOf(';', pos);
+        // Break if this is the end of the type variable names
+        if (signature.charAt(opening + 1) == '>')
+          break;
+      }
+      int colon = signature.indexOf(':', pos);
+      String typeVarName = signature.substring(opening + 1, colon);
+      typeVarNames.add(typeVarName);
+      pos = colon + 1;
+    }
+
+    String[] arrTypeVarNames = new String[typeVarNames.size()];
+    typeVarNames.toArray(arrTypeVarNames);
+
+    return arrTypeVarNames;
+  }
   
 }
index 9e8fc2b3d1f7cca3cd3b2a4866ed500159e8fa98..8ace89649bd8d992b6594377dbaf47bec18e4f13 100644 (file)
@@ -110,23 +110,34 @@ public class JPF_java_lang_Class extends NativePeer {
   }
 
   // TODO: Fix for Groovy's model-checking
-  // TODO: THIS NEEDS TO BE SUBSTITUTED BY THE PROPER METHODS! VERY DIRTY RIGHT NOW!
   @MJI
   public int getTypeParameters_____3Ljava_lang_reflect_TypeVariable_2 (MJIEnv env, int robj){
+    // Get the ClassInfo for this class
+    ClassInfo tci = env.getReferredClassInfo(robj);
+    String[] typeVars = tci.getGenericTypeVariableNames();
+
+    // Return with null if this is not a generic class
+    if (typeVars.length == 0) {
+      int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", 0);
+      return aRef;
+    }
+    // Now create a TypeVariableImpl object for every type variable name; get the ClassInfo for TypeVariableImpl
     ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
     ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl");
-    //ClassInfo rci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.Test");
-    // TODO: Need to 1) Just create the object of TypeVariableImpl, 2) Declare class type and name only, 3) Return the
-    //  object reference back to the caller
-    int tvRef = env.newObject(ci);
-    ElementInfo ei = env.getModifiableElementInfo(tvRef);
-
-    ClassInfo tci = env.getReferredClassInfo( robj);
-    //ei.setReferenceField("genericDeclaration", env.newObject(tci.getName() + ".class"));
-    ei.setReferenceField("name", env.newString("TUVW"));
-    int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", 1);
-    for (int i = 0; i < 1; i++) {
-      env.setReferenceArrayElement(aRef, i, tvRef);
+    int[] var = new int[typeVars.length];
+
+    for(int i = 0; i < typeVars.length; i++) {
+      int typeVarRef = env.newObject(ci);
+      ElementInfo ei = env.getModifiableElementInfo(typeVarRef);
+      ei.setReferenceField("genericDeclaration", tci.getClassObjectRef());
+      ei.setReferenceField("name", env.newString(typeVars[i]));
+      var[i] = typeVarRef;
+    }
+    int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", typeVars.length);
+
+    // Set references for every array element
+    for (int i = 0; i < typeVars.length; i++) {
+      env.setReferenceArrayElement(aRef, i, var[i]);
     }
 
     return aRef;