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