diff options
author | Colin Cross <ccross@android.com> | 2017-11-18 07:11:37 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-11-18 07:11:37 +0000 |
commit | 80375a9329669589dca4abd5228ad2366d8ff5f3 (patch) | |
tree | 750b180b6de65bb672f72f1e11e1970c846698a8 | |
parent | 323c7ea1a82ce4e44d30de7ed00b3af200e72a87 (diff) | |
parent | 839fa39f9c9b3acfd36a743bf09382df9ce66345 (diff) | |
download | turbine-pie-qpr1-s2-release.tar.gz |
Merge remote-tracking branch 'aosp/upstream-master' am: 2cab599388 am: 23c6959137android-9.0.0_r47android-9.0.0_r46android-9.0.0_r45android-9.0.0_r44android-9.0.0_r43android-9.0.0_r42android-9.0.0_r41android-9.0.0_r40android-9.0.0_r39android-9.0.0_r38android-9.0.0_r37android-9.0.0_r36android-9.0.0_r35android-9.0.0_r34android-9.0.0_r33android-9.0.0_r32android-9.0.0_r31android-9.0.0_r30android-9.0.0_r22android-9.0.0_r21android-9.0.0_r20android-9.0.0_r19android-9.0.0_r16android-9.0.0_r12android-9.0.0_r11pie-qpr3-s1-releasepie-qpr3-releasepie-qpr3-b-releasepie-qpr2-releasepie-qpr1-s3-releasepie-qpr1-s2-releasepie-qpr1-s1-releasepie-qpr1-releasepie-dr1-releasepie-dr1-devpie-devpie-b4s4-releasepie-b4s4-dev
am: 839fa39f9c
Change-Id: I77e64b2ad724a85710e03beec91d6a8b302a61fb
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 = @@ -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> |