Skip to content

Commit 2ae24c7

Browse files
manvithntomball
authored andcommitted
Simple interfaces are parsed into correct ASTs.
Change on 2017/06/22 by manvithn <[email protected]> ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=159857901
1 parent e84b3d9 commit 2ae24c7

File tree

9 files changed

+209
-61
lines changed

9 files changed

+209
-61
lines changed

translator/src/main/java/com/google/devtools/j2objc/ast/AbstractTypeDeclaration.java

+1-6
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public AbstractTypeDeclaration(AbstractTypeDeclaration other) {
4040
}
4141

4242
public AbstractTypeDeclaration(TypeElement typeElement) {
43-
super();
43+
super(typeElement);
4444
this.typeElement = typeElement;
4545
name.set(new SimpleName(typeElement));
4646
}
@@ -67,11 +67,6 @@ public List<BodyDeclaration> getBodyDeclarations() {
6767
return bodyDeclarations;
6868
}
6969

70-
public BodyDeclaration setBodyDeclarations(List<BodyDeclaration> newDeclarations) {
71-
bodyDeclarations.replaceAll(newDeclarations);
72-
return this;
73-
}
74-
7570
public List<Statement> getClassInitStatements() {
7671
return classInitStatements;
7772
}

translator/src/main/java/com/google/devtools/j2objc/ast/BodyDeclaration.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ public abstract class BodyDeclaration extends TreeNode {
2929
protected ChildLink<Javadoc> javadoc = ChildLink.create(Javadoc.class, this);
3030
protected ChildList<Annotation> annotations = ChildList.create(Annotation.class, this);
3131

32-
BodyDeclaration() {
33-
super();
34-
}
32+
BodyDeclaration() {}
3533

3634
public BodyDeclaration(BodyDeclaration other) {
3735
super(other);

translator/src/main/java/com/google/devtools/j2objc/ast/TypeDeclaration.java

-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ public TypeDeclaration(TypeDeclaration other) {
4545
public TypeDeclaration(TypeElement typeElement) {
4646
super(typeElement);
4747
isInterface = typeElement.getKind().isInterface();
48-
for (TypeMirror interfaceMirror : typeElement.getInterfaces()) {
49-
}
5048
}
5149

5250
@Override

translator/src/main/java/com/google/devtools/j2objc/javac/ClassFileConverter.java

+140-39
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@
1515
package com.google.devtools.j2objc.javac;
1616

1717
import com.google.devtools.j2objc.Options;
18+
import com.google.devtools.j2objc.ast.AbstractTypeDeclaration;
19+
import com.google.devtools.j2objc.ast.BodyDeclaration;
1820
import com.google.devtools.j2objc.ast.CompilationUnit;
21+
import com.google.devtools.j2objc.ast.MethodDeclaration;
1922
import com.google.devtools.j2objc.ast.Name;
2023
import com.google.devtools.j2objc.ast.PackageDeclaration;
2124
import com.google.devtools.j2objc.ast.QualifiedName;
2225
import com.google.devtools.j2objc.ast.SimpleName;
26+
import com.google.devtools.j2objc.ast.SingleVariableDeclaration;
2327
import com.google.devtools.j2objc.ast.SourcePosition;
28+
import com.google.devtools.j2objc.ast.TreeNode;
29+
import com.google.devtools.j2objc.ast.Type;
2430
import com.google.devtools.j2objc.ast.TypeDeclaration;
2531
import com.google.devtools.j2objc.file.InputFile;
2632
import com.google.devtools.j2objc.util.ErrorUtil;
@@ -29,56 +35,57 @@
2935
import com.sun.tools.javac.code.Symbol.PackageSymbol;
3036
import java.io.File;
3137
import java.io.IOException;
38+
import java.lang.reflect.Modifier;
3239
import java.util.ArrayList;
3340
import java.util.List;
41+
import javax.lang.model.element.Element;
42+
import javax.lang.model.element.ExecutableElement;
3443
import javax.lang.model.element.PackageElement;
3544
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;
3649
import javax.tools.StandardLocation;
3750
import org.objectweb.asm.ClassReader;
3851
import org.objectweb.asm.ClassVisitor;
3952
import org.objectweb.asm.Opcodes;
40-
import org.objectweb.asm.Type;
4153

4254
/**
4355
* Converts a JVM classfile into a CompilationUnit.
4456
*/
4557
public class ClassFileConverter extends ClassVisitor {
4658
private final JavacEnvironment parserEnv;
59+
private final TranslationEnvironment translationEnv;
4760
private final InputFile file;
4861
private String typeName;
49-
private TypeElement typeElement;
5062

51-
public static CompilationUnit convert(
63+
public static CompilationUnit convertClassFile(
5264
Options options, JavacEnvironment env, InputFile file) throws IOException {
5365
env.saveParameterNames();
5466
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);
5969
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();
6174
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();
6676
}
6777

68-
ClassFileConverter(JavacEnvironment parserEnv, InputFile file) {
78+
private ClassFileConverter(
79+
JavacEnvironment parserEnv, TranslationEnvironment translationEnv, InputFile file) {
6980
super(Opcodes.ASM5);
7081
this.parserEnv = parserEnv;
82+
this.translationEnv = translationEnv;
7183
this.file = file;
7284
}
7385

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+
*/
8289
private void setClassPath(String name) {
8390
try {
8491
String fullPath = file.getAbsolutePath();
@@ -91,34 +98,128 @@ private void setClassPath(String name) {
9198
}
9299
}
93100

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() */
96164
private Name convertName(Symbol symbol) {
97165
if (symbol.owner == null || symbol.owner.name.isEmpty()) {
98166
return new SimpleName(symbol);
99167
}
100168
return new QualifiedName(symbol, symbol.asType(), convertName(symbol.owner));
101169
}
102170

103-
private PackageDeclaration convertPackage(PackageElement pkgElem) {
171+
private TreeNode convertPackage(PackageElement element) {
104172
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)); */
107182
}
108183

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));
115191
}
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())); */
123224
}
124225
}

translator/src/main/java/com/google/devtools/j2objc/javac/JavacParser.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public CompilationUnit parse(InputFile file) {
7676
assert options.translateClassfiles();
7777
JavacEnvironment parserEnv =
7878
createEnvironment(Collections.emptyList(), Collections.emptyList(), false);
79-
return ClassFileConverter.convert(options, parserEnv, file);
79+
return ClassFileConverter.convertClassFile(options, parserEnv, file);
8080
}
8181
} catch (IOException e) {
8282
ErrorUtil.error(e.getMessage());

translator/src/main/java/com/google/devtools/j2objc/javac/TreeConverter.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ private TreeNode convertInner(JCTree javacNode) {
382382
private TreeNode convertAbstractTypeDeclaration(
383383
JCTree.JCClassDecl node, AbstractTypeDeclaration newNode) {
384384
convertBodyDeclaration(node, node.getModifiers(), newNode, node.sym);
385-
List<BodyDeclaration> bodyDeclarations = new ArrayList<>();
385+
List<BodyDeclaration> bodyDeclarations = newNode.getBodyDeclarations();
386386
for (JCTree bodyDecl : node.getMembers()) {
387387
Object member = convert(bodyDecl);
388388
if (member instanceof BodyDeclaration) { // Not true for enum constants.
@@ -395,8 +395,7 @@ private TreeNode convertAbstractTypeDeclaration(
395395
}
396396
return newNode
397397
.setName(convertSimpleName(node.sym, node.sym.asType(), getNamePosition(node)))
398-
.setTypeElement(node.sym)
399-
.setBodyDeclarations(bodyDeclarations);
398+
.setTypeElement(node.sym);
400399
}
401400

402401
private TreeNode convertAnnotation(JCTree.JCAnnotation node) {
@@ -644,7 +643,7 @@ private TreeNode convertEnum(JCTree.JCClassDecl node) {
644643
if (node.sym.isAnonymous()) {
645644
return convertClassDeclaration(node).setPosition(getPosition(node));
646645
}
647-
EnumDeclaration newNode = (EnumDeclaration) new EnumDeclaration();
646+
EnumDeclaration newNode = new EnumDeclaration();
648647
convertBodyDeclaration(node, node.getModifiers(), newNode, node.sym);
649648
newNode
650649
.setName(convertSimpleName(node.sym, node.type, getNamePosition(node)))

translator/src/test/java/com/google/devtools/j2objc/GenerationTest.java

+13
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,19 @@ protected void assertEqualASTs(TreeNode first, TreeNode second) {
385385
}
386386
}
387387

388+
/**
389+
* Compiles Java source, as contained in a source file, and compares the parsed compilation units
390+
* generated from the source and class files.
391+
*
392+
* @param type the public type being declared
393+
* @param source the source code
394+
*/
395+
protected void assertEqualSrcClassfile(String type, String source) throws IOException {
396+
CompilationUnit srcUnit = compileType(type, source);
397+
CompilationUnit classfileUnit = compileAsClassFile(type, source);
398+
assertEqualASTs(srcUnit, classfileUnit);
399+
}
400+
388401
/**
389402
* Translate a Java method into a JDT DOM MethodDeclaration. Although JDT
390403
* has support for parsing methods, it doesn't resolve them. The statements

translator/src/test/java/com/google/devtools/j2objc/SmallTests.java

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.google.devtools.j2objc.gen.StatementGeneratorTest;
3333
import com.google.devtools.j2objc.gen.TypeDeclarationGeneratorTest;
3434
import com.google.devtools.j2objc.gen.TypeImplementationGeneratorTest;
35+
import com.google.devtools.j2objc.javac.ClassFileConverterTest;
3536
import com.google.devtools.j2objc.javac.JavacTreeConverterTest;
3637
import com.google.devtools.j2objc.jdt.TreeConverterTest;
3738
import com.google.devtools.j2objc.pipeline.J2ObjCIncompatibleStripperTest;
@@ -103,6 +104,7 @@ public class SmallTests {
103104
ArrayRewriterTest.class,
104105
AutoboxerTest.class,
105106
CastResolverTest.class,
107+
ClassFileConverterTest.class,
106108
CodeReferenceMapTest.class,
107109
ComplexExpressionExtractorTest.class,
108110
CompoundTypeTest.class,

0 commit comments

Comments
 (0)