test/tools/javac/Diagnostics/6769027/T6769027.java

Thu, 02 Aug 2012 18:22:41 +0100

author
mcimadamore
date
Thu, 02 Aug 2012 18:22:41 +0100
changeset 1296
cddc2c894cc6
parent 929
e2890b8369f7
child 1482
954541f13717
permissions
-rw-r--r--

7175911: Simplify error reporting API in Check.CheckContext interface
Summary: Make error messages generated during Check.checkType more uniform and more scalable
Reviewed-by: jjg, dlsmith

     1 /*
     2  * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 /**
    25  * @test
    26  * @bug     6769027
    27  * @summary Source line should be displayed immediately after the first diagnostic line
    28  * @author  Maurizio Cimadamore
    29  * @run main/othervm T6769027
    30  */
    31 import java.net.URI;
    32 import java.util.regex.Matcher;
    33 import javax.tools.*;
    34 import com.sun.tools.javac.util.*;
    36 public class T6769027 {
    38     enum OutputKind {
    39         RAW("rawDiagnostics","rawDiagnostics"),
    40         BASIC("","");
    42         String key;
    43         String value;
    45         void init(Options opts) {
    46             opts.put(key, value);
    47         }
    49         OutputKind(String key, String value) {
    50             this.key = key;
    51             this.value = value;
    52         }
    53     }
    55     enum CaretKind {
    56         DEFAULT("", ""),
    57         SHOW("showCaret","true"),
    58         HIDE("showCaret","false");
    60         String key;
    61         String value;
    63         void init(Options opts) {
    64             opts.put(key, value);
    65         }
    67         CaretKind(String key, String value) {
    68             this.key = key;
    69             this.value = value;
    70         }
    72         boolean isEnabled() {
    73             return this == DEFAULT || this == SHOW;
    74         }
    75     }
    77     enum SourceLineKind {
    78         DEFAULT("", ""),
    79         AFTER_SUMMARY("sourcePosition", "top"),
    80         BOTTOM("sourcePosition", "bottom");
    82         String key;
    83         String value;
    85         void init(Options opts) {
    86             opts.put(key, value);
    87         }
    89         SourceLineKind(String key, String value) {
    90             this.key = key;
    91             this.value = value;
    92         }
    94         boolean isAfterSummary() {
    95             return this == DEFAULT || this == AFTER_SUMMARY;
    96         }
    97     }
    99     enum XDiagsSource {
   100         DEFAULT(""),
   101         SOURCE("source"),
   102         NO_SOURCE("-source");
   104         String flag;
   106         void init(Options opts) {
   107             if (this != DEFAULT) {
   108                 String flags = opts.get("diags");
   109                 flags = flags == null ? flag : flags + "," + flag;
   110                 opts.put("diags", flags);
   111             }
   112         }
   114         XDiagsSource(String flag) {
   115             this.flag = flag;
   116         }
   118         String getOutput(CaretKind caretKind, IndentKind indent, OutputKind outKind) {
   119             String spaces = (outKind == OutputKind.BASIC) ? indent.string : "";
   120             return "\n" + spaces + "This is a source line" +
   121                    (caretKind.isEnabled() ? "\n" + spaces + "     ^" : "");
   122         }
   123     }
   125     enum XDiagsCompact {
   126         DEFAULT(""),
   127         COMPACT("short"),
   128         NO_COMPACT("-short");
   130         String flag;
   132         void init(Options opts) {
   133             if (this != DEFAULT) {
   134                 String flags = opts.get("diags");
   135                 flags = flags == null ? flag : flags + "," + flag;
   136                 opts.put("diags", flags);
   137             }
   138         }
   140         XDiagsCompact(String flag) {
   141             this.flag = flag;
   142         }
   143     }
   145     enum ErrorKind {
   146         SINGLE("single",
   147             "compiler.err.single: Hello!",
   148             "KXThis is a test error message Hello!"),
   149         DOUBLE("double",
   150             "compiler.err.double: Hello!",
   151             "KXThis is a test error message.\n" +
   152             "KXYThis is another line of the above error message Hello!");
   154         String key;
   155         String rawOutput;
   156         String nonRawOutput;
   158         String key() {
   159             return key;
   160         }
   162         ErrorKind(String key, String rawOutput, String nonRawOutput) {
   163             this.key = key;
   164             this.rawOutput = rawOutput;
   165             this.nonRawOutput = nonRawOutput;
   166         }
   168         String getOutput(OutputKind outKind, IndentKind summaryIndent, IndentKind detailsIndent) {
   169             return outKind == OutputKind.RAW ?
   170                 rawOutput :
   171                 nonRawOutput.replace("X", summaryIndent.string).replace("Y", detailsIndent.string).replace("K", "");
   172         }
   174         String getOutput(OutputKind outKind, IndentKind summaryIndent, IndentKind detailsIndent, String indent) {
   175             return outKind == OutputKind.RAW ?
   176                 rawOutput :
   177                 nonRawOutput.replace("X", summaryIndent.string).replace("Y", detailsIndent.string).replace("K", indent);
   178         }
   179     }
   181     enum MultilineKind {
   182         NONE(0),
   183         DOUBLE(1),
   184         NESTED(2),
   185         DOUBLE_NESTED(3);
   187         static String[][] rawTemplates = {
   188             {"", ",{(E),(E)}", ",{(E,{(E)})}", ",{(E,{(E)}),(E,{(E)})}"}, //ENABLED
   189             {"", "", "", "",""}, //DISABLED
   190             {"", ",{(E)}", ",{(E,{(E)})}", ",{(E,{(E)})}"}, //LIMIT_LENGTH
   191             {"", ",{(E),(E)}", ",{(E)}", ",{(E),(E)}"}, //LIMIT_DEPTH
   192             {"", ",{(E)}", ",{(E)}", ",{(E)}"}}; //LIMIT_BOTH
   194         static String[][] basicTemplates = {
   195             {"", "\nE\nE", "\nE\nQ", "\nE\nQ\nE\nQ"}, //ENABLED
   196             {"", "", "", "",""}, //DISABLED
   197             {"", "\nE", "\nE\nQ", "\nE\nQ"}, //LIMIT_LENGTH
   198             {"", "\nE\nE", "\nE", "\nE\nE"}, //LIMIT_DEPTH
   199             {"", "\nE", "\nE", "\nE"}}; //LIMIT_BOTH
   202         int index;
   204         MultilineKind (int index) {
   205             this.index = index;
   206         }
   208         boolean isDouble() {
   209             return this == DOUBLE || this == DOUBLE_NESTED;
   210         }
   212         boolean isNested() {
   213             return this == NESTED || this == DOUBLE_NESTED;
   214         }
   216         String getOutput(OutputKind outKind, ErrorKind errKind, MultilinePolicy policy,
   217                 IndentKind summaryIndent, IndentKind detailsIndent, IndentKind multiIndent) {
   218             String constIndent = (errKind == ErrorKind.DOUBLE) ?
   219                 summaryIndent.string + detailsIndent.string :
   220                 summaryIndent.string;
   221             constIndent += multiIndent.string;
   223             String errMsg1 = errKind.getOutput(outKind, summaryIndent, detailsIndent, constIndent);
   224             String errMsg2 = errKind.getOutput(outKind, summaryIndent, detailsIndent, constIndent + constIndent);
   226             errMsg1 = errMsg1.replaceAll("compiler.err", "compiler.misc");
   227             errMsg1 = errMsg1.replaceAll("error message", "subdiagnostic");
   228             errMsg2 = errMsg2.replaceAll("compiler.err", "compiler.misc");
   229             errMsg2 = errMsg2.replaceAll("error message", "subdiagnostic");
   231             String template = outKind == OutputKind.RAW ?
   232                 rawTemplates[policy.index][index] :
   233                 basicTemplates[policy.index][index];
   235             template = template.replaceAll("E", errMsg1);
   236             return template.replaceAll("Q", errMsg2);
   237         }
   238     }
   240     enum MultilinePolicy {
   241         ENABLED(0, "multilinePolicy", "enabled"),
   242         DISABLED(1, "multilinePolicy", "disabled"),
   243         LIMIT_LENGTH(2, "multilinePolicy", "limit:1:*"),
   244         LIMIT_DEPTH(3, "multilinePolicy", "limit:*:1"),
   245         LIMIT_BOTH(4, "multilinePolicy", "limit:1:1");
   247         String name;
   248         String value;
   249         int index;
   251         MultilinePolicy(int index, String name, String value) {
   252             this.name = name;
   253             this.value = value;
   254             this.index = index;
   255         }
   257         void init(Options options) {
   258             options.put(name, value);
   259         }
   260     }
   262     enum PositionKind {
   263         NOPOS(Position.NOPOS, "- ", "error: "),
   264         POS(5, "Test.java:1:6: ", "/Test.java:1: error: ");
   266         int pos;
   267         String rawOutput;
   268         String nonRawOutput;
   270         PositionKind(int pos, String rawOutput, String nonRawOutput) {
   271             this.pos = pos;
   272             this.rawOutput = rawOutput;
   273             this.nonRawOutput = nonRawOutput;
   274         }
   276         JCDiagnostic.DiagnosticPosition pos() {
   277             return new JCDiagnostic.SimpleDiagnosticPosition(pos);
   278         }
   280         String getOutput(OutputKind outputKind) {
   281             return outputKind == OutputKind.RAW ?
   282                 rawOutput :
   283                 nonRawOutput;
   284         }
   285     }
   287     static class MyFileObject extends SimpleJavaFileObject {
   288         private String text;
   289         public MyFileObject(String text) {
   290             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   291             this.text = text;
   292         }
   293         @Override
   294         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   295             return text;
   296         }
   297     }
   299     enum IndentKind {
   300         NONE(""),
   301         CUSTOM("   ");
   303         String string;
   305         IndentKind(String indent) {
   306             string = indent;
   307         }
   308     }
   310     class MyLog extends Log {
   311         MyLog(Context ctx) {
   312             super(ctx);
   313         }
   315         @Override
   316         protected java.io.PrintWriter getWriterForDiagnosticType(JCDiagnostic.DiagnosticType dt) {
   317             return new java.io.PrintWriter(System.out);
   318         }
   320         @Override
   321         protected boolean shouldReport(JavaFileObject jfo, int pos) {
   322             return true;
   323         }
   324     }
   326     int nerrors = 0;
   328     void exec(OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
   329             MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource,
   330             XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind,
   331             IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent,
   332             IndentKind subdiagsIndent) {
   333         Context ctx = new Context();
   334         Options options = Options.instance(ctx);
   335         outputKind.init(options);
   336         multiPolicy.init(options);
   337         xdiagsSource.init(options);
   338         xdiagsCompact.init(options);
   339         caretKind.init(options);
   340         sourceLineKind.init(options);
   341         String indentString = "";
   342         indentString = (summaryIndent == IndentKind.CUSTOM) ? "3" : "0";
   343         indentString += (detailsIndent == IndentKind.CUSTOM) ? "|3" : "|0";
   344         indentString += (sourceIndent == IndentKind.CUSTOM) ? "|3" : "|0";
   345         indentString += (subdiagsIndent == IndentKind.CUSTOM) ? "|3" : "|0";
   346         options.put("diagsIndentation", indentString);
   347         MyLog log = new MyLog(ctx);
   348         JavacMessages messages = JavacMessages.instance(ctx);
   349         messages.add("tester");
   350         JCDiagnostic.Factory diags = JCDiagnostic.Factory.instance(ctx);
   351         log.useSource(new MyFileObject("This is a source line"));
   352         JCDiagnostic d = diags.error(log.currentSource(),
   353             posKind.pos(),
   354             errorKind.key(), "Hello!");
   355         if (multiKind != MultilineKind.NONE) {
   356             JCDiagnostic sub = diags.fragment(errorKind.key(), "Hello!");
   357             if (multiKind.isNested())
   358                 sub = new JCDiagnostic.MultilineDiagnostic(sub, List.of(sub));
   359             List<JCDiagnostic> subdiags = multiKind.isDouble() ?
   360                 List.of(sub, sub) :
   361                 List.of(sub);
   362             d = new JCDiagnostic.MultilineDiagnostic(d, subdiags);
   363         }
   364         String diag = log.getDiagnosticFormatter().format(d, messages.getCurrentLocale());
   365         checkOutput(diag,
   366                 outputKind,
   367                 errorKind,
   368                 multiKind,
   369                 multiPolicy,
   370                 posKind,
   371                 xdiagsSource,
   372                 xdiagsCompact,
   373                 caretKind,
   374                 sourceLineKind,
   375                 summaryIndent,
   376                 detailsIndent,
   377                 sourceIndent,
   378                 subdiagsIndent);
   379     }
   381     void test() {
   382         for (OutputKind outputKind : OutputKind.values()) {
   383             for (ErrorKind errKind : ErrorKind.values()) {
   384                 for (MultilineKind multiKind : MultilineKind.values()) {
   385                     for (MultilinePolicy multiPolicy : MultilinePolicy.values()) {
   386                         for (PositionKind posKind : PositionKind.values()) {
   387                             for (XDiagsSource xdiagsSource : XDiagsSource.values()) {
   388                                 for (XDiagsCompact xdiagsCompact : XDiagsCompact.values()) {
   389                                     for (CaretKind caretKind : CaretKind.values()) {
   390                                         for (SourceLineKind sourceLineKind : SourceLineKind.values()) {
   391                                             for (IndentKind summaryIndent : IndentKind.values()) {
   392                                                 for (IndentKind detailsIndent : IndentKind.values()) {
   393                                                     for (IndentKind sourceIndent : IndentKind.values()) {
   394                                                         for (IndentKind subdiagsIndent : IndentKind.values()) {
   395                                                             exec(outputKind,
   396                                                                 errKind,
   397                                                                 multiKind,
   398                                                                 multiPolicy,
   399                                                                 posKind,
   400                                                                 xdiagsSource,
   401                                                                 xdiagsCompact,
   402                                                                 caretKind,
   403                                                                 sourceLineKind,
   404                                                                 summaryIndent,
   405                                                                 detailsIndent,
   406                                                                 sourceIndent,
   407                                                                 subdiagsIndent);
   408                                                         }
   409                                                     }
   410                                                 }
   411                                             }
   412                                         }
   413                                     }
   414                                 }
   415                             }
   416                         }
   417                     }
   418                 }
   419             }
   420         }
   421         if (nerrors != 0)
   422             throw new AssertionError(nerrors + " errors found");
   423     }
   425     void printInfo(String msg, OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
   426             MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource,
   427             XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind,
   428             IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent,
   429             IndentKind subdiagsIndent, String errorLine) {
   430         String sep = "*********************************************************";
   431         String desc = "raw=" + outputKind + " pos=" + posKind + " key=" + errorKind.key() +
   432                 " multiline=" + multiKind +" multiPolicy=" + multiPolicy.value +
   433                 " diags= " + java.util.Arrays.asList(xdiagsSource.flag, xdiagsCompact.flag) +
   434                 " caret=" + caretKind + " sourcePosition=" + sourceLineKind +
   435                 " summaryIndent=" + summaryIndent + " detailsIndent=" + detailsIndent +
   436                 " sourceIndent=" + sourceIndent + " subdiagsIndent=" + subdiagsIndent;
   437         System.out.println(sep);
   438         System.out.println(desc);
   439         System.out.println(sep);
   440         System.out.println(msg);
   441         System.out.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine);
   442     }
   444     void checkOutput(String msg, OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
   445             MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource,
   446             XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind,
   447             IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent,
   448             IndentKind subdiagsIndent) {
   449         boolean shouldPrintSource = posKind == PositionKind.POS &&
   450                 xdiagsSource != XDiagsSource.NO_SOURCE &&
   451                 (xdiagsSource == XDiagsSource.SOURCE ||
   452                 outputKind == OutputKind.BASIC);
   453         String errorLine = posKind.getOutput(outputKind) +
   454                 errorKind.getOutput(outputKind, summaryIndent, detailsIndent);
   455         if (xdiagsCompact != XDiagsCompact.COMPACT)
   456             errorLine += multiKind.getOutput(outputKind, errorKind, multiPolicy, summaryIndent, detailsIndent, subdiagsIndent);
   457         String[] lines = errorLine.split("\n");
   458         if (xdiagsCompact == XDiagsCompact.COMPACT) {
   459             errorLine = lines[0];
   460             lines = new String[] {errorLine};
   461         }
   462         if (shouldPrintSource) {
   463             if (sourceLineKind.isAfterSummary()) {
   464                 String sep = "\n";
   465                 if (lines.length == 1) {
   466                     errorLine += "\n";
   467                     sep = "";
   468                 }
   469                 errorLine = errorLine.replaceFirst("\n",
   470                         Matcher.quoteReplacement(xdiagsSource.getOutput(caretKind, sourceIndent, outputKind) + sep));
   471             }
   472             else
   473                 errorLine += xdiagsSource.getOutput(caretKind, sourceIndent, outputKind);
   474         }
   476         if (!msg.equals(errorLine)) {
   477             printInfo(msg,
   478                     outputKind,
   479                     errorKind,
   480                     multiKind,
   481                     multiPolicy,
   482                     posKind,
   483                     xdiagsSource,
   484                     xdiagsCompact,
   485                     caretKind,
   486                     sourceLineKind,
   487                     summaryIndent,
   488                     detailsIndent,
   489                     sourceIndent,
   490                     subdiagsIndent,
   491                     errorLine);
   492             nerrors++;
   493         }
   494     }
   496     public static void main(String... args) throws Exception {
   497         new T6769027().test();
   498     }
   499 }

mercurial