langtools/test/tools/javac/Diagnostics/6769027/T6769027.java
changeset 2085 4792e12a8ca2
child 3995 73af8b6fb8bc
equal deleted inserted replaced
1998:29b961506419 2085:4792e12a8ca2
       
     1 /*
       
     2  * Copyright 2009 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any questions.
       
    22  */
       
    23 
       
    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.*;
       
    35 
       
    36 public class T6769027 {
       
    37 
       
    38     enum OutputKind {
       
    39         RAW("rawDiagnostics","rawDiagnostics"),
       
    40         BASIC("","");
       
    41 
       
    42         String key;
       
    43         String value;
       
    44 
       
    45         void init(Options opts) {
       
    46             opts.put(key, value);
       
    47         }
       
    48 
       
    49         OutputKind(String key, String value) {
       
    50             this.key = key;
       
    51             this.value = value;
       
    52         }
       
    53     }
       
    54 
       
    55     enum CaretKind {
       
    56         DEFAULT("", ""),
       
    57         SHOW("showCaret","true"),
       
    58         HIDE("showCaret","false");
       
    59 
       
    60         String key;
       
    61         String value;
       
    62 
       
    63         void init(Options opts) {
       
    64             opts.put(key, value);
       
    65         }
       
    66 
       
    67         CaretKind(String key, String value) {
       
    68             this.key = key;
       
    69             this.value = value;
       
    70         }
       
    71 
       
    72         boolean isEnabled() {
       
    73             return this == DEFAULT || this == SHOW;
       
    74         }
       
    75     }
       
    76 
       
    77     enum SourceLineKind {
       
    78         DEFAULT("", ""),
       
    79         AFTER_SUMMARY("sourcePosition", "top"),
       
    80         BOTTOM("sourcePosition", "bottom");
       
    81 
       
    82         String key;
       
    83         String value;
       
    84 
       
    85         void init(Options opts) {
       
    86             opts.put(key, value);
       
    87         }
       
    88 
       
    89         SourceLineKind(String key, String value) {
       
    90             this.key = key;
       
    91             this.value = value;
       
    92         }
       
    93 
       
    94         boolean isAfterSummary() {
       
    95             return this == DEFAULT || this == AFTER_SUMMARY;
       
    96         }
       
    97     }
       
    98 
       
    99     enum XDiagsSource {
       
   100         DEFAULT(""),
       
   101         SOURCE("source"),
       
   102         NO_SOURCE("-source");
       
   103 
       
   104         String flag;
       
   105 
       
   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         }
       
   113 
       
   114         XDiagsSource(String flag) {
       
   115             this.flag = flag;
       
   116         }
       
   117 
       
   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     }
       
   124 
       
   125     enum XDiagsCompact {
       
   126         DEFAULT(""),
       
   127         COMPACT("short"),
       
   128         NO_COMPACT("-short");
       
   129 
       
   130         String flag;
       
   131 
       
   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         }
       
   139 
       
   140         XDiagsCompact(String flag) {
       
   141             this.flag = flag;
       
   142         }
       
   143     }
       
   144 
       
   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!");
       
   153 
       
   154         String key;
       
   155         String rawOutput;
       
   156         String nonRawOutput;
       
   157 
       
   158         String key() {
       
   159             return key;
       
   160         }
       
   161 
       
   162         ErrorKind(String key, String rawOutput, String nonRawOutput) {
       
   163             this.key = key;
       
   164             this.rawOutput = rawOutput;
       
   165             this.nonRawOutput = nonRawOutput;
       
   166         }
       
   167 
       
   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         }
       
   173 
       
   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     }
       
   180 
       
   181     enum MultilineKind {
       
   182         NONE(0),
       
   183         DOUBLE(1),
       
   184         NESTED(2),
       
   185         DOUBLE_NESTED(3);
       
   186 
       
   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
       
   193 
       
   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
       
   200 
       
   201 
       
   202         int index;
       
   203 
       
   204         MultilineKind (int index) {
       
   205             this.index = index;
       
   206         }
       
   207 
       
   208         boolean isDouble() {
       
   209             return this == DOUBLE || this == DOUBLE_NESTED;
       
   210         }
       
   211 
       
   212         boolean isNested() {
       
   213             return this == NESTED || this == DOUBLE_NESTED;
       
   214         }
       
   215 
       
   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;
       
   222 
       
   223             String errMsg1 = errKind.getOutput(outKind, summaryIndent, detailsIndent, constIndent);
       
   224             String errMsg2 = errKind.getOutput(outKind, summaryIndent, detailsIndent, constIndent + constIndent);
       
   225 
       
   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");
       
   230 
       
   231             String template = outKind == OutputKind.RAW ?
       
   232                 rawTemplates[policy.index][index] :
       
   233                 basicTemplates[policy.index][index];
       
   234 
       
   235             template = template.replaceAll("E", errMsg1);
       
   236             return template.replaceAll("Q", errMsg2);
       
   237         }
       
   238     }
       
   239 
       
   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");
       
   246 
       
   247         String name;
       
   248         String value;
       
   249         int index;
       
   250 
       
   251         MultilinePolicy(int index, String name, String value) {
       
   252             this.name = name;
       
   253             this.value = value;
       
   254             this.index = index;
       
   255         }
       
   256 
       
   257         void init(Options options) {
       
   258             options.put(name, value);
       
   259         }
       
   260     }
       
   261 
       
   262     enum PositionKind {
       
   263         NOPOS(Position.NOPOS, "- ", "error: "),
       
   264         POS(5, "/Test.java:1:6: ", "myfo:/Test.java:1: ");
       
   265 
       
   266         int pos;
       
   267         String rawOutput;
       
   268         String nonRawOutput;
       
   269 
       
   270         PositionKind(int pos, String rawOutput, String nonRawOutput) {
       
   271             this.pos = pos;
       
   272             this.rawOutput = rawOutput;
       
   273             this.nonRawOutput = nonRawOutput;
       
   274         }
       
   275 
       
   276         JCDiagnostic.DiagnosticPosition pos() {
       
   277             return new JCDiagnostic.SimpleDiagnosticPosition(pos);
       
   278         }
       
   279 
       
   280         String getOutput(OutputKind outputKind) {
       
   281             return outputKind == OutputKind.RAW ?
       
   282                 rawOutput :
       
   283                 nonRawOutput;
       
   284         }
       
   285     }
       
   286 
       
   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     }
       
   298 
       
   299     enum IndentKind {
       
   300         NONE(""),
       
   301         CUSTOM("   ");
       
   302 
       
   303         String string;
       
   304 
       
   305         IndentKind(String indent) {
       
   306             string = indent;
       
   307         }
       
   308     }
       
   309 
       
   310     class MyLog extends Log {
       
   311         MyLog(Context ctx) {
       
   312             super(ctx);
       
   313         }
       
   314 
       
   315         @Override
       
   316         protected java.io.PrintWriter getWriterForDiagnosticType(JCDiagnostic.DiagnosticType dt) {
       
   317             return new java.io.PrintWriter(System.out);
       
   318         }
       
   319 
       
   320         @Override
       
   321         protected boolean shouldReport(JavaFileObject jfo, int pos) {
       
   322             return true;
       
   323         }
       
   324     }
       
   325 
       
   326     int nerrors = 0;
       
   327 
       
   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     }
       
   380 
       
   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     }
       
   424 
       
   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     }
       
   443 
       
   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         }
       
   475 
       
   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     }
       
   495 
       
   496     public static void main(String... args) throws Exception {
       
   497         new T6769027().test();
       
   498     }
       
   499 }