protected RichDiagnosticFormatter(Context context) { super((AbstractDiagnosticFormatter) Log.instance(context).getDiagnosticFormatter()); setRichPrinter(new RichPrinter()); this.syms = Symtab.instance(context); this.diags = JCDiagnostic.Factory.instance(context); this.types = Types.instance(context); this.messages = JavacMessages.instance(context); whereClauses = new LinkedHashMap<WhereClauseKind, Map<Type, JCDiagnostic>>(); configuration = new RichConfiguration(Options.instance(context), formatter); for (WhereClauseKind kind : WhereClauseKind.values()) whereClauses.put(kind, new LinkedHashMap<Type, JCDiagnostic>()); }
@Override public Void visitCapturedType(CapturedType t, Void ignored) { if (indexOf(t, WhereClauseKind.CAPTURED) == -1) { String suffix = t.lower == syms.botType ? ".1" : ""; JCDiagnostic d = diags.fragment("where.captured" + suffix, t, t.bound, t.lower, t.wildcard); whereClauses.get(WhereClauseKind.CAPTURED).put(t, d); visit(t.wildcard); visit(t.lower); visit(t.bound); } return null; }
@Override public Void visitTypeVar(TypeVar t, Void ignored) { if (indexOf(t, WhereClauseKind.TYPEVAR) == -1) { // access the bound type and skip error types Type bound = t.bound; while ((bound instanceof ErrorType)) bound = ((ErrorType) bound).getOriginalType(); // retrieve the bound list - if the type variable // has not been attributed the bound is not set List<Type> bounds = (bound != null && bound.tsym != null) ? types.getBounds(t) : List.<Type>nil(); nameSimplifier.addUsage(t.tsym); boolean boundErroneous = bounds.head == null || bounds.head.tag == NONE || bounds.head.tag == ERROR; if ((t.tsym.flags() & SYNTHETIC) == 0) { // this is a true typevar JCDiagnostic d = diags.fragment( "where.typevar" + (boundErroneous ? ".1" : ""), t, bounds, Kinds.kindName(t.tsym.location()), t.tsym.location()); whereClauses.get(WhereClauseKind.TYPEVAR).put(t, d); symbolPreprocessor.visit(t.tsym.location(), null); visit(bounds); } else { Assert.check(!boundErroneous); // this is a fresh (synthetic) tvar JCDiagnostic d = diags.fragment("where.fresh.typevar", t, bounds); whereClauses.get(WhereClauseKind.TYPEVAR).put(t, d); visit(bounds); } } return null; }
/** * Build a list of multiline diagnostics containing detailed info about type-variables, captured * types, and intersection types * * @return where clause list */ protected List<JCDiagnostic> getWhereClauses() { List<JCDiagnostic> clauses = List.nil(); for (WhereClauseKind kind : WhereClauseKind.values()) { List<JCDiagnostic> lines = List.nil(); for (Map.Entry<Type, JCDiagnostic> entry : whereClauses.get(kind).entrySet()) { lines = lines.prepend(entry.getValue()); } if (!lines.isEmpty()) { String key = kind.key(); if (lines.size() > 1) key += ".1"; JCDiagnostic d = diags.fragment(key, whereClauses.get(kind).keySet()); d = new JCDiagnostic.MultilineDiagnostic(d, lines.reverse()); clauses = clauses.prepend(d); } } return clauses.reverse(); }
@Override public Void visitClassType(ClassType t, Void ignored) { if (t.isCompound()) { if (indexOf(t, WhereClauseKind.INTERSECTION) == -1) { Type supertype = types.supertype(t); List<Type> interfaces = types.interfaces(t); JCDiagnostic d = diags.fragment("where.intersection", t, interfaces.prepend(supertype)); whereClauses.get(WhereClauseKind.INTERSECTION).put(t, d); visit(supertype); visit(interfaces); } } nameSimplifier.addUsage(t.tsym); visit(t.getTypeArguments()); if (t.getEnclosingType() != Type.noType) visit(t.getEnclosingType()); return null; }