aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2017-11-18 07:11:37 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-11-18 07:11:37 +0000
commit80375a9329669589dca4abd5228ad2366d8ff5f3 (patch)
tree750b180b6de65bb672f72f1e11e1970c846698a8
parent323c7ea1a82ce4e44d30de7ed00b3af200e72a87 (diff)
parent839fa39f9c9b3acfd36a743bf09382df9ce66345 (diff)
downloadturbine-pie-qpr1-s2-release.tar.gz
am: 839fa39f9c Change-Id: I77e64b2ad724a85710e03beec91d6a8b302a61fb
-rw-r--r--java/com/google/turbine/binder/ConstEvaluator.java15
-rw-r--r--java/com/google/turbine/binder/DisambiguateTypeAnnotations.java7
-rw-r--r--java/com/google/turbine/binder/TypeBinder.java17
-rw-r--r--java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java2
-rw-r--r--java/com/google/turbine/binder/sym/FieldSymbol.java5
-rw-r--r--java/com/google/turbine/binder/sym/MethodSymbol.java5
-rw-r--r--java/com/google/turbine/binder/sym/TyVarSymbol.java5
-rw-r--r--java/com/google/turbine/bytecode/ClassReader.java32
-rw-r--r--java/com/google/turbine/deps/Dependencies.java17
-rw-r--r--java/com/google/turbine/diag/TurbineError.java4
-rw-r--r--java/com/google/turbine/parse/Parser.java33
-rw-r--r--java/com/google/turbine/type/AnnoInfo.java27
-rw-r--r--javatests/com/google/turbine/binder/BinderErrorTest.java81
-rw-r--r--javatests/com/google/turbine/bytecode/ClassReaderTest.java25
-rw-r--r--javatests/com/google/turbine/bytecode/ClassWriterTest.java2
-rw-r--r--javatests/com/google/turbine/deps/AbstractTransitiveTest.java6
-rw-r--r--javatests/com/google/turbine/deps/DependenciesTest.java44
-rw-r--r--pom.xml2
18 files changed, 286 insertions, 43 deletions
diff --git a/java/com/google/turbine/binder/ConstEvaluator.java b/java/com/google/turbine/binder/ConstEvaluator.java
index b8243b9..0598d8e 100644
--- a/java/com/google/turbine/binder/ConstEvaluator.java
+++ b/java/com/google/turbine/binder/ConstEvaluator.java
@@ -878,7 +878,7 @@ public strictfp class ConstEvaluator {
ImmutableList<AnnoInfo> evaluateAnnotations(ImmutableList<AnnoInfo> annotations) {
ImmutableList.Builder<AnnoInfo> result = ImmutableList.builder();
for (AnnoInfo annotation : annotations) {
- result.add(evaluateAnnotation(annotation.sym(), annotation.args()));
+ result.add(evaluateAnnotation(annotation));
}
return result.build();
}
@@ -887,14 +887,14 @@ public strictfp class ConstEvaluator {
* Evaluates annotation arguments given the symbol of the annotation declaration and a list of
* expression trees.
*/
- AnnoInfo evaluateAnnotation(ClassSymbol sym, ImmutableList<Expression> args) {
+ AnnoInfo evaluateAnnotation(AnnoInfo info) {
Map<String, Type> template = new LinkedHashMap<>();
- for (MethodInfo method : env.get(sym).methods()) {
+ for (MethodInfo method : env.get(info.sym()).methods()) {
template.put(method.name(), method.returnType());
}
ImmutableMap.Builder<String, Const> values = ImmutableMap.builder();
- for (Expression arg : args) {
+ for (Expression arg : info.args()) {
Expression expr;
String key;
if (arg.kind() == Tree.Kind.ASSIGN) {
@@ -916,7 +916,7 @@ public strictfp class ConstEvaluator {
}
values.put(key, value);
}
- return new AnnoInfo(sym, args, values.build());
+ return info.withValues(values.build());
}
private AnnotationValue evalAnno(Tree.Anno t) {
@@ -925,7 +925,7 @@ public strictfp class ConstEvaluator {
for (String name : result.remaining()) {
sym = Resolve.resolve(env, sym, sym, name);
}
- AnnoInfo annoInfo = evaluateAnnotation(sym, t.args());
+ AnnoInfo annoInfo = evaluateAnnotation(new AnnoInfo(base.source(), sym, t, null));
return new AnnotationValue(annoInfo.sym(), annoInfo.values());
}
@@ -946,6 +946,9 @@ public strictfp class ConstEvaluator {
throw error(tree.position(), ErrorKind.EXPRESSION_ERROR);
}
Const value = eval(tree);
+ if (value == null) {
+ throw error(tree.position(), ErrorKind.EXPRESSION_ERROR);
+ }
switch (ty.tyKind()) {
case PRIM_TY:
return coerce((Const.Value) value, ((Type.PrimTy) ty).primkind());
diff --git a/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java b/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java
index afb899c..26dce32 100644
--- a/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java
+++ b/java/com/google/turbine/binder/DisambiguateTypeAnnotations.java
@@ -31,6 +31,8 @@ import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo;
import com.google.turbine.binder.bound.TypeBoundClass.ParamInfo;
import com.google.turbine.binder.env.Env;
import com.google.turbine.binder.sym.ClassSymbol;
+import com.google.turbine.diag.TurbineError;
+import com.google.turbine.diag.TurbineError.ErrorKind;
import com.google.turbine.model.Const;
import com.google.turbine.type.AnnoInfo;
import com.google.turbine.type.Type;
@@ -248,10 +250,13 @@ public class DisambiguateTypeAnnotations {
}
ClassSymbol container = env.get(symbol).annotationMetadata().repeatable();
if (container == null) {
- throw new AssertionError(symbol);
+ AnnoInfo anno = infos.iterator().next();
+ throw TurbineError.format(
+ anno.source(), anno.position(), ErrorKind.NONREPEATABLE_ANNOTATION, symbol);
}
result.add(
new AnnoInfo(
+ null,
container,
null,
ImmutableMap.of("value", new Const.ArrayInitValue(elements.build()))));
diff --git a/java/com/google/turbine/binder/TypeBinder.java b/java/com/google/turbine/binder/TypeBinder.java
index 5bee45d..b8f6ecd 100644
--- a/java/com/google/turbine/binder/TypeBinder.java
+++ b/java/com/google/turbine/binder/TypeBinder.java
@@ -16,6 +16,7 @@
package com.google.turbine.binder;
+import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.turbine.binder.bound.HeaderBoundClass;
@@ -51,8 +52,10 @@ import com.google.turbine.type.AnnoInfo;
import com.google.turbine.type.Type;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/** Type binding. */
public class TypeBinder {
@@ -515,10 +518,15 @@ public class TypeBinder {
}
private ImmutableList<FieldInfo> bindFields(CompoundScope scope, ImmutableList<Tree> members) {
+ Set<FieldSymbol> seen = new HashSet<>();
ImmutableList.Builder<FieldInfo> fields = ImmutableList.builder();
for (Tree member : members) {
if (member.kind() == Tree.Kind.VAR_DECL) {
- fields.add(bindField(scope, (Tree.VarDecl) member));
+ FieldInfo field = bindField(scope, (Tree.VarDecl) member);
+ if (!seen.add(field.sym())) {
+ throw error(member.position(), ErrorKind.DUPLICATE_DECLARATION, "field: " + field.name());
+ }
+ fields.add(field);
}
}
return fields.build();
@@ -549,16 +557,19 @@ public class TypeBinder {
for (Tree.Anno tree : trees) {
LookupResult lookupResult = scope.lookup(new LookupKey(tree.name()));
if (lookupResult == null) {
- throw error(tree.position(), ErrorKind.SYMBOL_NOT_FOUND, tree.name());
+ throw error(tree.position(), ErrorKind.SYMBOL_NOT_FOUND, Joiner.on('.').join(tree.name()));
}
ClassSymbol sym = (ClassSymbol) lookupResult.sym();
for (String name : lookupResult.remaining()) {
sym = Resolve.resolve(env, owner, sym, name);
+ if (sym == null) {
+ throw error(tree.position(), ErrorKind.SYMBOL_NOT_FOUND, name);
+ }
}
if (env.get(sym).kind() != TurbineTyKind.ANNOTATION) {
throw error(tree.position(), ErrorKind.NOT_AN_ANNOTATION, sym);
}
- result.add(new AnnoInfo(sym, tree.args(), null));
+ result.add(new AnnoInfo(base.source(), sym, tree, null));
}
return result.build();
}
diff --git a/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java b/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java
index b2ca745..76a06e5 100644
--- a/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java
+++ b/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java
@@ -83,7 +83,7 @@ public class BytecodeBoundClass implements BoundClass, HeaderBoundClass, TypeBou
new Supplier<ClassFile>() {
@Override
public ClassFile get() {
- ClassFile cf = ClassReader.read(bytes.get());
+ ClassFile cf = ClassReader.read(jarFile + "!" + sym, bytes.get());
verify(
cf.name().equals(sym.binaryName()),
"expected class data for %s, saw %s instead",
diff --git a/java/com/google/turbine/binder/sym/FieldSymbol.java b/java/com/google/turbine/binder/sym/FieldSymbol.java
index 9ff8fb1..21304e7 100644
--- a/java/com/google/turbine/binder/sym/FieldSymbol.java
+++ b/java/com/google/turbine/binder/sym/FieldSymbol.java
@@ -58,4 +58,9 @@ public class FieldSymbol implements Symbol {
FieldSymbol other = (FieldSymbol) obj;
return name().equals(other.name()) && owner().equals(other.owner());
}
+
+ @Override
+ public String toString() {
+ return owner + "#" + name;
+ }
}
diff --git a/java/com/google/turbine/binder/sym/MethodSymbol.java b/java/com/google/turbine/binder/sym/MethodSymbol.java
index 17459b4..b2050f4 100644
--- a/java/com/google/turbine/binder/sym/MethodSymbol.java
+++ b/java/com/google/turbine/binder/sym/MethodSymbol.java
@@ -58,4 +58,9 @@ public class MethodSymbol implements Symbol {
MethodSymbol other = (MethodSymbol) obj;
return name().equals(other.name()) && owner().equals(other.owner());
}
+
+ @Override
+ public String toString() {
+ return owner + "#" + name;
+ }
}
diff --git a/java/com/google/turbine/binder/sym/TyVarSymbol.java b/java/com/google/turbine/binder/sym/TyVarSymbol.java
index 9276f91..a73a79e 100644
--- a/java/com/google/turbine/binder/sym/TyVarSymbol.java
+++ b/java/com/google/turbine/binder/sym/TyVarSymbol.java
@@ -59,4 +59,9 @@ public class TyVarSymbol implements Symbol {
TyVarSymbol other = (TyVarSymbol) obj;
return name.equals(other.name()) && owner().equals(other.owner());
}
+
+ @Override
+ public String toString() {
+ return owner + "#" + name;
+ }
}
diff --git a/java/com/google/turbine/bytecode/ClassReader.java b/java/com/google/turbine/bytecode/ClassReader.java
index b59448a..96ad454 100644
--- a/java/com/google/turbine/bytecode/ClassReader.java
+++ b/java/com/google/turbine/bytecode/ClassReader.java
@@ -26,30 +26,50 @@ import com.google.turbine.model.TurbineFlag;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
/** A JVMS ยง4 class file reader. */
public class ClassReader {
/** Reads the given bytes into an {@link ClassFile}. */
+ @Deprecated
public static ClassFile read(byte[] bytes) {
- return new ClassReader(bytes).read();
+ return read(null, bytes);
}
+ /** Reads the given bytes into an {@link ClassFile}. */
+ public static ClassFile read(@Nullable String path, byte[] bytes) {
+ return new ClassReader(path, bytes).read();
+ }
+
+ @Nullable private final String path;
private final ByteReader reader;
- private ClassReader(byte[] bytes) {
+ private ClassReader(@Nullable String path, byte[] bytes) {
+ this.path = path;
this.reader = new ByteReader(bytes, 0);
}
+ @CheckReturnValue
+ Error error(String format, Object... args) {
+ StringBuilder sb = new StringBuilder();
+ if (path != null) {
+ sb.append(path).append(": ");
+ }
+ sb.append(String.format(format, args));
+ return new AssertionError(sb.toString());
+ }
+
private ClassFile read() {
int magic = reader.u4();
if (magic != 0xcafebabe) {
- throw new AssertionError(String.format("bad magic: 0x%x", magic));
+ throw error("bad magic: 0x%x", path, magic);
}
int minorVersion = reader.u2();
int majorVersion = reader.u2();
- if (majorVersion < 45 || majorVersion > 52) {
- throw new AssertionError(String.format("bad version: %d.%d", majorVersion, minorVersion));
+ if (majorVersion < 45 || majorVersion > 53) {
+ throw error("bad version: %d.%d", majorVersion, minorVersion);
}
ConstantPoolReader constantPool = ConstantPoolReader.readConstantPool(reader);
int accessFlags = reader.u2();
@@ -253,7 +273,7 @@ public class ClassReader {
break;
}
default:
- throw new AssertionError(String.format("bad tag value %c", tag));
+ throw error("bad tag value %c", tag);
}
return null;
}
diff --git a/java/com/google/turbine/deps/Dependencies.java b/java/com/google/turbine/deps/Dependencies.java
index 110d420..a6ac05f 100644
--- a/java/com/google/turbine/deps/Dependencies.java
+++ b/java/com/google/turbine/deps/Dependencies.java
@@ -52,6 +52,7 @@ public class Dependencies {
Lowered lowered) {
DepsProto.Dependencies.Builder deps = DepsProto.Dependencies.newBuilder();
Set<ClassSymbol> closure = superTypeClosure(bound, lowered);
+ addPackageInfos(closure, bound);
Set<String> jars = new LinkedHashSet<>();
for (ClassSymbol sym : closure) {
BytecodeBoundClass info = bound.classPathEnv().get(sym);
@@ -108,6 +109,22 @@ public class Dependencies {
}
}
+ private static void addPackageInfos(Set<ClassSymbol> closure, BindingResult bound) {
+ Set<ClassSymbol> packages = new LinkedHashSet<>();
+ for (ClassSymbol sym : closure) {
+ int idx = sym.binaryName().lastIndexOf('/');
+ if (idx == -1) {
+ continue;
+ }
+ packages.add(new ClassSymbol(sym.binaryName().substring(0, idx) + "/package-info"));
+ }
+ for (ClassSymbol pkg : packages) {
+ if (bound.classPathEnv().get(pkg) != null) {
+ closure.add(pkg);
+ }
+ }
+ }
+
/**
* Filters a transitive classpath to contain only the entries for direct dependencies, and the
* types needed to compile those direct deps as reported by jdeps.
diff --git a/java/com/google/turbine/diag/TurbineError.java b/java/com/google/turbine/diag/TurbineError.java
index 9db3b67..22abd3e 100644
--- a/java/com/google/turbine/diag/TurbineError.java
+++ b/java/com/google/turbine/diag/TurbineError.java
@@ -39,7 +39,9 @@ public class TurbineError extends Error {
CANNOT_RESOLVE("cannot resolve %s"),
EXPRESSION_ERROR("could not evaluate constant expression"),
CYCLIC_HIERARCHY("cycle in class hierarchy: %s"),
- NOT_AN_ANNOTATION("%s is not an annotation");
+ NOT_AN_ANNOTATION("%s is not an annotation"),
+ NONREPEATABLE_ANNOTATION("%s is not @Repeatable"),
+ DUPLICATE_DECLARATION("duplicate declaration of %s");
private final String message;
diff --git a/java/com/google/turbine/parse/Parser.java b/java/com/google/turbine/parse/Parser.java
index 1ec8a38..88529de 100644
--- a/java/com/google/turbine/parse/Parser.java
+++ b/java/com/google/turbine/parse/Parser.java
@@ -481,8 +481,9 @@ public class Parser {
{
result = new Tree.VoidTy(position);
next();
+ int pos = position;
name = eatIdent();
- return memberRest(access, annos, typaram, result, name);
+ return memberRest(pos, access, annos, typaram, result, name);
}
case BOOLEAN:
case BYTE:
@@ -494,17 +495,19 @@ public class Parser {
case FLOAT:
{
result = referenceType(ImmutableList.of());
+ int pos = position;
name = eatIdent();
- return memberRest(access, annos, typaram, result, name);
+ return memberRest(pos, access, annos, typaram, result, name);
}
case IDENT:
{
+ int pos = position;
String ident = eatIdent();
switch (token) {
case LPAREN:
{
name = ident;
- return ImmutableList.of(methodRest(access, annos, typaram, null, name));
+ return ImmutableList.of(methodRest(pos, access, annos, typaram, null, name));
}
case IDENT:
{
@@ -515,8 +518,9 @@ public class Parser {
ident,
ImmutableList.<Type>of(),
ImmutableList.of());
+ pos = position;
name = eatIdent();
- return memberRest(access, annos, typaram, result, name);
+ return memberRest(pos, access, annos, typaram, result, name);
}
case AT:
case LBRACK:
@@ -560,10 +564,11 @@ public class Parser {
result = classty((ClassTy) result);
}
result = maybeDims(maybeAnnos(), result);
+ pos = position;
name = eatIdent();
switch (token) {
case LPAREN:
- return ImmutableList.of(methodRest(access, annos, typaram, result, name));
+ return ImmutableList.of(methodRest(pos, access, annos, typaram, result, name));
case LBRACK:
case SEMI:
case ASSIGN:
@@ -572,7 +577,7 @@ public class Parser {
if (!typaram.isEmpty()) {
throw error(ErrorKind.UNEXPECTED_TYPE_PARAMETER, typaram);
}
- return fieldRest(access, annos, result, name);
+ return fieldRest(pos, access, annos, result, name);
}
default:
throw error(token);
@@ -596,6 +601,7 @@ public class Parser {
}
private ImmutableList<Tree> memberRest(
+ int pos,
EnumSet<TurbineModifier> access,
ImmutableList<Anno> annos,
ImmutableList<TyParam> typaram,
@@ -610,17 +616,21 @@ public class Parser {
if (!typaram.isEmpty()) {
throw error(ErrorKind.UNEXPECTED_TYPE_PARAMETER, typaram);
}
- return fieldRest(access, annos, result, name);
+ return fieldRest(pos, access, annos, result, name);
}
case LPAREN:
- return ImmutableList.of(methodRest(access, annos, typaram, result, name));
+ return ImmutableList.of(methodRest(pos, access, annos, typaram, result, name));
default:
throw error(token);
}
}
private ImmutableList<Tree> fieldRest(
- EnumSet<TurbineModifier> access, ImmutableList<Anno> annos, Type baseTy, String name) {
+ int pos,
+ EnumSet<TurbineModifier> access,
+ ImmutableList<Anno> annos,
+ Type baseTy,
+ String name) {
ImmutableList.Builder<Tree> result = ImmutableList.builder();
VariableInitializerParser initializerParser = new VariableInitializerParser(token, lexer);
List<List<SavedToken>> bits = initializerParser.parseInitializers();
@@ -642,13 +652,14 @@ public class Parser {
if (init != null && init.kind() == Tree.Kind.ARRAY_INIT) {
init = null;
}
- result.add(new VarDecl(position, access, annos, ty, name, Optional.fromNullable(init)));
+ result.add(new VarDecl(pos, access, annos, ty, name, Optional.fromNullable(init)));
}
eat(Token.SEMI);
return result.build();
}
private Tree methodRest(
+ int pos,
EnumSet<TurbineModifier> access,
ImmutableList<Anno> annos,
ImmutableList<TyParam> typaram,
@@ -697,7 +708,7 @@ public class Parser {
name = CTOR_NAME;
}
return new MethDecl(
- position,
+ pos,
access,
annos,
typaram,
diff --git a/java/com/google/turbine/type/AnnoInfo.java b/java/com/google/turbine/type/AnnoInfo.java
index 4af2e66..c564f48 100644
--- a/java/com/google/turbine/type/AnnoInfo.java
+++ b/java/com/google/turbine/type/AnnoInfo.java
@@ -21,25 +21,40 @@ import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.turbine.binder.sym.ClassSymbol;
+import com.google.turbine.diag.SourceFile;
import com.google.turbine.model.Const;
+import com.google.turbine.tree.Tree;
+import com.google.turbine.tree.Tree.Anno;
import com.google.turbine.tree.Tree.Expression;
/** An annotation use. */
public class AnnoInfo {
+ private final SourceFile source;
private final ClassSymbol sym;
- private final ImmutableList<Expression> args;
+ private final Tree.Anno tree;
private final ImmutableMap<String, Const> values;
public AnnoInfo(
- ClassSymbol sym, ImmutableList<Expression> args, ImmutableMap<String, Const> values) {
+ SourceFile source, ClassSymbol sym, Anno tree, ImmutableMap<String, Const> values) {
+ this.source = source;
this.sym = requireNonNull(sym);
- this.args = args;
+ this.tree = tree;
this.values = values;
}
+ /** The annotation's source, for diagnostics. */
+ public SourceFile source() {
+ return source;
+ }
+
+ /** The annotation's diagnostic position. */
+ public int position() {
+ return tree.position();
+ }
+
/** Arguments, either assignments or a single expression. */
public ImmutableList<Expression> args() {
- return args;
+ return tree.args();
}
/** Bound element-value pairs. */
@@ -51,4 +66,8 @@ public class AnnoInfo {
public ClassSymbol sym() {
return sym;
}
+
+ public AnnoInfo withValues(ImmutableMap<String, Const> values) {
+ return new AnnoInfo(source, sym, tree, values);
+ }
}
diff --git a/javatests/com/google/turbine/binder/BinderErrorTest.java b/javatests/com/google/turbine/binder/BinderErrorTest.java
index c6535ca..102db93 100644
--- a/javatests/com/google/turbine/binder/BinderErrorTest.java
+++ b/javatests/com/google/turbine/binder/BinderErrorTest.java
@@ -257,7 +257,86 @@ public class BinderErrorTest {
" @Object int x;",
" ^",
},
- }
+ },
+ {
+ {
+ "public class Test {", //
+ " @Deprecated @Deprecated int x;",
+ "}",
+ },
+ {
+ "<>:2: error: java/lang/Deprecated is not @Repeatable", //
+ " @Deprecated @Deprecated int x;",
+ " ^",
+ },
+ },
+ {
+ {
+ "public class Test {", //
+ " @NoSuch.NoSuch int x;",
+ "}",
+ },
+ {
+ "<>:2: error: symbol not found NoSuch.NoSuch", //
+ " @NoSuch.NoSuch int x;",
+ " ^",
+ },
+ },
+ {
+ {
+ "public class Test {", //
+ " @Deprecated.NoSuch int x;",
+ "}",
+ },
+ {
+ "<>:2: error: symbol not found NoSuch", //
+ " @Deprecated.NoSuch int x;",
+ " ^",
+ },
+ },
+ {
+ {
+ "public class Test {", //
+ " @interface Anno {",
+ " int[] value() default 0;",
+ " }",
+ " @Anno(value=Test.NO_SUCH) int x;",
+ "}",
+ },
+ {
+ "<>:5: error: could not evaluate constant expression", //
+ " @Anno(value=Test.NO_SUCH) int x;",
+ " ^",
+ },
+ },
+ {
+ {
+ "public class Test {", //
+ " @interface Anno {",
+ " String value() default \"\";",
+ " }",
+ " @Anno(value=null) int x;",
+ "}",
+ },
+ {
+ "<>:5: error: invalid annotation argument", //
+ " @Anno(value=null) int x;",
+ " ^",
+ },
+ },
+ {
+ {
+ "public class Test {", //
+ " static final String x = 1;",
+ " static final String x = 2;",
+ "}",
+ },
+ {
+ "<>:3: error: duplicate declaration of field: x", //
+ " static final String x = 2;",
+ " ^",
+ },
+ },
};
return Arrays.asList((Object[][]) testCases);
}
diff --git a/javatests/com/google/turbine/bytecode/ClassReaderTest.java b/javatests/com/google/turbine/bytecode/ClassReaderTest.java
index 30e3d5b..dde37d5 100644
--- a/javatests/com/google/turbine/bytecode/ClassReaderTest.java
+++ b/javatests/com/google/turbine/bytecode/ClassReaderTest.java
@@ -60,7 +60,7 @@ public class ClassReaderTest {
cw.visitMethod(0, "h", "(I)V", null, null);
byte[] bytes = cw.toByteArray();
- ClassFile classFile = com.google.turbine.bytecode.ClassReader.read(bytes);
+ ClassFile classFile = com.google.turbine.bytecode.ClassReader.read(null, bytes);
assertThat(classFile.access())
.isEqualTo(TurbineFlag.ACC_PUBLIC | TurbineFlag.ACC_FINAL | TurbineFlag.ACC_SUPER);
@@ -110,7 +110,7 @@ public class ClassReaderTest {
cw.visitEnd();
byte[] bytes = cw.toByteArray();
- ClassFile classFile = com.google.turbine.bytecode.ClassReader.read(bytes);
+ ClassFile classFile = com.google.turbine.bytecode.ClassReader.read(null, bytes);
assertThat(classFile.access())
.isEqualTo(
@@ -157,7 +157,7 @@ public class ClassReaderTest {
cw.visitEnd();
byte[] bytes = cw.toByteArray();
- ClassFile classFile = com.google.turbine.bytecode.ClassReader.read(bytes);
+ ClassFile classFile = com.google.turbine.bytecode.ClassReader.read(null, bytes);
assertThat(classFile.fields()).hasSize(3);
@@ -193,7 +193,7 @@ public class ClassReaderTest {
cw.visitInnerClass("test/Hello$Inner$InnerMost", "test/Hello$Inner", "InnerMost", 0);
byte[] bytes = cw.toByteArray();
- ClassFile classFile = com.google.turbine.bytecode.ClassReader.read(bytes);
+ ClassFile classFile = com.google.turbine.bytecode.ClassReader.read(null, bytes);
assertThat(classFile.innerClasses()).hasSize(2);
@@ -217,7 +217,22 @@ public class ClassReaderTest {
cw.visit(52, Opcodes.ACC_SUPER, jumbo, null, "java/lang/Object", null);
byte[] bytes = cw.toByteArray();
- ClassFile cf = ClassReader.read(bytes);
+ ClassFile cf = ClassReader.read(null, bytes);
assertThat(cf.name()).isEqualTo(jumbo);
}
+
+ @Test
+ public void v53() {
+ ClassWriter cw = new ClassWriter(0);
+ cw.visitAnnotation("Ljava/lang/Deprecated;", true);
+ cw.visit(
+ 53,
+ Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER,
+ "Hello",
+ null,
+ "java/lang/Object",
+ null);
+ ClassFile cf = ClassReader.read(null, cw.toByteArray());
+ assertThat(cf.name()).isEqualTo("Hello");
+ }
}
diff --git a/javatests/com/google/turbine/bytecode/ClassWriterTest.java b/javatests/com/google/turbine/bytecode/ClassWriterTest.java
index d95c00b..a2544fc 100644
--- a/javatests/com/google/turbine/bytecode/ClassWriterTest.java
+++ b/javatests/com/google/turbine/bytecode/ClassWriterTest.java
@@ -84,7 +84,7 @@ public class ClassWriterTest {
assertThat(task.call()).named(collector.getDiagnostics().toString()).isTrue();
byte[] original = Files.readAllBytes(out.resolve("test/Test.class"));
- byte[] actual = ClassWriter.writeClass(ClassReader.read(original));
+ byte[] actual = ClassWriter.writeClass(ClassReader.read(null, original));
assertThat(AsmUtils.textify(original)).isEqualTo(AsmUtils.textify(actual));
}
diff --git a/javatests/com/google/turbine/deps/AbstractTransitiveTest.java b/javatests/com/google/turbine/deps/AbstractTransitiveTest.java
index 3c24de4..6335216 100644
--- a/javatests/com/google/turbine/deps/AbstractTransitiveTest.java
+++ b/javatests/com/google/turbine/deps/AbstractTransitiveTest.java
@@ -129,7 +129,7 @@ public abstract class AbstractTransitiveTest {
"META-INF/TRANSITIVE/a/A$Anno.class",
"META-INF/TRANSITIVE/a/A$Inner.class");
- ClassFile a = ClassReader.read(readJar(libb).get("META-INF/TRANSITIVE/a/A.class"));
+ ClassFile a = ClassReader.read(null, readJar(libb).get("META-INF/TRANSITIVE/a/A.class"));
// methods and non-constant fields are removed
assertThat(getOnlyElement(a.fields()).name()).isEqualTo("CONST");
assertThat(a.methods()).isEmpty();
@@ -137,7 +137,9 @@ public abstract class AbstractTransitiveTest {
.containsExactly("a/A$Anno", "a/A$Inner");
// annotation interface methods are preserved
- assertThat(ClassReader.read(readJar(libb).get("META-INF/TRANSITIVE/a/A$Anno.class")).methods())
+ assertThat(
+ ClassReader.read(null, readJar(libb).get("META-INF/TRANSITIVE/a/A$Anno.class"))
+ .methods())
.hasSize(1);
// A class that references members of the transitive supertype A by simple name
diff --git a/javatests/com/google/turbine/deps/DependenciesTest.java b/javatests/com/google/turbine/deps/DependenciesTest.java
index 6a882f9..dd94650 100644
--- a/javatests/com/google/turbine/deps/DependenciesTest.java
+++ b/javatests/com/google/turbine/deps/DependenciesTest.java
@@ -296,6 +296,50 @@ public class DependenciesTest {
.inOrder();
}
+ @Test
+ public void packageInfo() throws Exception {
+ Path libpackageInfo =
+ new LibraryBuilder()
+ .addSourceLines(
+ "p/Anno.java",
+ "package p;",
+ "import java.lang.annotation.Retention;",
+ "import static java.lang.annotation.RetentionPolicy.RUNTIME;",
+ "@Retention(RUNTIME)",
+ "@interface Anno {}")
+ .addSourceLines(
+ "p/package-info.java", //
+ "@Anno",
+ "package p;")
+ .compileToJar("libpackage-info.jar");
+ Path libp =
+ new LibraryBuilder()
+ .setClasspath(libpackageInfo)
+ .addSourceLines(
+ "p/P.java", //
+ "package p;",
+ "public class P {}")
+ .compileToJar("libp.jar");
+ {
+ DepsProto.Dependencies deps =
+ new DepsBuilder()
+ .setClasspath(libp, libpackageInfo)
+ .addSourceLines(
+ "Test.java", //
+ "import p.P;",
+ "class Test {",
+ " P p;",
+ "}")
+ .run();
+ assertThat(depsMap(deps))
+ .containsExactly(
+ libpackageInfo,
+ DepsProto.Dependency.Kind.EXPLICIT,
+ libp,
+ DepsProto.Dependency.Kind.EXPLICIT);
+ }
+ }
+
void writeDeps(Path path, ImmutableMap<String, DepsProto.Dependency.Kind> deps)
throws IOException {
DepsProto.Dependencies.Builder builder =
diff --git a/pom.xml b/pom.xml
index ade3cef..6829bce 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,7 +69,7 @@
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
- <version>0.25</version>
+ <version>0.36</version>
<scope>test</scope>
</dependency>
<dependency>