diff options
author | Colin Cross <ccross@android.com> | 2019-01-29 11:42:19 -0800 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2019-01-29 11:42:35 -0800 |
commit | a8a207a9f1578d8aaf5360ad99b910bcab097b86 (patch) | |
tree | 1341c1adbe2adae484c8f3018179457ca5a39a6c | |
parent | bcab8b65c6fa5de2d7376acb73c619942a70b624 (diff) | |
parent | 86a7c8a2f17d1ac976d94880c3123e6820f7d5cc (diff) | |
download | turbine-a8a207a9f1578d8aaf5360ad99b910bcab097b86.tar.gz |
Merge remote-tracking branch 'aosp/upstream-master' into master
* aosp/upstream-master:
Perform best-effort unescaping of command line options
Fix error reporting for resolution failures on nested annotations
Don't crash on type variables used as qualifiers in const exprs
Use a newer version of guava
Fix an NPE in constant expression binding of malformed annotations
Reformat with google-java-format
Miscellaneous cleanups
Report diagnostics for unterminated expressions at the beginning of the expression instead of at the end of the file, which is probably farther from the problem.
Fix error reporting for import resolution errors on nested types
Add flag control for the reduced classpath optimization
Bug: 122929601
Test: m checkbuild
Change-Id: I30c0efadd5379f668772bc047d54ccfbbce118f8
35 files changed, 332 insertions, 153 deletions
diff --git a/java/com/google/turbine/binder/ConstBinder.java b/java/com/google/turbine/binder/ConstBinder.java index e5717b2..0f989dd 100644 --- a/java/com/google/turbine/binder/ConstBinder.java +++ b/java/com/google/turbine/binder/ConstBinder.java @@ -20,9 +20,9 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.turbine.binder.bound.AnnotationMetadata; -import com.google.turbine.binder.bound.ClassValue; import com.google.turbine.binder.bound.EnumConstantValue; import com.google.turbine.binder.bound.SourceTypeBoundClass; +import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.bound.TypeBoundClass; import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; @@ -215,7 +215,7 @@ public class ConstBinder { if (value.kind() != Kind.CLASS_LITERAL) { return null; } - Type type = ((ClassValue) value).type(); + Type type = ((TurbineClassValue) value).type(); if (type.tyKind() != TyKind.CLASS_TY) { return null; } diff --git a/java/com/google/turbine/binder/ConstEvaluator.java b/java/com/google/turbine/binder/ConstEvaluator.java index 2d8ce2d..0e837a4 100644 --- a/java/com/google/turbine/binder/ConstEvaluator.java +++ b/java/com/google/turbine/binder/ConstEvaluator.java @@ -18,12 +18,13 @@ package com.google.turbine.binder; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.turbine.binder.bound.AnnotationValue; -import com.google.turbine.binder.bound.ClassValue; import com.google.turbine.binder.bound.EnumConstantValue; +import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.bound.TypeBoundClass; import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; @@ -35,6 +36,7 @@ import com.google.turbine.binder.lookup.MemberImportIndex; import com.google.turbine.binder.lookup.Scope; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.FieldSymbol; +import com.google.turbine.binder.sym.Symbol; import com.google.turbine.diag.SourceFile; import com.google.turbine.diag.TurbineError; import com.google.turbine.diag.TurbineError.ErrorKind; @@ -166,7 +168,7 @@ public strictfp class ConstEvaluator { /** Evaluates a class literal. */ Const evalClassLiteral(ClassLiteral t) { - return new ClassValue(evalClassLiteralType(t.type())); + return new TurbineClassValue(evalClassLiteralType(t.type())); } private Type evalClassLiteralType(Tree.Type type) { @@ -203,6 +205,9 @@ public strictfp class ConstEvaluator { if (result == null) { throw error(classTy.position(), ErrorKind.CANNOT_RESOLVE, flat.peekFirst()); } + if (result.sym().symKind() != Symbol.Kind.CLASS) { + throw error(classTy.position(), ErrorKind.UNEXPECTED_TYPE_PARAMETER, flat.peekFirst()); + } ClassSymbol classSym = (ClassSymbol) result.sym(); for (Ident bit : result.remaining()) { classSym = resolveNext(classTy.position(), classSym, bit); @@ -949,9 +954,19 @@ public strictfp class ConstEvaluator { private AnnotationValue evalAnno(Tree.Anno t) { LookupResult result = scope.lookup(new LookupKey(t.name())); + if (result == null) { + throw error( + t.name().get(0).position(), ErrorKind.CANNOT_RESOLVE, Joiner.on(".").join(t.name())); + } ClassSymbol sym = (ClassSymbol) result.sym(); for (Ident name : result.remaining()) { sym = Resolve.resolve(env, sym, sym, name); + if (sym == null) { + throw error(name.position(), ErrorKind.CANNOT_RESOLVE, name.value()); + } + } + if (sym == null) { + return null; } AnnoInfo annoInfo = evaluateAnnotation(new AnnoInfo(source, sym, t, null)); return new AnnotationValue(annoInfo.sym(), annoInfo.values()); diff --git a/java/com/google/turbine/binder/CtSymClassBinder.java b/java/com/google/turbine/binder/CtSymClassBinder.java index fd2e544..d9d74ab 100644 --- a/java/com/google/turbine/binder/CtSymClassBinder.java +++ b/java/com/google/turbine/binder/CtSymClassBinder.java @@ -16,6 +16,8 @@ package com.google.turbine.binder; +import static com.google.common.base.StandardSystemProperty.JAVA_HOME; + import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMap; @@ -42,7 +44,7 @@ public class CtSymClassBinder { @Nullable public static ClassPath bind(String version) throws IOException { - Path javaHome = Paths.get(System.getProperty("java.home")); + Path javaHome = Paths.get(JAVA_HOME.value()); Path ctSym = javaHome.resolve("lib/ct.sym"); if (!Files.exists(ctSym)) { throw new IllegalStateException("lib/ct.sym does not exist in " + javaHome); diff --git a/java/com/google/turbine/binder/JimageClassBinder.java b/java/com/google/turbine/binder/JimageClassBinder.java index 72bcb2f..b32b8ea 100644 --- a/java/com/google/turbine/binder/JimageClassBinder.java +++ b/java/com/google/turbine/binder/JimageClassBinder.java @@ -16,6 +16,8 @@ package com.google.turbine.binder; +import static com.google.common.base.StandardSystemProperty.JAVA_HOME; + import com.google.common.base.Joiner; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; @@ -79,7 +81,7 @@ public class JimageClassBinder { /** Returns a platform classpath for the given JDK's jimage file. */ public static ClassPath bind(String javaHome) throws IOException { - if (javaHome.equals(System.getProperty("java.home"))) { + if (javaHome.equals(JAVA_HOME.value())) { return bindDefault(); } FileSystem fileSystem = diff --git a/java/com/google/turbine/binder/bound/ClassValue.java b/java/com/google/turbine/binder/bound/TurbineClassValue.java index a75db42..df55501 100644 --- a/java/com/google/turbine/binder/bound/ClassValue.java +++ b/java/com/google/turbine/binder/bound/TurbineClassValue.java @@ -21,11 +21,11 @@ import com.google.turbine.type.Type; import java.util.Objects; /** A class literal constant. */ -public class ClassValue extends Const { +public class TurbineClassValue extends Const { private final Type type; - public ClassValue(Type type) { + public TurbineClassValue(Type type) { this.type = type; } @@ -46,11 +46,11 @@ public class ClassValue extends Const { @Override public int hashCode() { - return Objects.hash(type); + return Objects.hashCode(type); } @Override public boolean equals(Object obj) { - return obj instanceof ClassValue && type().equals(((ClassValue) obj).type()); + return obj instanceof TurbineClassValue && type().equals(((TurbineClassValue) obj).type()); } } diff --git a/java/com/google/turbine/binder/bytecode/BytecodeBinder.java b/java/com/google/turbine/binder/bytecode/BytecodeBinder.java index e5ba343..1d2eecb 100644 --- a/java/com/google/turbine/binder/bytecode/BytecodeBinder.java +++ b/java/com/google/turbine/binder/bytecode/BytecodeBinder.java @@ -19,9 +19,9 @@ package com.google.turbine.binder.bytecode; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.turbine.binder.bound.AnnotationValue; -import com.google.turbine.binder.bound.ClassValue; import com.google.turbine.binder.bound.EnumConstantValue; import com.google.turbine.binder.bound.ModuleInfo; +import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.FieldSymbol; import com.google.turbine.binder.sym.TyVarSymbol; @@ -29,7 +29,7 @@ import com.google.turbine.bytecode.ClassFile; import com.google.turbine.bytecode.ClassFile.AnnotationInfo; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ArrayValue; -import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstClassValue; +import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstTurbineClassValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.EnumConstValue; import com.google.turbine.bytecode.ClassReader; @@ -118,9 +118,9 @@ public class BytecodeBinder { case ARRAY: return bindArrayValue(type, (ArrayValue) value); case CLASS: - return new ClassValue( + return new TurbineClassValue( bindTy( - new SigParser(((ConstClassValue) value).className()).parseType(), + new SigParser(((ConstTurbineClassValue) value).className()).parseType(), x -> { throw new IllegalStateException(x); })); diff --git a/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java b/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java index f21760b..6e882e6 100644 --- a/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java +++ b/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java @@ -37,7 +37,7 @@ import com.google.turbine.bytecode.ClassFile; import com.google.turbine.bytecode.ClassFile.AnnotationInfo; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ArrayValue; -import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstClassValue; +import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstTurbineClassValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.EnumConstValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.Kind; import com.google.turbine.bytecode.ClassFile.MethodInfo.ParameterInfo; @@ -530,7 +530,7 @@ public class BytecodeBoundClass implements BoundClass, HeaderBoundClass, TypeBou ElementValue val = annotation.elementValuePairs().get("value"); switch (val.kind()) { case CLASS: - String className = ((ConstClassValue) val).className(); + String className = ((ConstTurbineClassValue) val).className(); return new ClassSymbol(className.substring(1, className.length() - 1)); default: break; diff --git a/java/com/google/turbine/binder/lookup/ImportIndex.java b/java/com/google/turbine/binder/lookup/ImportIndex.java index f28d905..afa985a 100644 --- a/java/com/google/turbine/binder/lookup/ImportIndex.java +++ b/java/com/google/turbine/binder/lookup/ImportIndex.java @@ -105,7 +105,10 @@ public class ImportIndex implements ImportScope { } ClassSymbol sym = (ClassSymbol) result.sym(); for (Tree.Ident bit : result.remaining()) { - sym = resolveNext(log, i.position(), resolve, sym, bit); + sym = resolveNext(log, resolve, sym, bit); + if (sym == null) { + return null; + } } ClassSymbol resolved = sym; return new ImportScope() { @@ -117,15 +120,13 @@ public class ImportIndex implements ImportScope { } private static ClassSymbol resolveNext( - TurbineLogWithSource log, - int position, - CanonicalSymbolResolver resolve, - ClassSymbol sym, - Ident bit) { + TurbineLogWithSource log, CanonicalSymbolResolver resolve, ClassSymbol sym, Ident bit) { ClassSymbol next = resolve.resolveOne(sym, bit); if (next == null) { log.error( - position, ErrorKind.SYMBOL_NOT_FOUND, new ClassSymbol(sym.binaryName() + '$' + bit)); + bit.position(), + ErrorKind.SYMBOL_NOT_FOUND, + new ClassSymbol(sym.binaryName() + '$' + bit)); } return next; } diff --git a/java/com/google/turbine/binder/lookup/LookupResult.java b/java/com/google/turbine/binder/lookup/LookupResult.java index 7e0f737..8340386 100644 --- a/java/com/google/turbine/binder/lookup/LookupResult.java +++ b/java/com/google/turbine/binder/lookup/LookupResult.java @@ -16,6 +16,8 @@ package com.google.turbine.binder.lookup; +import static java.util.Objects.requireNonNull; + import com.google.common.collect.ImmutableList; import com.google.errorprone.annotations.Immutable; import com.google.turbine.binder.sym.ClassSymbol; @@ -45,7 +47,7 @@ public class LookupResult { private final ImmutableList<Tree.Ident> remaining; public LookupResult(Symbol sym, LookupKey remaining) { - this.sym = sym; + this.sym = requireNonNull(sym); this.remaining = remaining.hasNext() ? remaining.rest().simpleNames() : ImmutableList.of(); } } diff --git a/java/com/google/turbine/binder/lookup/WildImportIndex.java b/java/com/google/turbine/binder/lookup/WildImportIndex.java index 043ccc5..cfe58c7 100644 --- a/java/com/google/turbine/binder/lookup/WildImportIndex.java +++ b/java/com/google/turbine/binder/lookup/WildImportIndex.java @@ -67,9 +67,7 @@ public class WildImportIndex implements ImportScope { /** Full resolve the type for a non-static on-demand import. */ private static ImportScope onDemandImport( - TopLevelIndex cpi, - ImportDecl i, - final CanonicalSymbolResolver importResolver) { + TopLevelIndex cpi, ImportDecl i, final CanonicalSymbolResolver importResolver) { ImmutableList.Builder<String> flatNames = ImmutableList.builder(); for (Tree.Ident ident : i.type()) { flatNames.add(ident.value()); @@ -106,9 +104,7 @@ public class WildImportIndex implements ImportScope { * deferred). */ private static ImportScope staticOnDemandImport( - TopLevelIndex cpi, - ImportDecl i, - final CanonicalSymbolResolver importResolver) { + TopLevelIndex cpi, ImportDecl i, final CanonicalSymbolResolver importResolver) { LookupResult result = cpi.scope().lookup(new LookupKey(i.type())); if (result == null) { return null; @@ -141,9 +137,7 @@ public class WildImportIndex implements ImportScope { } static ClassSymbol resolveImportBase( - LookupResult result, - ResolveFunction resolve, - CanonicalSymbolResolver importResolver) { + LookupResult result, ResolveFunction resolve, CanonicalSymbolResolver importResolver) { ClassSymbol member = (ClassSymbol) result.sym(); for (Tree.Ident bit : result.remaining()) { member = resolve.resolveOne(member, bit); diff --git a/java/com/google/turbine/bytecode/AnnotationWriter.java b/java/com/google/turbine/bytecode/AnnotationWriter.java index b52cc5e..868b548 100644 --- a/java/com/google/turbine/bytecode/AnnotationWriter.java +++ b/java/com/google/turbine/bytecode/AnnotationWriter.java @@ -22,7 +22,7 @@ import com.google.turbine.bytecode.ClassFile.AnnotationInfo; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.AnnotationValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ArrayValue; -import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstClassValue; +import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstTurbineClassValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.EnumConstValue; import com.google.turbine.bytecode.ClassFile.TypeAnnotationInfo; @@ -65,7 +65,7 @@ public class AnnotationWriter { writeEnumElementValue((EnumConstValue) value); break; case CLASS: - writeClassElementValue((ConstClassValue) value); + writeClassElementValue((ConstTurbineClassValue) value); break; case ARRAY: writeArrayElementValue((ArrayValue) value); @@ -123,7 +123,7 @@ public class AnnotationWriter { output.writeShort(pool.utf8(value.constName())); } - private void writeClassElementValue(ConstClassValue value) { + private void writeClassElementValue(ConstTurbineClassValue value) { output.writeByte('c'); output.writeShort(pool.utf8(value.className())); } diff --git a/java/com/google/turbine/bytecode/ClassFile.java b/java/com/google/turbine/bytecode/ClassFile.java index 502e295..422f8c6 100644 --- a/java/com/google/turbine/bytecode/ClassFile.java +++ b/java/com/google/turbine/bytecode/ClassFile.java @@ -450,11 +450,11 @@ public class ClassFile { } /** A constant class literal value. */ - class ConstClassValue implements ElementValue { + class ConstTurbineClassValue implements ElementValue { private final String className; - public ConstClassValue(String className) { + public ConstTurbineClassValue(String className) { this.className = className; } diff --git a/java/com/google/turbine/bytecode/ClassReader.java b/java/com/google/turbine/bytecode/ClassReader.java index 0070527..dc5e050 100644 --- a/java/com/google/turbine/bytecode/ClassReader.java +++ b/java/com/google/turbine/bytecode/ClassReader.java @@ -22,7 +22,7 @@ import com.google.errorprone.annotations.CheckReturnValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.AnnotationValue; -import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstClassValue; +import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstTurbineClassValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.ConstValue; import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue.EnumConstValue; import com.google.turbine.bytecode.ClassFile.MethodInfo.ParameterInfo; @@ -34,7 +34,6 @@ import com.google.turbine.bytecode.ClassFile.ModuleInfo.RequireInfo; import com.google.turbine.bytecode.ClassFile.ModuleInfo.UseInfo; import com.google.turbine.model.Const; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import javax.annotation.Nullable; @@ -101,7 +100,7 @@ public class ClassReader { List<ClassFile.MethodInfo> methodinfos = readMethods(constantPool); String signature = null; - List<ClassFile.InnerClass> innerclasses = Collections.emptyList(); + List<ClassFile.InnerClass> innerclasses = ImmutableList.of(); ImmutableList.Builder<ClassFile.AnnotationInfo> annotations = ImmutableList.builder(); ClassFile.ModuleInfo module = null; int attributesCount = reader.u2(); @@ -346,7 +345,7 @@ public class ClassReader { { int classInfoIndex = reader.u2(); String className = constantPool.utf8(classInfoIndex); - return new ConstClassValue(className); + return new ConstTurbineClassValue(className); } case '@': return new AnnotationValue(readAnnotation(constantPool)); diff --git a/java/com/google/turbine/diag/TurbineError.java b/java/com/google/turbine/diag/TurbineError.java index e13eb44..b8b2a54 100644 --- a/java/com/google/turbine/diag/TurbineError.java +++ b/java/com/google/turbine/diag/TurbineError.java @@ -30,6 +30,7 @@ public class TurbineError extends Error { UNEXPECTED_EOF("unexpected end of input"), UNTERMINATED_STRING("unterminated string literal"), UNTERMINATED_CHARACTER_LITERAL("unterminated char literal"), + UNTERMINATED_EXPRESSION("unterminated expression, expected ';' not found"), EMPTY_CHARACTER_LITERAL("empty char literal"), EXPECTED_TOKEN("expected token %s"), INVALID_LITERAL("invalid literal: %s"), diff --git a/java/com/google/turbine/lower/Lower.java b/java/com/google/turbine/lower/Lower.java index 99b5627..97fbd6e 100644 --- a/java/com/google/turbine/lower/Lower.java +++ b/java/com/google/turbine/lower/Lower.java @@ -25,7 +25,6 @@ import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.turbine.binder.bound.AnnotationValue; -import com.google.turbine.binder.bound.ClassValue; import com.google.turbine.binder.bound.EnumConstantValue; import com.google.turbine.binder.bound.ModuleInfo.ExportInfo; import com.google.turbine.binder.bound.ModuleInfo.OpenInfo; @@ -34,6 +33,7 @@ import com.google.turbine.binder.bound.ModuleInfo.RequireInfo; import com.google.turbine.binder.bound.ModuleInfo.UseInfo; import com.google.turbine.binder.bound.SourceModuleInfo; import com.google.turbine.binder.bound.SourceTypeBoundClass; +import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.bound.TypeBoundClass; import com.google.turbine.binder.bound.TypeBoundClass.FieldInfo; import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; @@ -79,7 +79,6 @@ import com.google.turbine.types.Erasure; import java.lang.annotation.RetentionPolicy; import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Collections; import java.util.Deque; import java.util.LinkedHashSet; import java.util.List; @@ -373,7 +372,7 @@ public class Lower { private ClassFile.FieldInfo lowerField(FieldInfo f) { final String name = f.name(); - Function<TyVarSymbol, TyVarInfo> tenv = new TyVarEnv(Collections.emptyMap()); + Function<TyVarSymbol, TyVarInfo> tenv = new TyVarEnv(ImmutableMap.of()); String desc = SigWriter.type(sig.signature(Erasure.erase(f.type(), tenv))); String signature = sig.fieldSignature(f.type()); @@ -543,8 +542,9 @@ public class Lower { switch (value.kind()) { case CLASS_LITERAL: { - ClassValue classValue = (ClassValue) value; - return new ElementValue.ConstClassValue(SigWriter.type(sig.signature(classValue.type()))); + TurbineClassValue classValue = (TurbineClassValue) value; + return new ElementValue.ConstTurbineClassValue( + SigWriter.type(sig.signature(classValue.type()))); } case ENUM_CONSTANT: { diff --git a/java/com/google/turbine/main/Main.java b/java/com/google/turbine/main/Main.java index 03a68ce..34421e1 100644 --- a/java/com/google/turbine/main/Main.java +++ b/java/com/google/turbine/main/Main.java @@ -16,10 +16,12 @@ package com.google.turbine.main; +import static com.google.common.base.StandardSystemProperty.JAVA_SPECIFICATION_VERSION; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.collect.ImmutableList; import com.google.common.hash.Hashing; +import com.google.common.io.MoreFiles; import com.google.turbine.binder.Binder; import com.google.turbine.binder.Binder.BindingResult; import com.google.turbine.binder.ClassPath; @@ -145,7 +147,7 @@ public class Main { if (options.release().isPresent()) { String release = options.release().get(); - if (release.equals(System.getProperty("java.specification.version"))) { + if (release.equals(JAVA_SPECIFICATION_VERSION.value())) { // if --release matches the host JDK, use its jimage instead of ct.sym return JimageClassBinder.bindDefault(); } @@ -172,7 +174,7 @@ public class Main { ImmutableList.Builder<CompUnit> units = ImmutableList.builder(); for (String source : options.sources()) { Path path = Paths.get(source); - units.add(Parser.parse(new SourceFile(source, new String(Files.readAllBytes(path), UTF_8)))); + units.add(Parser.parse(new SourceFile(source, MoreFiles.asCharSource(path, UTF_8).read()))); } for (String sourceJar : options.sourceJars()) { for (Zip.Entry ze : new Zip.ZipIterable(Paths.get(sourceJar))) { diff --git a/java/com/google/turbine/options/TurbineOptionsParser.java b/java/com/google/turbine/options/TurbineOptionsParser.java index 2976285..5b1f326 100644 --- a/java/com/google/turbine/options/TurbineOptionsParser.java +++ b/java/com/google/turbine/options/TurbineOptionsParser.java @@ -16,6 +16,7 @@ package com.google.turbine.options; +import static com.google.common.base.Preconditions.checkArgument; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.CharMatcher; @@ -116,6 +117,12 @@ public class TurbineOptionsParser { case "--nojavac_fallback": builder.setJavacFallback(false); break; + case "--reduce_classpath": + builder.setShouldReduceClassPath(true); + break; + case "--noreduce_classpath": + builder.setShouldReduceClassPath(false); + break; case "--help": builder.setHelp(true); break; @@ -138,6 +145,13 @@ public class TurbineOptionsParser { if (arg.isEmpty()) { continue; } + if (arg.charAt(0) == '\'') { + // perform best-effort unescaping as a concession to ninja, see: + // https://android.googlesource.com/platform/external/ninja/+/6f903faaf5488dc052ffc4e3e0b12757b426e088/src/util.cc#274 + checkArgument(arg.charAt(arg.length() - 1) == '\'', arg); + arg = arg.substring(1, arg.length() - 1); + checkArgument(!arg.contains("'"), arg); + } if (arg.startsWith("@@")) { argumentDeque.addLast(arg.substring(1)); } else if (arg.startsWith("@")) { diff --git a/java/com/google/turbine/parse/Parser.java b/java/com/google/turbine/parse/Parser.java index ba76659..dd45b0d 100644 --- a/java/com/google/turbine/parse/Parser.java +++ b/java/com/google/turbine/parse/Parser.java @@ -20,6 +20,7 @@ import static com.google.turbine.parse.Token.COMMA; import static com.google.turbine.parse.Token.INTERFACE; import static com.google.turbine.parse.Token.LPAREN; import static com.google.turbine.parse.Token.RPAREN; +import static com.google.turbine.parse.Token.SEMI; import static com.google.turbine.tree.TurbineModifier.PROTECTED; import static com.google.turbine.tree.TurbineModifier.PUBLIC; @@ -812,6 +813,7 @@ public class Parser { token = initializerParser.token; boolean first = true; + int expressionStart = pos; for (List<SavedToken> bit : bits) { IteratorLexer lexer = new IteratorLexer(this.lexer.source(), bit.iterator()); Parser parser = new Parser(lexer); @@ -823,12 +825,17 @@ public class Parser { Type ty = baseTy; ty = parser.extraDims(ty); // TODO(cushon): skip more fields that are definitely non-const - Expression init = new ConstExpressionParser(lexer, lexer.next()).expression(); + ConstExpressionParser constExpressionParser = new ConstExpressionParser(lexer, lexer.next()); + expressionStart = lexer.position(); + Expression init = constExpressionParser.expression(); if (init != null && init.kind() == Tree.Kind.ARRAY_INIT) { init = null; } result.add(new VarDecl(pos, access, annos, ty, name, Optional.ofNullable(init))); } + if (token != SEMI) { + throw TurbineError.format(lexer.source(), expressionStart, ErrorKind.UNTERMINATED_EXPRESSION); + } eat(Token.SEMI); return result.build(); } diff --git a/java/com/google/turbine/type/Type.java b/java/com/google/turbine/type/Type.java index 3bf47d6..8950ec0 100644 --- a/java/com/google/turbine/type/Type.java +++ b/java/com/google/turbine/type/Type.java @@ -19,6 +19,7 @@ package com.google.turbine.type; import com.google.auto.value.AutoValue; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.binder.sym.TyVarSymbol; import com.google.turbine.model.TurbineConstantTypeKind; @@ -100,7 +101,7 @@ public interface Type { /** The class symbol. */ public ClassSymbol sym() { - return classes().get(classes().size() - 1).sym(); + return Iterables.getLast(classes()).sym(); } @Override diff --git a/java/com/google/turbine/types/Canonicalize.java b/java/com/google/turbine/types/Canonicalize.java index d3328b7..a8861da 100644 --- a/java/com/google/turbine/types/Canonicalize.java +++ b/java/com/google/turbine/types/Canonicalize.java @@ -157,7 +157,7 @@ public class Canonicalize { private Collection<ClassTy.SimpleClassTy> lexicalBase(ClassSymbol first, ClassSymbol owner) { if ((getInfo(first).access() & TurbineFlag.ACC_STATIC) == TurbineFlag.ACC_STATIC) { - return Collections.emptyList(); + return ImmutableList.of(); } ClassSymbol canonOwner = getInfo(first).owner(); Deque<ClassTy.SimpleClassTy> result = new ArrayDeque<>(); diff --git a/javatests/com/google/turbine/binder/BinderErrorTest.java b/javatests/com/google/turbine/binder/BinderErrorTest.java index f6fb317..5a4d97e 100644 --- a/javatests/com/google/turbine/binder/BinderErrorTest.java +++ b/javatests/com/google/turbine/binder/BinderErrorTest.java @@ -26,7 +26,6 @@ import com.google.turbine.diag.TurbineError; import com.google.turbine.parse.Parser; import com.google.turbine.tree.Tree.CompUnit; import java.util.Arrays; -import java.util.Collections; import java.util.Optional; import org.junit.Test; import org.junit.runner.RunWith; @@ -180,7 +179,7 @@ public class BinderErrorTest { { "<>:2: error: symbol not found java.util.List$NoSuch", // "import java.util.List.NoSuch;", - " ^", + " ^", "<>:3: error: could not resolve NoSuch", "public class Test extends NoSuch {", " ^", @@ -488,6 +487,88 @@ public class BinderErrorTest { " ^", }, }, + { + { + "package p;", // + "import java.util.List.NoSuchAnno;", + "@NoSuchAnno", + "public class Test {", + "}", + }, + { + "<>:2: error: symbol not found java.util.List$NoSuchAnno", + "import java.util.List.NoSuchAnno;", + " ^", + "<>:3: error: could not resolve NoSuchAnno", + "@NoSuchAnno", + " ^", + }, + }, + { + { + "package p;", // + "import java.lang.annotation.Retention;", + "import java.lang.annotation.RetentionPolicy;", + "@Retention(@RetentionPolicy.RUNTIME)", + "public @interface A {", + "}", + }, + { + "<>:4: error: could not resolve RUNTIME", + "@Retention(@RetentionPolicy.RUNTIME)", + " ^", + }, + }, + { + { + "@interface Param {", + " Class<?> type();", + "}", + "class Foo<T> {", + " @Param(type = T.class)", + " public void bar() {}", + "}", + }, + { + "<>:5: error: unexpected type parameter T", + " @Param(type = T.class)", + " ^", + }, + }, + { + { + "class One {", + " @interface A {", // + " B[] b();", + " }", + " @interface B {}", + "}", + "@One.A(b = {@B})", + "class T {}", + }, + { + "<>:7: error: could not resolve B", // + "@One.A(b = {@B})", + " ^", + }, + }, + { + { + "class One {", + " @interface A {", // + " B[] b();", + " }", + " @interface B {}", + "}", + "@One.A(b = {@One.NoSuch})", + "class T {}", + }, + { + "<>:7: error: could not resolve NoSuch", // + "@One.A(b = {@One.NoSuch})", + " ^", + }, + } }; return Arrays.asList((Object[][]) testCases); } @@ -505,13 +586,13 @@ public class BinderErrorTest { try { Binder.bind( ImmutableList.of(parseLines(source)), - ClassPathBinder.bindClasspath(Collections.emptyList()), + ClassPathBinder.bindClasspath(ImmutableList.of()), TURBINE_BOOTCLASSPATH, /* moduleVersion=*/ Optional.empty()) .units(); fail(Joiner.on('\n').join(source)); } catch (TurbineError e) { - assertThat(e.getMessage()).isEqualTo(lines(expected)); + assertThat(e).hasMessageThat().isEqualTo(lines(expected)); } } diff --git a/javatests/com/google/turbine/binder/BinderTest.java b/javatests/com/google/turbine/binder/BinderTest.java index 8bf4cd3..4b1e890 100644 --- a/javatests/com/google/turbine/binder/BinderTest.java +++ b/javatests/com/google/turbine/binder/BinderTest.java @@ -37,7 +37,6 @@ import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -76,7 +75,7 @@ public class BinderTest { ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( units, - ClassPathBinder.bindClasspath(Collections.emptyList()), + ClassPathBinder.bindClasspath(ImmutableList.of()), TURBINE_BOOTCLASSPATH, /* moduleVersion=*/ Optional.empty()) .units(); @@ -122,7 +121,7 @@ public class BinderTest { ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( units, - ClassPathBinder.bindClasspath(Collections.emptyList()), + ClassPathBinder.bindClasspath(ImmutableList.of()), TURBINE_BOOTCLASSPATH, /* moduleVersion=*/ Optional.empty()) .units(); @@ -162,7 +161,7 @@ public class BinderTest { ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( units, - ClassPathBinder.bindClasspath(Collections.emptyList()), + ClassPathBinder.bindClasspath(ImmutableList.of()), TURBINE_BOOTCLASSPATH, /* moduleVersion=*/ Optional.empty()) .units(); @@ -192,12 +191,12 @@ public class BinderTest { try { Binder.bind( units, - ClassPathBinder.bindClasspath(Collections.emptyList()), + ClassPathBinder.bindClasspath(ImmutableList.of()), TURBINE_BOOTCLASSPATH, /* moduleVersion=*/ Optional.empty()); fail(); } catch (TurbineError e) { - assertThat(e.getMessage()).contains("cycle in class hierarchy: a.A -> b.B -> a.A"); + assertThat(e).hasMessageThat().contains("cycle in class hierarchy: a.A -> b.B -> a.A"); } } @@ -213,7 +212,7 @@ public class BinderTest { ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( units, - ClassPathBinder.bindClasspath(Collections.emptyList()), + ClassPathBinder.bindClasspath(ImmutableList.of()), TURBINE_BOOTCLASSPATH, /* moduleVersion=*/ Optional.empty()) .units(); @@ -242,7 +241,7 @@ public class BinderTest { ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( units, - ClassPathBinder.bindClasspath(Collections.emptyList()), + ClassPathBinder.bindClasspath(ImmutableList.of()), TURBINE_BOOTCLASSPATH, /* moduleVersion=*/ Optional.empty()) .units(); @@ -306,7 +305,7 @@ public class BinderTest { ImmutableMap<ClassSymbol, SourceTypeBoundClass> bound = Binder.bind( units, - ClassPathBinder.bindClasspath(Collections.emptyList()), + ClassPathBinder.bindClasspath(ImmutableList.of()), TURBINE_BOOTCLASSPATH, /* moduleVersion=*/ Optional.empty()) .units(); diff --git a/javatests/com/google/turbine/binder/ClassPathBinderTest.java b/javatests/com/google/turbine/binder/ClassPathBinderTest.java index 0b063d4..3f41706 100644 --- a/javatests/com/google/turbine/binder/ClassPathBinderTest.java +++ b/javatests/com/google/turbine/binder/ClassPathBinderTest.java @@ -27,6 +27,7 @@ import static org.junit.Assert.fail; import com.google.common.base.VerifyException; import com.google.common.collect.ImmutableList; import com.google.common.io.ByteStreams; +import com.google.common.io.MoreFiles; import com.google.turbine.binder.bound.EnumConstantValue; import com.google.turbine.binder.bound.TypeBoundClass; import com.google.turbine.binder.bytecode.BytecodeBoundClass; @@ -43,7 +44,6 @@ import com.google.turbine.type.AnnoInfo; import com.google.turbine.type.Type.ClassTy; import java.io.IOError; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import org.junit.Rule; import org.junit.Test; @@ -85,7 +85,7 @@ public class ClassPathBinderTest { .isEqualTo(TurbineTyKind.ANNOTATION); c = env.get(new ClassSymbol("java/util/ArrayList")); - assertThat((c.access() & TurbineFlag.ACC_PUBLIC) == TurbineFlag.ACC_PUBLIC).isTrue(); + assertThat((c.access() & TurbineFlag.ACC_PUBLIC)).isEqualTo(TurbineFlag.ACC_PUBLIC); assertThat(c.superclass()).isEqualTo(new ClassSymbol("java/util/AbstractList")); assertThat(c.interfaces()).contains(new ClassSymbol("java/util/List")); assertThat(c.owner()).isNull(); @@ -143,7 +143,8 @@ public class ClassPathBinderTest { c.owner(); fail(); } catch (VerifyException e) { - assertThat(e.getMessage()) + assertThat(e) + .hasMessageThat() .contains("expected class data for java/util/List, saw java/util/ArrayList instead"); } } @@ -151,13 +152,13 @@ public class ClassPathBinderTest { @Test public void nonJarFile() throws Exception { Path lib = temporaryFolder.newFile("NOT_A_JAR").toPath(); - Files.write(lib, "hello".getBytes(UTF_8)); + MoreFiles.asCharSink(lib, UTF_8).write("hello"); try { ClassPathBinder.bindClasspath(ImmutableList.of(lib)); fail(); } catch (IOException e) { - assertThat(e.getMessage()).contains("NOT_A_JAR"); + assertThat(e).hasMessageThat().contains("NOT_A_JAR"); } } } diff --git a/javatests/com/google/turbine/binder/JimageClassBinderTest.java b/javatests/com/google/turbine/binder/JimageClassBinderTest.java index bbcb245..11d6823 100644 --- a/javatests/com/google/turbine/binder/JimageClassBinderTest.java +++ b/javatests/com/google/turbine/binder/JimageClassBinderTest.java @@ -16,6 +16,7 @@ package com.google.turbine.binder; +import static com.google.common.base.StandardSystemProperty.JAVA_CLASS_VERSION; import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.truth.Truth.assertThat; @@ -34,7 +35,7 @@ import org.junit.runners.JUnit4; public class JimageClassBinderTest { @Test public void testDefaultJimage() throws IOException { - if (Double.parseDouble(System.getProperty("java.class.version")) < 53) { + if (Double.parseDouble(JAVA_CLASS_VERSION.value()) < 53) { // only run on JDK 9 and later return; } diff --git a/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java b/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java index 4e3ec9a..2a0de48 100644 --- a/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java +++ b/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java @@ -24,7 +24,7 @@ import static java.util.Objects.requireNonNull; import com.google.common.collect.ImmutableMap; import com.google.common.io.ByteStreams; -import com.google.turbine.binder.bound.ClassValue; +import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.bound.TypeBoundClass; import com.google.turbine.binder.bound.TypeBoundClass.MethodInfo; import com.google.turbine.binder.env.CompoundEnv; @@ -110,9 +110,9 @@ public class BytecodeBoundClassTest { BytecodeBoundClass c = getBytecodeBoundClass(VoidAnno.class); assertThat(c.methods()).hasSize(2); - assertThat(((ClassValue) c.methods().get(0).defaultValue()).type().tyKind()) + assertThat(((TurbineClassValue) c.methods().get(0).defaultValue()).type().tyKind()) .isEqualTo(Type.TyKind.VOID_TY); - assertThat(((ClassValue) c.methods().get(1).defaultValue()).type().tyKind()) + assertThat(((TurbineClassValue) c.methods().get(1).defaultValue()).type().tyKind()) .isEqualTo(Type.TyKind.ARRAY_TY); } diff --git a/javatests/com/google/turbine/deps/AbstractTransitiveTest.java b/javatests/com/google/turbine/deps/AbstractTransitiveTest.java index 1bd9349..4cb8adf 100644 --- a/javatests/com/google/turbine/deps/AbstractTransitiveTest.java +++ b/javatests/com/google/turbine/deps/AbstractTransitiveTest.java @@ -145,17 +145,16 @@ public abstract class AbstractTransitiveTest { Path libc = temporaryFolder.newFolder().toPath().resolve("out.jar"); List<String> sources = new SourceBuilder() - .addSourceLines( - "c/C.java", - "package c;", - "public class C extends b.B {", - " @Anno(x = 2) static final Inner i; // a.A$Inner ", - " static final int X = CONST; // a.A#CONST", - "}") - .build() - .stream() - .map(Path::toString) - .collect(toImmutableList()); + .addSourceLines( + "c/C.java", + "package c;", + "public class C extends b.B {", + " @Anno(x = 2) static final Inner i; // a.A$Inner ", + " static final int X = CONST; // a.A#CONST", + "}") + .build().stream() + .map(Path::toString) + .collect(toImmutableList()); boolean ok = Main.compile( optionsWithBootclasspath() diff --git a/javatests/com/google/turbine/deps/DependenciesTest.java b/javatests/com/google/turbine/deps/DependenciesTest.java index 4c2362f..b1da209 100644 --- a/javatests/com/google/turbine/deps/DependenciesTest.java +++ b/javatests/com/google/turbine/deps/DependenciesTest.java @@ -22,6 +22,7 @@ import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Streams; import com.google.turbine.binder.Binder; import com.google.turbine.binder.Binder.BindingResult; import com.google.turbine.binder.ClassPathBinder; @@ -47,7 +48,6 @@ import java.util.Optional; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.stream.Collectors; -import java.util.stream.StreamSupport; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -116,7 +116,7 @@ public class DependenciesTest { } private Map<Path, DepsProto.Dependency.Kind> depsMap(DepsProto.Dependencies deps) { - return StreamSupport.stream(deps.getDependencyList().spliterator(), false) + return Streams.stream(deps.getDependencyList()) .collect(Collectors.toMap(d -> Paths.get(d.getPath()), DepsProto.Dependency::getKind)); } @@ -130,7 +130,7 @@ public class DependenciesTest { .addSourceLines("Test.java", "class Test extends A {}") .run(); - assertThat(depsMap(deps)).isEqualTo(ImmutableMap.of(liba, DepsProto.Dependency.Kind.EXPLICIT)); + assertThat(depsMap(deps)).containsExactly(liba, DepsProto.Dependency.Kind.EXPLICIT); } @Test @@ -156,7 +156,7 @@ public class DependenciesTest { .addSourceLines("Test.java", "class Test extends B {}") .run(); - assertThat(depsMap(deps)).isEqualTo(ImmutableMap.of(libb, DepsProto.Dependency.Kind.EXPLICIT)); + assertThat(depsMap(deps)).containsExactly(libb, DepsProto.Dependency.Kind.EXPLICIT); } @Test @@ -184,10 +184,8 @@ public class DependenciesTest { "}") .run(); assertThat(depsMap(deps)) - .isEqualTo( - ImmutableMap.of( - libb, DepsProto.Dependency.Kind.EXPLICIT, - liba, DepsProto.Dependency.Kind.EXPLICIT)); + .containsExactly( + libb, DepsProto.Dependency.Kind.EXPLICIT, liba, DepsProto.Dependency.Kind.EXPLICIT); } @Test @@ -227,11 +225,13 @@ public class DependenciesTest { "class Test extends B {}") .run(); assertThat(depsMap(deps)) - .isEqualTo( - ImmutableMap.of( - libi, DepsProto.Dependency.Kind.EXPLICIT, - libb, DepsProto.Dependency.Kind.EXPLICIT, - liba, DepsProto.Dependency.Kind.EXPLICIT)); + .containsExactly( + libi, + DepsProto.Dependency.Kind.EXPLICIT, + libb, + DepsProto.Dependency.Kind.EXPLICIT, + liba, + DepsProto.Dependency.Kind.EXPLICIT); } { // partial classpath @@ -244,10 +244,8 @@ public class DependenciesTest { "class Test extends B {}") .run(); assertThat(depsMap(deps)) - .isEqualTo( - ImmutableMap.of( - libb, DepsProto.Dependency.Kind.EXPLICIT, - liba, DepsProto.Dependency.Kind.EXPLICIT)); + .containsExactly( + libb, DepsProto.Dependency.Kind.EXPLICIT, liba, DepsProto.Dependency.Kind.EXPLICIT); } } @@ -260,7 +258,7 @@ public class DependenciesTest { ImmutableSet<String> directJars = ImmutableSet.of(); ImmutableList<String> depsArtifacts = ImmutableList.of(); assertThat(Dependencies.reduceClasspath(classpath, directJars, depsArtifacts)) - .isEqualTo(classpath); + .containsExactlyElementsIn(classpath); } @Test diff --git a/javatests/com/google/turbine/lower/IntegrationTestSupport.java b/javatests/com/google/turbine/lower/IntegrationTestSupport.java index c039241..680b073 100644 --- a/javatests/com/google/turbine/lower/IntegrationTestSupport.java +++ b/javatests/com/google/turbine/lower/IntegrationTestSupport.java @@ -25,6 +25,7 @@ import static java.util.stream.Collectors.toList; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; +import com.google.common.io.MoreFiles; import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; import com.google.turbine.binder.Binder; @@ -135,12 +136,10 @@ public class IntegrationTestSupport { if (!isDeprecated(n.visibleAnnotations)) { n.access &= ~Opcodes.ACC_DEPRECATED; } - n.methods - .stream() + n.methods.stream() .filter(m -> !isDeprecated(m.visibleAnnotations)) .forEach(m -> m.access &= ~Opcodes.ACC_DEPRECATED); - n.fields - .stream() + n.fields.stream() .filter(f -> !isDeprecated(f.visibleAnnotations)) .forEach(f -> f.access &= ~Opcodes.ACC_DEPRECATED); } @@ -188,21 +187,18 @@ public class IntegrationTestSupport { /** Remove elements that are omitted by turbine, e.g. private and synthetic members. */ private static void removeImplementation(ClassNode n) { n.innerClasses = - n.innerClasses - .stream() + n.innerClasses.stream() .filter(x -> (x.access & Opcodes.ACC_SYNTHETIC) == 0 && x.innerName != null) .collect(toList()); n.methods = - n.methods - .stream() + n.methods.stream() .filter(x -> (x.access & (Opcodes.ACC_SYNTHETIC | Opcodes.ACC_PRIVATE)) == 0) .filter(x -> !x.name.equals("<clinit>")) .collect(toList()); n.fields = - n.fields - .stream() + n.fields.stream() .filter(x -> (x.access & (Opcodes.ACC_SYNTHETIC | Opcodes.ACC_PRIVATE)) == 0) .collect(toList()); } @@ -344,14 +340,14 @@ public class IntegrationTestSupport { if (annos == null) { return; } - annos.stream().forEach(a -> collectTypesFromAnnotation(types, a)); + annos.forEach(a -> collectTypesFromAnnotation(types, a)); } private static void addTypesInAnnotations(Set<String> types, List<AnnotationNode> annos) { if (annos == null) { return; } - annos.stream().forEach(a -> collectTypesFromAnnotation(types, a)); + annos.forEach(a -> collectTypesFromAnnotation(types, a)); } private static void collectTypesFromAnnotation(Set<String> types, AnnotationNode a) { @@ -441,9 +437,7 @@ public class IntegrationTestSupport { Optional<String> moduleVersion) throws IOException { List<Tree.CompUnit> units = - input - .entrySet() - .stream() + input.entrySet().stream() .map(e -> new SourceFile(e.getKey(), e.getValue())) .map(Parser::parse) .collect(toList()); @@ -476,7 +470,7 @@ public class IntegrationTestSupport { if (path.getParent() != null) { Files.createDirectories(path.getParent()); } - Files.write(path, entry.getValue().getBytes(UTF_8)); + MoreFiles.asCharSink(path, UTF_8).write(entry.getValue()); inputs.add(path); } diff --git a/javatests/com/google/turbine/lower/LowerTest.java b/javatests/com/google/turbine/lower/LowerTest.java index ef070f9..0de55c3 100644 --- a/javatests/com/google/turbine/lower/LowerTest.java +++ b/javatests/com/google/turbine/lower/LowerTest.java @@ -431,7 +431,7 @@ public class LowerTest { } }, 0); - assertThat((acc[0] & Opcodes.ACC_DEPRECATED) == Opcodes.ACC_DEPRECATED).isTrue(); + assertThat((acc[0] & Opcodes.ACC_DEPRECATED)).isEqualTo(Opcodes.ACC_DEPRECATED); } @Test @@ -635,8 +635,8 @@ public class LowerTest { } }, 0); - assertThat((testAccess[0] & TurbineFlag.ACC_PUBLIC) == TurbineFlag.ACC_PUBLIC).isTrue(); - assertThat((testAccess[0] & TurbineFlag.ACC_PROTECTED) == TurbineFlag.ACC_PROTECTED).isFalse(); + assertThat((testAccess[0] & TurbineFlag.ACC_PUBLIC)).isEqualTo(TurbineFlag.ACC_PUBLIC); + assertThat((testAccess[0] & TurbineFlag.ACC_PROTECTED)).isNotEqualTo(TurbineFlag.ACC_PROTECTED); } static String lines(String... lines) { diff --git a/javatests/com/google/turbine/lower/ModuleIntegrationTest.java b/javatests/com/google/turbine/lower/ModuleIntegrationTest.java index 4067bd1..03c6fb7 100644 --- a/javatests/com/google/turbine/lower/ModuleIntegrationTest.java +++ b/javatests/com/google/turbine/lower/ModuleIntegrationTest.java @@ -16,6 +16,7 @@ package com.google.turbine.lower; +import static com.google.common.base.StandardSystemProperty.JAVA_CLASS_VERSION; import static com.google.common.collect.ImmutableMap.toImmutableMap; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.stream.Collectors.toList; @@ -61,7 +62,7 @@ public class ModuleIntegrationTest { @Test public void test() throws Exception { - if (Double.parseDouble(System.getProperty("java.class.version")) < 53) { + if (Double.parseDouble(JAVA_CLASS_VERSION.value()) < 53) { // only run on JDK 9 and later return; } @@ -97,7 +98,7 @@ public class ModuleIntegrationTest { IntegrationTestSupport.runTurbine( input.sources, classpathJar, - Double.parseDouble(System.getProperty("java.class.version")) < 54 + Double.parseDouble(JAVA_CLASS_VERSION.value()) < 54 ? JimageClassBinder.bindDefault() : CtSymClassBinder.bind("9"), Optional.of("42")); @@ -107,8 +108,7 @@ public class ModuleIntegrationTest { private String dump(Map<String, byte[]> map) throws Exception { return IntegrationTestSupport.dump( - map.entrySet() - .stream() + map.entrySet().stream() .filter(e -> e.getKey().endsWith("module-info")) .collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue))); } diff --git a/javatests/com/google/turbine/main/MainTest.java b/javatests/com/google/turbine/main/MainTest.java index 654a89b..65f3167 100644 --- a/javatests/com/google/turbine/main/MainTest.java +++ b/javatests/com/google/turbine/main/MainTest.java @@ -16,6 +16,7 @@ package com.google.turbine.main; +import static com.google.common.base.StandardSystemProperty.JAVA_CLASS_VERSION; import static com.google.common.truth.Truth.assertThat; import static com.google.turbine.testing.TestClassPaths.optionsWithBootclasspath; import static java.nio.charset.StandardCharsets.UTF_8; @@ -23,6 +24,7 @@ import static org.junit.Assert.fail; import com.google.common.collect.ImmutableList; import com.google.common.io.ByteStreams; +import com.google.common.io.MoreFiles; import com.google.turbine.diag.TurbineError; import com.google.turbine.options.TurbineOptions; import java.io.IOException; @@ -71,14 +73,14 @@ public class MainTest { .build()); fail(); } catch (TurbineError e) { - assertThat(e.getMessage()).contains("error: duplicate declaration of Test"); + assertThat(e).hasMessageThat().contains("error: duplicate declaration of Test"); } } @Test public void packageInfo() throws IOException { Path src = temporaryFolder.newFile("package-info.jar").toPath(); - Files.write(src, "@Deprecated package test;".getBytes(UTF_8)); + MoreFiles.asCharSink(src, UTF_8).write("@Deprecated package test;"); Path output = temporaryFolder.newFile("output.jar").toPath(); @@ -130,7 +132,7 @@ public class MainTest { @Test public void moduleInfos() throws IOException { - if (Double.parseDouble(System.getProperty("java.class.version")) < 53) { + if (Double.parseDouble(JAVA_CLASS_VERSION.value()) < 53) { // only run on JDK 9 and later return; } @@ -144,7 +146,7 @@ public class MainTest { } Path src = temporaryFolder.newFile("module-info.java").toPath(); - Files.write(src, "module baz {}".getBytes(UTF_8)); + MoreFiles.asCharSink(src, UTF_8).write("module baz {}"); Path output = temporaryFolder.newFile("output.jar").toPath(); @@ -166,7 +168,7 @@ public class MainTest { @Test public void testManifest() throws IOException { Path src = temporaryFolder.newFile("Foo.java").toPath(); - Files.write(src, "class Foo {}".getBytes(UTF_8)); + MoreFiles.asCharSink(src, UTF_8).write("class Foo {}"); Path output = temporaryFolder.newFile("output.jar").toPath(); @@ -195,7 +197,7 @@ public class MainTest { public void emptyBootClassPath() throws IOException { Path src = temporaryFolder.newFolder().toPath().resolve("java/lang/Object.java"); Files.createDirectories(src.getParent()); - Files.write(src, "package java.lang; public class Object {}".getBytes(UTF_8)); + MoreFiles.asCharSink(src, UTF_8).write("package java.lang; public class Object {}"); Path output = temporaryFolder.newFile("output.jar").toPath(); @@ -214,7 +216,7 @@ public class MainTest { @Test public void emptyBootClassPath_noJavaLang() throws IOException { Path src = temporaryFolder.newFile("Test.java").toPath(); - Files.write(src, "public class Test {}".getBytes(UTF_8)); + MoreFiles.asCharSink(src, UTF_8).write("public class Test {}"); Path output = temporaryFolder.newFile("output.jar").toPath(); @@ -233,7 +235,7 @@ public class MainTest { @Test public void usage() throws IOException { Path src = temporaryFolder.newFile("Test.java").toPath(); - Files.write(src, "public class Test {}".getBytes(UTF_8)); + MoreFiles.asCharSink(src, UTF_8).write("public class Test {}"); try { Main.compile(optionsWithBootclasspath().addSources(ImmutableList.of(src.toString())).build()); diff --git a/javatests/com/google/turbine/model/ConstTest.java b/javatests/com/google/turbine/model/ConstTest.java index 7940124..a64d0bf 100644 --- a/javatests/com/google/turbine/model/ConstTest.java +++ b/javatests/com/google/turbine/model/ConstTest.java @@ -20,7 +20,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.testing.EqualsTester; import com.google.turbine.binder.bound.AnnotationValue; -import com.google.turbine.binder.bound.ClassValue; +import com.google.turbine.binder.bound.TurbineClassValue; import com.google.turbine.binder.sym.ClassSymbol; import com.google.turbine.type.Type.ClassTy; import com.google.turbine.type.Type.PrimTy; @@ -72,14 +72,14 @@ public class ConstTest { new AnnotationValue( new ClassSymbol("test/Anno"), ImmutableMap.of("value", new Const.IntValue(4)))) .addEqualityGroup( - new ClassValue(ClassTy.asNonParametricClassTy(new ClassSymbol("test/Clazz"))), - new ClassValue(ClassTy.asNonParametricClassTy(new ClassSymbol("test/Clazz")))) + new TurbineClassValue(ClassTy.asNonParametricClassTy(new ClassSymbol("test/Clazz"))), + new TurbineClassValue(ClassTy.asNonParametricClassTy(new ClassSymbol("test/Clazz")))) .addEqualityGroup( - new ClassValue(ClassTy.asNonParametricClassTy(new ClassSymbol("test/Other"))), - new ClassValue(ClassTy.asNonParametricClassTy(new ClassSymbol("test/Other")))) + new TurbineClassValue(ClassTy.asNonParametricClassTy(new ClassSymbol("test/Other"))), + new TurbineClassValue(ClassTy.asNonParametricClassTy(new ClassSymbol("test/Other")))) .addEqualityGroup( - new ClassValue(PrimTy.create(TurbineConstantTypeKind.INT, ImmutableList.of())), - new ClassValue(PrimTy.create(TurbineConstantTypeKind.INT, ImmutableList.of()))) + new TurbineClassValue(PrimTy.create(TurbineConstantTypeKind.INT, ImmutableList.of())), + new TurbineClassValue(PrimTy.create(TurbineConstantTypeKind.INT, ImmutableList.of()))) .testEquals(); } } diff --git a/javatests/com/google/turbine/options/TurbineOptionsTest.java b/javatests/com/google/turbine/options/TurbineOptionsTest.java index 5953bac..a5872d9 100644 --- a/javatests/com/google/turbine/options/TurbineOptionsTest.java +++ b/javatests/com/google/turbine/options/TurbineOptionsTest.java @@ -95,6 +95,7 @@ public class TurbineOptionsTest { assertThat(options.outputDeps()).hasValue("out.jdeps"); assertThat(options.targetLabel()).hasValue("//java/com/google/test"); assertThat(options.injectingRuleKind()).hasValue("foo_library"); + assertThat(options.shouldReduceClassPath()).isTrue(); } @Test @@ -312,4 +313,41 @@ public class TurbineOptionsTest { .containsExactly("--release", "8", "--release", "7", "--release") .inOrder(); } + + @Test + public void shouldReduceClasspath() throws Exception { + { + TurbineOptions options = + TurbineOptionsParser.parse( + Iterables.concat(BASE_ARGS, ImmutableList.of("--reduce_classpath"))); + assertThat(options.shouldReduceClassPath()).isTrue(); + } + + { + TurbineOptions options = + TurbineOptionsParser.parse( + Iterables.concat(BASE_ARGS, ImmutableList.of("--noreduce_classpath"))); + assertThat(options.shouldReduceClassPath()).isFalse(); + } + } + + @Test + public void unescape() throws Exception { + String[] lines = { + "--sources", "Test.java", "'Foo$Bar.java'", + }; + TurbineOptions options = + TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); + assertThat(options.sources()).containsExactly("Test.java", "Foo$Bar.java").inOrder(); + } + + @Test + public void invalidUnescape() throws Exception { + String[] lines = {"--sources", "'Foo$Bar.java"}; + try { + TurbineOptionsParser.parse(Iterables.concat(BASE_ARGS, Arrays.asList(lines))); + fail(); + } catch (IllegalArgumentException expected) { + } + } } diff --git a/javatests/com/google/turbine/parse/ParseErrorTest.java b/javatests/com/google/turbine/parse/ParseErrorTest.java index 53864ef..49fb273 100644 --- a/javatests/com/google/turbine/parse/ParseErrorTest.java +++ b/javatests/com/google/turbine/parse/ParseErrorTest.java @@ -40,7 +40,7 @@ public class ParseErrorTest { parser.expression(); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()).contains("invalid literal"); + assertThat(e).hasMessageThat().contains("invalid literal"); } } @@ -54,7 +54,7 @@ public class ParseErrorTest { parser.expression(); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()).contains("invalid literal"); + assertThat(e).hasMessageThat().contains("invalid literal"); } } @@ -65,7 +65,8 @@ public class ParseErrorTest { Parser.parse(input); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()) + assertThat(e) + .hasMessageThat() .isEqualTo( lines( "<>:1: error: unexpected token: void", @@ -81,7 +82,8 @@ public class ParseErrorTest { Parser.parse(input); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()) + assertThat(e) + .hasMessageThat() .isEqualTo( lines( "<>:1: error: unexpected identifier 'clas'", // @@ -97,7 +99,8 @@ public class ParseErrorTest { Parser.parse(input); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()) + assertThat(e) + .hasMessageThat() .isEqualTo( lines( "<>:2: error: unexpected end of input", // @@ -113,7 +116,8 @@ public class ParseErrorTest { Parser.parse(input); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()) + assertThat(e) + .hasMessageThat() .isEqualTo( lines( "<>:1: error: invalid annotation argument", // @@ -129,7 +133,8 @@ public class ParseErrorTest { Parser.parse(input); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()) + assertThat(e) + .hasMessageThat() .isEqualTo( lines( "<>:1: error: unexpected end of input", // @@ -145,7 +150,8 @@ public class ParseErrorTest { Parser.parse(input); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()) + assertThat(e) + .hasMessageThat() .isEqualTo( lines( "<>:1: error: unexpected end of input", // @@ -161,7 +167,8 @@ public class ParseErrorTest { Parser.parse(input); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()) + assertThat(e) + .hasMessageThat() .isEqualTo( lines( "<>:1: error: unterminated string literal", // @@ -177,7 +184,8 @@ public class ParseErrorTest { Parser.parse(input); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()) + assertThat(e) + .hasMessageThat() .isEqualTo( lines( "<>:1: error: empty char literal", // @@ -193,7 +201,8 @@ public class ParseErrorTest { Parser.parse(input); fail("expected parsing to fail"); } catch (TurbineError e) { - assertThat(e.getMessage()) + assertThat(e) + .hasMessageThat() .isEqualTo( lines( "<>:1: error: unterminated char literal", // @@ -202,6 +211,23 @@ public class ParseErrorTest { } } + @Test + public void unterminatedExpr() { + String input = "class T { String s = hello + world }"; + try { + Parser.parse(input); + fail("expected parsing to fail"); + } catch (TurbineError e) { + assertThat(e) + .hasMessageThat() + .isEqualTo( + lines( + "<>:1: error: unterminated expression, expected ';' not found", // + "class T { String s = hello + world }", + " ^")); + } + } + private static String lines(String... lines) { return Joiner.on(System.lineSeparator()).join(lines); } @@ -17,7 +17,7 @@ <properties> <asm.version>7.0</asm.version> <javac.version>9+181-r4173-1</javac.version> - <guava.version>25.1-jre</guava.version> + <guava.version>27.0.1-jre</guava.version> </properties> <dependencies> |