diff options
| author | Michael Williamson <mike@zwobble.org> | 2016-02-11 21:55:36 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2016-02-11 21:55:36 +0000 |
| commit | 904dff6724e224f24772854fa184f62ca33c1795 (patch) | |
| tree | e9e4989c0930e3c220f9cfcda7f7bac1cbb4548e /src | |
| parent | a34a00ba19f6ffb61762da4629b53b8a633f9d17 (diff) | |
Read static field accesses and static constructors in Java frontend
Diffstat (limited to 'src')
3 files changed, 88 insertions, 5 deletions
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java index ba08fd8..3d8e1c0 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java @@ -144,11 +144,18 @@ public class JavaExpressionReader { } private ExpressionNode readVariableBinding(IVariableBinding binding) { - TypeName type = typeOf(binding); if (binding.getDeclaringClass() == null) { return scope.reference(binding.getKey()); } else { - return FieldAccessNode.fieldAccess(ThisReferenceNode.thisReference(typeOf(binding.getDeclaringClass())), binding.getName(), type); + boolean isStatic = Modifier.isStatic(binding.getModifiers()); + TypeName classType = typeOf(binding.getDeclaringClass()); + Receiver receiver = isStatic + ? new StaticReceiver(classType) + : new InstanceReceiver(ThisReferenceNode.thisReference(classType)); + return FieldAccessNode.fieldAccess( + receiver, + binding.getName(), + typeOf(binding)); } } @@ -157,7 +164,16 @@ public class JavaExpressionReader { } private ExpressionNode readFieldAccess(FieldAccess expression) { - return FieldAccessNode.fieldAccess(readExpressionWithoutBoxing(expression.getExpression()), expression.getName().getIdentifier(), typeOf(expression)); + IVariableBinding fieldBinding = expression.resolveFieldBinding(); + boolean isStatic = Modifier.isStatic(fieldBinding.getModifiers()); + Receiver receiver = isStatic + ? new StaticReceiver(typeOf(fieldBinding.getDeclaringClass())) + : new InstanceReceiver(readExpressionWithoutBoxing(expression.getExpression())); + + return FieldAccessNode.fieldAccess( + receiver, + expression.getName().getIdentifier(), + typeOf(expression)); } private ExpressionNode readMethodInvocation(MethodInvocation expression) { diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java index ca0f87a..2f68380 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -70,7 +70,7 @@ public class JavaReader { name, superTypes(type), body.getFields(), - list(), + body.getStaticConstructor(), body.getConstructor(), body.getMethods()); } @@ -231,11 +231,17 @@ public class JavaReader { private static class TypeDeclarationBody { private final List<FieldDeclarationNode> fields; + private final List<StatementNode> staticConstructor; private final ConstructorNode constructor; private final List<MethodNode> methods; - public TypeDeclarationBody(List<FieldDeclarationNode> fields, ConstructorNode constructor, List<MethodNode> methods) { + public TypeDeclarationBody( + List<FieldDeclarationNode> fields, + List<StatementNode> staticConstructor, ConstructorNode constructor, + List<MethodNode> methods) + { this.fields = fields; + this.staticConstructor = staticConstructor; this.constructor = constructor; this.methods = methods; } @@ -244,6 +250,10 @@ public class JavaReader { return fields; } + public List<StatementNode> getStaticConstructor() { + return staticConstructor; + } + public ConstructorNode getConstructor() { return constructor; } @@ -264,8 +274,14 @@ public class JavaReader { methods.add((MethodNode) callable); } } + // TODO: handle instance initializers + List<Initializer> initializers = ofType(bodyDeclarations, Initializer.class); + List<StatementNode> staticConstructor = eagerFlatMap( + initializers, + initializer -> readStatement(scope, initializer.getBody())); return new TypeDeclarationBody( readFields(ofType(bodyDeclarations, FieldDeclaration.class)), + staticConstructor, constructor, methods.build()); } @@ -330,6 +346,11 @@ public class JavaReader { return readStatements(scope, statements, returnType); } + List<StatementNode> readStatement(Scope scope, Statement statement) { + JavaStatementReader statementReader = new JavaStatementReader(scope, expressionReader(scope), Optional.empty()); + return statementReader.readStatement(statement); + } + List<StatementNode> readStatements(Scope scope, List<Statement> body, Optional<TypeName> returnType) { JavaStatementReader statementReader = new JavaStatementReader(scope, expressionReader(scope), returnType); return eagerFlatMap(body, statementReader::readStatement); diff --git a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java index 6bc0816..13484c2 100644 --- a/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java +++ b/src/test/java/org/zwobble/couscous/tests/frontends/java/JavaReaderTests.java @@ -99,6 +99,32 @@ public class JavaReaderTests { StringValue.REF), returnNode.getValue()); } + + @Test + public void canReadExplicitStaticFieldReference() { + canReadStaticFieldReference("this.name"); + } + + @Test + public void canReadImplicitStaticFieldReference() { + canReadStaticFieldReference("name"); + } + + private void canReadStaticFieldReference(String expression) { + ClassNode classNode = readClass( + "private static String name;" + + "public String getName() {" + + " return " + expression + ";" + + "}"); + + ReturnNode returnNode = (ReturnNode) classNode.getMethods().get(0).getBody().get(0); + assertEquals( + fieldAccess( + TypeName.of("com.example.Example"), + "name", + StringValue.REF), + returnNode.getValue()); + } @Test public void canReadInstanceMethodCalls() { @@ -610,6 +636,26 @@ public class JavaReaderTests { literal("Flaws"))), constructor.getBody()); } + + @Test + public void canDeclareStaticConstructor() { + ClassNode classNode = readClass( + "private static final String name;" + + "static {" + + " name = \"Flaws\";" + + "}"); + + List<StatementNode> staticConstructor = classNode.getStaticConstructor(); + + assertEquals( + list(assignStatement( + fieldAccess( + TypeName.of("com.example.Example"), + "name", + StringValue.REF), + literal("Flaws"))), + staticConstructor); + } @Test public void canDeclareStaticMethodWithAnnotation() { |
