aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcushon <cushon@google.com>2018-11-13 17:39:30 -0800
committerLiam Miller-Cushon <cushon@google.com>2018-11-13 17:43:55 -0800
commit5a26f8cf360ab8f450d6268574a8a8ab50588d0d (patch)
treea8e8dfae6835a2f6c36af07d84ffbdebde6a1c2e
parent180ba7e85bd168ecb0f8cce2c2ae04f27c7f7d36 (diff)
downloadturbine-5a26f8cf360ab8f450d6268574a8a8ab50588d0d.tar.gz
Accumulate diagnostics during hierarchy and type binding
instead of failing eagerly on the first error. If there are multiple missing symbols it's usually more helpful to report them all at once. MOE_MIGRATED_REVID=221365669
-rw-r--r--java/com/google/turbine/binder/Binder.java25
-rw-r--r--java/com/google/turbine/binder/CanonicalTypeBinder.java22
-rw-r--r--java/com/google/turbine/binder/ConstBinder.java12
-rw-r--r--java/com/google/turbine/binder/HierarchyBinder.java33
-rw-r--r--java/com/google/turbine/binder/TypeBinder.java76
-rw-r--r--java/com/google/turbine/binder/bound/SourceTypeBoundClass.java39
-rw-r--r--java/com/google/turbine/binder/bound/TypeBoundClass.java4
-rw-r--r--java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java10
-rw-r--r--java/com/google/turbine/binder/lookup/ImportIndex.java41
-rw-r--r--java/com/google/turbine/diag/TurbineDiagnostic.java128
-rw-r--r--java/com/google/turbine/diag/TurbineError.java60
-rw-r--r--java/com/google/turbine/diag/TurbineLog.java56
-rw-r--r--java/com/google/turbine/lower/LowerSignature.java8
-rw-r--r--java/com/google/turbine/type/AnnoInfo.java4
-rw-r--r--java/com/google/turbine/type/Type.java17
-rw-r--r--java/com/google/turbine/types/Canonicalize.java2
-rw-r--r--javatests/com/google/turbine/binder/BinderErrorTest.java18
-rw-r--r--javatests/com/google/turbine/binder/ClassPathBinderTest.java9
-rw-r--r--javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java15
-rw-r--r--javatests/com/google/turbine/lower/LowerTest.java2
20 files changed, 397 insertions, 184 deletions
diff --git a/java/com/google/turbine/binder/Binder.java b/java/com/google/turbine/binder/Binder.java
index 9ed83d2..cffe291 100644
--- a/java/com/google/turbine/binder/Binder.java
+++ b/java/com/google/turbine/binder/Binder.java
@@ -53,6 +53,7 @@ import com.google.turbine.binder.sym.FieldSymbol;
import com.google.turbine.binder.sym.ModuleSymbol;
import com.google.turbine.diag.TurbineError;
import com.google.turbine.diag.TurbineError.ErrorKind;
+import com.google.turbine.diag.TurbineLog;
import com.google.turbine.model.Const;
import com.google.turbine.model.TurbineFlag;
import com.google.turbine.tree.Tree;
@@ -90,17 +91,24 @@ public class Binder {
CompoundEnv<ModuleSymbol, ModuleInfo> classPathModuleEnv =
CompoundEnv.of(classpath.moduleEnv()).append(bootclasspath.moduleEnv());
+ TurbineLog log = new TurbineLog();
+
BindPackagesResult bindPackagesResult =
- bindPackages(ienv, tli, preProcessedUnits, classPathEnv);
+ bindPackages(log, ienv, tli, preProcessedUnits, classPathEnv);
SimpleEnv<ClassSymbol, PackageSourceBoundClass> psenv = bindPackagesResult.classes;
SimpleEnv<ModuleSymbol, PackageSourceBoundModule> modules = bindPackagesResult.modules;
- Env<ClassSymbol, SourceHeaderBoundClass> henv = bindHierarchy(syms, psenv, classPathEnv);
+ Env<ClassSymbol, SourceHeaderBoundClass> henv = bindHierarchy(log, syms, psenv, classPathEnv);
Env<ClassSymbol, SourceTypeBoundClass> tenv =
bindTypes(
- syms, henv, CompoundEnv.<ClassSymbol, HeaderBoundClass>of(classPathEnv).append(henv));
+ log,
+ syms,
+ henv,
+ CompoundEnv.<ClassSymbol, HeaderBoundClass>of(classPathEnv).append(henv));
+
+ log.maybeThrow();
tenv =
constants(
@@ -156,6 +164,7 @@ public class Binder {
/** Initializes scopes for compilation unit and package-level lookup. */
private static BindPackagesResult bindPackages(
+ TurbineLog log,
Env<ClassSymbol, SourceBoundClass> ienv,
TopLevelIndex tli,
ImmutableList<PreprocessedCompUnit> units,
@@ -179,7 +188,7 @@ public class Binder {
unit.packageName(),
CompoundEnv.<ClassSymbol, BoundClass>of(classPathEnv).append(ienv));
ImportScope importScope =
- ImportIndex.create(unit.source(), importResolver, tli, unit.imports());
+ ImportIndex.create(log.withSource(unit.source()), importResolver, tli, unit.imports());
ImportScope wildImportScope = WildImportIndex.create(importResolver, tli, unit.imports());
MemberImportIndex memberImports =
new MemberImportIndex(unit.source(), importResolver, tli, unit.imports());
@@ -203,6 +212,7 @@ public class Binder {
/** Binds the type hierarchy (superclasses and interfaces) for all classes in the compilation. */
private static Env<ClassSymbol, SourceHeaderBoundClass> bindHierarchy(
+ TurbineLog log,
Iterable<ClassSymbol> syms,
final SimpleEnv<ClassSymbol, PackageSourceBoundClass> psenv,
CompoundEnv<ClassSymbol, BytecodeBoundClass> classPathEnv) {
@@ -216,7 +226,8 @@ public class Binder {
@Override
public SourceHeaderBoundClass complete(
Env<ClassSymbol, HeaderBoundClass> henv, ClassSymbol sym) {
- return HierarchyBinder.bind(sym, psenv.get(sym), henv);
+ PackageSourceBoundClass base = psenv.get(sym);
+ return HierarchyBinder.bind(log.withSource(base.source()), sym, base, henv);
}
});
}
@@ -224,12 +235,14 @@ public class Binder {
}
private static Env<ClassSymbol, SourceTypeBoundClass> bindTypes(
+ TurbineLog log,
ImmutableSet<ClassSymbol> syms,
Env<ClassSymbol, SourceHeaderBoundClass> shenv,
Env<ClassSymbol, HeaderBoundClass> henv) {
SimpleEnv.Builder<ClassSymbol, SourceTypeBoundClass> builder = SimpleEnv.builder();
for (ClassSymbol sym : syms) {
- builder.put(sym, TypeBinder.bind(henv, sym, shenv.get(sym)));
+ SourceHeaderBoundClass base = shenv.get(sym);
+ builder.put(sym, TypeBinder.bind(log.withSource(base.source()), henv, sym, base));
}
return builder.build();
}
diff --git a/java/com/google/turbine/binder/CanonicalTypeBinder.java b/java/com/google/turbine/binder/CanonicalTypeBinder.java
index caeda97..934ec54 100644
--- a/java/com/google/turbine/binder/CanonicalTypeBinder.java
+++ b/java/com/google/turbine/binder/CanonicalTypeBinder.java
@@ -31,6 +31,7 @@ import com.google.turbine.diag.SourceFile;
import com.google.turbine.type.Type;
import com.google.turbine.type.Type.ClassTy;
import com.google.turbine.type.Type.IntersectionTy;
+import com.google.turbine.type.Type.TyKind;
import com.google.turbine.types.Canonicalize;
import java.util.Map;
@@ -42,16 +43,23 @@ public class CanonicalTypeBinder {
static SourceTypeBoundClass bind(
ClassSymbol sym, SourceTypeBoundClass base, Env<ClassSymbol, TypeBoundClass> env) {
ClassTy superClassType = null;
- if (base.superClassType() != null) {
+ if (base.superClassType() != null && base.superClassType().tyKind() == TyKind.CLASS_TY) {
superClassType =
Canonicalize.canonicalizeClassTy(
- base.source(), base.decl().position(), env, base.owner(), base.superClassType());
+ base.source(),
+ base.decl().position(),
+ env,
+ base.owner(),
+ (ClassTy) base.superClassType());
}
- ImmutableList.Builder<ClassTy> interfaceTypes = ImmutableList.builder();
- for (ClassTy i : base.interfaceTypes()) {
- interfaceTypes.add(
- Canonicalize.canonicalizeClassTy(
- base.source(), base.decl().position(), env, base.owner(), i));
+ ImmutableList.Builder<Type> interfaceTypes = ImmutableList.builder();
+ for (Type i : base.interfaceTypes()) {
+ if (i.tyKind() == TyKind.CLASS_TY) {
+ i =
+ Canonicalize.canonicalizeClassTy(
+ base.source(), base.decl().position(), env, base.owner(), (ClassTy) i);
+ }
+ interfaceTypes.add(i);
}
ImmutableMap<TyVarSymbol, TyVarInfo> typParamTypes =
typeParameters(base.source(), base.decl().position(), env, sym, base.typeParameterTypes());
diff --git a/java/com/google/turbine/binder/ConstBinder.java b/java/com/google/turbine/binder/ConstBinder.java
index 0e81201..e5717b2 100644
--- a/java/com/google/turbine/binder/ConstBinder.java
+++ b/java/com/google/turbine/binder/ConstBinder.java
@@ -92,8 +92,8 @@ public class ConstBinder {
ImmutableList<TypeBoundClass.FieldInfo> fields = fields(base.fields());
ImmutableList<MethodInfo> methods = bindMethods(base.methods());
return new SourceTypeBoundClass(
- bindClassTypes(base.interfaceTypes()),
- base.superClassType() != null ? bindClassType(base.superClassType()) : null,
+ bindTypes(base.interfaceTypes()),
+ base.superClassType() != null ? bindType(base.superClassType()) : null,
bindTypeParameters(base.typeParameterTypes()),
base.access(),
methods,
@@ -270,14 +270,6 @@ public class ConstBinder {
return value;
}
- private ImmutableList<ClassTy> bindClassTypes(ImmutableList<ClassTy> types) {
- ImmutableList.Builder<ClassTy> result = ImmutableList.builder();
- for (ClassTy t : types) {
- result.add(bindClassType(t));
- }
- return result.build();
- }
-
private ImmutableList<Type> bindTypes(ImmutableList<Type> types) {
ImmutableList.Builder<Type> result = ImmutableList.builder();
for (Type t : types) {
diff --git a/java/com/google/turbine/binder/HierarchyBinder.java b/java/com/google/turbine/binder/HierarchyBinder.java
index 9d7807c..8549d3a 100644
--- a/java/com/google/turbine/binder/HierarchyBinder.java
+++ b/java/com/google/turbine/binder/HierarchyBinder.java
@@ -27,8 +27,8 @@ import com.google.turbine.binder.lookup.LookupKey;
import com.google.turbine.binder.lookup.LookupResult;
import com.google.turbine.binder.sym.ClassSymbol;
import com.google.turbine.binder.sym.TyVarSymbol;
-import com.google.turbine.diag.TurbineError;
import com.google.turbine.diag.TurbineError.ErrorKind;
+import com.google.turbine.diag.TurbineLog.TurbineLogWithSource;
import com.google.turbine.model.TurbineTyKind;
import com.google.turbine.tree.Tree;
import com.google.turbine.tree.Tree.ClassTy;
@@ -39,20 +39,24 @@ public class HierarchyBinder {
/** Binds the type hierarchy (superclasses and interfaces) for a single class. */
public static SourceHeaderBoundClass bind(
+ TurbineLogWithSource log,
ClassSymbol origin,
PackageSourceBoundClass base,
Env<ClassSymbol, ? extends HeaderBoundClass> env) {
- return new HierarchyBinder(origin, base, env).bind();
+ return new HierarchyBinder(log, origin, base, env).bind();
}
+ private final TurbineLogWithSource log;
private final ClassSymbol origin;
private final PackageSourceBoundClass base;
private final Env<ClassSymbol, ? extends HeaderBoundClass> env;
private HierarchyBinder(
+ TurbineLogWithSource log,
ClassSymbol origin,
PackageSourceBoundClass base,
Env<ClassSymbol, ? extends HeaderBoundClass> env) {
+ this.log = log;
this.origin = origin;
this.base = base;
this.env = env;
@@ -84,7 +88,7 @@ public class HierarchyBinder {
for (Tree.ClassTy i : decl.impls()) {
ClassSymbol result = resolveClass(i);
if (result == null) {
- throw new AssertionError(i);
+ continue;
}
interfaces.add(result);
}
@@ -102,7 +106,6 @@ public class HierarchyBinder {
return new SourceHeaderBoundClass(base, superclass, interfaces.build(), typeParameters.build());
}
-
/**
* Resolves the {@link ClassSymbol} for the given {@link Tree.ClassTy}, with handling for
* non-canonical qualified type names.
@@ -117,13 +120,17 @@ public class HierarchyBinder {
// Resolve the base symbol in the qualified name.
LookupResult result = lookup(ty, new LookupKey(ImmutableList.copyOf(flat)));
if (result == null) {
- throw TurbineError.format(base.source(), ty.position(), ErrorKind.CANNOT_RESOLVE, ty);
+ log.error(ty.position(), ErrorKind.CANNOT_RESOLVE, ty);
+ return null;
}
// Resolve pieces in the qualified name referring to member types.
// This needs to consider member type declarations inherited from supertypes and interfaces.
ClassSymbol sym = (ClassSymbol) result.sym();
for (Tree.Ident bit : result.remaining()) {
sym = resolveNext(ty, sym, bit);
+ if (sym == null) {
+ break;
+ }
}
return sym;
}
@@ -133,11 +140,14 @@ public class HierarchyBinder {
try {
next = Resolve.resolve(env, origin, sym, bit);
} catch (LazyBindingError e) {
- throw error(ty.position(), ErrorKind.CYCLIC_HIERARCHY, e.getMessage());
+ log.error(ty.position(), ErrorKind.CYCLIC_HIERARCHY, e.getMessage());
+ return null;
}
if (next == null) {
- throw error(
- ty.position(), ErrorKind.SYMBOL_NOT_FOUND, new ClassSymbol(sym.binaryName() + '$' + bit));
+ log.error(
+ bit.position(),
+ ErrorKind.SYMBOL_NOT_FOUND,
+ new ClassSymbol(sym.binaryName() + '$' + bit));
}
return next;
}
@@ -152,7 +162,8 @@ public class HierarchyBinder {
try {
result = Resolve.resolve(env, origin, curr, lookup.first());
} catch (LazyBindingError e) {
- throw error(tree.position(), ErrorKind.CYCLIC_HIERARCHY, e.getMessage());
+ log.error(tree.position(), ErrorKind.CYCLIC_HIERARCHY, e.getMessage());
+ result = null;
}
if (result != null) {
return new LookupResult(result, lookup);
@@ -162,8 +173,4 @@ public class HierarchyBinder {
// qualified name resolution).
return base.scope().lookup(lookup, Resolve.resolveFunction(env, origin));
}
-
- private TurbineError error(int position, ErrorKind kind, Object... args) {
- return TurbineError.format(base.source(), position, kind, args);
- }
}
diff --git a/java/com/google/turbine/binder/TypeBinder.java b/java/com/google/turbine/binder/TypeBinder.java
index 71c3f69..8cf71e1 100644
--- a/java/com/google/turbine/binder/TypeBinder.java
+++ b/java/com/google/turbine/binder/TypeBinder.java
@@ -36,13 +36,14 @@ import com.google.turbine.binder.sym.FieldSymbol;
import com.google.turbine.binder.sym.MethodSymbol;
import com.google.turbine.binder.sym.Symbol;
import com.google.turbine.binder.sym.TyVarSymbol;
-import com.google.turbine.diag.TurbineError;
import com.google.turbine.diag.TurbineError.ErrorKind;
+import com.google.turbine.diag.TurbineLog.TurbineLogWithSource;
import com.google.turbine.model.TurbineConstantTypeKind;
import com.google.turbine.model.TurbineFlag;
import com.google.turbine.model.TurbineTyKind;
import com.google.turbine.model.TurbineVisibility;
import com.google.turbine.tree.Tree;
+import com.google.turbine.tree.Tree.Anno;
import com.google.turbine.tree.Tree.ClassTy;
import com.google.turbine.tree.Tree.Ident;
import com.google.turbine.tree.Tree.Kind;
@@ -131,16 +132,24 @@ public class TypeBinder {
/** Creates {@link SourceTypeBoundClass} nodes for a compilation. */
public static SourceTypeBoundClass bind(
- Env<ClassSymbol, HeaderBoundClass> env, ClassSymbol sym, SourceHeaderBoundClass base) {
- return new TypeBinder(env, sym, base).bind();
+ TurbineLogWithSource log,
+ Env<ClassSymbol, HeaderBoundClass> env,
+ ClassSymbol sym,
+ SourceHeaderBoundClass base) {
+ return new TypeBinder(log, env, sym, base).bind();
}
+ private final TurbineLogWithSource log;
private final Env<ClassSymbol, HeaderBoundClass> env;
private final ClassSymbol owner;
private final SourceHeaderBoundClass base;
private TypeBinder(
- Env<ClassSymbol, HeaderBoundClass> env, ClassSymbol owner, SourceHeaderBoundClass base) {
+ TurbineLogWithSource log,
+ Env<ClassSymbol, HeaderBoundClass> env,
+ ClassSymbol owner,
+ SourceHeaderBoundClass base) {
+ this.log = log;
this.env = env;
this.owner = owner;
this.base = base;
@@ -167,8 +176,8 @@ public class TypeBinder {
final ImmutableMap<TyVarSymbol, TyVarInfo> typeParameterTypes =
bindTyParams(base.decl().typarams(), bindingScope, base.typeParameters());
- ImmutableList.Builder<Type.ClassTy> interfaceTypes = ImmutableList.builder();
- Type.ClassTy superClassType;
+ ImmutableList.Builder<Type> interfaceTypes = ImmutableList.builder();
+ Type superClassType;
switch (base.kind()) {
case ENUM:
superClassType =
@@ -185,7 +194,7 @@ public class TypeBinder {
break;
case CLASS:
if (base.decl().xtnds().isPresent()) {
- superClassType = (Type.ClassTy) bindClassTy(bindingScope, base.decl().xtnds().get());
+ superClassType = bindClassTy(bindingScope, base.decl().xtnds().get());
} else if (owner.equals(ClassSymbol.OBJECT)) {
// java.lang.Object doesn't have a superclass
superClassType = null;
@@ -204,7 +213,7 @@ public class TypeBinder {
}
for (Tree.ClassTy i : base.decl().impls()) {
- interfaceTypes.add((Type.ClassTy) bindClassTy(bindingScope, i));
+ interfaceTypes.add(bindClassTy(bindingScope, i));
}
CompoundScope scope =
@@ -517,7 +526,8 @@ public class TypeBinder {
if (member.kind() == Tree.Kind.VAR_DECL) {
FieldInfo field = bindField(scope, (Tree.VarDecl) member);
if (!seen.add(field.sym())) {
- throw error(member.position(), ErrorKind.DUPLICATE_DECLARATION, "field: " + field.name());
+ log.error(member.position(), ErrorKind.DUPLICATE_DECLARATION, "field: " + field.name());
+ continue;
}
fields.add(field);
}
@@ -548,26 +558,37 @@ public class TypeBinder {
CompoundScope scope, ImmutableList<Tree.Anno> trees) {
ImmutableList.Builder<AnnoInfo> result = ImmutableList.builder();
for (Tree.Anno tree : trees) {
- LookupResult lookupResult = scope.lookup(new LookupKey(tree.name()));
- if (lookupResult == null) {
- throw error(tree.position(), ErrorKind.CANNOT_RESOLVE, Joiner.on('.').join(tree.name()));
- }
- ClassSymbol sym = (ClassSymbol) lookupResult.sym();
- for (Ident name : lookupResult.remaining()) {
- sym = resolveNext(sym, name);
- }
- if (env.get(sym).kind() != TurbineTyKind.ANNOTATION) {
- throw error(tree.position(), ErrorKind.NOT_AN_ANNOTATION, sym);
- }
+ ImmutableList<Ident> name = tree.name();
+ LookupResult lookupResult = scope.lookup(new LookupKey(name));
+ ClassSymbol sym = resolveAnnoSymbol(tree, name, lookupResult);
result.add(new AnnoInfo(base.source(), sym, tree, null));
}
return result.build();
}
+ private ClassSymbol resolveAnnoSymbol(
+ Anno tree, ImmutableList<Ident> name, LookupResult lookupResult) {
+ if (lookupResult == null) {
+ log.error(tree.position(), ErrorKind.CANNOT_RESOLVE, Joiner.on('.').join(name));
+ return null;
+ }
+ ClassSymbol sym = (ClassSymbol) lookupResult.sym();
+ for (Ident ident : lookupResult.remaining()) {
+ sym = resolveNext(sym, ident);
+ if (sym == null) {
+ return null;
+ }
+ }
+ if (env.get(sym).kind() != TurbineTyKind.ANNOTATION) {
+ log.error(tree.position(), ErrorKind.NOT_AN_ANNOTATION, sym);
+ }
+ return sym;
+ }
+
private ClassSymbol resolveNext(ClassSymbol sym, Ident bit) {
ClassSymbol next = Resolve.resolve(env, owner, sym, bit);
if (next == null) {
- throw error(
+ log.error(
bit.position(),
ErrorKind.SYMBOL_NOT_FOUND,
new ClassSymbol(sym.binaryName() + '$' + bit));
@@ -626,7 +647,8 @@ public class TypeBinder {
// resolve the prefix to a symbol
LookupResult result = scope.lookup(new LookupKey(names));
if (result == null || result.sym() == null) {
- throw error(names.get(0).position(), ErrorKind.CANNOT_RESOLVE, Joiner.on('.').join(names));
+ log.error(names.get(0).position(), ErrorKind.CANNOT_RESOLVE, Joiner.on('.').join(names));
+ return Type.ErrorTy.create();
}
Symbol sym = result.sym();
int annoIdx = flat.size() - result.remaining().size() - 1;
@@ -637,7 +659,8 @@ public class TypeBinder {
return bindClassTyRest(scope, flat, names, result, (ClassSymbol) sym, annos);
case TY_PARAM:
if (!result.remaining().isEmpty()) {
- throw error(t.position(), ErrorKind.TYPE_PARAMETER_QUALIFIER);
+ log.error(t.position(), ErrorKind.TYPE_PARAMETER_QUALIFIER);
+ return Type.ErrorTy.create();
}
return Type.TyVar.create((TyVarSymbol) sym, annos);
default:
@@ -660,6 +683,9 @@ public class TypeBinder {
for (; idx < flat.size(); idx++) {
Tree.ClassTy curr = flat.get(idx);
sym = resolveNext(sym, curr.name());
+ if (sym == null) {
+ return Type.ErrorTy.create();
+ }
annotations = bindAnnotations(scope, curr.annos());
classes.add(
@@ -686,8 +712,4 @@ public class TypeBinder {
return Type.WildUnboundedTy.create(annotations);
}
}
-
- private TurbineError error(int position, ErrorKind kind, Object... args) {
- return TurbineError.format(base.source(), position, kind, args);
- }
}
diff --git a/java/com/google/turbine/binder/bound/SourceTypeBoundClass.java b/java/com/google/turbine/binder/bound/SourceTypeBoundClass.java
index dd34b16..69a2593 100644
--- a/java/com/google/turbine/binder/bound/SourceTypeBoundClass.java
+++ b/java/com/google/turbine/binder/bound/SourceTypeBoundClass.java
@@ -16,10 +16,8 @@
package com.google.turbine.binder.bound;
-import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
import com.google.turbine.binder.lookup.CompoundScope;
import com.google.turbine.binder.lookup.MemberImportIndex;
import com.google.turbine.binder.sym.ClassSymbol;
@@ -30,6 +28,7 @@ import com.google.turbine.tree.Tree;
import com.google.turbine.type.AnnoInfo;
import com.google.turbine.type.Type;
import com.google.turbine.type.Type.ClassTy;
+import com.google.turbine.type.Type.TyKind;
import org.checkerframework.checker.nullness.qual.Nullable;
/** A HeaderBoundClass for classes compiled from source. */
@@ -43,8 +42,8 @@ public class SourceTypeBoundClass implements TypeBoundClass {
private final ImmutableMap<String, TyVarSymbol> typeParameters;
private final ImmutableMap<TyVarSymbol, TyVarInfo> typeParameterTypes;
- private final Type.ClassTy superClassType;
- private final ImmutableList<Type.ClassTy> interfaceTypes;
+ private final Type superClassType;
+ private final ImmutableList<Type> interfaceTypes;
private final ImmutableList<MethodInfo> methods;
private final ImmutableList<FieldInfo> fields;
private final CompoundScope enclosingScope;
@@ -56,8 +55,8 @@ public class SourceTypeBoundClass implements TypeBoundClass {
private final SourceFile source;
public SourceTypeBoundClass(
- ImmutableList<ClassTy> interfaceTypes,
- ClassTy superClassType,
+ ImmutableList<Type> interfaceTypes,
+ Type superClassType,
ImmutableMap<TyVarSymbol, TyVarInfo> typeParameterTypes,
int access,
ImmutableList<MethodInfo> methods,
@@ -94,20 +93,24 @@ public class SourceTypeBoundClass implements TypeBoundClass {
@Override
public ClassSymbol superclass() {
- return superClassType() != null ? superClassType().sym() : null;
+ if (superClassType == null) {
+ return null;
+ }
+ if (superClassType.tyKind() != TyKind.CLASS_TY) {
+ return null;
+ }
+ return ((ClassTy) superClassType).sym();
}
@Override
public ImmutableList<ClassSymbol> interfaces() {
- return ImmutableList.copyOf(
- Iterables.transform(
- interfaceTypes,
- new Function<ClassTy, ClassSymbol>() {
- @Override
- public ClassSymbol apply(ClassTy classTy) {
- return classTy.sym();
- }
- }));
+ ImmutableList.Builder<ClassSymbol> result = ImmutableList.builder();
+ for (Type type : interfaceTypes) {
+ if (type.tyKind() == TyKind.CLASS_TY) {
+ result.add(((ClassTy) type).sym());
+ }
+ }
+ return result.build();
}
@Override
@@ -137,13 +140,13 @@ public class SourceTypeBoundClass implements TypeBoundClass {
}
@Override
- public ImmutableList<Type.ClassTy> interfaceTypes() {
+ public ImmutableList<Type> interfaceTypes() {
return interfaceTypes;
}
/** The super-class type. */
@Override
- public Type.ClassTy superClassType() {
+ public Type superClassType() {
return superClassType;
}
diff --git a/java/com/google/turbine/binder/bound/TypeBoundClass.java b/java/com/google/turbine/binder/bound/TypeBoundClass.java
index dc6bb43..350d311 100644
--- a/java/com/google/turbine/binder/bound/TypeBoundClass.java
+++ b/java/com/google/turbine/binder/bound/TypeBoundClass.java
@@ -33,10 +33,10 @@ import com.google.turbine.type.Type.IntersectionTy;
public interface TypeBoundClass extends HeaderBoundClass {
/** The super-class type. */
- Type.ClassTy superClassType();
+ Type superClassType();
/** Implemented interface types. */
- ImmutableList<Type.ClassTy> interfaceTypes();
+ ImmutableList<Type> interfaceTypes();
ImmutableMap<TyVarSymbol, TyVarInfo> typeParameterTypes();
diff --git a/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java b/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java
index e500302..962c5b4 100644
--- a/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java
+++ b/java/com/google/turbine/binder/bytecode/BytecodeBoundClass.java
@@ -279,15 +279,15 @@ public class BytecodeBoundClass implements BoundClass, HeaderBoundClass, TypeBou
return superClassType.get();
}
- private final Supplier<ImmutableList<ClassTy>> interfaceTypes =
+ private final Supplier<ImmutableList<Type>> interfaceTypes =
Suppliers.memoize(
- new Supplier<ImmutableList<ClassTy>>() {
+ new Supplier<ImmutableList<Type>>() {
@Override
- public ImmutableList<ClassTy> get() {
+ public ImmutableList<Type> get() {
if (interfaces().isEmpty()) {
return ImmutableList.of();
}
- ImmutableList.Builder<ClassTy> result = ImmutableList.builder();
+ ImmutableList.Builder<Type> result = ImmutableList.builder();
if (sig.get() == null || sig.get().interfaces() == null) {
for (ClassSymbol sym : interfaces()) {
result.add(ClassTy.asNonParametricClassTy(sym));
@@ -303,7 +303,7 @@ public class BytecodeBoundClass implements BoundClass, HeaderBoundClass, TypeBou
});
@Override
- public ImmutableList<ClassTy> interfaceTypes() {
+ public ImmutableList<Type> interfaceTypes() {
return interfaceTypes.get();
}
diff --git a/java/com/google/turbine/binder/lookup/ImportIndex.java b/java/com/google/turbine/binder/lookup/ImportIndex.java
index cf6d8f5..f28d905 100644
--- a/java/com/google/turbine/binder/lookup/ImportIndex.java
+++ b/java/com/google/turbine/binder/lookup/ImportIndex.java
@@ -24,10 +24,10 @@ import com.google.common.base.Suppliers;
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.diag.TurbineError;
import com.google.turbine.diag.TurbineError.ErrorKind;
+import com.google.turbine.diag.TurbineLog.TurbineLogWithSource;
import com.google.turbine.tree.Tree;
+import com.google.turbine.tree.Tree.Ident;
import com.google.turbine.tree.Tree.ImportDecl;
import java.util.HashMap;
import java.util.Map;
@@ -49,13 +49,13 @@ public class ImportIndex implements ImportScope {
*/
private final Map<String, Supplier<ImportScope>> thunks;
- public ImportIndex(ImmutableMap<String, Supplier<ImportScope>> thunks) {
+ public ImportIndex(TurbineLogWithSource log, ImmutableMap<String, Supplier<ImportScope>> thunks) {
this.thunks = thunks;
}
/** Creates an import index for the given top-level environment. */
public static ImportIndex create(
- SourceFile source,
+ TurbineLogWithSource log,
CanonicalSymbolResolver resolve,
final TopLevelIndex cpi,
ImmutableList<ImportDecl> imports) {
@@ -70,7 +70,7 @@ public class ImportIndex implements ImportScope {
new Supplier<ImportScope>() {
@Override
public ImportScope get() {
- return namedImport(source, cpi, i, resolve);
+ return namedImport(log, cpi, i, resolve);
}
}));
}
@@ -87,27 +87,25 @@ public class ImportIndex implements ImportScope {
new Supplier<ImportScope>() {
@Override
public ImportScope get() {
- return staticNamedImport(cpi, i);
+ return staticNamedImport(log, cpi, i);
}
}));
}
- return new ImportIndex(ImmutableMap.copyOf(thunks));
+ return new ImportIndex(log, ImmutableMap.copyOf(thunks));
}
/** Fully resolve the canonical name of a non-static named import. */
private static ImportScope namedImport(
- SourceFile source, TopLevelIndex cpi, ImportDecl i, CanonicalSymbolResolver resolve) {
+ TurbineLogWithSource log, TopLevelIndex cpi, ImportDecl i, CanonicalSymbolResolver resolve) {
LookupResult result = cpi.scope().lookup(new LookupKey(i.type()));
if (result == null) {
- throw TurbineError.format(
- source,
- i.position(),
- ErrorKind.SYMBOL_NOT_FOUND,
- new ClassSymbol(Joiner.on('/').join(i.type())));
+ log.error(
+ i.position(), ErrorKind.SYMBOL_NOT_FOUND, new ClassSymbol(Joiner.on('/').join(i.type())));
+ return null;
}
ClassSymbol sym = (ClassSymbol) result.sym();
for (Tree.Ident bit : result.remaining()) {
- sym = resolveNext(source, i.position(), resolve, sym, bit);
+ sym = resolveNext(log, i.position(), resolve, sym, bit);
}
ClassSymbol resolved = sym;
return new ImportScope() {
@@ -119,18 +117,15 @@ public class ImportIndex implements ImportScope {
}
private static ClassSymbol resolveNext(
- SourceFile source,
+ TurbineLogWithSource log,
int position,
CanonicalSymbolResolver resolve,
ClassSymbol sym,
- Tree.Ident bit) {
+ Ident bit) {
ClassSymbol next = resolve.resolveOne(sym, bit);
if (next == null) {
- throw TurbineError.format(
- source,
- position,
- ErrorKind.SYMBOL_NOT_FOUND,
- new ClassSymbol(sym.binaryName() + '$' + bit));
+ log.error(
+ position, ErrorKind.SYMBOL_NOT_FOUND, new ClassSymbol(sym.binaryName() + '$' + bit));
}
return next;
}
@@ -142,9 +137,11 @@ public class ImportIndex implements ImportScope {
* hierarchy analysis is complete, so for now we resolve the base {@code java.util.HashMap} and
* defer the rest.
*/
- private static ImportScope staticNamedImport(TopLevelIndex cpi, ImportDecl i) {
+ private static ImportScope staticNamedImport(
+ TurbineLogWithSource log, TopLevelIndex cpi, ImportDecl i) {
LookupResult base = cpi.scope().lookup(new LookupKey(i.type()));
if (base == null) {
+ log.error(i.position(), ErrorKind.SYMBOL_NOT_FOUND, Joiner.on(".").join(i.type()));
return null;
}
return new ImportScope() {
diff --git a/java/com/google/turbine/diag/TurbineDiagnostic.java b/java/com/google/turbine/diag/TurbineDiagnostic.java
new file mode 100644
index 0000000..0404a8e
--- /dev/null
+++ b/java/com/google/turbine/diag/TurbineDiagnostic.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.turbine.diag;
+
+import static com.google.common.base.MoreObjects.firstNonNull;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.turbine.binder.sym.ClassSymbol;
+import com.google.turbine.diag.TurbineError.ErrorKind;
+import java.util.Objects;
+
+/** A compilation error. */
+public class TurbineDiagnostic {
+
+ private final ErrorKind kind;
+ private final String diagnostic;
+ private final ImmutableList<Object> args;
+
+ private TurbineDiagnostic(ErrorKind kind, String diagnostic, ImmutableList<Object> args) {
+ this.kind = requireNonNull(kind);
+ this.diagnostic = requireNonNull(diagnostic);
+ this.args = requireNonNull(args);
+ }
+
+ /** The diagnostic kind. */
+ public ErrorKind kind() {
+ return kind;
+ }
+
+ /** The diagnostic message. */
+ public String diagnostic() {
+ return diagnostic;
+ }
+
+ /** The diagnostic arguments. */
+ public ImmutableList<Object> args() {
+ return args;
+ }
+
+ private static TurbineDiagnostic create(
+ ErrorKind kind, String diagnostic, ImmutableList<Object> args) {
+ switch (kind) {
+ case SYMBOL_NOT_FOUND:
+ {
+ checkArgument(
+ args.size() == 1 && getOnlyElement(args) instanceof ClassSymbol,
+ "diagnostic (%s) has invalid argument args %s",
+ diagnostic,
+ args);
+ break;
+ }
+ default: // fall out
+ }
+ return new TurbineDiagnostic(kind, diagnostic, args);
+ }
+
+ /**
+ * Formats a diagnostic.
+ *
+ * @param source the current source file
+ * @param kind the error kind
+ * @param args format args
+ */
+ public static TurbineDiagnostic format(SourceFile source, ErrorKind kind, Object... args) {
+ String path = firstNonNull(source.path(), "<>");
+ String message = kind.format(args);
+ String diagnostic = path + ": error: " + message.trim() + System.lineSeparator();
+ return create(kind, diagnostic, ImmutableList.copyOf(args));
+ }
+
+ /**
+ * Formats a diagnostic.
+ *
+ * @param position the diagnostic position
+ * @param kind the error kind
+ * @param args format args
+ */
+ public static TurbineDiagnostic format(
+ SourceFile source, int position, ErrorKind kind, Object... args) {
+ String path = firstNonNull(source.path(), "<>");
+ LineMap lineMap = LineMap.create(source.source());
+ int lineNumber = lineMap.lineNumber(position);
+ int column = lineMap.column(position);
+ String message = kind.format(args);
+
+ StringBuilder sb = new StringBuilder(path).append(":");
+ sb.append(lineNumber).append(": error: ");
+ sb.append(message.trim()).append(System.lineSeparator());
+ sb.append(CharMatcher.breakingWhitespace().trimTrailingFrom(lineMap.line(position)))
+ .append(System.lineSeparator());
+ sb.append(Strings.repeat(" ", column)).append('^');
+ String diagnostic = sb.toString();
+ return create(kind, diagnostic, ImmutableList.copyOf(args));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(diagnostic, kind);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof TurbineDiagnostic)) {
+ return false;
+ }
+ TurbineDiagnostic that = (TurbineDiagnostic) obj;
+ return diagnostic.equals(that.diagnostic) && kind.equals(that.kind);
+ }
+}
diff --git a/java/com/google/turbine/diag/TurbineError.java b/java/com/google/turbine/diag/TurbineError.java
index f9ddcd5..e13eb44 100644
--- a/java/com/google/turbine/diag/TurbineError.java
+++ b/java/com/google/turbine/diag/TurbineError.java
@@ -16,14 +16,9 @@
package com.google.turbine.diag;
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.getOnlyElement;
+import static java.util.stream.Collectors.joining;
-import com.google.common.base.CharMatcher;
-import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
-import com.google.turbine.binder.sym.ClassSymbol;
/** A compilation error. */
public class TurbineError extends Error {
@@ -71,10 +66,7 @@ public class TurbineError extends Error {
* @param args format args
*/
public static TurbineError format(SourceFile source, ErrorKind kind, Object... args) {
- String path = firstNonNull(source.path(), "<>");
- String message = kind.format(args);
- String diagnostic = path + ": error: " + message.trim() + System.lineSeparator();
- return new TurbineError(kind, diagnostic, ImmutableList.copyOf(args));
+ return new TurbineError(ImmutableList.of(TurbineDiagnostic.format(source, kind, args)));
}
/**
@@ -86,50 +78,18 @@ public class TurbineError extends Error {
*/
public static TurbineError format(
SourceFile source, int position, ErrorKind kind, Object... args) {
- String path = firstNonNull(source.path(), "<>");
- LineMap lineMap = LineMap.create(source.source());
- int lineNumber = lineMap.lineNumber(position);
- int column = lineMap.column(position);
- String message = kind.format(args);
-
- StringBuilder sb = new StringBuilder(path).append(":");
- sb.append(lineNumber).append(": error: ");
- sb.append(message.trim()).append(System.lineSeparator());
- sb.append(CharMatcher.breakingWhitespace().trimTrailingFrom(lineMap.line(position)))
- .append(System.lineSeparator());
- sb.append(Strings.repeat(" ", column)).append('^');
- String diagnostic = sb.toString();
- return new TurbineError(kind, diagnostic, ImmutableList.copyOf(args));
+ return new TurbineError(
+ ImmutableList.of(TurbineDiagnostic.format(source, position, kind, args)));
}
- private final ErrorKind kind;
- private final ImmutableList<Object> args;
-
- private TurbineError(ErrorKind kind, String diagnostic, ImmutableList<Object> args) {
- super(diagnostic);
- switch (kind) {
- case SYMBOL_NOT_FOUND:
- {
- checkArgument(
- args.size() == 1 && getOnlyElement(args) instanceof ClassSymbol,
- "diagnostic (%s) has invalid argument args %s",
- diagnostic,
- args);
- break;
- }
- default: // fall out
- }
- this.kind = kind;
- this.args = args;
- }
+ private final ImmutableList<TurbineDiagnostic> diagnostics;
- /** The diagnostic kind. */
- public ErrorKind kind() {
- return kind;
+ public TurbineError(ImmutableList<TurbineDiagnostic> diagnostics) {
+ super(diagnostics.stream().map(d -> d.diagnostic()).collect(joining("\n")));
+ this.diagnostics = diagnostics;
}
- /** The diagnostic arguments. */
- public ImmutableList<Object> args() {
- return args;
+ public ImmutableList<TurbineDiagnostic> diagnostics() {
+ return diagnostics;
}
}
diff --git a/java/com/google/turbine/diag/TurbineLog.java b/java/com/google/turbine/diag/TurbineLog.java
new file mode 100644
index 0000000..fd8fc38
--- /dev/null
+++ b/java/com/google/turbine/diag/TurbineLog.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.turbine.diag;
+
+import com.google.common.collect.ImmutableList;
+import com.google.turbine.diag.TurbineError.ErrorKind;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/** A log that collects diagnostics. */
+public class TurbineLog {
+
+ private final Set<TurbineDiagnostic> errors = new LinkedHashSet<>();
+
+ public TurbineLogWithSource withSource(SourceFile source) {
+ return new TurbineLogWithSource(source);
+ }
+
+ public void maybeThrow() {
+ if (!errors.isEmpty()) {
+ throw new TurbineError(ImmutableList.copyOf(errors));
+ }
+ }
+
+ /** A log for a specific source file. */
+ public class TurbineLogWithSource {
+
+ private final SourceFile source;
+
+ private TurbineLogWithSource(SourceFile source) {
+ this.source = source;
+ }
+
+ public void error(ErrorKind kind, Object... args) {
+ errors.add(TurbineDiagnostic.format(source, kind, args));
+ }
+
+ public void error(int position, ErrorKind kind, Object... args) {
+ errors.add(TurbineDiagnostic.format(source, position, kind, args));
+ }
+ }
+}
diff --git a/java/com/google/turbine/lower/LowerSignature.java b/java/com/google/turbine/lower/LowerSignature.java
index 624cbf8..fe9b912 100644
--- a/java/com/google/turbine/lower/LowerSignature.java
+++ b/java/com/google/turbine/lower/LowerSignature.java
@@ -214,11 +214,11 @@ public class LowerSignature {
ClassTySig xtnd = null;
if (info.superClassType() != null) {
- xtnd = classTySig(info.superClassType());
+ xtnd = classTySig((ClassTy) info.superClassType());
}
ImmutableList.Builder<ClassTySig> impl = ImmutableList.builder();
- for (ClassTy i : info.interfaceTypes()) {
- impl.add(classTySig(i));
+ for (Type i : info.interfaceTypes()) {
+ impl.add(classTySig((ClassTy) i));
}
ClassSig sig = new ClassSig(typarams, xtnd, impl.build());
return SigWriter.classSig(sig);
@@ -238,7 +238,7 @@ public class LowerSignature {
if (ci.superClassType() != null && needsSig(ci.superClassType())) {
return true;
}
- for (ClassTy i : ci.interfaceTypes()) {
+ for (Type i : ci.interfaceTypes()) {
if (needsSig(i)) {
return true;
}
diff --git a/java/com/google/turbine/type/AnnoInfo.java b/java/com/google/turbine/type/AnnoInfo.java
index a3c0294..9c907aa 100644
--- a/java/com/google/turbine/type/AnnoInfo.java
+++ b/java/com/google/turbine/type/AnnoInfo.java
@@ -16,8 +16,6 @@
package com.google.turbine.type;
-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;
@@ -38,7 +36,7 @@ public class AnnoInfo {
public AnnoInfo(
SourceFile source, ClassSymbol sym, Anno tree, ImmutableMap<String, Const> values) {
this.source = source;
- this.sym = requireNonNull(sym);
+ this.sym = sym;
this.tree = tree;
this.values = values;
}
diff --git a/java/com/google/turbine/type/Type.java b/java/com/google/turbine/type/Type.java
index e25eca5..3bf47d6 100644
--- a/java/com/google/turbine/type/Type.java
+++ b/java/com/google/turbine/type/Type.java
@@ -46,7 +46,9 @@ public interface Type {
/** A wildcard type. */
WILD_TY,
/** An intersection type. */
- INTERSECTION_TY
+ INTERSECTION_TY,
+
+ ERROR_TY
}
/** The type kind. */
@@ -299,4 +301,17 @@ public interface Type {
return TyKind.INTERSECTION_TY;
}
}
+
+ /** An error type. */
+ @AutoValue
+ abstract class ErrorTy implements Type {
+ public static ErrorTy create() {
+ return new AutoValue_Type_ErrorTy();
+ }
+
+ @Override
+ public TyKind tyKind() {
+ return TyKind.ERROR_TY;
+ }
+ }
}
diff --git a/java/com/google/turbine/types/Canonicalize.java b/java/com/google/turbine/types/Canonicalize.java
index 0016011..e133ab0 100644
--- a/java/com/google/turbine/types/Canonicalize.java
+++ b/java/com/google/turbine/types/Canonicalize.java
@@ -227,7 +227,7 @@ public class Canonicalize {
break;
}
TypeBoundClass info = getInfo(curr.sym());
- curr = canon(info.owner(), info.superClassType());
+ curr = canon(info.owner(), (ClassTy) info.superClassType());
}
simples.add(ty);
return ClassTy.create(simples.build());
diff --git a/javatests/com/google/turbine/binder/BinderErrorTest.java b/javatests/com/google/turbine/binder/BinderErrorTest.java
index 8d2dfce..f6fb317 100644
--- a/javatests/com/google/turbine/binder/BinderErrorTest.java
+++ b/javatests/com/google/turbine/binder/BinderErrorTest.java
@@ -59,11 +59,10 @@ public class BinderErrorTest {
"class B extends A.NoSuch {",
"}",
},
- // TODO(cushon): we'd prefer the caret at NoSuch instead of A
{
"<>:4: error: symbol not found a.A$NoSuch", //
"class B extends A.NoSuch {",
- " ^",
+ " ^",
}
},
{
@@ -149,7 +148,10 @@ public class BinderErrorTest {
"<>:4: error: cycle in class hierarchy: p.OuterExtendsInner$Inner"
+ " -> p.OuterExtendsInner$Inner",
" public static class Inner extends Foo {}",
- " ^"
+ " ^",
+ "<>:4: error: could not resolve Foo",
+ " public static class Inner extends Foo {}",
+ " ^",
},
},
{
@@ -162,7 +164,10 @@ public class BinderErrorTest {
{
"<>:2: error: symbol not found java.lang.NoSuch", //
"import java.lang.NoSuch;",
- " ^"
+ " ^",
+ "<>:3: error: could not resolve NoSuch",
+ "public class Test extends NoSuch {",
+ " ^"
},
},
{
@@ -175,7 +180,10 @@ 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 {",
+ " ^",
},
},
{
diff --git a/javatests/com/google/turbine/binder/ClassPathBinderTest.java b/javatests/com/google/turbine/binder/ClassPathBinderTest.java
index 95ef9c8..0b063d4 100644
--- a/javatests/com/google/turbine/binder/ClassPathBinderTest.java
+++ b/javatests/com/google/turbine/binder/ClassPathBinderTest.java
@@ -97,14 +97,15 @@ public class ClassPathBinderTest {
TypeBoundClass c = env.get(new ClassSymbol("java/lang/annotation/Retention"));
assertThat(c.interfaceTypes()).hasSize(1);
- assertThat(getOnlyElement(c.interfaceTypes()).sym())
+ assertThat(((ClassTy) getOnlyElement(c.interfaceTypes())).sym())
.isEqualTo(new ClassSymbol("java/lang/annotation/Annotation"));
c = env.get(new ClassSymbol("java/util/ArrayList"));
ClassTy listInterface =
- c.interfaceTypes().stream()
- .filter(i -> i.sym().equals(new ClassSymbol("java/util/List")))
- .collect(onlyElement());
+ (ClassTy)
+ c.interfaceTypes().stream()
+ .filter(i -> ((ClassTy) i).sym().equals(new ClassSymbol("java/util/List")))
+ .collect(onlyElement());
assertThat(getLast(listInterface.classes()).targs()).hasSize(1);
}
diff --git a/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java b/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java
index ea0feb2..4e3ec9a 100644
--- a/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java
+++ b/javatests/com/google/turbine/binder/bytecode/BytecodeBoundClassTest.java
@@ -60,16 +60,21 @@ public class BytecodeBoundClassTest {
assertThat(noInterfaces.interfaceTypes()).isEmpty();
assertThat(rawInterfaces.interfaceTypes()).hasSize(1);
- assertThat(rawInterfaces.interfaceTypes().get(0).sym())
+ assertThat(((ClassTy) rawInterfaces.interfaceTypes().get(0)).sym())
.isEqualTo(new ClassSymbol("java/io/Serializable"));
- assertThat(getLast(rawInterfaces.interfaceTypes().get(0).classes()).targs()).isEmpty();
+ assertThat(getLast(((ClassTy) rawInterfaces.interfaceTypes().get(0)).classes()).targs())
+ .isEmpty();
assertThat(genericInterfaces.interfaceTypes()).hasSize(1);
- assertThat(genericInterfaces.interfaceTypes().get(0).sym())
+ assertThat(((ClassTy) genericInterfaces.interfaceTypes().get(0)).sym())
.isEqualTo(new ClassSymbol("java/util/List"));
- assertThat(getLast(genericInterfaces.interfaceTypes().get(0).classes()).targs()).hasSize(1);
+ assertThat(getLast(((ClassTy) genericInterfaces.interfaceTypes().get(0)).classes()).targs())
+ .hasSize(1);
assertThat(
- ((ClassTy) getLast(genericInterfaces.interfaceTypes().get(0).classes()).targs().get(0))
+ ((ClassTy)
+ getLast(((ClassTy) genericInterfaces.interfaceTypes().get(0)).classes())
+ .targs()
+ .get(0))
.sym())
.isEqualTo(new ClassSymbol("java/lang/String"));
}
diff --git a/javatests/com/google/turbine/lower/LowerTest.java b/javatests/com/google/turbine/lower/LowerTest.java
index ec7d9f9..ef070f9 100644
--- a/javatests/com/google/turbine/lower/LowerTest.java
+++ b/javatests/com/google/turbine/lower/LowerTest.java
@@ -80,7 +80,7 @@ public class LowerTest {
@Test
public void hello() throws Exception {
- ImmutableList<Type.ClassTy> interfaceTypes =
+ ImmutableList<Type> interfaceTypes =
ImmutableList.of(
ClassTy.create(
ImmutableList.of(