mcimadamore@950: /* mcimadamore@950: * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. mcimadamore@950: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. mcimadamore@950: * mcimadamore@950: * This code is free software; you can redistribute it and/or modify it mcimadamore@950: * under the terms of the GNU General Public License version 2 only, as mcimadamore@950: * published by the Free Software Foundation. mcimadamore@950: * mcimadamore@950: * This code is distributed in the hope that it will be useful, but WITHOUT mcimadamore@950: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or mcimadamore@950: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License mcimadamore@950: * version 2 for more details (a copy is included in the LICENSE file that mcimadamore@950: * accompanied this code). mcimadamore@950: * mcimadamore@950: * You should have received a copy of the GNU General Public License version mcimadamore@950: * 2 along with this work; if not, write to the Free Software Foundation, mcimadamore@950: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. mcimadamore@950: * mcimadamore@950: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA mcimadamore@950: * or visit www.oracle.com if you need additional information or have any mcimadamore@950: * questions. mcimadamore@950: */ mcimadamore@950: mcimadamore@950: /* mcimadamore@950: * @test mcimadamore@950: * @bug 7030150 mcimadamore@950: * @summary Type inference for generic instance creation failed for formal type parameter mcimadamore@950: */ mcimadamore@950: mcimadamore@950: import com.sun.source.util.JavacTask; mcimadamore@950: import java.net.URI; mcimadamore@950: import java.util.Arrays; mcimadamore@950: import javax.tools.Diagnostic; mcimadamore@950: import javax.tools.JavaCompiler; mcimadamore@950: import javax.tools.JavaFileObject; mcimadamore@950: import javax.tools.SimpleJavaFileObject; mcimadamore@950: import javax.tools.StandardJavaFileManager; mcimadamore@950: import javax.tools.ToolProvider; mcimadamore@950: mcimadamore@950: public class GenericConstructorAndDiamondTest { mcimadamore@950: mcimadamore@950: enum BoundKind { mcimadamore@950: NO_BOUND(""), mcimadamore@950: STRING_BOUND("extends String"), mcimadamore@950: INTEGER_BOUND("extends Integer"); mcimadamore@950: mcimadamore@950: String boundStr; mcimadamore@950: mcimadamore@950: private BoundKind(String boundStr) { mcimadamore@950: this.boundStr = boundStr; mcimadamore@950: } mcimadamore@950: mcimadamore@950: boolean matches(TypeArgumentKind tak) { mcimadamore@950: switch (tak) { mcimadamore@950: case NONE: return true; mcimadamore@950: case STRING: return this != INTEGER_BOUND; mcimadamore@950: case INTEGER: return this != STRING_BOUND; mcimadamore@950: default: return false; mcimadamore@950: } mcimadamore@950: } mcimadamore@950: } mcimadamore@950: mcimadamore@950: enum ConstructorKind { mcimadamore@950: NON_GENERIC("Foo(Object o) {}"), mcimadamore@950: GENERIC_NO_BOUND(" Foo(T t) {}"), mcimadamore@950: GENERIC_STRING_BOUND(" Foo(T t) {}"), mcimadamore@950: GENERIC_INTEGER_BOUND(" Foo(T t) {}"); mcimadamore@950: mcimadamore@950: String constrStr; mcimadamore@950: mcimadamore@950: private ConstructorKind(String constrStr) { mcimadamore@950: this.constrStr = constrStr; mcimadamore@950: } mcimadamore@950: mcimadamore@950: boolean matches(ArgumentKind ak) { mcimadamore@950: switch (ak) { mcimadamore@950: case STRING: return this != GENERIC_INTEGER_BOUND; mcimadamore@950: case INTEGER: return this != GENERIC_STRING_BOUND; mcimadamore@950: default: return false; mcimadamore@950: } mcimadamore@950: } mcimadamore@950: } mcimadamore@950: mcimadamore@950: enum TypeArgArity { mcimadamore@950: ONE(1), mcimadamore@950: TWO(2), mcimadamore@950: THREE(3); mcimadamore@950: mcimadamore@950: int n; mcimadamore@950: mcimadamore@950: private TypeArgArity(int n) { mcimadamore@950: this.n = n; mcimadamore@950: } mcimadamore@950: } mcimadamore@950: mcimadamore@950: enum TypeArgumentKind { mcimadamore@950: NONE(""), mcimadamore@950: STRING("String"), mcimadamore@950: INTEGER("Integer"); mcimadamore@950: mcimadamore@950: String typeargStr; mcimadamore@950: mcimadamore@950: private TypeArgumentKind(String typeargStr) { mcimadamore@950: this.typeargStr = typeargStr; mcimadamore@950: } mcimadamore@950: mcimadamore@950: String getArgs(TypeArgArity arity) { mcimadamore@950: if (this == NONE) return ""; mcimadamore@950: else { mcimadamore@950: StringBuilder buf = new StringBuilder(); mcimadamore@950: String sep = ""; mcimadamore@950: for (int i = 0 ; i < arity.n ; i++) { mcimadamore@950: buf.append(sep); mcimadamore@950: buf.append(typeargStr); mcimadamore@950: sep = ","; mcimadamore@950: } mcimadamore@950: return "<" + buf.toString() + ">"; mcimadamore@950: } mcimadamore@950: } mcimadamore@950: mcimadamore@950: boolean matches(ArgumentKind ak) { mcimadamore@950: switch (ak) { mcimadamore@950: case STRING: return this != INTEGER; mcimadamore@950: case INTEGER: return this != STRING; mcimadamore@950: default: return false; mcimadamore@950: } mcimadamore@950: } mcimadamore@950: } mcimadamore@950: mcimadamore@950: enum ArgumentKind { mcimadamore@950: STRING("\"\""), mcimadamore@950: INTEGER("1"); mcimadamore@950: mcimadamore@950: String argStr; mcimadamore@950: mcimadamore@950: private ArgumentKind(String argStr) { mcimadamore@950: this.argStr = argStr; mcimadamore@950: } mcimadamore@950: } mcimadamore@950: mcimadamore@950: public static void main(String... args) throws Exception { mcimadamore@950: mcimadamore@950: //create default shared JavaCompiler - reused across multiple compilations mcimadamore@950: JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); mcimadamore@950: StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); mcimadamore@950: mcimadamore@950: for (BoundKind boundKind : BoundKind.values()) { mcimadamore@950: for (ConstructorKind constructorKind : ConstructorKind.values()) { mcimadamore@950: for (TypeArgumentKind declArgKind : TypeArgumentKind.values()) { mcimadamore@950: for (TypeArgArity arity : TypeArgArity.values()) { mcimadamore@950: for (TypeArgumentKind useArgKind : TypeArgumentKind.values()) { mcimadamore@950: for (ArgumentKind argKind : ArgumentKind.values()) { mcimadamore@950: new GenericConstructorAndDiamondTest(boundKind, constructorKind, mcimadamore@950: declArgKind, arity, useArgKind, argKind).run(comp, fm); mcimadamore@950: } mcimadamore@950: } mcimadamore@950: } mcimadamore@950: } mcimadamore@950: } mcimadamore@950: } mcimadamore@950: } mcimadamore@950: mcimadamore@950: BoundKind boundKind; mcimadamore@950: ConstructorKind constructorKind; mcimadamore@950: TypeArgumentKind declTypeArgumentKind; mcimadamore@950: TypeArgArity useTypeArgArity; mcimadamore@950: TypeArgumentKind useTypeArgumentKind; mcimadamore@950: ArgumentKind argumentKind; mcimadamore@950: JavaSource source; mcimadamore@950: DiagnosticChecker diagChecker; mcimadamore@950: mcimadamore@950: GenericConstructorAndDiamondTest(BoundKind boundKind, ConstructorKind constructorKind, mcimadamore@950: TypeArgumentKind declTypeArgumentKind, TypeArgArity useTypeArgArity, mcimadamore@950: TypeArgumentKind useTypeArgumentKind, ArgumentKind argumentKind) { mcimadamore@950: this.boundKind = boundKind; mcimadamore@950: this.constructorKind = constructorKind; mcimadamore@950: this.declTypeArgumentKind = declTypeArgumentKind; mcimadamore@950: this.useTypeArgArity = useTypeArgArity; mcimadamore@950: this.useTypeArgumentKind = useTypeArgumentKind; mcimadamore@950: this.argumentKind = argumentKind; mcimadamore@950: this.source = new JavaSource(); mcimadamore@950: this.diagChecker = new DiagnosticChecker(); mcimadamore@950: } mcimadamore@950: mcimadamore@950: class JavaSource extends SimpleJavaFileObject { mcimadamore@950: mcimadamore@950: String template = "class Foo {\n" + mcimadamore@950: "#CK\n" + mcimadamore@950: "}\n" + mcimadamore@950: "class Test {\n" + mcimadamore@950: "void test() {\n" + mcimadamore@950: "Foo#TA1 f = new #TA2 Foo<>(#A);\n" + mcimadamore@950: "}\n" + mcimadamore@950: "}\n"; mcimadamore@950: mcimadamore@950: String source; mcimadamore@950: mcimadamore@950: public JavaSource() { mcimadamore@950: super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); mcimadamore@950: source = template.replace("#BK", boundKind.boundStr). mcimadamore@950: replace("#CK", constructorKind.constrStr) mcimadamore@950: .replace("#TA1", declTypeArgumentKind.getArgs(TypeArgArity.ONE)) mcimadamore@950: .replace("#TA2", useTypeArgumentKind.getArgs(useTypeArgArity)) mcimadamore@950: .replace("#A", argumentKind.argStr); mcimadamore@950: } mcimadamore@950: mcimadamore@950: @Override mcimadamore@950: public CharSequence getCharContent(boolean ignoreEncodingErrors) { mcimadamore@950: return source; mcimadamore@950: } mcimadamore@950: } mcimadamore@950: mcimadamore@950: void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { mcimadamore@950: JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, mcimadamore@950: null, null, Arrays.asList(source)); mcimadamore@950: ct.analyze(); mcimadamore@950: check(); mcimadamore@950: } mcimadamore@950: mcimadamore@950: void check() { mcimadamore@950: boolean badActual = !constructorKind.matches(argumentKind); mcimadamore@950: mcimadamore@950: boolean badArity = constructorKind != ConstructorKind.NON_GENERIC && mcimadamore@950: useTypeArgumentKind != TypeArgumentKind.NONE && mcimadamore@950: useTypeArgArity != TypeArgArity.ONE; mcimadamore@950: mcimadamore@950: boolean badMethodTypeArg = constructorKind != ConstructorKind.NON_GENERIC && mcimadamore@950: !useTypeArgumentKind.matches(argumentKind); mcimadamore@950: mcimadamore@950: boolean badGenericType = !boundKind.matches(declTypeArgumentKind); mcimadamore@950: mcimadamore@950: boolean shouldFail = badActual || badArity || badMethodTypeArg || badGenericType; mcimadamore@950: mcimadamore@950: if (shouldFail != diagChecker.errorFound) { mcimadamore@950: throw new Error("invalid diagnostics for source:\n" + mcimadamore@950: source.getCharContent(true) + mcimadamore@950: "\nFound error: " + diagChecker.errorFound + mcimadamore@950: "\nExpected error: " + shouldFail); mcimadamore@950: } mcimadamore@950: } mcimadamore@950: mcimadamore@950: static class DiagnosticChecker implements javax.tools.DiagnosticListener { mcimadamore@950: mcimadamore@950: boolean errorFound; mcimadamore@950: mcimadamore@950: public void report(Diagnostic diagnostic) { mcimadamore@950: if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { mcimadamore@950: errorFound = true; mcimadamore@950: } mcimadamore@950: } mcimadamore@950: } mcimadamore@950: }