src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java

Thu, 10 Jun 2010 16:08:01 -0700

author
jjg
date
Thu, 10 Jun 2010 16:08:01 -0700
changeset 581
f2fdd52e4e87
parent 554
9d9f26857129
child 1085
ed338593b0b6
permissions
-rw-r--r--

6944312: Potential rebranding issues in openjdk/langtools repository sources
Reviewed-by: darcy

mcimadamore@288 1 /*
ohair@554 2 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
mcimadamore@288 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@288 4 *
mcimadamore@288 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@288 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
mcimadamore@288 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
mcimadamore@288 10 *
mcimadamore@288 11 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@288 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@288 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@288 14 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@288 15 * accompanied this code).
mcimadamore@288 16 *
mcimadamore@288 17 * You should have received a copy of the GNU General Public License version
mcimadamore@288 18 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@288 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@288 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
mcimadamore@288 24 */
mcimadamore@288 25 package com.sun.tools.javac.util;
mcimadamore@288 26
mcimadamore@288 27 import java.util.EnumSet;
mcimadamore@288 28 import java.util.HashMap;
mcimadamore@288 29 import java.util.LinkedHashMap;
mcimadamore@288 30 import java.util.Locale;
mcimadamore@288 31 import java.util.Map;
mcimadamore@288 32
mcimadamore@288 33 import com.sun.tools.javac.code.Kinds;
mcimadamore@288 34 import com.sun.tools.javac.code.Printer;
mcimadamore@288 35 import com.sun.tools.javac.code.Symbol;
mcimadamore@288 36 import com.sun.tools.javac.code.Symbol.*;
mcimadamore@288 37 import com.sun.tools.javac.code.Symtab;
mcimadamore@288 38 import com.sun.tools.javac.code.Type;
mcimadamore@288 39 import com.sun.tools.javac.code.Type.*;
mcimadamore@288 40 import com.sun.tools.javac.code.Types;
mcimadamore@288 41
mcimadamore@288 42 import static com.sun.tools.javac.code.TypeTags.*;
mcimadamore@288 43 import static com.sun.tools.javac.code.Flags.*;
mcimadamore@288 44 import static com.sun.tools.javac.util.LayoutCharacters.*;
mcimadamore@288 45 import static com.sun.tools.javac.util.RichDiagnosticFormatter.RichConfiguration.*;
mcimadamore@288 46
mcimadamore@288 47 /**
mcimadamore@288 48 * A rich diagnostic formatter is a formatter that provides better integration
mcimadamore@288 49 * with javac's type system. A diagostic is first preprocessed in order to keep
mcimadamore@288 50 * track of each types/symbols in it; after these informations are collected,
mcimadamore@288 51 * the diagnostic is rendered using a standard formatter, whose type/symbol printer
mcimadamore@288 52 * has been replaced by a more refined version provided by this rich formatter.
mcimadamore@288 53 * The rich formatter currently enables three different features: (i) simple class
mcimadamore@288 54 * names - that is class names are displayed used a non qualified name (thus
mcimadamore@288 55 * omitting package info) whenever possible - (ii) where clause list - a list of
mcimadamore@288 56 * additional subdiagnostics that provide specific info about type-variables,
mcimadamore@288 57 * captured types, intersection types that occur in the diagnostic that is to be
mcimadamore@288 58 * formatted and (iii) type-variable disambiguation - when the diagnostic refers
mcimadamore@288 59 * to two different type-variables with the same name, their representation is
mcimadamore@288 60 * disambiguated by appending an index to the type variable name.
jjg@333 61 *
jjg@581 62 * <p><b>This is NOT part of any supported API.
jjg@333 63 * If you write code that depends on this, you do so at your own risk.
jjg@333 64 * This code and its internal interfaces are subject to change or
jjg@333 65 * deletion without notice.</b>
mcimadamore@288 66 */
mcimadamore@288 67 public class RichDiagnosticFormatter extends
mcimadamore@288 68 ForwardingDiagnosticFormatter<JCDiagnostic, AbstractDiagnosticFormatter> {
mcimadamore@288 69
mcimadamore@288 70 final Symtab syms;
mcimadamore@288 71 final Types types;
mcimadamore@288 72 final JCDiagnostic.Factory diags;
mcimadamore@288 73 final JavacMessages messages;
mcimadamore@288 74
mcimadamore@288 75 /* name simplifier used by this formatter */
mcimadamore@304 76 protected ClassNameSimplifier nameSimplifier;
mcimadamore@304 77
mcimadamore@304 78 /* type/symbol printer used by this formatter */
mcimadamore@304 79 private RichPrinter printer;
mcimadamore@288 80
mcimadamore@288 81 /* map for keeping track of a where clause associated to a given type */
mcimadamore@288 82 Map<WhereClauseKind, Map<Type, JCDiagnostic>> whereClauses;
mcimadamore@288 83
mcimadamore@288 84 /** Get the DiagnosticFormatter instance for this context. */
mcimadamore@288 85 public static RichDiagnosticFormatter instance(Context context) {
mcimadamore@288 86 RichDiagnosticFormatter instance = context.get(RichDiagnosticFormatter.class);
mcimadamore@288 87 if (instance == null)
mcimadamore@288 88 instance = new RichDiagnosticFormatter(context);
mcimadamore@288 89 return instance;
mcimadamore@288 90 }
mcimadamore@288 91
mcimadamore@288 92 protected RichDiagnosticFormatter(Context context) {
mcimadamore@288 93 super((AbstractDiagnosticFormatter)Log.instance(context).getDiagnosticFormatter());
mcimadamore@304 94 setRichPrinter(new RichPrinter());
mcimadamore@288 95 this.syms = Symtab.instance(context);
mcimadamore@288 96 this.diags = JCDiagnostic.Factory.instance(context);
mcimadamore@288 97 this.types = Types.instance(context);
mcimadamore@288 98 this.messages = JavacMessages.instance(context);
mcimadamore@288 99 whereClauses = new LinkedHashMap<WhereClauseKind, Map<Type, JCDiagnostic>>();
mcimadamore@288 100 configuration = new RichConfiguration(Options.instance(context), formatter);
mcimadamore@288 101 for (WhereClauseKind kind : WhereClauseKind.values())
mcimadamore@288 102 whereClauses.put(kind, new LinkedHashMap<Type, JCDiagnostic>());
mcimadamore@288 103 }
mcimadamore@288 104
mcimadamore@288 105 @Override
mcimadamore@288 106 public String format(JCDiagnostic diag, Locale l) {
mcimadamore@288 107 StringBuilder sb = new StringBuilder();
mcimadamore@288 108 nameSimplifier = new ClassNameSimplifier();
mcimadamore@288 109 for (WhereClauseKind kind : WhereClauseKind.values())
mcimadamore@288 110 whereClauses.get(kind).clear();
mcimadamore@288 111 preprocessDiagnostic(diag);
mcimadamore@288 112 sb.append(formatter.format(diag, l));
mcimadamore@288 113 if (getConfiguration().isEnabled(RichFormatterFeature.WHERE_CLAUSES)) {
mcimadamore@288 114 List<JCDiagnostic> clauses = getWhereClauses();
mcimadamore@288 115 String indent = formatter.isRaw() ? "" :
mcimadamore@288 116 formatter.indentString(DetailsInc);
mcimadamore@288 117 for (JCDiagnostic d : clauses) {
mcimadamore@288 118 String whereClause = formatter.format(d, l);
mcimadamore@288 119 if (whereClause.length() > 0) {
mcimadamore@288 120 sb.append('\n' + indent + whereClause);
mcimadamore@288 121 }
mcimadamore@288 122 }
mcimadamore@288 123 }
mcimadamore@288 124 return sb.toString();
mcimadamore@288 125 }
mcimadamore@288 126
mcimadamore@288 127 /**
mcimadamore@304 128 * Sets the type/symbol printer used by this formatter.
mcimadamore@304 129 * @param printer the rich printer to be set
mcimadamore@304 130 */
mcimadamore@304 131 protected void setRichPrinter(RichPrinter printer) {
mcimadamore@304 132 this.printer = printer;
mcimadamore@304 133 formatter.setPrinter(printer);
mcimadamore@304 134 }
mcimadamore@304 135
mcimadamore@304 136 /**
mcimadamore@304 137 * Gets the type/symbol printer used by this formatter.
mcimadamore@304 138 * @return type/symbol rich printer
mcimadamore@304 139 */
mcimadamore@304 140 protected RichPrinter getRichPrinter() {
mcimadamore@304 141 return printer;
mcimadamore@304 142 }
mcimadamore@304 143
mcimadamore@304 144 /**
mcimadamore@288 145 * Preprocess a given diagnostic by looking both into its arguments and into
mcimadamore@288 146 * its subdiagnostics (if any). This preprocessing is responsible for
mcimadamore@288 147 * generating info corresponding to features like where clauses, name
mcimadamore@288 148 * simplification, etc.
mcimadamore@288 149 *
mcimadamore@288 150 * @param diag the diagnostic to be preprocessed
mcimadamore@288 151 */
mcimadamore@288 152 protected void preprocessDiagnostic(JCDiagnostic diag) {
mcimadamore@288 153 for (Object o : diag.getArgs()) {
mcimadamore@288 154 if (o != null) {
mcimadamore@288 155 preprocessArgument(o);
mcimadamore@288 156 }
mcimadamore@288 157 }
mcimadamore@288 158 if (diag.isMultiline()) {
mcimadamore@288 159 for (JCDiagnostic d : diag.getSubdiagnostics())
mcimadamore@288 160 preprocessDiagnostic(d);
mcimadamore@288 161 }
mcimadamore@288 162 }
mcimadamore@288 163
mcimadamore@288 164 /**
mcimadamore@288 165 * Preprocess a diagnostic argument. A type/symbol argument is
mcimadamore@288 166 * preprocessed by specialized type/symbol preprocessors.
mcimadamore@288 167 *
mcimadamore@288 168 * @param arg the argument to be translated
mcimadamore@288 169 */
mcimadamore@288 170 protected void preprocessArgument(Object arg) {
mcimadamore@288 171 if (arg instanceof Type) {
mcimadamore@288 172 preprocessType((Type)arg);
mcimadamore@288 173 }
mcimadamore@288 174 else if (arg instanceof Symbol) {
mcimadamore@288 175 preprocessSymbol((Symbol)arg);
mcimadamore@288 176 }
mcimadamore@288 177 else if (arg instanceof JCDiagnostic) {
mcimadamore@288 178 preprocessDiagnostic((JCDiagnostic)arg);
mcimadamore@288 179 }
mcimadamore@288 180 else if (arg instanceof Iterable<?>) {
mcimadamore@288 181 for (Object o : (Iterable<?>)arg) {
mcimadamore@288 182 preprocessArgument(o);
mcimadamore@288 183 }
mcimadamore@288 184 }
mcimadamore@288 185 }
mcimadamore@288 186
mcimadamore@288 187 /**
mcimadamore@288 188 * Build a list of multiline diagnostics containing detailed info about
mcimadamore@288 189 * type-variables, captured types, and intersection types
mcimadamore@288 190 *
mcimadamore@288 191 * @return where clause list
mcimadamore@288 192 */
mcimadamore@288 193 protected List<JCDiagnostic> getWhereClauses() {
mcimadamore@288 194 List<JCDiagnostic> clauses = List.nil();
mcimadamore@288 195 for (WhereClauseKind kind : WhereClauseKind.values()) {
mcimadamore@288 196 List<JCDiagnostic> lines = List.nil();
mcimadamore@288 197 for (Map.Entry<Type, JCDiagnostic> entry : whereClauses.get(kind).entrySet()) {
mcimadamore@288 198 lines = lines.prepend(entry.getValue());
mcimadamore@288 199 }
mcimadamore@288 200 if (!lines.isEmpty()) {
mcimadamore@288 201 String key = kind.key();
mcimadamore@288 202 if (lines.size() > 1)
mcimadamore@288 203 key += ".1";
mcimadamore@288 204 JCDiagnostic d = diags.fragment(key, whereClauses.get(kind).keySet());
mcimadamore@288 205 d = new JCDiagnostic.MultilineDiagnostic(d, lines.reverse());
mcimadamore@288 206 clauses = clauses.prepend(d);
mcimadamore@288 207 }
mcimadamore@288 208 }
mcimadamore@288 209 return clauses.reverse();
mcimadamore@288 210 }
mcimadamore@342 211
mcimadamore@342 212 private int indexOf(Type type, WhereClauseKind kind) {
mcimadamore@342 213 int index = 1;
mcimadamore@342 214 for (Type t : whereClauses.get(kind).keySet()) {
mcimadamore@342 215 if (t.tsym == type.tsym) {
mcimadamore@342 216 return index;
mcimadamore@342 217 }
mcimadamore@342 218 if (kind != WhereClauseKind.TYPEVAR ||
mcimadamore@342 219 t.toString().equals(type.toString())) {
mcimadamore@342 220 index++;
mcimadamore@342 221 }
mcimadamore@342 222 }
mcimadamore@342 223 return -1;
mcimadamore@342 224 }
mcimadamore@342 225
mcimadamore@342 226 private boolean unique(TypeVar typevar) {
mcimadamore@342 227 int found = 0;
mcimadamore@342 228 for (Type t : whereClauses.get(WhereClauseKind.TYPEVAR).keySet()) {
mcimadamore@342 229 if (t.toString().equals(typevar.toString())) {
mcimadamore@342 230 found++;
mcimadamore@342 231 }
mcimadamore@342 232 }
mcimadamore@342 233 if (found < 1)
mcimadamore@342 234 throw new AssertionError("Missing type variable in where clause " + typevar);
mcimadamore@342 235 return found == 1;
mcimadamore@342 236 }
mcimadamore@288 237 //where
mcimadamore@288 238 /**
mcimadamore@288 239 * This enum defines all posssible kinds of where clauses that can be
mcimadamore@288 240 * attached by a rich diagnostic formatter to a given diagnostic
mcimadamore@288 241 */
mcimadamore@288 242 enum WhereClauseKind {
mcimadamore@288 243
mcimadamore@288 244 /** where clause regarding a type variable */
mcimadamore@288 245 TYPEVAR("where.description.typevar"),
mcimadamore@288 246 /** where clause regarding a captured type */
mcimadamore@288 247 CAPTURED("where.description.captured"),
mcimadamore@288 248 /** where clause regarding an intersection type */
mcimadamore@288 249 INTERSECTION("where.description.intersection");
mcimadamore@288 250
mcimadamore@288 251 /** resource key for this where clause kind */
mcimadamore@288 252 private String key;
mcimadamore@288 253
mcimadamore@288 254 WhereClauseKind(String key) {
mcimadamore@288 255 this.key = key;
mcimadamore@288 256 }
mcimadamore@288 257
mcimadamore@288 258 String key() {
mcimadamore@288 259 return key;
mcimadamore@288 260 }
mcimadamore@288 261 }
mcimadamore@288 262
mcimadamore@288 263 // <editor-fold defaultstate="collapsed" desc="name simplifier">
mcimadamore@288 264 /**
mcimadamore@288 265 * A name simplifier keeps track of class names usages in order to determine
mcimadamore@288 266 * whether a class name can be compacted or not. Short names are not used
mcimadamore@288 267 * if a conflict is detected, e.g. when two classes with the same simple
mcimadamore@288 268 * name belong to different packages - in this case the formatter reverts
mcimadamore@288 269 * to fullnames as compact names might lead to a confusing diagnostic.
mcimadamore@288 270 */
mcimadamore@304 271 protected class ClassNameSimplifier {
mcimadamore@288 272
mcimadamore@288 273 /* table for keeping track of all short name usages */
mcimadamore@288 274 Map<Name, List<Symbol>> nameClashes = new HashMap<Name, List<Symbol>>();
mcimadamore@288 275
mcimadamore@288 276 /**
mcimadamore@288 277 * Add a name usage to the simplifier's internal cache
mcimadamore@288 278 */
mcimadamore@288 279 protected void addUsage(Symbol sym) {
mcimadamore@288 280 Name n = sym.getSimpleName();
mcimadamore@288 281 List<Symbol> conflicts = nameClashes.get(n);
mcimadamore@288 282 if (conflicts == null) {
mcimadamore@288 283 conflicts = List.nil();
mcimadamore@288 284 }
mcimadamore@288 285 if (!conflicts.contains(sym))
mcimadamore@288 286 nameClashes.put(n, conflicts.append(sym));
mcimadamore@288 287 }
mcimadamore@288 288
mcimadamore@288 289 public String simplify(Symbol s) {
mcimadamore@288 290 String name = s.getQualifiedName().toString();
mcimadamore@288 291 if (!s.type.isCompound()) {
mcimadamore@288 292 List<Symbol> conflicts = nameClashes.get(s.getSimpleName());
mcimadamore@288 293 if (conflicts == null ||
mcimadamore@288 294 (conflicts.size() == 1 &&
mcimadamore@288 295 conflicts.contains(s))) {
mcimadamore@288 296 List<Name> l = List.nil();
mcimadamore@288 297 Symbol s2 = s;
mcimadamore@288 298 while (s2.type.getEnclosingType().tag == CLASS
mcimadamore@288 299 && s2.owner.kind == Kinds.TYP) {
mcimadamore@288 300 l = l.prepend(s2.getSimpleName());
mcimadamore@288 301 s2 = s2.owner;
mcimadamore@288 302 }
mcimadamore@288 303 l = l.prepend(s2.getSimpleName());
mcimadamore@288 304 StringBuilder buf = new StringBuilder();
mcimadamore@288 305 String sep = "";
mcimadamore@288 306 for (Name n2 : l) {
mcimadamore@288 307 buf.append(sep);
mcimadamore@288 308 buf.append(n2);
mcimadamore@288 309 sep = ".";
mcimadamore@288 310 }
mcimadamore@288 311 name = buf.toString();
mcimadamore@288 312 }
mcimadamore@288 313 }
mcimadamore@288 314 return name;
mcimadamore@288 315 }
mcimadamore@288 316 };
mcimadamore@288 317 // </editor-fold>
mcimadamore@288 318
mcimadamore@288 319 // <editor-fold defaultstate="collapsed" desc="rich printer">
mcimadamore@288 320 /**
mcimadamore@288 321 * Enhanced type/symbol printer that provides support for features like simple names
mcimadamore@288 322 * and type variable disambiguation. This enriched printer exploits the info
mcimadamore@288 323 * discovered during type/symbol preprocessing. This printer is set on the delegate
mcimadamore@288 324 * formatter so that rich type/symbol info can be properly rendered.
mcimadamore@288 325 */
mcimadamore@304 326 protected class RichPrinter extends Printer {
mcimadamore@288 327
mcimadamore@288 328 @Override
mcimadamore@288 329 public String localize(Locale locale, String key, Object... args) {
mcimadamore@288 330 return formatter.localize(locale, key, args);
mcimadamore@288 331 }
mcimadamore@288 332
mcimadamore@288 333 @Override
mcimadamore@288 334 public String capturedVarId(CapturedType t, Locale locale) {
mcimadamore@288 335 return indexOf(t, WhereClauseKind.CAPTURED) + "";
mcimadamore@288 336 }
mcimadamore@288 337
mcimadamore@288 338 @Override
mcimadamore@288 339 public String visitType(Type t, Locale locale) {
mcimadamore@288 340 String s = super.visitType(t, locale);
mcimadamore@288 341 if (t == syms.botType)
mcimadamore@288 342 s = localize(locale, "compiler.misc.type.null");
mcimadamore@288 343 return s;
mcimadamore@288 344 }
mcimadamore@288 345
mcimadamore@288 346 @Override
mcimadamore@288 347 public String visitCapturedType(CapturedType t, Locale locale) {
mcimadamore@288 348 if (getConfiguration().isEnabled(RichFormatterFeature.WHERE_CLAUSES)) {
mcimadamore@288 349 return localize(locale,
mcimadamore@288 350 "compiler.misc.captured.type",
mcimadamore@288 351 indexOf(t, WhereClauseKind.CAPTURED));
mcimadamore@288 352 }
mcimadamore@288 353 else
mcimadamore@288 354 return super.visitCapturedType(t, locale);
mcimadamore@288 355 }
mcimadamore@288 356
mcimadamore@288 357 @Override
mcimadamore@288 358 public String visitClassType(ClassType t, Locale locale) {
mcimadamore@288 359 if (t.isCompound() &&
mcimadamore@288 360 getConfiguration().isEnabled(RichFormatterFeature.WHERE_CLAUSES)) {
mcimadamore@288 361 return localize(locale,
mcimadamore@288 362 "compiler.misc.intersection.type",
mcimadamore@288 363 indexOf(t, WhereClauseKind.INTERSECTION));
mcimadamore@288 364 }
mcimadamore@288 365 else
mcimadamore@288 366 return super.visitClassType(t, locale);
mcimadamore@288 367 }
mcimadamore@288 368
mcimadamore@288 369 @Override
mcimadamore@288 370 protected String className(ClassType t, boolean longform, Locale locale) {
mcimadamore@288 371 Symbol sym = t.tsym;
mcimadamore@288 372 if (sym.name.length() == 0 ||
mcimadamore@288 373 !getConfiguration().isEnabled(RichFormatterFeature.SIMPLE_NAMES)) {
mcimadamore@288 374 return super.className(t, longform, locale);
mcimadamore@288 375 }
mcimadamore@288 376 else if (longform)
mcimadamore@288 377 return nameSimplifier.simplify(sym).toString();
mcimadamore@288 378 else
mcimadamore@288 379 return sym.name.toString();
mcimadamore@288 380 }
mcimadamore@288 381
mcimadamore@288 382 @Override
mcimadamore@288 383 public String visitTypeVar(TypeVar t, Locale locale) {
mcimadamore@288 384 if (unique(t) ||
mcimadamore@288 385 !getConfiguration().isEnabled(RichFormatterFeature.UNIQUE_TYPEVAR_NAMES)) {
mcimadamore@288 386 return t.toString();
mcimadamore@288 387 }
mcimadamore@288 388 else {
mcimadamore@288 389 return localize(locale,
mcimadamore@288 390 "compiler.misc.type.var",
mcimadamore@288 391 t.toString(), indexOf(t, WhereClauseKind.TYPEVAR));
mcimadamore@288 392 }
mcimadamore@288 393 }
mcimadamore@288 394
mcimadamore@288 395 @Override
mcimadamore@288 396 protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) {
mcimadamore@288 397 return super.printMethodArgs(args, varArgs, locale);
mcimadamore@288 398 }
mcimadamore@288 399
mcimadamore@288 400 @Override
mcimadamore@288 401 public String visitClassSymbol(ClassSymbol s, Locale locale) {
mcimadamore@288 402 String name = nameSimplifier.simplify(s);
mcimadamore@288 403 if (name.length() == 0 ||
mcimadamore@288 404 !getConfiguration().isEnabled(RichFormatterFeature.SIMPLE_NAMES)) {
mcimadamore@288 405 return super.visitClassSymbol(s, locale);
mcimadamore@288 406 }
mcimadamore@288 407 else {
mcimadamore@288 408 return name;
mcimadamore@288 409 }
mcimadamore@288 410 }
mcimadamore@288 411
mcimadamore@288 412 @Override
mcimadamore@288 413 public String visitMethodSymbol(MethodSymbol s, Locale locale) {
mcimadamore@288 414 String ownerName = visit(s.owner, locale);
mcimadamore@288 415 if ((s.flags() & BLOCK) != 0) {
mcimadamore@288 416 return ownerName;
mcimadamore@288 417 } else {
mcimadamore@288 418 String ms = (s.name == s.name.table.names.init)
mcimadamore@288 419 ? ownerName
mcimadamore@288 420 : s.name.toString();
mcimadamore@288 421 if (s.type != null) {
mcimadamore@288 422 if (s.type.tag == FORALL) {
mcimadamore@288 423 ms = "<" + visitTypes(s.type.getTypeArguments(), locale) + ">" + ms;
mcimadamore@288 424 }
mcimadamore@288 425 ms += "(" + printMethodArgs(
mcimadamore@288 426 s.type.getParameterTypes(),
mcimadamore@288 427 (s.flags() & VARARGS) != 0,
mcimadamore@288 428 locale) + ")";
mcimadamore@288 429 }
mcimadamore@288 430 return ms;
mcimadamore@288 431 }
mcimadamore@288 432 }
mcimadamore@288 433 };
mcimadamore@288 434 // </editor-fold>
mcimadamore@288 435
mcimadamore@288 436 // <editor-fold defaultstate="collapsed" desc="type scanner">
mcimadamore@288 437 /**
mcimadamore@288 438 * Preprocess a given type looking for (i) additional info (where clauses) to be
mcimadamore@288 439 * added to the main diagnostic (ii) names to be compacted.
mcimadamore@288 440 */
mcimadamore@288 441 protected void preprocessType(Type t) {
mcimadamore@288 442 typePreprocessor.visit(t);
mcimadamore@288 443 }
mcimadamore@288 444 //where
mcimadamore@288 445 protected Types.UnaryVisitor<Void> typePreprocessor =
mcimadamore@288 446 new Types.UnaryVisitor<Void>() {
mcimadamore@288 447
mcimadamore@288 448 public Void visit(List<Type> ts) {
mcimadamore@288 449 for (Type t : ts)
mcimadamore@288 450 visit(t);
mcimadamore@288 451 return null;
mcimadamore@288 452 }
mcimadamore@288 453
mcimadamore@288 454 @Override
mcimadamore@288 455 public Void visitForAll(ForAll t, Void ignored) {
mcimadamore@288 456 visit(t.tvars);
mcimadamore@288 457 visit(t.qtype);
mcimadamore@288 458 return null;
mcimadamore@288 459 }
mcimadamore@288 460
mcimadamore@288 461 @Override
mcimadamore@288 462 public Void visitMethodType(MethodType t, Void ignored) {
mcimadamore@288 463 visit(t.argtypes);
mcimadamore@288 464 visit(t.restype);
mcimadamore@288 465 return null;
mcimadamore@288 466 }
mcimadamore@288 467
mcimadamore@288 468 @Override
mcimadamore@288 469 public Void visitErrorType(ErrorType t, Void ignored) {
mcimadamore@288 470 Type ot = t.getOriginalType();
mcimadamore@288 471 if (ot != null)
mcimadamore@288 472 visit(ot);
mcimadamore@288 473 return null;
mcimadamore@288 474 }
mcimadamore@288 475
mcimadamore@288 476 @Override
mcimadamore@288 477 public Void visitArrayType(ArrayType t, Void ignored) {
mcimadamore@288 478 visit(t.elemtype);
mcimadamore@288 479 return null;
mcimadamore@288 480 }
mcimadamore@288 481
mcimadamore@288 482 @Override
mcimadamore@288 483 public Void visitWildcardType(WildcardType t, Void ignored) {
mcimadamore@288 484 visit(t.type);
mcimadamore@288 485 return null;
mcimadamore@288 486 }
mcimadamore@288 487
mcimadamore@288 488 public Void visitType(Type t, Void ignored) {
mcimadamore@288 489 return null;
mcimadamore@288 490 }
mcimadamore@288 491
mcimadamore@288 492 @Override
mcimadamore@288 493 public Void visitCapturedType(CapturedType t, Void ignored) {
mcimadamore@342 494 if (indexOf(t, WhereClauseKind.CAPTURED) == -1) {
mcimadamore@288 495 String suffix = t.lower == syms.botType ? ".1" : "";
mcimadamore@288 496 JCDiagnostic d = diags.fragment("where.captured"+ suffix, t, t.bound, t.lower, t.wildcard);
mcimadamore@288 497 whereClauses.get(WhereClauseKind.CAPTURED).put(t, d);
mcimadamore@288 498 visit(t.wildcard);
mcimadamore@288 499 visit(t.lower);
mcimadamore@288 500 visit(t.bound);
mcimadamore@288 501 }
mcimadamore@288 502 return null;
mcimadamore@288 503 }
mcimadamore@288 504
mcimadamore@288 505 @Override
mcimadamore@288 506 public Void visitClassType(ClassType t, Void ignored) {
mcimadamore@288 507 if (t.isCompound()) {
mcimadamore@342 508 if (indexOf(t, WhereClauseKind.INTERSECTION) == -1) {
mcimadamore@288 509 Type supertype = types.supertype(t);
mcimadamore@288 510 List<Type> interfaces = types.interfaces(t);
mcimadamore@288 511 JCDiagnostic d = diags.fragment("where.intersection", t, interfaces.prepend(supertype));
mcimadamore@288 512 whereClauses.get(WhereClauseKind.INTERSECTION).put(t, d);
mcimadamore@288 513 visit(supertype);
mcimadamore@288 514 visit(interfaces);
mcimadamore@288 515 }
mcimadamore@288 516 }
mcimadamore@288 517 nameSimplifier.addUsage(t.tsym);
mcimadamore@288 518 visit(t.getTypeArguments());
mcimadamore@288 519 if (t.getEnclosingType() != Type.noType)
mcimadamore@288 520 visit(t.getEnclosingType());
mcimadamore@288 521 return null;
mcimadamore@288 522 }
mcimadamore@288 523
mcimadamore@288 524 @Override
mcimadamore@288 525 public Void visitTypeVar(TypeVar t, Void ignored) {
mcimadamore@342 526 if (indexOf(t, WhereClauseKind.TYPEVAR) == -1) {
mcimadamore@343 527 //access the bound type and skip error types
mcimadamore@288 528 Type bound = t.bound;
mcimadamore@288 529 while ((bound instanceof ErrorType))
mcimadamore@288 530 bound = ((ErrorType)bound).getOriginalType();
mcimadamore@343 531 //retrieve the bound list - if the type variable
mcimadamore@343 532 //has not been attributed the bound is not set
mcimadamore@343 533 List<Type> bounds = bound != null ?
mcimadamore@343 534 types.getBounds(t) :
mcimadamore@343 535 List.<Type>nil();
mcimadamore@343 536
mcimadamore@288 537 nameSimplifier.addUsage(t.tsym);
mcimadamore@288 538
mcimadamore@288 539 boolean boundErroneous = bounds.head == null ||
mcimadamore@288 540 bounds.head.tag == NONE ||
mcimadamore@288 541 bounds.head.tag == ERROR;
mcimadamore@288 542
mcimadamore@288 543
mcimadamore@288 544 JCDiagnostic d = diags.fragment("where.typevar" +
mcimadamore@288 545 (boundErroneous ? ".1" : ""), t, bounds,
mcimadamore@288 546 Kinds.kindName(t.tsym.location()), t.tsym.location());
mcimadamore@288 547 whereClauses.get(WhereClauseKind.TYPEVAR).put(t, d);
mcimadamore@288 548 symbolPreprocessor.visit(t.tsym.location(), null);
mcimadamore@288 549 visit(bounds);
mcimadamore@288 550 }
mcimadamore@288 551 return null;
mcimadamore@288 552 }
mcimadamore@288 553 };
mcimadamore@288 554 // </editor-fold>
mcimadamore@288 555
mcimadamore@288 556 // <editor-fold defaultstate="collapsed" desc="symbol scanner">
mcimadamore@288 557 /**
mcimadamore@288 558 * Preprocess a given symbol looking for (i) additional info (where clauses) to be
mcimadamore@288 559 * asdded to the main diagnostic (ii) names to be compacted
mcimadamore@288 560 */
mcimadamore@288 561 protected void preprocessSymbol(Symbol s) {
mcimadamore@288 562 symbolPreprocessor.visit(s, null);
mcimadamore@288 563 }
mcimadamore@288 564 //where
mcimadamore@288 565 protected Types.DefaultSymbolVisitor<Void, Void> symbolPreprocessor =
mcimadamore@288 566 new Types.DefaultSymbolVisitor<Void, Void>() {
mcimadamore@288 567
mcimadamore@288 568 @Override
mcimadamore@288 569 public Void visitClassSymbol(ClassSymbol s, Void ignored) {
mcimadamore@288 570 nameSimplifier.addUsage(s);
mcimadamore@288 571 return null;
mcimadamore@288 572 }
mcimadamore@288 573
mcimadamore@288 574 @Override
mcimadamore@288 575 public Void visitSymbol(Symbol s, Void ignored) {
mcimadamore@288 576 return null;
mcimadamore@288 577 }
mcimadamore@288 578
mcimadamore@288 579 @Override
mcimadamore@288 580 public Void visitMethodSymbol(MethodSymbol s, Void ignored) {
mcimadamore@288 581 visit(s.owner, null);
mcimadamore@326 582 if (s.type != null)
mcimadamore@326 583 typePreprocessor.visit(s.type);
mcimadamore@288 584 return null;
mcimadamore@288 585 }
mcimadamore@288 586 };
mcimadamore@288 587 // </editor-fold>
mcimadamore@288 588
mcimadamore@288 589 @Override
mcimadamore@288 590 public RichConfiguration getConfiguration() {
mcimadamore@288 591 //the following cast is always safe - see init
mcimadamore@288 592 return (RichConfiguration)configuration;
mcimadamore@288 593 }
mcimadamore@288 594
mcimadamore@288 595 /**
mcimadamore@288 596 * Configuration object provided by the rich formatter.
mcimadamore@288 597 */
mcimadamore@288 598 public static class RichConfiguration extends ForwardingDiagnosticFormatter.ForwardingConfiguration {
mcimadamore@288 599
mcimadamore@288 600 /** set of enabled rich formatter's features */
mcimadamore@288 601 protected java.util.EnumSet<RichFormatterFeature> features;
mcimadamore@288 602
mcimadamore@288 603 @SuppressWarnings("fallthrough")
mcimadamore@288 604 public RichConfiguration(Options options, AbstractDiagnosticFormatter formatter) {
mcimadamore@288 605 super(formatter.getConfiguration());
mcimadamore@288 606 features = formatter.isRaw() ? EnumSet.noneOf(RichFormatterFeature.class) :
mcimadamore@288 607 EnumSet.of(RichFormatterFeature.SIMPLE_NAMES,
mcimadamore@288 608 RichFormatterFeature.WHERE_CLAUSES,
mcimadamore@288 609 RichFormatterFeature.UNIQUE_TYPEVAR_NAMES);
mcimadamore@288 610 String diagOpts = options.get("diags");
mcimadamore@288 611 if (diagOpts != null) {
mcimadamore@288 612 for (String args: diagOpts.split(",")) {
mcimadamore@288 613 if (args.equals("-where")) {
mcimadamore@288 614 features.remove(RichFormatterFeature.WHERE_CLAUSES);
mcimadamore@288 615 }
mcimadamore@288 616 else if (args.equals("where")) {
mcimadamore@288 617 features.add(RichFormatterFeature.WHERE_CLAUSES);
mcimadamore@288 618 }
mcimadamore@288 619 if (args.equals("-simpleNames")) {
mcimadamore@288 620 features.remove(RichFormatterFeature.SIMPLE_NAMES);
mcimadamore@288 621 }
mcimadamore@288 622 else if (args.equals("simpleNames")) {
mcimadamore@288 623 features.add(RichFormatterFeature.SIMPLE_NAMES);
mcimadamore@288 624 }
mcimadamore@288 625 if (args.equals("-disambiguateTvars")) {
mcimadamore@288 626 features.remove(RichFormatterFeature.UNIQUE_TYPEVAR_NAMES);
mcimadamore@288 627 }
mcimadamore@288 628 else if (args.equals("disambiguateTvars")) {
mcimadamore@288 629 features.add(RichFormatterFeature.UNIQUE_TYPEVAR_NAMES);
mcimadamore@288 630 }
mcimadamore@288 631 }
mcimadamore@288 632 }
mcimadamore@288 633 }
mcimadamore@288 634
mcimadamore@288 635 /**
mcimadamore@288 636 * Returns a list of all the features supported by the rich formatter.
mcimadamore@288 637 * @return list of supported features
mcimadamore@288 638 */
mcimadamore@288 639 public RichFormatterFeature[] getAvailableFeatures() {
mcimadamore@288 640 return RichFormatterFeature.values();
mcimadamore@288 641 }
mcimadamore@288 642
mcimadamore@288 643 /**
mcimadamore@288 644 * Enable a specific feature on this rich formatter.
mcimadamore@288 645 * @param feature feature to be enabled
mcimadamore@288 646 */
mcimadamore@288 647 public void enable(RichFormatterFeature feature) {
mcimadamore@288 648 features.add(feature);
mcimadamore@288 649 }
mcimadamore@288 650
mcimadamore@288 651 /**
mcimadamore@288 652 * Disable a specific feature on this rich formatter.
mcimadamore@288 653 * @param feature feature to be disabled
mcimadamore@288 654 */
mcimadamore@288 655 public void disable(RichFormatterFeature feature) {
mcimadamore@288 656 features.remove(feature);
mcimadamore@288 657 }
mcimadamore@288 658
mcimadamore@288 659 /**
mcimadamore@288 660 * Is a given feature enabled on this formatter?
mcimadamore@288 661 * @param feature feature to be tested
mcimadamore@288 662 */
mcimadamore@288 663 public boolean isEnabled(RichFormatterFeature feature) {
mcimadamore@288 664 return features.contains(feature);
mcimadamore@288 665 }
mcimadamore@288 666
mcimadamore@288 667 /**
mcimadamore@288 668 * The advanced formatting features provided by the rich formatter
mcimadamore@288 669 */
mcimadamore@288 670 public enum RichFormatterFeature {
mcimadamore@288 671 /** a list of additional info regarding a given type/symbol */
mcimadamore@288 672 WHERE_CLAUSES,
mcimadamore@288 673 /** full class names simplification (where possible) */
mcimadamore@288 674 SIMPLE_NAMES,
mcimadamore@288 675 /** type-variable names disambiguation */
mcimadamore@288 676 UNIQUE_TYPEVAR_NAMES;
mcimadamore@288 677 }
mcimadamore@288 678 }
mcimadamore@288 679 }

mercurial