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

Fri, 10 Dec 2010 15:24:17 +0000

author
mcimadamore
date
Fri, 10 Dec 2010 15:24:17 +0000
changeset 787
b1c98bfd4709
parent 581
f2fdd52e4e87
child 795
7b99f98b3035
permissions
-rw-r--r--

6199075: Unambiguous varargs method calls flagged as ambiguous
Summary: javac does not implement overload resolution w.r.t. varargs methods as described in the JLS
Reviewed-by: jjg

     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
    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("unchecked"),
    52         VARARGS("varargs");
    54         String category;
    56         Warning(String category) {
    57             this.category = category;
    58         }
    60         boolean isEnabled(XlintOption xlint, SuppressLevel suppressLevel) {
    61             return Arrays.asList(xlint.enabledWarnings).contains(this);
    62         }
    64         boolean isSuppressed(SuppressLevel suppressLevel) {
    65             return Arrays.asList(suppressLevel.suppressedWarnings).contains(VARARGS);
    66         }
    67     }
    69     enum XlintOption {
    70         NONE(),
    71         UNCHECKED(Warning.UNCHECKED),
    72         VARARGS(Warning.VARARGS),
    73         ALL(Warning.UNCHECKED, Warning.VARARGS);
    75         Warning[] enabledWarnings;
    77         XlintOption(Warning... enabledWarnings) {
    78             this.enabledWarnings = enabledWarnings;
    79         }
    81         String getXlintOption() {
    82             StringBuilder buf = new StringBuilder();
    83             String sep = "";
    84             for (Warning w : enabledWarnings) {
    85                 buf.append(sep);
    86                 buf.append(w.category);
    87                 sep=",";
    88             }
    89             return "-Xlint:" +
    90                     (this == NONE ? "none" : buf.toString());
    91         }
    92     }
    94     enum SuppressLevel {
    95         NONE(),
    96         UNCHECKED(Warning.UNCHECKED),
    97         VARARGS(Warning.VARARGS),
    98         ALL(Warning.UNCHECKED, Warning.VARARGS);
   100         Warning[] suppressedWarnings;
   102         SuppressLevel(Warning... suppressedWarnings) {
   103             this.suppressedWarnings = suppressedWarnings;
   104         }
   106         String getSuppressAnnotation() {
   107             StringBuilder buf = new StringBuilder();
   108             String sep = "";
   109             for (Warning w : suppressedWarnings) {
   110                 buf.append(sep);
   111                 buf.append("\"");
   112                 buf.append(w.category);
   113                 buf.append("\"");
   114                 sep=",";
   115             }
   116             return this == NONE ? "" :
   117                 "@SuppressWarnings({" + buf.toString() + "})";
   118         }
   119     }
   121     enum Signature {
   123         EXTENDS_TVAR("<Z> void #name(List<? extends Z>#arity arg) { #body }",
   124             new Warning[][] {both, both, both, both, error, both, both, both, error}),
   125         SUPER_TVAR("<Z> void #name(List<? super Z>#arity arg) { #body }",
   126             new Warning[][] {error, both, error, both, error, error, both, both, error}),
   127         UNBOUND("void #name(List<?>#arity arg) { #body }",
   128             new Warning[][] {none, none, none, none, none, none, none, none, error}),
   129         INVARIANT_TVAR("<Z> void #name(List<Z>#arity arg) { #body }",
   130             new Warning[][] {both, both, both, both, error, both, both, both, error}),
   131         TVAR("<Z> void #name(Z#arity arg) { #body }",
   132             new Warning[][] {both, both, both, both, both, both, both, both, vararg}),
   133         EXTENDS("void #name(List<? extends String>#arity arg) { #body }",
   134             new Warning[][] {error, error, error, error, error, both, error, both, error}),
   135         SUPER("void #name(List<? super String>#arity arg) { #body }",
   136             new Warning[][] {error, error, error, error, error, error, both, both, error}),
   137         INVARIANT("void #name(List<String>#arity arg) { #body }",
   138             new Warning[][] {error, error, error, error, error, error, error, both, error}),
   139         UNPARAMETERIZED("void #name(String#arity arg) { #body }",
   140             new Warning[][] {error, error, error, error, error, error, error, error, none});
   142         String template;
   143         Warning[][] warnings;
   145         Signature(String template, Warning[][] warnings) {
   146             this.template = template;
   147             this.warnings = warnings;
   148         }
   150         boolean isApplicableTo(Signature other) {
   151             return warnings[other.ordinal()] != null;
   152         }
   154         boolean giveUnchecked(Signature other) {
   155             return warnings[other.ordinal()] == unchecked ||
   156                     warnings[other.ordinal()] == both;
   157         }
   159         boolean giveVarargs(Signature other) {
   160             return warnings[other.ordinal()] == vararg ||
   161                     warnings[other.ordinal()] == both;
   162         }
   163     }
   165     public static void main(String... args) throws Exception {
   166         for (XlintOption xlint : XlintOption.values()) {
   167             for (SuppressLevel suppressLevel : SuppressLevel.values()) {
   168                 for (Signature vararg_meth : Signature.values()) {
   169                     for (Signature client_meth : Signature.values()) {
   170                         if (vararg_meth.isApplicableTo(client_meth)) {
   171                             test(xlint,
   172                                     suppressLevel,
   173                                     vararg_meth,
   174                                     client_meth);
   175                         }
   176                     }
   177                 }
   178             }
   179         }
   180     }
   182     static void test(XlintOption xlint, SuppressLevel suppressLevel,
   183             Signature vararg_meth, Signature client_meth) throws Exception {
   184         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
   185         JavaSource source = new JavaSource(suppressLevel, vararg_meth, client_meth);
   186         DiagnosticChecker dc = new DiagnosticChecker();
   187         JavacTask ct = (JavacTask)tool.getTask(null, null, dc,
   188                 Arrays.asList(xlint.getXlintOption()), null, Arrays.asList(source));
   189         ct.generate(); //to get mandatory notes
   190         check(dc.warnings,
   191                 dc.notes,
   192                 new boolean[] {vararg_meth.giveUnchecked(client_meth),
   193                                vararg_meth.giveVarargs(client_meth)},
   194                 source, xlint, suppressLevel);
   195     }
   197     static void check(Set<Warning> warnings, Set<Warning> notes, boolean[] warnArr, JavaSource source, XlintOption xlint, SuppressLevel suppressLevel) {
   198         boolean badOutput = false;
   199         for (Warning wkind : Warning.values()) {
   200             badOutput |= (warnArr[wkind.ordinal()] && !wkind.isSuppressed(suppressLevel)) !=
   201                     (wkind.isEnabled(xlint, suppressLevel) ?
   202                         warnings.contains(wkind) :
   203                         notes.contains(wkind));
   204         }
   205         if (badOutput) {
   206             throw new Error("invalid diagnostics for source:\n" +
   207                     source.getCharContent(true) +
   208                     "\nOptions: " + xlint.getXlintOption() +
   209                     "\nExpected unchecked warning: " + warnArr[0] +
   210                     "\nExpected unsafe vararg warning: " + warnArr[1] +
   211                     "\nWarnings: " + warnings +
   212                     "\nNotes: " + notes);
   213         }
   214     }
   216     static class JavaSource extends SimpleJavaFileObject {
   218         String source;
   220         public JavaSource(SuppressLevel suppressLevel, Signature vararg_meth, Signature client_meth) {
   221             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   222             String meth1 = vararg_meth.template.replace("#arity", "...");
   223             meth1 = meth1.replace("#name", "m");
   224             meth1 = meth1.replace("#body", "");
   225             meth1 = suppressLevel.getSuppressAnnotation() + meth1;
   226             String meth2 = client_meth.template.replace("#arity", "");
   227             meth2 = meth2.replace("#name", "test");
   228             meth2 = meth2.replace("#body", "m(arg);");
   229             source = "import java.util.List;\n" +
   230                "class Test {\n" + meth1 +
   231                "\n" + meth2 + "\n}\n";
   232         }
   234         @Override
   235         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   236             return source;
   237         }
   238     }
   240     static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
   242         Set<Warning> warnings = new HashSet<>();
   243         Set<Warning> notes = new HashSet<>();
   245         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   246             if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING ||
   247                     diagnostic.getKind() == Diagnostic.Kind.WARNING) {
   248                 warnings.add(diagnostic.getCode().contains("varargs") ?
   249                     Warning.VARARGS :
   250                     Warning.UNCHECKED);
   251             }
   252             else if (diagnostic.getKind() == Diagnostic.Kind.NOTE) {
   253                 notes.add(diagnostic.getCode().contains("varargs") ?
   254                     Warning.VARARGS :
   255                     Warning.UNCHECKED);
   256             }
   257         }
   258     }
   259 }

mercurial