test/tools/javac/varargs/warning/Warn5.java

Wed, 13 Aug 2014 14:50:00 -0700

author
katleman
date
Wed, 13 Aug 2014 14:50:00 -0700
changeset 2549
0b6cc4ea670f
parent 1520
5c956be64b9e
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Added tag jdk8u40-b01 for changeset bf89a471779d

     1 /*
     2  * Copyright (c) 2010, 2013, 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     6993978 7097436 8006694
    27  * @summary Project Coin: Annotation to reduce varargs warnings
    28  *  temporarily workaround combo tests are causing time out in several platforms
    29  * @author  mcimadamore
    30  * @library ../../lib
    31  * @build JavacTestingAbstractThreadedTest
    32  * @run main/othervm Warn5
    33  */
    35 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
    36 // see JDK-8006746
    38 import java.net.URI;
    39 import java.util.Arrays;
    40 import java.util.EnumSet;
    41 import javax.tools.Diagnostic;
    42 import javax.tools.JavaCompiler;
    43 import javax.tools.JavaFileObject;
    44 import javax.tools.SimpleJavaFileObject;
    45 import javax.tools.ToolProvider;
    46 import com.sun.source.util.JavacTask;
    48 public class Warn5
    49     extends JavacTestingAbstractThreadedTest
    50     implements Runnable {
    52     enum XlintOption {
    53         NONE("none"),
    54         ALL("all");
    56         String opt;
    58         XlintOption(String opt) {
    59             this.opt = opt;
    60         }
    62         String getXlintOption() {
    63             return "-Xlint:" + opt;
    64         }
    65     }
    67     enum TrustMe {
    68         DONT_TRUST(""),
    69         TRUST("@java.lang.SafeVarargs");
    71         String anno;
    73         TrustMe(String anno) {
    74             this.anno = anno;
    75         }
    76     }
    78     enum SuppressLevel {
    79         NONE,
    80         VARARGS;
    82         String getSuppressAnno() {
    83             return this == VARARGS ?
    84                 "@SuppressWarnings(\"varargs\")" :
    85                 "";
    86         }
    87     }
    89     enum ModifierKind {
    90         NONE(""),
    91         FINAL("final"),
    92         STATIC("static");
    94         String mod;
    96         ModifierKind(String mod) {
    97             this.mod = mod;
    98         }
    99     }
   101     enum MethodKind {
   102         METHOD("void m"),
   103         CONSTRUCTOR("Test");
   105         String name;
   107         MethodKind(String name) {
   108             this.name = name;
   109         }
   110     }
   112     enum SourceLevel {
   113         JDK_6("6"),
   114         JDK_7("7");
   116         String sourceKey;
   118         SourceLevel(String sourceKey) {
   119             this.sourceKey = sourceKey;
   120         }
   121     }
   123     enum SignatureKind {
   124         VARARGS_X("#K <X>#N(X... x)", false, true),
   125         VARARGS_STRING("#K #N(String... x)", true, true),
   126         ARRAY_X("#K <X>#N(X[] x)", false, false),
   127         ARRAY_STRING("#K #N(String[] x)", true, false);
   129         String stub;
   130         boolean isReifiableArg;
   131         boolean isVarargs;
   133         SignatureKind(String stub, boolean isReifiableArg, boolean isVarargs) {
   134             this.stub = stub;
   135             this.isReifiableArg = isReifiableArg;
   136             this.isVarargs = isVarargs;
   137         }
   139         String getSignature(ModifierKind modKind, MethodKind methKind) {
   140             return methKind != MethodKind.CONSTRUCTOR ?
   141                 stub.replace("#K", modKind.mod).replace("#N", methKind.name) :
   142                 stub.replace("#K", "").replace("#N", methKind.name);
   143         }
   144     }
   146     enum BodyKind {
   147         ASSIGN("Object o = x;", true),
   148         CAST("Object o = (Object)x;", true),
   149         METH("test(x);", true),
   150         PRINT("System.out.println(x.toString());", false),
   151         ARRAY_ASSIGN("Object[] o = x;", true),
   152         ARRAY_CAST("Object[] o = (Object[])x;", true),
   153         ARRAY_METH("testArr(x);", true);
   155         String body;
   156         boolean hasAliasing;
   158         BodyKind(String body, boolean hasAliasing) {
   159             this.body = body;
   160             this.hasAliasing = hasAliasing;
   161         }
   162     }
   164     enum WarningKind {
   165         UNSAFE_BODY,
   166         UNSAFE_DECL,
   167         MALFORMED_SAFEVARARGS,
   168         REDUNDANT_SAFEVARARGS;
   169     }
   171     public static void main(String... args) throws Exception {
   172         for (SourceLevel sourceLevel : SourceLevel.values()) {
   173             for (XlintOption xlint : XlintOption.values()) {
   174                 for (TrustMe trustMe : TrustMe.values()) {
   175                     for (SuppressLevel suppressLevel : SuppressLevel.values()) {
   176                         for (ModifierKind modKind : ModifierKind.values()) {
   177                             for (MethodKind methKind : MethodKind.values()) {
   178                                 for (SignatureKind sig : SignatureKind.values()) {
   179                                     for (BodyKind body : BodyKind.values()) {
   180                                         pool.execute(new Warn5(sourceLevel,
   181                                                 xlint, trustMe, suppressLevel,
   182                                                 modKind, methKind, sig, body));
   183                                     }
   184                                 }
   185                             }
   186                         }
   187                     }
   188                 }
   189             }
   190         }
   192         checkAfterExec(false);
   193     }
   195     final SourceLevel sourceLevel;
   196     final XlintOption xlint;
   197     final TrustMe trustMe;
   198     final SuppressLevel suppressLevel;
   199     final ModifierKind modKind;
   200     final MethodKind methKind;
   201     final SignatureKind sig;
   202     final BodyKind body;
   203     final JavaSource source;
   204     final DiagnosticChecker dc;
   206     public Warn5(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe,
   207             SuppressLevel suppressLevel, ModifierKind modKind,
   208             MethodKind methKind, SignatureKind sig, BodyKind body) {
   209         this.sourceLevel = sourceLevel;
   210         this.xlint = xlint;
   211         this.trustMe = trustMe;
   212         this.suppressLevel = suppressLevel;
   213         this.modKind = modKind;
   214         this.methKind = methKind;
   215         this.sig = sig;
   216         this.body = body;
   217         this.source = new JavaSource();
   218         this.dc = new DiagnosticChecker();
   219     }
   221     @Override
   222     public void run() {
   223         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
   224         JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc,
   225                 Arrays.asList(xlint.getXlintOption(),
   226                     "-source", sourceLevel.sourceKey),
   227                 null, Arrays.asList(source));
   228         try {
   229             ct.analyze();
   230         } catch (Throwable t) {
   231             processException(t);
   232         }
   233         check();
   234     }
   236     void check() {
   238         EnumSet<WarningKind> expectedWarnings =
   239                 EnumSet.noneOf(WarningKind.class);
   241         if (sourceLevel == SourceLevel.JDK_7 &&
   242                 trustMe == TrustMe.TRUST &&
   243                 suppressLevel != SuppressLevel.VARARGS &&
   244                 xlint != XlintOption.NONE &&
   245                 sig.isVarargs &&
   246                 !sig.isReifiableArg &&
   247                 body.hasAliasing &&
   248                 (methKind == MethodKind.CONSTRUCTOR ||
   249                 (methKind == MethodKind.METHOD &&
   250                 modKind != ModifierKind.NONE))) {
   251             expectedWarnings.add(WarningKind.UNSAFE_BODY);
   252         }
   254         if (sourceLevel == SourceLevel.JDK_7 &&
   255                 trustMe == TrustMe.DONT_TRUST &&
   256                 sig.isVarargs &&
   257                 !sig.isReifiableArg &&
   258                 xlint == XlintOption.ALL) {
   259             expectedWarnings.add(WarningKind.UNSAFE_DECL);
   260         }
   262         if (sourceLevel == SourceLevel.JDK_7 &&
   263                 trustMe == TrustMe.TRUST &&
   264                 (!sig.isVarargs ||
   265                 (modKind == ModifierKind.NONE &&
   266                 methKind == MethodKind.METHOD))) {
   267             expectedWarnings.add(WarningKind.MALFORMED_SAFEVARARGS);
   268         }
   270         if (sourceLevel == SourceLevel.JDK_7 &&
   271                 trustMe == TrustMe.TRUST &&
   272                 xlint != XlintOption.NONE &&
   273                 suppressLevel != SuppressLevel.VARARGS &&
   274                 (modKind != ModifierKind.NONE ||
   275                 methKind == MethodKind.CONSTRUCTOR) &&
   276                 sig.isVarargs &&
   277                 sig.isReifiableArg) {
   278             expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS);
   279         }
   281         if (!expectedWarnings.containsAll(dc.warnings) ||
   282                 !dc.warnings.containsAll(expectedWarnings)) {
   283             throw new Error("invalid diagnostics for source:\n" +
   284                     source.getCharContent(true) +
   285                     "\nOptions: " + xlint.getXlintOption() +
   286                     "\nExpected warnings: " + expectedWarnings +
   287                     "\nFound warnings: " + dc.warnings);
   288         }
   289     }
   291     class JavaSource extends SimpleJavaFileObject {
   293         String template = "import com.sun.tools.javac.api.*;\n" +
   294                           "import java.util.List;\n" +
   295                           "class Test {\n" +
   296                           "   static void test(Object o) {}\n" +
   297                           "   static void testArr(Object[] o) {}\n" +
   298                           "   #T \n #S #M { #B }\n" +
   299                           "}\n";
   301         String source;
   303         public JavaSource() {
   304             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   305             source = template.replace("#T", trustMe.anno).
   306                     replace("#S", suppressLevel.getSuppressAnno()).
   307                     replace("#M", sig.getSignature(modKind, methKind)).
   308                     replace("#B", body.body);
   309         }
   311         @Override
   312         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   313             return source;
   314         }
   315     }
   317     class DiagnosticChecker
   318         implements javax.tools.DiagnosticListener<JavaFileObject> {
   320         EnumSet<WarningKind> warnings = EnumSet.noneOf(WarningKind.class);
   322         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   323             if (diagnostic.getKind() == Diagnostic.Kind.WARNING) {
   324                     if (diagnostic.getCode().
   325                             contains("unsafe.use.varargs.param")) {
   326                         setWarning(WarningKind.UNSAFE_BODY);
   327                     } else if (diagnostic.getCode().
   328                             contains("redundant.trustme")) {
   329                         setWarning(WarningKind.REDUNDANT_SAFEVARARGS);
   330                     }
   331             } else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING &&
   332                     diagnostic.getCode().
   333                         contains("varargs.non.reifiable.type")) {
   334                 setWarning(WarningKind.UNSAFE_DECL);
   335             } else if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
   336                     diagnostic.getCode().contains("invalid.trustme")) {
   337                 setWarning(WarningKind.MALFORMED_SAFEVARARGS);
   338             }
   339         }
   341         void setWarning(WarningKind wk) {
   342             if (!warnings.add(wk)) {
   343                 throw new AssertionError("Duplicate warning of kind " +
   344                         wk + " in source:\n" + source);
   345             }
   346         }
   348         boolean hasWarning(WarningKind wk) {
   349             return warnings.contains(wk);
   350         }
   351     }
   353 }

mercurial