diff options
author | cushon <cushon@google.com> | 2016-10-31 19:20:19 -0700 |
---|---|---|
committer | Liam Miller-Cushon <cushon@google.com> | 2016-10-31 20:15:31 -0700 |
commit | 57c8dbfe42ab7413b1450f74d8f3a19a9f214dec (patch) | |
tree | f2ccdd40f9536c2684385118516bf36590c8bc3b | |
parent | cb5c2b23fe5c5adda2085043425e882009c456eb (diff) | |
download | turbine-57c8dbfe42ab7413b1450f74d8f3a19a9f214dec.tar.gz |
Initial implementation of receiver parameters
MOE_MIGRATED_REVID=137778383
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) {} +} |