aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcushon <cushon@google.com>2016-10-31 19:20:19 -0700
committerLiam Miller-Cushon <cushon@google.com>2016-10-31 20:15:31 -0700
commit57c8dbfe42ab7413b1450f74d8f3a19a9f214dec (patch)
treef2ccdd40f9536c2684385118516bf36590c8bc3b
parentcb5c2b23fe5c5adda2085043425e882009c456eb (diff)
downloadturbine-57c8dbfe42ab7413b1450f74d8f3a19a9f214dec.tar.gz
Initial implementation of receiver parameters
MOE_MIGRATED_REVID=137778383
-rw-r--r--java/com/google/turbine/binder/CanonicalTypeBinder.java3
-rw-r--r--java/com/google/turbine/binder/ConstBinder.java11
-rw-r--r--java/com/google/turbine/binder/DisambiguateTypeAnnotations.java3
-rw-r--r--java/com/google/turbine/binder/TypeBinder.java25
-rw-r--r--java/com/google/turbine/binder/bound/TypeBoundClass.java10
-rw-r--r--java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java3
-rw-r--r--java/com/google/turbine/lower/Lower.java8
-rw-r--r--java/com/google/turbine/parse/Parser.java23
-rw-r--r--javatests/com/google/turbine/lower/LowerIntegrationTest.java1
-rw-r--r--javatests/com/google/turbine/lower/LowerTest.java6
-rw-r--r--javatests/com/google/turbine/lower/testdata/receiver_param.test19
11 files changed, 94 insertions, 18 deletions
diff --git a/java/com/google/turbine/binder/CanonicalTypeBinder.java b/java/com/google/turbine/binder/CanonicalTypeBinder.java
index 9b7b0f6..edfc02d 100644
--- a/java/com/google/turbine/binder/CanonicalTypeBinder.java
+++ b/java/com/google/turbine/binder/CanonicalTypeBinder.java
@@ -114,7 +114,8 @@ public class CanonicalTypeBinder {
base.access(),
base.defaultValue(),
base.decl(),
- base.annotations()));
+ base.annotations(),
+ base.receiver()));
}
return result.build();
}
diff --git a/java/com/google/turbine/binder/ConstBinder.java b/java/com/google/turbine/binder/ConstBinder.java
index f737835..959e62a 100644
--- a/java/com/google/turbine/binder/ConstBinder.java
+++ b/java/com/google/turbine/binder/ConstBinder.java
@@ -125,19 +125,24 @@ public class ConstBinder {
base.access(),
value,
base.decl(),
- bindAnnotations(base.annotations(), scope));
+ bindAnnotations(base.annotations(), scope),
+ base.receiver() != null ? bindParameter(base.receiver(), scope) : null);
}
private ImmutableList<ParamInfo> bindParameters(
ImmutableList<ParamInfo> formals, CompoundScope scope) {
ImmutableList.Builder<ParamInfo> result = ImmutableList.builder();
for (ParamInfo base : formals) {
- ImmutableList<AnnoInfo> annos = bindAnnotations(base.annotations(), scope);
- result.add(new ParamInfo(bindType(base.type()), annos, base.synthetic()));
+ result.add(bindParameter(base, scope));
}
return result.build();
}
+ private ParamInfo bindParameter(ParamInfo base, CompoundScope scope) {
+ ImmutableList<AnnoInfo> annos = bindAnnotations(base.annotations(), scope);
+ return new ParamInfo(bindType(base.type()), annos, base.synthetic());
+ }
+
/** Returns the {@link RetentionPolicy} for an annotation declaration, or {@code null}. */
@Nullable
static RetentionPolicy bindRetention(TurbineTyKind kind, Iterable<AnnoInfo> annotations) {
diff --git a/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java b/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java
index 5ca0c0c..656d511 100644
--- a/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java
+++ b/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java
@@ -102,7 +102,8 @@ public class DisambiguateTypeAnnotations {
base.access(),
base.defaultValue(),
base.decl(),
- declarationAnnotations.build());
+ declarationAnnotations.build(),
+ base.receiver() != null ? bindParam(env, base.receiver()) : null);
}
private static ImmutableList<ParamInfo> bindParameters(
diff --git a/java/com/google/turbine/binder/TypeBinder.java b/java/com/google/turbine/binder/TypeBinder.java
index 8fd53d4..9fe340e 100644
--- a/java/com/google/turbine/binder/TypeBinder.java
+++ b/java/com/google/turbine/binder/TypeBinder.java
@@ -274,7 +274,8 @@ public class TypeBinder {
access,
null,
null,
- ImmutableList.of()));
+ ImmutableList.of(),
+ null));
}
private void addEnumMethods(List<MethodInfo> methods) {
@@ -294,7 +295,8 @@ public class TypeBinder {
TurbineFlag.ACC_PRIVATE | TurbineFlag.ACC_SYNTH_CTOR,
null,
null,
- ImmutableList.of()));
+ ImmutableList.of(),
+ null));
}
methods.add(
@@ -307,7 +309,8 @@ public class TypeBinder {
TurbineFlag.ACC_PUBLIC | TurbineFlag.ACC_STATIC,
null,
null,
- ImmutableList.of()));
+ ImmutableList.of(),
+ null));
methods.add(
new MethodInfo(
@@ -319,7 +322,8 @@ public class TypeBinder {
TurbineFlag.ACC_PUBLIC | TurbineFlag.ACC_STATIC,
null,
null,
- ImmutableList.of()));
+ ImmutableList.of(),
+ null));
}
private static boolean hasConstructor(List<MethodInfo> methods) {
@@ -416,10 +420,16 @@ public class TypeBinder {
/*synthetic*/ true));
}
}
+ ParamInfo receiver = null;
for (Tree.VarDecl p : t.params()) {
- parameters.add(
+ ParamInfo param =
new ParamInfo(
- bindTy(scope, p.ty()), bindAnnotations(scope, p.annos()), /*synthetic*/ false));
+ bindTy(scope, p.ty()), bindAnnotations(scope, p.annos()), /*synthetic*/ false);
+ if (p.name().equals("this")) {
+ receiver = param;
+ continue;
+ }
+ parameters.add(param);
}
ImmutableList.Builder<Type> exceptions = ImmutableList.builder();
for (Tree.ClassTy p : t.exntys()) {
@@ -460,7 +470,8 @@ public class TypeBinder {
access,
null,
t,
- annotations);
+ annotations,
+ receiver);
}
private static boolean hasEnclosingInstance(HeaderBoundClass base) {
diff --git a/java/com/google/turbine/binder/bound/TypeBoundClass.java b/java/com/google/turbine/binder/bound/TypeBoundClass.java
index 6fddf64..6232b93 100644
--- a/java/com/google/turbine/binder/bound/TypeBoundClass.java
+++ b/java/com/google/turbine/binder/bound/TypeBoundClass.java
@@ -153,6 +153,7 @@ public interface TypeBoundClass extends HeaderBoundClass {
private final Const defaultValue;
private final MethDecl decl;
private final ImmutableList<AnnoInfo> annotations;
+ private final ParamInfo receiver;
public MethodInfo(
MethodSymbol sym,
@@ -163,7 +164,8 @@ public interface TypeBoundClass extends HeaderBoundClass {
int access,
Const defaultValue,
MethDecl decl,
- ImmutableList<AnnoInfo> annotations) {
+ ImmutableList<AnnoInfo> annotations,
+ ParamInfo receiver) {
this.sym = sym;
this.tyParams = tyParams;
this.returnType = returnType;
@@ -173,6 +175,7 @@ public interface TypeBoundClass extends HeaderBoundClass {
this.defaultValue = defaultValue;
this.decl = decl;
this.annotations = annotations;
+ this.receiver = receiver;
}
/** The method symbol. */
@@ -224,6 +227,11 @@ public interface TypeBoundClass extends HeaderBoundClass {
public ImmutableList<AnnoInfo> annotations() {
return annotations;
}
+
+ /** Receiver parameter. */
+ public ParamInfo receiver() {
+ return receiver;
+ }
}
/** A formal parameter declaration. */
diff --git a/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java b/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java
index a6efe01..f0eed37 100644
--- a/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java
+++ b/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java
@@ -380,7 +380,8 @@ public class BytecodeBoundClass implements BoundClass, HeaderBoundClass, TypeBou
m.access(),
null /*defaultValue*/,
null /*decl*/,
- ImmutableList.of());
+ ImmutableList.of(),
+ null);
}
@Override
diff --git a/java/com/google/turbine/lower/Lower.java b/java/com/google/turbine/lower/Lower.java
index 84e0cab..62c0843 100644
--- a/java/com/google/turbine/lower/Lower.java
+++ b/java/com/google/turbine/lower/Lower.java
@@ -504,6 +504,14 @@ public class Lower {
}
}
+ if (m.receiver() != null) {
+ lowerTypeAnnotations(
+ result,
+ m.receiver().type(),
+ TargetType.METHOD_RECEIVER_PARAMETER,
+ TypeAnnotationInfo.EMPTY_TARGET);
+ }
+
lowerTypeAnnotations(
result, m.returnType(), TargetType.METHOD_RETURN, TypeAnnotationInfo.EMPTY_TARGET);
diff --git a/java/com/google/turbine/parse/Parser.java b/java/com/google/turbine/parse/Parser.java
index 7d70c00..f057fde 100644
--- a/java/com/google/turbine/parse/Parser.java
+++ b/java/com/google/turbine/parse/Parser.java
@@ -782,10 +782,29 @@ public class Parser {
ty = new ArrTy(position, typeAnnos, ty);
typeAnnos = maybeAnnos();
}
- String name = eatIdent();
+ // the parameter name is `this` for receiver parameters, and a qualified this expression
+ // for inner classes
+ String name = identOrThis();
+ while (token == Token.DOT) {
+ eat(Token.DOT);
+ // Overwrite everything up to the terminal 'this' for inner classes; we don't need it
+ name = identOrThis();
+ }
return new VarDecl(position, access, annos.build(), ty, name, Optional.<Expression>absent());
}
+ private String identOrThis() {
+ switch (token) {
+ case IDENT:
+ return eatIdent();
+ case THIS:
+ eat(Token.THIS);
+ return "this";
+ default:
+ throw error(token);
+ }
+ }
+
private void dropParens() {
eat(Token.LPAREN);
int depth = 1;
@@ -1122,7 +1141,7 @@ public class Parser {
private void eat(Token kind) {
if (token != kind) {
- throw error(token);
+ throw error("expected %s, was %s", kind, token);
}
next();
}
diff --git a/javatests/com/google/turbine/lower/LowerIntegrationTest.java b/javatests/com/google/turbine/lower/LowerIntegrationTest.java
index 2042f1c..220c91e 100644
--- a/javatests/com/google/turbine/lower/LowerIntegrationTest.java
+++ b/javatests/com/google/turbine/lower/LowerIntegrationTest.java
@@ -251,6 +251,7 @@ public class LowerIntegrationTest {
"unicode.test",
"annotation_scope.test",
"visible_package_private_toplevel.test",
+ "receiver_param.test",
};
List<Object[]> tests =
ImmutableList.copyOf(testCases).stream().map(x -> new Object[] {x}).collect(toList());
diff --git a/javatests/com/google/turbine/lower/LowerTest.java b/javatests/com/google/turbine/lower/LowerTest.java
index 65f3dfb..6864a7d 100644
--- a/javatests/com/google/turbine/lower/LowerTest.java
+++ b/javatests/com/google/turbine/lower/LowerTest.java
@@ -105,7 +105,8 @@ public class LowerTest {
TurbineFlag.ACC_STATIC | TurbineFlag.ACC_PUBLIC,
null,
null,
- ImmutableList.of()),
+ ImmutableList.of(),
+ null),
new SourceTypeBoundClass.MethodInfo(
new MethodSymbol(new ClassSymbol("test/Test"), "g"),
ImmutableMap.of(
@@ -143,7 +144,8 @@ public class LowerTest {
TurbineFlag.ACC_PUBLIC,
null,
null,
- ImmutableList.of()));
+ ImmutableList.of(),
+ null));
ImmutableList<SourceTypeBoundClass.FieldInfo> fields =
ImmutableList.of(
new SourceTypeBoundClass.FieldInfo(
diff --git a/javatests/com/google/turbine/lower/testdata/receiver_param.test b/javatests/com/google/turbine/lower/testdata/receiver_param.test
new file mode 100644
index 0000000..72e9c9a
--- /dev/null
+++ b/javatests/com/google/turbine/lower/testdata/receiver_param.test
@@ -0,0 +1,19 @@
+=== Test.java ===
+package p;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE_USE) @interface A {}
+@Target(ElementType.TYPE_USE) @interface B {}
+
+class Test {
+ class Inner {
+ Inner(Test Test.this) {}
+ class InnerMost {
+ InnerMost(Inner p.Test.Inner.this) {}
+ }
+ }
+
+ void f(@A Test this, int x) {}
+}