15
15
package com .google .devtools .j2objc .javac ;
16
16
17
17
import com .google .devtools .j2objc .Options ;
18
+ import com .google .devtools .j2objc .ast .AbstractTypeDeclaration ;
19
+ import com .google .devtools .j2objc .ast .BodyDeclaration ;
18
20
import com .google .devtools .j2objc .ast .CompilationUnit ;
21
+ import com .google .devtools .j2objc .ast .MethodDeclaration ;
19
22
import com .google .devtools .j2objc .ast .Name ;
20
23
import com .google .devtools .j2objc .ast .PackageDeclaration ;
21
24
import com .google .devtools .j2objc .ast .QualifiedName ;
22
25
import com .google .devtools .j2objc .ast .SimpleName ;
26
+ import com .google .devtools .j2objc .ast .SingleVariableDeclaration ;
23
27
import com .google .devtools .j2objc .ast .SourcePosition ;
28
+ import com .google .devtools .j2objc .ast .TreeNode ;
29
+ import com .google .devtools .j2objc .ast .Type ;
24
30
import com .google .devtools .j2objc .ast .TypeDeclaration ;
25
31
import com .google .devtools .j2objc .file .InputFile ;
26
32
import com .google .devtools .j2objc .util .ErrorUtil ;
29
35
import com .sun .tools .javac .code .Symbol .PackageSymbol ;
30
36
import java .io .File ;
31
37
import java .io .IOException ;
38
+ import java .lang .reflect .Modifier ;
32
39
import java .util .ArrayList ;
33
40
import java .util .List ;
41
+ import javax .lang .model .element .Element ;
42
+ import javax .lang .model .element .ExecutableElement ;
34
43
import javax .lang .model .element .PackageElement ;
35
44
import javax .lang .model .element .TypeElement ;
45
+ import javax .lang .model .element .VariableElement ;
46
+ import javax .lang .model .type .ArrayType ;
47
+ import javax .lang .model .type .TypeKind ;
48
+ import javax .lang .model .type .TypeMirror ;
36
49
import javax .tools .StandardLocation ;
37
50
import org .objectweb .asm .ClassReader ;
38
51
import org .objectweb .asm .ClassVisitor ;
39
52
import org .objectweb .asm .Opcodes ;
40
- import org .objectweb .asm .Type ;
41
53
42
54
/**
43
55
* Converts a JVM classfile into a CompilationUnit.
44
56
*/
45
57
public class ClassFileConverter extends ClassVisitor {
46
58
private final JavacEnvironment parserEnv ;
59
+ private final TranslationEnvironment translationEnv ;
47
60
private final InputFile file ;
48
61
private String typeName ;
49
- private TypeElement typeElement ;
50
62
51
- public static CompilationUnit convert (
63
+ public static CompilationUnit convertClassFile (
52
64
Options options , JavacEnvironment env , InputFile file ) throws IOException {
53
65
env .saveParameterNames ();
54
66
ClassReader classReader = new ClassReader (file .getInputStream ());
55
- ClassFileConverter converter = new ClassFileConverter (env , file );
56
- /* TODO(user): need to return canonical name for use in visit()
57
- * when dealing with inner classes, see
58
- * https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.7 */
67
+ ClassFileConverter converter = new ClassFileConverter (
68
+ env , new TranslationEnvironment (options , env ), file );
59
69
String internalName = classReader .getClassName ();
60
- converter .typeName = Type .getObjectType (internalName ).getClassName ();
70
+ converter .setClassPath (internalName );
71
+ /* TODO(user): inner classes; need to return canonical name for use in visit(); see
72
+ * https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.7 */
73
+ converter .typeName = org .objectweb .asm .Type .getObjectType (internalName ).getClassName ();
61
74
classReader .accept (converter , 0 );
62
- if (converter .typeElement == null ) {
63
- ErrorUtil .error ("Invalid class file: " + file .getOriginalLocation ());
64
- }
65
- return converter .createUnit (new TranslationEnvironment (options , env ));
75
+ return converter .createUnit ();
66
76
}
67
77
68
- ClassFileConverter (JavacEnvironment parserEnv , InputFile file ) {
78
+ private ClassFileConverter (
79
+ JavacEnvironment parserEnv , TranslationEnvironment translationEnv , InputFile file ) {
69
80
super (Opcodes .ASM5 );
70
81
this .parserEnv = parserEnv ;
82
+ this .translationEnv = translationEnv ;
71
83
this .file = file ;
72
84
}
73
85
74
- @ Override
75
- public void visit (int version , int access , String name , String signature ,
76
- String superName , String [] interfaces ) {
77
- setClassPath (name );
78
- typeElement = parserEnv .elementUtilities ().getTypeElement (typeName );
79
- }
80
-
81
- // Set classpath to the root path of the input file, to support typeElement lookup.
86
+ /**
87
+ * Set classpath to the root path of the input file, to support typeElement lookup.
88
+ */
82
89
private void setClassPath (String name ) {
83
90
try {
84
91
String fullPath = file .getAbsolutePath ();
@@ -91,34 +98,128 @@ private void setClassPath(String name) {
91
98
}
92
99
}
93
100
94
- /* TODO(user): see TreeConverter.convertName() when source-level debugging
95
- * is needed */
101
+ private CompilationUnit createUnit () {
102
+ TypeElement typeElement = parserEnv .elementUtilities ().getTypeElement (typeName );
103
+ if (typeElement == null ) {
104
+ ErrorUtil .error ("Invalid class file: " + file .getOriginalLocation ());
105
+ }
106
+ PackageElement pkgElement = parserEnv .elementUtilities ().getPackageOf (typeElement );
107
+ if (pkgElement == null ) {
108
+ pkgElement = parserEnv .defaultPackage ();
109
+ }
110
+ String mainTypeName = typeElement .getSimpleName ().toString ();
111
+ CompilationUnit compUnit = new CompilationUnit (translationEnv , mainTypeName );
112
+ compUnit .setPackage ((PackageDeclaration ) convert (pkgElement ));
113
+ compUnit .addType ((AbstractTypeDeclaration ) convert (typeElement ));
114
+ return compUnit ;
115
+ }
116
+
117
+ @ SuppressWarnings ("fallthrough" )
118
+ private TreeNode convert (Element element ) {
119
+ TreeNode node ;
120
+ switch (element .getKind ()) {
121
+ // case ANNOTATION_TYPE:
122
+ // break;
123
+ case CLASS :
124
+ case INTERFACE :
125
+ node = convertTypeDeclaration ((TypeElement ) element );
126
+ break ;
127
+ case CONSTRUCTOR :
128
+ case METHOD :
129
+ node = convertMethodDeclaration ((ExecutableElement ) element );
130
+ break ;
131
+ // case ENUM:
132
+ // break;
133
+ // case ENUM_CONSTANT:
134
+ // break;
135
+ // case EXCEPTION_PARAMETER:
136
+ // break;
137
+ // case FIELD:
138
+ // break;
139
+ // case INSTANCE_INIT:
140
+ // break;
141
+ // case LOCAL_VARIABLE:
142
+ // break;
143
+ // case OTHER:
144
+ // break;
145
+ case PACKAGE :
146
+ node = convertPackage ((PackageElement ) element );
147
+ break ;
148
+ case PARAMETER :
149
+ node = convertParameter ((VariableElement ) element );
150
+ break ;
151
+ // case RESOURCE_VARIABLE:
152
+ // break;
153
+ // case STATIC_INIT:
154
+ // break;
155
+ // case TYPE_PARAMETER:
156
+ // break;
157
+ default :
158
+ throw new AssertionError ("Unknown element kind: " + element .getKind ());
159
+ }
160
+ return node .setPosition (SourcePosition .NO_POSITION );
161
+ }
162
+
163
+ /* TODO(user): source-level debugging; see TreeConverter.convertName() */
96
164
private Name convertName (Symbol symbol ) {
97
165
if (symbol .owner == null || symbol .owner .name .isEmpty ()) {
98
166
return new SimpleName (symbol );
99
167
}
100
168
return new QualifiedName (symbol , symbol .asType (), convertName (symbol .owner ));
101
169
}
102
170
103
- private PackageDeclaration convertPackage (PackageElement pkgElem ) {
171
+ private TreeNode convertPackage (PackageElement element ) {
104
172
return new PackageDeclaration ()
105
- .setPackageElement (pkgElem )
106
- .setName (convertName ((PackageSymbol ) pkgElem ));
173
+ .setPackageElement (element )
174
+ .setName (convertName ((PackageSymbol ) element ));
175
+ }
176
+
177
+ private TreeNode convertBodyDeclaration (BodyDeclaration newNode ) {
178
+ return newNode ;
179
+ /* TODO(user): annotations, source-level debugging; finish when supported
180
+ * .setAnnotations(convertAnnotations(modifiers))
181
+ * .setJavadoc((Javadoc) getAssociatedJavaDoc(node, element)); */
107
182
}
108
183
109
- private CompilationUnit createUnit (TranslationEnvironment translationEnv ) {
110
- CompilationUnit compUnit = new CompilationUnit (translationEnv ,
111
- typeElement .getSimpleName ().toString ());
112
- PackageElement pkgElem = parserEnv .elementUtilities ().getPackageOf (typeElement );
113
- if (pkgElem == null ) {
114
- pkgElem = parserEnv .defaultPackage ();
184
+ private TreeNode convertTypeDeclaration (TypeElement element ) {
185
+ TypeDeclaration typeDecl = new TypeDeclaration (element );
186
+ convertBodyDeclaration (typeDecl );
187
+ /* TODO(user): inheritance; may need to also use Elements.getAllMembers(TypeElement type) or
188
+ * ElementUtil.getMethods(), etc. */
189
+ for (Element elem : element .getEnclosedElements ()) {
190
+ typeDecl .addBodyDeclaration ((BodyDeclaration ) convert (elem ));
115
191
}
116
- PackageDeclaration pkgDecl = (PackageDeclaration ) convertPackage (pkgElem )
117
- .setPosition (SourcePosition .NO_POSITION );
118
- TypeDeclaration typeDecl = (TypeDeclaration ) new TypeDeclaration (typeElement )
119
- .setPosition (SourcePosition .NO_POSITION );
120
- compUnit .setPackage (pkgDecl );
121
- compUnit .addType (typeDecl );
122
- return compUnit ;
192
+ if (typeDecl .isInterface ()) {
193
+ typeDecl .removeModifiers (Modifier .PUBLIC | Modifier .ABSTRACT );
194
+ for (BodyDeclaration bodyDecl : typeDecl .getBodyDeclarations ()) {
195
+ bodyDecl .removeModifiers (Modifier .PUBLIC | Modifier .ABSTRACT );
196
+ }
197
+ }
198
+ return typeDecl ;
199
+ }
200
+
201
+ private TreeNode convertMethodDeclaration (ExecutableElement element ) {
202
+ MethodDeclaration methodDecl = new MethodDeclaration (element );
203
+ List <SingleVariableDeclaration > parameters = methodDecl .getParameters ();
204
+ for (VariableElement param : element .getParameters ()) {
205
+ parameters .add ((SingleVariableDeclaration ) convert (param ));
206
+ }
207
+ if (element .isVarArgs ()) {
208
+ SingleVariableDeclaration lastParam = parameters .get (parameters .size () - 1 );
209
+ TypeMirror paramType = lastParam .getType ().getTypeMirror ();
210
+ assert paramType .getKind () == TypeKind .ARRAY ;
211
+ TypeMirror varArgType = ((ArrayType ) paramType ).getComponentType ();
212
+ lastParam .setType (Type .newType (varArgType ));
213
+ lastParam .setIsVarargs (true );
214
+ }
215
+ return methodDecl ;
216
+ /* TODO(user): method translation; finish when supported
217
+ * .setBody((Block) convert(node.getBody())); */
218
+ }
219
+
220
+ private TreeNode convertParameter (VariableElement element ) {
221
+ return new SingleVariableDeclaration (element );
222
+ /* TODO(user): annotations; finish when supported
223
+ * .setAnnotations(convertAnnotations(node.getModifiers())); */
123
224
}
124
225
}
0 commit comments