Finalizing the beta version of the implementation for Groovy extension in JPF: JPF...
[jpf-core.git] / src / main / gov / nasa / jpf / vm / Types.java
index ee64f70a8a2ad9c735e44a20b6006288bdfc7aa4..313e8aab7d0fb0f01027262c8ea64abc1ea0fe91 100644 (file)
@@ -73,6 +73,9 @@ public class Types {
     return args;
   }
 
+  // TODO: Fix for Groovy's model-checking
+  // TODO: We return the generic type name whenever possible (the one between '<' and '>')
+  // TODO: To do this we fixed the implementation of getTypeLength
   public static String[] getArgumentTypeNames (String signature) {
     int len = signature.length();
 
@@ -95,7 +98,7 @@ public class Types {
     
     return typeNames;
   }
-  
+
   public static String dequalify (String typeName){
     int idx = typeName.lastIndexOf('.');
     if (idx > 0) {
@@ -585,6 +588,11 @@ public class Types {
     int i = signature.indexOf(')');
     return getTypeName(signature.substring(i+1));
   }
+
+  public static String getGenericReturnTypeName (String signature){
+    int i = signature.indexOf(')');
+    return getTypeName(signature.substring(i+1));
+  }
   
   public static String getTypeSignature (String type, boolean asDotNotation) {
     String  t = null;
@@ -906,9 +914,17 @@ public class Types {
 
     int len1 = len-1;
     if (signature.charAt(len1) == ';') {
-      return signature.substring(1, len1).replace('/', '.');
+      // TODO: Fix for Groovy's model-checking
+      // TODO: Cleaning up the generic type part inside '<' and '>'
+      return signature.substring(1, len1).replace('/', '.').
+              replaceAll(";L", ", ").
+              replace("<L","<").
+              replace(";>", ">").
+              replaceAll("<T", "<");
     }
 
+
+
     throw new JPFException("invalid type string: " + signature);
   }
 
@@ -1091,6 +1107,22 @@ public class Types {
     case 'L':
 
       int semicolon = signature.indexOf(';', idx);
+      // TODO: Fix for Groovy's model-checking
+      // Check if this is a generic!
+      String currParam = signature.substring(idx,semicolon);
+      int genericStart = currParam.indexOf('<');
+      if (genericStart != -1) {
+        if (currParam.charAt(genericStart + 1) == '*') {
+          // Need to offset with idx to anticipate for array types (idx is incremented for array types)
+          semicolon = genericStart + idx + 3;
+        } else {
+          int generic = signature.indexOf('>', semicolon);
+          if (generic != -1) {
+            // Advance one character past the ';'
+            semicolon = generic + 1;
+          }
+        }
+      }
 
       if (semicolon == -1) {
         throw new JPFException("invalid type signature: " +
@@ -1152,5 +1184,147 @@ public class Types {
 
     throw new JPFException("invalid method declaration: " + methodDecl);
   }
-  
+
+  // TODO: Fix for Groovy's model-checking
+  public static String[] getGenericTypeVariableNames(String signature) {
+    int pos = 0;
+    int marker = 0;
+    ArrayList<String> typeVarNames = new ArrayList<>();
+
+    while (pos < signature.length()) {
+      if (pos > 0) {
+        // Start from ';' if this is not the first type variable name
+        marker = signature.indexOf(';', pos);
+        // Break if this is the end of the type variable names
+        if (signature.charAt(marker + 1) == '>')
+          break;
+      }
+      int colon = signature.indexOf(':', pos);
+      String typeVarName = signature.substring(marker + 1, colon);
+      typeVarNames.add(typeVarName);
+      pos = colon + 1;
+    }
+
+    String[] arrTypeVarNames = new String[typeVarNames.size()];
+    typeVarNames.toArray(arrTypeVarNames);
+
+    return arrTypeVarNames;
+  }
+
+  public static String[] getParameterizedTypes(String signature) {
+    int pos = signature.indexOf('<', 0);
+    if (pos == -1)
+      return new String[0];
+    ArrayList<String> typeVarNames = new ArrayList<>();
+
+    while (pos < signature.length()) {
+      String typeVarName = "";
+      int comma = signature.indexOf(',', pos);
+      if (comma == -1) {
+        int closing = signature.lastIndexOf('>', signature.length());
+        typeVarName = signature.substring(pos + 1, closing);
+        pos = signature.length();
+      } else {
+        typeVarName = signature.substring(pos + 1, comma);
+        pos = comma + 1;
+      }
+      typeVarNames.add(typeVarName);
+    }
+
+    String[] arrTypeVarNames = new String[typeVarNames.size()];
+    typeVarNames.toArray(arrTypeVarNames);
+
+    return arrTypeVarNames;
+  }
+
+  public static String getGenericClassName(String signature) {
+    int opening = signature.indexOf('<');
+    if (opening == -1)
+      return signature;
+    else
+      return signature.substring(0, opening);
+  }
+
+  public static String getArrayClassName(String signature) {
+    int opening = signature.indexOf('[');
+    if (opening == -1)
+      return signature;
+    else
+      return signature.substring(0, opening);
+  }
+
+  public static String getOwnerClassName(String signature) {
+    int marker = signature.indexOf('$');
+    if (marker == -1)
+      return null;
+    else
+      return signature.substring(0, marker);
+  }
+
+  public static boolean isGenericSignature(String signature) {
+    if (signature == null || signature.equals(""))
+      return false;
+    int opening = signature.indexOf('<');
+    return (opening != -1);
+  }
+
+  public static boolean isParameterizedType(String signature) {
+    return Types.isGenericSignature(signature);
+  }
+
+  public static boolean isArraySignature(String signature) {
+    if (signature == null || signature.equals(""))
+      return false;
+    int opening = signature.indexOf('[');
+    return (opening != -1);
+  }
+
+  public static boolean isTypeParameter(String parameterizedType, String signature) {
+    if (signature == null || signature.equals(""))
+      return false;
+    String typeParamSig = parameterizedType.concat(":");
+    return signature.contains(typeParamSig);
+  }
+
+  public static boolean isWildcardType(String signature) {
+    return (signature.startsWith("+L") ||
+            signature.startsWith("-L") ||
+            signature.startsWith("+")  ||
+            signature.startsWith("-")  ||
+            signature.equals("*"));
+  }
+
+  public static String getWildcardType(String signature) {
+    if (signature.equals("*")) {
+      return "java.lang.Object";
+    }
+    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("\\+|-", "");
+    if (cleanSig.length()%2 != 0) {
+      // This is probably a class, e.g., +java.lang.Class
+      return signature;
+    }
+
+    // Check if this is not a class name, e.g., +java.lang.Class
+    if (cleanSig.contains(".")) {
+      return signature;
+    }
+
+    // Just return the second half of the signature to get the Type parameter
+    int halfPos = cleanSig.length()/2;
+    //String firstHalf = cleanSig.substring(0, halfPos);
+    String secondHalf = cleanSig.substring(halfPos, cleanSig.length());
+    return secondHalf;
+  }
+  // TODO: Fix for Groovy's model-checking
 }