• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package annotations.util;
2 
3 import com.sun.source.tree.ArrayTypeTree;
4 import com.sun.source.tree.MethodTree;
5 import com.sun.source.tree.Tree;
6 import com.sun.tools.javac.code.Type;
7 import com.sun.tools.javac.code.TypeTag;
8 import com.sun.tools.javac.tree.JCTree.JCExpression;
9 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
10 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
11 import com.sun.tools.javac.util.List;
12 
13 import plume.UtilMDE;
14 
15 import javax.lang.model.element.ExecutableElement;
16 import javax.lang.model.element.VariableElement;
17 import javax.lang.model.type.ArrayType;
18 import javax.lang.model.type.TypeKind;
19 import javax.lang.model.type.TypeMirror;
20 
21 /**
22  * Class to generate class formatted names from Trees.
23  *
24  * @author mcarthur
25  */
26 public class JVMNames {
27 
28     /**
29      * Converts a MethodTree into a jvml format method signature.
30      * There is probably an API to do this, but I couldn't find it.
31      *
32      * @param methodTree the tree to convert
33      * @return a String signature of methodTree in jvml format
34      */
getJVMMethodName(MethodTree methodTree)35     public static String getJVMMethodName(MethodTree methodTree) {
36         ExecutableElement methodElement = ((JCMethodDecl) methodTree).sym;
37         StringBuilder builder = new StringBuilder();
38         String returnTypeStr;
39         builder.append(methodTree.getName());
40         builder.append("(");
41 
42         if (methodElement == null) {
43             // use source AST in lieu of symbol table
44             List<JCVariableDecl> params = ((JCMethodDecl) methodTree).params;
45             JCVariableDecl param = params.head;
46             JCExpression typeTree = ((JCMethodDecl) methodTree).restype;
47             returnTypeStr = treeToJVMLString(typeTree);
48             while (param != null) {
49                 builder.append(treeToJVMLString(param.vartype));
50                 params = params.tail;
51                 param = params.head;
52             }
53         } else {
54             TypeMirror returnType = methodElement.getReturnType();
55             returnTypeStr = typeToJvmlString((Type)returnType);
56             for (VariableElement ve : methodElement.getParameters()) {
57                 Type vt = (Type) ve.asType();
58                 if (vt.getTag() == TypeTag.TYPEVAR) {
59                     vt = vt.getUpperBound();
60                 }
61                 builder.append(typeToJvmlString(vt));
62             }
63         }
64         builder.append(")");
65         builder.append(returnTypeStr);
66         return builder.toString();
67     }
68 
69     /**
70      * Converts a method element into a jvml format method signature.
71      * There is probably an API to do this, but I couldn't find it.
72      *
73      * @param methodElement the method element to convert
74      * @return a String signature of methodElement in jvml format
75      */
getJVMMethodName(ExecutableElement methodElement)76     public static String getJVMMethodName(ExecutableElement methodElement) {
77         StringBuilder builder = new StringBuilder();
78         String returnTypeStr;
79         builder.append(methodElement.getSimpleName());
80         builder.append("(");
81         TypeMirror returnType = methodElement.getReturnType();
82         returnTypeStr = typeToJvmlString((Type)returnType);
83         for (VariableElement ve : methodElement.getParameters()) {
84             Type vt = (Type) ve.asType();
85             if (vt.getTag() == TypeTag.TYPEVAR) {
86                 vt = vt.getUpperBound();
87             }
88             builder.append(typeToJvmlString(vt));
89         }
90         builder.append(")");
91         builder.append(returnTypeStr);
92         return builder.toString();
93     }
94 
95     /**
96      * Create a JVML string for a type.
97      * Uses {@link UtilMDE#binaryNameToFieldDescriptor(String)}
98      *
99      * Array strings are built by recursively converting the component type.
100      *
101      * @param type the Type to convert to JVML
102      * @return the JVML representation of type
103      */
typeToJvmlString(Type type)104     public static String typeToJvmlString(Type type) {
105         if (type.getKind() == TypeKind.ARRAY) {
106             return "[" + typeToJvmlString((Type) ((ArrayType) type).getComponentType());
107         } else if (type.getKind() == TypeKind.INTERSECTION) {
108             // replace w/erasure (== erasure of 1st conjunct)
109             return typeToJvmlString(type.tsym.erasure_field);
110         } else if (type.getKind() == TypeKind.VOID) {
111             return "V";  // special case since UtilMDE doesn't handle void
112         } else {
113             return UtilMDE.binaryNameToFieldDescriptor(type.tsym.flatName().toString());
114         }
115     }
116 
117     /**
118      * Create a JVML string for an AST node representing a type.
119      *
120      * @param typeTree a Tree representing a type
121      * @return the JVML representation of type
122      */
treeToJVMLString(Tree typeTree)123     private static String treeToJVMLString(Tree typeTree) {
124         StringBuilder builder = new StringBuilder();
125         treeToJVMLString(typeTree, builder);
126         return builder.toString();
127     }
128 
treeToJVMLString(Tree typeTree, StringBuilder builder)129     private static void treeToJVMLString(Tree typeTree, StringBuilder builder) {
130         // FIXME: not robust in presence of comments
131         switch (typeTree.getKind()) {
132         case ARRAY_TYPE:
133             builder.append('[');
134             treeToJVMLString(((ArrayTypeTree) typeTree).getType(), builder);
135             break;
136         default:
137             String str = typeTree.toString();
138             builder.append("void".equals(str) ? "V"
139                 : UtilMDE.binaryNameToFieldDescriptor(typeTree.toString()));
140             break;
141         }
142     }
143 
jvmlStringToJavaTypeString(String str)144     public static String jvmlStringToJavaTypeString(String str) {
145         return str.equals("V") ? "void"
146                 : UtilMDE.fieldDescriptorToBinaryName(str);
147     }
148 }
149