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

Mon, 13 Dec 2010 15:11:00 -0800

author
mcimadamore
date
Mon, 13 Dec 2010 15:11:00 -0800
changeset 795
7b99f98b3035
parent 581
f2fdd52e4e87
child 892
3e30c95da3c6
permissions
-rw-r--r--

6993978: Project Coin: Compiler support of annotation to reduce varargs warnings
Reviewed-by: jjg, darcy

     1 /*
     2  * Copyright (c) 2010, 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     6945418 6993978
    27  * @summary Project Coin: Simplified Varargs Method Invocation
    28  * @author  mcimadamore
    29  * @run main Warn4
    30  */
    31 import com.sun.source.util.JavacTask;
    32 import java.net.URI;
    33 import java.util.Arrays;
    34 import java.util.Set;
    35 import java.util.HashSet;
    36 import javax.tools.Diagnostic;
    37 import javax.tools.JavaCompiler;
    38 import javax.tools.JavaFileObject;
    39 import javax.tools.SimpleJavaFileObject;
    40 import javax.tools.ToolProvider;
    42 public class Warn4 {
    44     final static Warning[] error = null;
    45     final static Warning[] none = new Warning[] {};
    46     final static Warning[] vararg = new Warning[] { Warning.VARARGS };
    47     final static Warning[] unchecked = new Warning[] { Warning.UNCHECKED };
    48     final static Warning[] both = new Warning[] { Warning.VARARGS, Warning.UNCHECKED };
    50     enum Warning {
    51         UNCHECKED("generic.array.creation"),
    52         VARARGS("varargs.non.reifiable.type");
    54         String key;
    56         Warning(String key) {
    57             this.key = key;
    58         }
    60         boolean isSuppressed(TrustMe trustMe, SourceLevel source, SuppressLevel suppressLevelClient,
    61                 SuppressLevel suppressLevelDecl, ModifierKind modKind) {
    62             switch(this) {
    63                 case VARARGS:
    64                     return source == SourceLevel.JDK_6 ||
    65                             suppressLevelDecl == SuppressLevel.UNCHECKED ||
    66                             trustMe == TrustMe.TRUST;
    67                 case UNCHECKED:
    68                     return suppressLevelClient == SuppressLevel.UNCHECKED ||
    69                         (trustMe == TrustMe.TRUST && modKind != ModifierKind.NONE && source == SourceLevel.JDK_7);
    70             }
    72             SuppressLevel supLev = this == VARARGS ?
    73                 suppressLevelDecl :
    74                 suppressLevelClient;
    75             return supLev == SuppressLevel.UNCHECKED ||
    76                     (trustMe == TrustMe.TRUST && modKind != ModifierKind.NONE);
    77         }
    78     }
    80     enum SourceLevel {
    81         JDK_6("6"),
    82         JDK_7("7");
    84         String sourceKey;
    86         SourceLevel(String sourceKey) {
    87             this.sourceKey = sourceKey;
    88         }
    89     }
    91     enum TrustMe {
    92         DONT_TRUST(""),
    93         TRUST("@java.lang.SafeVarargs");
    95         String anno;
    97         TrustMe(String anno) {
    98             this.anno = anno;
    99         }
   100     }
   102     enum ModifierKind {
   103         NONE(" "),
   104         FINAL("final "),
   105         STATIC("static ");
   107         String mod;
   109         ModifierKind(String mod) {
   110             this.mod = mod;
   111         }
   112     }
   114     enum SuppressLevel {
   115         NONE(""),
   116         UNCHECKED("unchecked");
   118         String lint;
   120         SuppressLevel(String lint) {
   121             this.lint = lint;
   122         }
   124         String getSuppressAnno() {
   125             return "@SuppressWarnings(\"" + lint + "\")";
   126         }
   127     }
   129     enum Signature {
   130         UNBOUND("void #name(List<?>#arity arg) { #body }",
   131             new Warning[][] {none, none, none, none, error}),
   132         INVARIANT_TVAR("<Z> void #name(List<Z>#arity arg) { #body }",
   133             new Warning[][] {both, both, error, both, error}),
   134         TVAR("<Z> void #name(Z#arity arg) { #body }",
   135             new Warning[][] {both, both, both, both, vararg}),
   136         INVARIANT("void #name(List<String>#arity arg) { #body }",
   137             new Warning[][] {error, error, error, both, error}),
   138         UNPARAMETERIZED("void #name(String#arity arg) { #body }",
   139             new Warning[][] {error, error, error, error, none});
   141         String template;
   142         Warning[][] warnings;
   144         Signature(String template, Warning[][] warnings) {
   145             this.template = template;
   146             this.warnings = warnings;
   147         }
   149         boolean isApplicableTo(Signature other) {
   150             return warnings[other.ordinal()] != null;
   151         }
   153         boolean giveUnchecked(Signature other) {
   154             return warnings[other.ordinal()] == unchecked ||
   155                     warnings[other.ordinal()] == both;
   156         }
   158         boolean giveVarargs(Signature other) {
   159             return warnings[other.ordinal()] == vararg ||
   160                     warnings[other.ordinal()] == both;
   161         }
   162     }
   164     public static void main(String... args) throws Exception {
   165         for (SourceLevel sourceLevel : SourceLevel.values()) {
   166             for (TrustMe trustMe : TrustMe.values()) {
   167                 for (SuppressLevel suppressLevelClient : SuppressLevel.values()) {
   168                     for (SuppressLevel suppressLevelDecl : SuppressLevel.values()) {
   169                         for (ModifierKind modKind : ModifierKind.values()) {
   170                             for (Signature vararg_meth : Signature.values()) {
   171                                 for (Signature client_meth : Signature.values()) {
   172                                     if (vararg_meth.isApplicableTo(client_meth)) {
   173                                         test(sourceLevel,
   174                                                 trustMe,
   175                                                 suppressLevelClient,
   176                                                 suppressLevelDecl,
   177                                                 modKind,
   178                                                 vararg_meth,
   179                                                 client_meth);
   180                                     }
   181                                 }
   182                             }
   183                         }
   184                     }
   185                 }
   186             }
   187         }
   188     }
   190     static void test(SourceLevel sourceLevel, TrustMe trustMe, SuppressLevel suppressLevelClient,
   191             SuppressLevel suppressLevelDecl, ModifierKind modKind, Signature vararg_meth, Signature client_meth) throws Exception {
   192         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
   193         JavaSource source = new JavaSource(trustMe, suppressLevelClient, suppressLevelDecl, modKind, vararg_meth, client_meth);
   194         DiagnosticChecker dc = new DiagnosticChecker();
   195         JavacTask ct = (JavacTask)tool.getTask(null, null, dc,
   196                 Arrays.asList("-Xlint:unchecked", "-source", sourceLevel.sourceKey),
   197                 null, Arrays.asList(source));
   198         ct.generate(); //to get mandatory notes
   199         check(dc.warnings, sourceLevel,
   200                 new boolean[] {vararg_meth.giveUnchecked(client_meth),
   201                                vararg_meth.giveVarargs(client_meth)},
   202                 source, trustMe, suppressLevelClient, suppressLevelDecl, modKind);
   203     }
   205     static void check(Set<Warning> warnings, SourceLevel sourceLevel, boolean[] warnArr, JavaSource source,
   206             TrustMe trustMe, SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl, ModifierKind modKind) {
   207         boolean badOutput = false;
   208         for (Warning wkind : Warning.values()) {
   209             boolean isSuppressed = wkind.isSuppressed(trustMe, sourceLevel,
   210                     suppressLevelClient, suppressLevelDecl, modKind);
   211             System.out.println("SUPPRESSED = " + isSuppressed);
   212             badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) != warnings.contains(wkind);
   213         }
   214         if (badOutput) {
   215             throw new Error("invalid diagnostics for source:\n" +
   216                     source.getCharContent(true) +
   217                     "\nExpected unchecked warning: " + warnArr[0] +
   218                     "\nExpected unsafe vararg warning: " + warnArr[1] +
   219                     "\nWarnings: " + warnings +
   220                     "\nSource level: " + sourceLevel);
   221         }
   222     }
   224     static class JavaSource extends SimpleJavaFileObject {
   226         String source;
   228         public JavaSource(TrustMe trustMe, SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl,
   229                 ModifierKind modKind, Signature vararg_meth, Signature client_meth) {
   230             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   231             String meth1 = vararg_meth.template.replace("#arity", "...");
   232             meth1 = meth1.replace("#name", "m");
   233             meth1 = meth1.replace("#body", "");
   234             meth1 = trustMe.anno + "\n" + suppressLevelDecl.getSuppressAnno() + modKind.mod + meth1;
   235             String meth2 = client_meth.template.replace("#arity", "");
   236             meth2 = meth2.replace("#name", "test");
   237             meth2 = meth2.replace("#body", "m(arg);");
   238             meth2 = suppressLevelClient.getSuppressAnno() + meth2;
   239             source = "import java.util.List;\n" +
   240                      "class Test {\n" + meth1 +
   241                      "\n" + meth2 + "\n}\n";
   242         }
   244         @Override
   245         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   246             return source;
   247         }
   248     }
   250     static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
   252         Set<Warning> warnings = new HashSet<>();
   254         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   255             if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING ||
   256                     diagnostic.getKind() == Diagnostic.Kind.WARNING) {
   257                 if (diagnostic.getCode().contains(Warning.VARARGS.key)) {
   258                     warnings.add(Warning.VARARGS);
   259                 } else if(diagnostic.getCode().contains(Warning.UNCHECKED.key)) {
   260                     warnings.add(Warning.UNCHECKED);
   261                 }
   262             }
   263         }
   264     }
   265 }

mercurial