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

Thu, 25 Aug 2011 17:18:25 -0700

author
schien
date
Thu, 25 Aug 2011 17:18:25 -0700
changeset 1067
f497fac86cf9
parent 962
0ff2bbd38f10
child 1108
b5d0b8effc85
permissions
-rw-r--r--

Added tag jdk8-b02 for changeset b3c059de2a61

     1 /*
     2  * Copyright (c) 2010, 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     6993978
    27  * @summary Project Coin: Annotation to reduce varargs warnings
    28  * @author  mcimadamore
    29  * @run main Warn5
    30  */
    31 import com.sun.source.util.JavacTask;
    32 import com.sun.tools.javac.api.JavacTool;
    33 import java.net.URI;
    34 import java.util.ArrayList;
    35 import java.util.Arrays;
    36 import javax.tools.Diagnostic;
    37 import javax.tools.JavaCompiler;
    38 import javax.tools.JavaFileObject;
    39 import javax.tools.SimpleJavaFileObject;
    40 import javax.tools.StandardJavaFileManager;
    41 import javax.tools.ToolProvider;
    43 public class Warn5 {
    45     enum XlintOption {
    46         NONE("none"),
    47         ALL("all");
    49         String opt;
    51         XlintOption(String opt) {
    52             this.opt = opt;
    53         }
    55         String getXlintOption() {
    56             return "-Xlint:" + opt;
    57         }
    58     }
    60     enum TrustMe {
    61         DONT_TRUST(""),
    62         TRUST("@java.lang.SafeVarargs");
    64         String anno;
    66         TrustMe(String anno) {
    67             this.anno = anno;
    68         }
    69     }
    71     enum SuppressLevel {
    72         NONE,
    73         VARARGS;
    75         String getSuppressAnno() {
    76             return this == VARARGS ?
    77                 "@SuppressWarnings(\"varargs\")" :
    78                 "";
    79         }
    80     }
    82     enum ModifierKind {
    83         NONE(""),
    84         FINAL("final"),
    85         STATIC("static");
    87         String mod;
    89         ModifierKind(String mod) {
    90             this.mod = mod;
    91         }
    92     }
    94     enum MethodKind {
    95         METHOD("void m"),
    96         CONSTRUCTOR("Test");
    99         String name;
   101         MethodKind(String name) {
   102             this.name = name;
   103         }
   104     }
   106     enum SourceLevel {
   107         JDK_6("6"),
   108         JDK_7("7");
   110         String sourceKey;
   112         SourceLevel(String sourceKey) {
   113             this.sourceKey = sourceKey;
   114         }
   115     }
   117     enum SignatureKind {
   118         VARARGS_X("#K <X>#N(X... x)", false, true),
   119         VARARGS_STRING("#K #N(String... x)", true, true),
   120         ARRAY_X("#K <X>#N(X[] x)", false, false),
   121         ARRAY_STRING("#K #N(String[] x)", true, false);
   123         String stub;
   124         boolean isReifiableArg;
   125         boolean isVarargs;
   127         SignatureKind(String stub, boolean isReifiableArg, boolean isVarargs) {
   128             this.stub = stub;
   129             this.isReifiableArg = isReifiableArg;
   130             this.isVarargs = isVarargs;
   131         }
   133         String getSignature(ModifierKind modKind, MethodKind methKind) {
   134             return methKind != MethodKind.CONSTRUCTOR ?
   135                 stub.replace("#K", modKind.mod).replace("#N", methKind.name) :
   136                 stub.replace("#K", "").replace("#N", methKind.name);
   137         }
   138     }
   140     enum BodyKind {
   141         ASSIGN("Object o = x;", true),
   142         CAST("Object o = (Object)x;", true),
   143         METH("test(x);", true),
   144         PRINT("System.out.println(x.toString());", false),
   145         ARRAY_ASSIGN("Object[] o = x;", true),
   146         ARRAY_CAST("Object[] o = (Object[])x;", true),
   147         ARRAY_METH("testArr(x);", true);
   149         String body;
   150         boolean hasAliasing;
   152         BodyKind(String body, boolean hasAliasing) {
   153             this.body = body;
   154             this.hasAliasing = hasAliasing;
   155         }
   156     }
   158     static class JavaSource extends SimpleJavaFileObject {
   160         String template = "import com.sun.tools.javac.api.*;\n" +
   161                           "import java.util.List;\n" +
   162                           "class Test {\n" +
   163                           "   static void test(Object o) {}\n" +
   164                           "   static void testArr(Object[] o) {}\n" +
   165                           "   #T \n #S #M { #B }\n" +
   166                           "}\n";
   168         String source;
   170         public JavaSource(TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind,
   171                 MethodKind methKind, SignatureKind meth, BodyKind body) {
   172             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   173             source = template.replace("#T", trustMe.anno).
   174                     replace("#S", suppressLevel.getSuppressAnno()).
   175                     replace("#M", meth.getSignature(modKind, methKind)).
   176                     replace("#B", body.body);
   177         }
   179         @Override
   180         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   181             return source;
   182         }
   183     }
   185     public static void main(String... args) throws Exception {
   186         for (SourceLevel sourceLevel : SourceLevel.values()) {
   187             for (XlintOption xlint : XlintOption.values()) {
   188                 for (TrustMe trustMe : TrustMe.values()) {
   189                     for (SuppressLevel suppressLevel : SuppressLevel.values()) {
   190                         for (ModifierKind modKind : ModifierKind.values()) {
   191                             for (MethodKind methKind : MethodKind.values()) {
   192                                 for (SignatureKind sig : SignatureKind.values()) {
   193                                     for (BodyKind body : BodyKind.values()) {
   194                                         test(sourceLevel,
   195                                                 xlint,
   196                                                 trustMe,
   197                                                 suppressLevel,
   198                                                 modKind,
   199                                                 methKind,
   200                                                 sig,
   201                                                 body);
   202                                     }
   203                                 }
   204                             }
   205                         }
   206                     }
   207                 }
   208             }
   209         }
   210     }
   212     // Create a single file manager and reuse it for each compile to save time.
   213     static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
   215     static void test(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel,
   216             ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) throws Exception {
   217         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
   218         JavaSource source = new JavaSource(trustMe, suppressLevel, modKind, methKind, sig, body);
   219         DiagnosticChecker dc = new DiagnosticChecker();
   220         JavacTask ct = (JavacTask)tool.getTask(null, fm, dc,
   221                 Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source));
   222         ct.analyze();
   223         check(sourceLevel, dc, source, xlint, trustMe,
   224                 suppressLevel, modKind, methKind, sig, body);
   225     }
   227     static void check(SourceLevel sourceLevel, DiagnosticChecker dc, JavaSource source,
   228             XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind,
   229             MethodKind methKind, SignatureKind meth, BodyKind body) {
   231         boolean hasPotentiallyUnsafeBody = sourceLevel == SourceLevel.JDK_7 &&
   232                 trustMe == TrustMe.TRUST &&
   233                 suppressLevel != SuppressLevel.VARARGS &&
   234                 xlint != XlintOption.NONE &&
   235                 meth.isVarargs && !meth.isReifiableArg && body.hasAliasing &&
   236                 (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE));
   238         boolean hasPotentiallyPollutingDecl = sourceLevel == SourceLevel.JDK_7 &&
   239                 trustMe == TrustMe.DONT_TRUST &&
   240                 meth.isVarargs &&
   241                 !meth.isReifiableArg &&
   242                 xlint == XlintOption.ALL;
   244         boolean hasMalformedAnnoInDecl = sourceLevel == SourceLevel.JDK_7 &&
   245                 trustMe == TrustMe.TRUST &&
   246                 (!meth.isVarargs ||
   247                 (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD));
   249         boolean hasRedundantAnnoInDecl = sourceLevel == SourceLevel.JDK_7 &&
   250                 trustMe == TrustMe.TRUST &&
   251                 xlint != XlintOption.NONE &&
   252                 suppressLevel != SuppressLevel.VARARGS &&
   253                 (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) &&
   254                 meth.isVarargs &&
   255                 meth.isReifiableArg;
   257         if (hasPotentiallyUnsafeBody != dc.hasPotentiallyUnsafeBody ||
   258                 hasPotentiallyPollutingDecl != dc.hasPotentiallyPollutingDecl ||
   259                 hasMalformedAnnoInDecl != dc.hasMalformedAnnoInDecl ||
   260                 hasRedundantAnnoInDecl != dc.hasRedundantAnnoInDecl) {
   261             throw new Error("invalid diagnostics for source:\n" +
   262                     source.getCharContent(true) +
   263                     "\nOptions: " + xlint.getXlintOption() +
   264                     "\nExpected potentially unsafe body warning: " + hasPotentiallyUnsafeBody +
   265                     "\nExpected potentially polluting decl warning: " + hasPotentiallyPollutingDecl +
   266                     "\nExpected malformed anno error: " + hasMalformedAnnoInDecl +
   267                     "\nExpected redundant anno warning: " + hasRedundantAnnoInDecl +
   268                     "\nFound potentially unsafe body warning: " + dc.hasPotentiallyUnsafeBody +
   269                     "\nFound potentially polluting decl warning: " + dc.hasPotentiallyPollutingDecl +
   270                     "\nFound malformed anno error: " + dc.hasMalformedAnnoInDecl +
   271                     "\nFound redundant anno warning: " + dc.hasRedundantAnnoInDecl);
   272         }
   273     }
   275     static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
   277         boolean hasPotentiallyUnsafeBody = false;
   278         boolean hasPotentiallyPollutingDecl = false;
   279         boolean hasMalformedAnnoInDecl = false;
   280         boolean hasRedundantAnnoInDecl = false;
   282         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   283             if (diagnostic.getKind() == Diagnostic.Kind.WARNING) {
   284                     if (diagnostic.getCode().contains("unsafe.use.varargs.param")) {
   285                         hasPotentiallyUnsafeBody = true;
   286                     } else if (diagnostic.getCode().contains("redundant.trustme")) {
   287                         hasRedundantAnnoInDecl = true;
   288                     }
   289             } else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING &&
   290                     diagnostic.getCode().contains("varargs.non.reifiable.type")) {
   291                 hasPotentiallyPollutingDecl = true;
   292             } else if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
   293                     diagnostic.getCode().contains("invalid.trustme")) {
   294                 hasMalformedAnnoInDecl = true;
   295             }
   296         }
   297     }
   298 }

mercurial