Handle array class literals, which can appear in annotations
MOE_MIGRATED_REVID=137779342
diff --git a/java/com/google/turbine/binder/ConstEvaluator.java b/java/com/google/turbine/binder/ConstEvaluator.java
index 07c95c4..29a8836 100644
--- a/java/com/google/turbine/binder/ConstEvaluator.java
+++ b/java/com/google/turbine/binder/ConstEvaluator.java
@@ -147,16 +147,22 @@
/** Evaluates a class literal. */
Const evalClassLiteral(ClassLiteral t) {
- switch (t.type().kind()) {
+ return new ClassValue(evalClassLiteralType(t.type()));
+ }
+
+ private Type evalClassLiteralType(Tree.Type type) {
+ switch (type.kind()) {
case PRIM_TY:
- return new ClassValue(new Type.PrimTy(((PrimTy) t.type()).tykind(), ImmutableList.of()));
+ return new Type.PrimTy(((PrimTy) type).tykind(), ImmutableList.of());
case VOID_TY:
- return new ClassValue(Type.VOID);
+ return Type.VOID;
case CLASS_TY:
- return new ClassValue(
- Type.ClassTy.asNonParametricClassTy(resolveClass((ClassTy) t.type())));
+ return Type.ClassTy.asNonParametricClassTy(resolveClass((ClassTy) type));
+ case ARR_TY:
+ return new Type.ArrayTy(
+ evalClassLiteralType(((Tree.ArrTy) type).elem()), ImmutableList.of());
default:
- throw new AssertionError(t.type().kind());
+ throw new AssertionError(type.kind());
}
}
diff --git a/java/com/google/turbine/parse/ConstExpressionParser.java b/java/com/google/turbine/parse/ConstExpressionParser.java
index 87a4e96..c8bca7b 100644
--- a/java/com/google/turbine/parse/ConstExpressionParser.java
+++ b/java/com/google/turbine/parse/ConstExpressionParser.java
@@ -152,7 +152,8 @@
case BOOLEAN:
return primitiveClassLiteral(TurbineConstantTypeKind.BOOLEAN);
case VOID:
- return primitiveClassLiteral(new Tree.VoidTy(position, ImmutableList.of()));
+ eat();
+ return finishClassLiteral(position, new Tree.VoidTy(position, ImmutableList.of()));
case AT:
return annotation();
default:
@@ -161,20 +162,8 @@
}
private Expression primitiveClassLiteral(TurbineConstantTypeKind type) {
- return primitiveClassLiteral(new Tree.PrimTy(position, ImmutableList.of(), type));
- }
-
- private Expression primitiveClassLiteral(Tree.Type type) {
eat();
- if (token != Token.DOT) {
- return null;
- }
- eat();
- if (token != Token.CLASS) {
- return null;
- }
- eat();
- return new ClassLiteral(position, type);
+ return finishClassLiteral(position, new Tree.PrimTy(position, ImmutableList.of(), type));
}
private Tree.Expression maybeCast() {
@@ -428,6 +417,9 @@
ImmutableList.Builder<String> bits = ImmutableList.builder();
bits.add(lexer.stringValue());
eat();
+ if (token == Token.LBRACK) {
+ return finishClassLiteral(pos, asClassTy(bits.build()));
+ }
while (token == Token.DOT) {
eat();
switch (token) {
@@ -446,6 +438,26 @@
return new Tree.ConstVarName(pos, bits.build());
}
+ private Expression finishClassLiteral(int pos, Tree.Type type) {
+ while (token == Token.LBRACK) {
+ eat();
+ if (token != Token.RBRACK) {
+ return null;
+ }
+ eat();
+ type = new Tree.ArrTy(position, ImmutableList.of(), type);
+ }
+ if (token != Token.DOT) {
+ return null;
+ }
+ eat();
+ if (token != Token.CLASS) {
+ return null;
+ }
+ eat();
+ return new ClassLiteral(pos, type);
+ }
+
public Tree.Expression expression() {
Tree.Expression result = expression(null);
switch (token) {
diff --git a/java/com/google/turbine/parse/Parser.java b/java/com/google/turbine/parse/Parser.java
index 5740701..1762282 100644
--- a/java/com/google/turbine/parse/Parser.java
+++ b/java/com/google/turbine/parse/Parser.java
@@ -1126,7 +1126,11 @@
eat(LPAREN);
while (token != RPAREN) {
ConstExpressionParser cparser = new ConstExpressionParser(lexer, token);
- args.add(cparser.expression());
+ Expression arg = cparser.expression();
+ if (arg == null) {
+ throw error("invalid annotation argument");
+ }
+ args.add(arg);
token = cparser.token;
if (!maybe(COMMA)) {
break;
diff --git a/javatests/com/google/turbine/lower/LowerIntegrationTest.java b/javatests/com/google/turbine/lower/LowerIntegrationTest.java
index 26282e4..cd41dd6 100644
--- a/javatests/com/google/turbine/lower/LowerIntegrationTest.java
+++ b/javatests/com/google/turbine/lower/LowerIntegrationTest.java
@@ -254,6 +254,7 @@
"receiver_param.test",
"static_member_type_import.test",
"type_anno_qual.test",
+ "array_class_literal.test",
};
List<Object[]> tests =
ImmutableList.copyOf(testCases).stream().map(x -> new Object[] {x}).collect(toList());
diff --git a/javatests/com/google/turbine/lower/testdata/array_class_literal.test b/javatests/com/google/turbine/lower/testdata/array_class_literal.test
new file mode 100644
index 0000000..9033b04
--- /dev/null
+++ b/javatests/com/google/turbine/lower/testdata/array_class_literal.test
@@ -0,0 +1,11 @@
+=== Test.java ===
+@interface Anno {
+ Class<?> value() default Object.class;
+}
+
+class Test {
+ @Anno(byte[].class) int a;
+ @Anno(byte[][].class) int b;
+ @Anno(int[][].class) int c;
+ @Anno(Object[].class) int d;
+}