aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2016-04-22 21:34:36 +0100
committerMichael Williamson <mike@zwobble.org>2016-04-22 21:34:36 +0100
commit3bfe9eaf41f994221dc11090c5c3a283a49310ab (patch)
tree79e010cceb19d436a2cfad330c78d7d6aa01f6eb
parent8b80e624f5279b637497e65eb944ad930d522aef (diff)
Add support for this references in anonymous types
-rw-r--r--src/main/java/org/zwobble/couscous/ast/sugar/AnonymousClass.java10
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/AnonymousType.java35
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java15
-rw-r--r--src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java2
-rw-r--r--src/test/java/org/zwobble/couscous/tests/CompilerTests.java2
-rw-r--r--src/test/resources/java/anonymous-class-this-reference/com/example/AnonymousClass.java18
-rw-r--r--src/test/resources/java/anonymous-class-this-reference/com/example/IntSupplier.java5
7 files changed, 81 insertions, 6 deletions
diff --git a/src/main/java/org/zwobble/couscous/ast/sugar/AnonymousClass.java b/src/main/java/org/zwobble/couscous/ast/sugar/AnonymousClass.java
index edf71d4..08bb9a3 100644
--- a/src/main/java/org/zwobble/couscous/ast/sugar/AnonymousClass.java
+++ b/src/main/java/org/zwobble/couscous/ast/sugar/AnonymousClass.java
@@ -2,27 +2,35 @@ package org.zwobble.couscous.ast.sugar;
import org.zwobble.couscous.ast.FieldDeclarationNode;
import org.zwobble.couscous.ast.MethodNode;
+import org.zwobble.couscous.frontends.java.AnonymousType;
import org.zwobble.couscous.types.Type;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
public class AnonymousClass {
+ private final Optional<AnonymousType> type;
private final Set<Type> superTypes;
private final List<FieldDeclarationNode> fields;
private final List<MethodNode> methods;
public AnonymousClass(
+ Optional<AnonymousType> type,
Set<Type> superTypes,
List<FieldDeclarationNode> fields,
List<MethodNode> methods)
{
-
+ this.type = type;
this.superTypes = superTypes;
this.fields = fields;
this.methods = methods;
}
+ public Optional<AnonymousType> getType() {
+ return type;
+ }
+
public Set<Type> getSuperTypes() {
return superTypes;
}
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/AnonymousType.java b/src/main/java/org/zwobble/couscous/frontends/java/AnonymousType.java
new file mode 100644
index 0000000..845c6f9
--- /dev/null
+++ b/src/main/java/org/zwobble/couscous/frontends/java/AnonymousType.java
@@ -0,0 +1,35 @@
+package org.zwobble.couscous.frontends.java;
+
+import org.zwobble.couscous.types.Type;
+
+public class AnonymousType implements Type {
+ public static Type anonymousType(String key) {
+ return new AnonymousType(key);
+ }
+
+ private final String key;
+
+ public AnonymousType(String key) {
+ this.key = key;
+ }
+
+ @Override
+ public <T> T accept(Visitor<T> visitor) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AnonymousType that = (AnonymousType) o;
+
+ return key.equals(that.key);
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode();
+ }
+}
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 08adbcc..7fae204 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java
@@ -49,6 +49,7 @@ import static org.zwobble.couscous.types.Types.erasure;
import static org.zwobble.couscous.util.Casts.tryCast;
import static org.zwobble.couscous.util.ExtraIterables.lazyMap;
import static org.zwobble.couscous.util.ExtraLists.*;
+import static org.zwobble.couscous.util.ExtraMaps.map;
public class JavaReader {
public static List<TypeNode> readClassesFromFiles(List<Path> sourcePaths, List<Path> sourceFiles) throws IOException {
@@ -183,6 +184,7 @@ public class JavaReader {
overrides(functionalInterfaceMethod));
return new AnonymousClass(
+ Optional.empty(),
superTypesAndSelf(functionalInterfaceMethod.getDeclaringClass()),
list(),
list(method));
@@ -233,6 +235,7 @@ public class JavaReader {
Scope scope = outerScope.enterClass(className);
TypeDeclarationBody bodyDeclarations = readTypeDeclarationBody(scope, className, declaration.bodyDeclarations());
AnonymousClass anonymousClass = new AnonymousClass(
+ Optional.of((AnonymousType) typeOf(declaration.resolveBinding())),
superTypes(declaration),
bodyDeclarations.getFields(),
bodyDeclarations.getMethods());
@@ -305,14 +308,22 @@ public class JavaReader {
ScalarType className,
AnonymousClass anonymousClass
) {
- return classWithCapture(scope, ClassNode.declareClass(
+ ClassNode classNode = ClassNode.declareClass(
className,
list(),
anonymousClass.getSuperTypes(),
anonymousClass.getFields(),
list(),
ConstructorNode.DEFAULT,
- anonymousClass.getMethods()));
+ anonymousClass.getMethods());
+ if (anonymousClass.getType().isPresent()) {
+ NodeTransformer nodeTransformer = NodeTransformer.replaceExpressions(map(
+ thisReference(anonymousClass.getType().get()),
+ thisReference(className)
+ ));
+ classNode = classNode.transform(nodeTransformer);
+ }
+ return classWithCapture(scope, classNode);
}
private FieldDeclarationNode fieldForCapture(ReferenceNode freeVariable) {
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java
index 1421e83..9b634b9 100644
--- a/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java
+++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java
@@ -37,7 +37,7 @@ public class JavaTypes {
static Type typeOf(ITypeBinding typeBinding) {
if (typeBinding.isAnonymous()) {
- throw new RuntimeException("Cannot get type of anonymous type binding");
+ return new AnonymousType(typeBinding.getKey());
}
if (typeBinding.isArray()) {
return Types.array(typeOf(typeBinding.getElementType()));
diff --git a/src/test/java/org/zwobble/couscous/tests/CompilerTests.java b/src/test/java/org/zwobble/couscous/tests/CompilerTests.java
index 1408ca9..be3ca29 100644
--- a/src/test/java/org/zwobble/couscous/tests/CompilerTests.java
+++ b/src/test/java/org/zwobble/couscous/tests/CompilerTests.java
@@ -1,6 +1,5 @@
package org.zwobble.couscous.tests;
-import org.junit.Ignore;
import org.junit.Test;
import org.zwobble.couscous.types.ScalarType;
import org.zwobble.couscous.types.Types;
@@ -158,7 +157,6 @@ public abstract class CompilerTests {
}
@Test
- @Ignore("WIP")
public void anonymousClassesWithThisReference() throws Exception {
assertEquals(
value(42),
diff --git a/src/test/resources/java/anonymous-class-this-reference/com/example/AnonymousClass.java b/src/test/resources/java/anonymous-class-this-reference/com/example/AnonymousClass.java
new file mode 100644
index 0000000..6269b0b
--- /dev/null
+++ b/src/test/resources/java/anonymous-class-this-reference/com/example/AnonymousClass.java
@@ -0,0 +1,18 @@
+package com.example;
+
+public class AnonymousClass {
+ public static int value() {
+ IntSupplier supplier = new IntSupplier() {
+ @Override
+ public int get() {
+ return 21 * factor();
+ }
+
+ private int factor() {
+ return 2;
+ }
+ };
+
+ return supplier.get();
+ }
+}
diff --git a/src/test/resources/java/anonymous-class-this-reference/com/example/IntSupplier.java b/src/test/resources/java/anonymous-class-this-reference/com/example/IntSupplier.java
new file mode 100644
index 0000000..4c5e5a5
--- /dev/null
+++ b/src/test/resources/java/anonymous-class-this-reference/com/example/IntSupplier.java
@@ -0,0 +1,5 @@
+package com.example;
+
+public interface IntSupplier {
+ int get();
+}