1105N/A/*
1105N/A * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
1105N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1105N/A *
1105N/A * This code is free software; you can redistribute it and/or modify it
1105N/A * under the terms of the GNU General Public License version 2 only, as
1105N/A * published by the Free Software Foundation.
1105N/A *
1105N/A * This code is distributed in the hope that it will be useful, but WITHOUT
1105N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1105N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1105N/A * version 2 for more details (a copy is included in the LICENSE file that
1105N/A * accompanied this code).
1105N/A *
1105N/A * You should have received a copy of the GNU General Public License version
1105N/A * 2 along with this work; if not, write to the Free Software Foundation,
1105N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1105N/A *
1105N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1105N/A * or visit www.oracle.com if you need additional information or have any
1105N/A * questions.
1105N/A */
1105N/A
1105N/A/*
1105N/A * @test
1105N/A * @bug 7086601
1105N/A * @summary Error message bug: cause for method mismatch is 'null'
1105N/A */
1105N/A
1105N/Aimport com.sun.source.util.JavacTask;
1105N/Aimport java.net.URI;
1105N/Aimport java.util.Arrays;
1105N/Aimport java.util.ArrayList;
1105N/Aimport javax.tools.Diagnostic;
1105N/Aimport javax.tools.JavaCompiler;
1105N/Aimport javax.tools.JavaFileObject;
1105N/Aimport javax.tools.SimpleJavaFileObject;
1105N/Aimport javax.tools.StandardJavaFileManager;
1105N/Aimport javax.tools.ToolProvider;
1105N/A
1105N/A
1105N/Apublic class T7086601b {
1105N/A
1105N/A static int checkCount = 0;
1105N/A
1105N/A enum TypeKind {
1105N/A STRING("String", false),
1105N/A INTEGER("Integer", false),
1105N/A NUMBER("Number", false),
1105N/A SERIALIZABLE("java.io.Serializable", true),
1105N/A CLONEABLE("Cloneable", true),
1105N/A X("X", false),
1105N/A Y("Y", false),
1105N/A Z("Z", false);
1105N/A
1105N/A String typeStr;
1105N/A boolean isInterface;
1105N/A
1105N/A private TypeKind(String typeStr, boolean isInterface) {
1105N/A this.typeStr = typeStr;
1105N/A this.isInterface = isInterface;
1105N/A }
1105N/A
1105N/A boolean isSubtypeof(TypeKind other) {
1105N/A return (this == INTEGER && other == NUMBER ||
1105N/A this == Z && other == Y ||
1105N/A this == other);
1105N/A }
1105N/A }
1105N/A
1105N/A enum MethodCallKind {
1105N/A ARITY_ONE("m(a1);", 1),
1105N/A ARITY_TWO("m(a1, a2);", 2),
1105N/A ARITY_THREE("m(a1, a2, a3);", 3);
1105N/A
1105N/A String invokeString;
1105N/A int arity;
1105N/A
1105N/A private MethodCallKind(String invokeString, int arity) {
1105N/A this.invokeString = invokeString;
1105N/A this.arity = arity;
1105N/A }
1105N/A }
1105N/A
1105N/A public static void main(String... args) throws Exception {
1105N/A
1105N/A //create default shared JavaCompiler - reused across multiple compilations
1105N/A JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
1105N/A StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
1105N/A
1105N/A for (TypeKind a1 : TypeKind.values()) {
1105N/A for (TypeKind a2 : TypeKind.values()) {
1105N/A for (TypeKind a3 : TypeKind.values()) {
1105N/A for (MethodCallKind mck : MethodCallKind.values()) {
1105N/A new T7086601b(a1, a2, a3, mck).run(comp, fm);
1105N/A }
1105N/A }
1105N/A }
1105N/A }
1105N/A System.out.println("Total check executed: " + checkCount);
1105N/A }
1105N/A
1105N/A TypeKind a1;
1105N/A TypeKind a2;
1105N/A TypeKind a3;
1105N/A MethodCallKind mck;
1105N/A JavaSource source;
1105N/A DiagnosticChecker diagChecker;
1105N/A
1105N/A T7086601b(TypeKind a1, TypeKind a2, TypeKind a3, MethodCallKind mck) {
1105N/A this.a1 = a1;
1105N/A this.a2 = a2;
1105N/A this.a3 = a3;
1105N/A this.mck = mck;
1105N/A this.source = new JavaSource();
1105N/A this.diagChecker = new DiagnosticChecker();
1105N/A }
1105N/A
1105N/A class JavaSource extends SimpleJavaFileObject {
1105N/A
1105N/A final String bodyTemplate = "import java.util.List;\n"+
1105N/A "class Test {\n" +
1105N/A " <Z> void m(List<? super Z> l1) { }\n" +
1105N/A " <Z> void m(List<? super Z> l1, List<? super Z> l2) { }\n" +
1105N/A " <Z> void m(List<? super Z> l1, List<? super Z> l2, List<? super Z> l3) { }\n" +
1105N/A " <X,Y,Z extends Y> void test(List<#A1> a1, List<#A2> a2, List<#A3> a3) { #MC } }";
1105N/A
1105N/A String source;
1105N/A
1105N/A public JavaSource() {
1105N/A super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
1105N/A source = bodyTemplate.replace("#A1", a1.typeStr)
1105N/A .replace("#A2", a2.typeStr).replace("#A3", a3.typeStr)
1105N/A .replace("#MC", mck.invokeString);
1105N/A }
1105N/A
1105N/A @Override
1105N/A public CharSequence getCharContent(boolean ignoreEncodingErrors) {
1105N/A return source;
1105N/A }
1105N/A }
1105N/A
1105N/A void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
1105N/A JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
1105N/A null, null, Arrays.asList(source));
1105N/A try {
1105N/A ct.analyze();
1105N/A } catch (Throwable ex) {
1105N/A throw new AssertionError("Error thron when compiling the following code:\n" + source.getCharContent(true));
1105N/A }
1105N/A check();
1105N/A }
1105N/A
1105N/A void check() {
1105N/A checkCount++;
1105N/A
1105N/A boolean errorExpected = false;
1105N/A
1105N/A if (mck.arity > 1) {
1105N/A TypeKind[] argtypes = { a1, a2, a3 };
1105N/A ArrayList<TypeKind> classes = new ArrayList<>();
1105N/A for (int i = 0 ; i < mck.arity ; i ++ ) {
1105N/A if (!argtypes[i].isInterface) {
1105N/A classes.add(argtypes[i]);
1105N/A }
1105N/A }
1105N/A boolean glb_exists = true;
1105N/A for (TypeKind arg_i : classes) {
1105N/A glb_exists = true;
1105N/A for (TypeKind arg_j : classes) {
1105N/A if (!arg_i.isSubtypeof(arg_j)) {
1105N/A glb_exists = false;
1105N/A break;
1105N/A }
1105N/A }
1105N/A if (glb_exists) break;
1105N/A }
1105N/A errorExpected = !glb_exists;
1105N/A }
1105N/A
1105N/A if (errorExpected != diagChecker.errorFound) {
1105N/A throw new Error("invalid diagnostics for source:\n" +
1105N/A source.getCharContent(true) +
1105N/A "\nFound error: " + diagChecker.errorFound +
1105N/A "\nExpected error: " + errorExpected);
1105N/A }
1105N/A }
1105N/A
1105N/A static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
1105N/A
1105N/A boolean errorFound;
1105N/A
1105N/A public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
1105N/A if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
1105N/A errorFound = true;
1105N/A }
1105N/A }
1105N/A }
1105N/A}