test/tools/javac/generics/diamond/7030150/GenericConstructorAndDiamondTest.java

changeset 0
959103a6100f
child 2525
2eb010b6cb22
equal deleted inserted replaced
-1:000000000000 0:959103a6100f
1 /*
2 * Copyright (c) 2011, 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 */
23
24 /*
25 * @test
26 * @bug 7030150 7039931
27 * @summary Type inference for generic instance creation failed for formal type parameter
28 */
29
30 import com.sun.source.util.JavacTask;
31 import java.net.URI;
32 import java.util.Arrays;
33 import javax.tools.Diagnostic;
34 import javax.tools.JavaCompiler;
35 import javax.tools.JavaFileObject;
36 import javax.tools.SimpleJavaFileObject;
37 import javax.tools.StandardJavaFileManager;
38 import javax.tools.ToolProvider;
39
40 public class GenericConstructorAndDiamondTest {
41
42 enum BoundKind {
43 NO_BOUND(""),
44 STRING_BOUND("extends String"),
45 INTEGER_BOUND("extends Integer");
46
47 String boundStr;
48
49 private BoundKind(String boundStr) {
50 this.boundStr = boundStr;
51 }
52
53 boolean matches(TypeArgumentKind tak) {
54 switch (tak) {
55 case NONE: return true;
56 case STRING: return this != INTEGER_BOUND;
57 case INTEGER: return this != STRING_BOUND;
58 default: return false;
59 }
60 }
61 }
62
63 enum ConstructorKind {
64 NON_GENERIC("Foo(Object o) {}"),
65 GENERIC_NO_BOUND("<T> Foo(T t) {}"),
66 GENERIC_STRING_BOUND("<T extends String> Foo(T t) {}"),
67 GENERIC_INTEGER_BOUND("<T extends Integer> Foo(T t) {}");
68
69 String constrStr;
70
71 private ConstructorKind(String constrStr) {
72 this.constrStr = constrStr;
73 }
74
75 boolean matches(ArgumentKind ak) {
76 switch (ak) {
77 case STRING: return this != GENERIC_INTEGER_BOUND;
78 case INTEGER: return this != GENERIC_STRING_BOUND;
79 default: return false;
80 }
81 }
82 }
83
84 enum TypeArgArity {
85 ONE(1),
86 TWO(2),
87 THREE(3);
88
89 int n;
90
91 private TypeArgArity(int n) {
92 this.n = n;
93 }
94 }
95
96 enum TypeArgumentKind {
97 NONE(""),
98 STRING("String"),
99 INTEGER("Integer");
100
101 String typeargStr;
102
103 private TypeArgumentKind(String typeargStr) {
104 this.typeargStr = typeargStr;
105 }
106
107 String getArgs(TypeArgArity arity) {
108 if (this == NONE) return "";
109 else {
110 StringBuilder buf = new StringBuilder();
111 String sep = "";
112 for (int i = 0 ; i < arity.n ; i++) {
113 buf.append(sep);
114 buf.append(typeargStr);
115 sep = ",";
116 }
117 return "<" + buf.toString() + ">";
118 }
119 }
120
121 boolean matches(ArgumentKind ak) {
122 switch (ak) {
123 case STRING: return this != INTEGER;
124 case INTEGER: return this != STRING;
125 default: return false;
126 }
127 }
128
129 boolean matches(TypeArgumentKind other) {
130 switch (other) {
131 case STRING: return this != INTEGER;
132 case INTEGER: return this != STRING;
133 default: return true;
134 }
135 }
136 }
137
138 enum ArgumentKind {
139 STRING("\"\""),
140 INTEGER("1");
141
142 String argStr;
143
144 private ArgumentKind(String argStr) {
145 this.argStr = argStr;
146 }
147 }
148
149 public static void main(String... args) throws Exception {
150
151 //create default shared JavaCompiler - reused across multiple compilations
152 JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
153 StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
154
155 for (BoundKind boundKind : BoundKind.values()) {
156 for (ConstructorKind constructorKind : ConstructorKind.values()) {
157 for (TypeArgumentKind declArgKind : TypeArgumentKind.values()) {
158 for (TypeArgArity arity : TypeArgArity.values()) {
159 for (TypeArgumentKind useArgKind : TypeArgumentKind.values()) {
160 for (TypeArgumentKind diamondArgKind : TypeArgumentKind.values()) {
161 for (ArgumentKind argKind : ArgumentKind.values()) {
162 new GenericConstructorAndDiamondTest(boundKind, constructorKind,
163 declArgKind, arity, useArgKind, diamondArgKind, argKind).run(comp, fm);
164 }
165 }
166 }
167 }
168 }
169 }
170 }
171 }
172
173 BoundKind boundKind;
174 ConstructorKind constructorKind;
175 TypeArgumentKind declTypeArgumentKind;
176 TypeArgArity useTypeArgArity;
177 TypeArgumentKind useTypeArgumentKind;
178 TypeArgumentKind diamondTypeArgumentKind;
179 ArgumentKind argumentKind;
180 JavaSource source;
181 DiagnosticChecker diagChecker;
182
183 GenericConstructorAndDiamondTest(BoundKind boundKind, ConstructorKind constructorKind,
184 TypeArgumentKind declTypeArgumentKind, TypeArgArity useTypeArgArity,
185 TypeArgumentKind useTypeArgumentKind, TypeArgumentKind diamondTypeArgumentKind,
186 ArgumentKind argumentKind) {
187 this.boundKind = boundKind;
188 this.constructorKind = constructorKind;
189 this.declTypeArgumentKind = declTypeArgumentKind;
190 this.useTypeArgArity = useTypeArgArity;
191 this.useTypeArgumentKind = useTypeArgumentKind;
192 this.diamondTypeArgumentKind = diamondTypeArgumentKind;
193 this.argumentKind = argumentKind;
194 this.source = new JavaSource();
195 this.diagChecker = new DiagnosticChecker();
196 }
197
198 class JavaSource extends SimpleJavaFileObject {
199
200 String template = "class Foo<X #BK> {\n" +
201 "#CK\n" +
202 "}\n" +
203 "class Test {\n" +
204 "void test() {\n" +
205 "Foo#TA1 f = new #TA2 Foo<#TA3>(#A);\n" +
206 "}\n" +
207 "}\n";
208
209 String source;
210
211 public JavaSource() {
212 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
213 source = template.replace("#BK", boundKind.boundStr).
214 replace("#CK", constructorKind.constrStr)
215 .replace("#TA1", declTypeArgumentKind.getArgs(TypeArgArity.ONE))
216 .replace("#TA2", useTypeArgumentKind.getArgs(useTypeArgArity))
217 .replace("#TA3", diamondTypeArgumentKind.typeargStr)
218 .replace("#A", argumentKind.argStr);
219 }
220
221 @Override
222 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
223 return source;
224 }
225 }
226
227 void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
228 JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
229 null, null, Arrays.asList(source));
230 ct.analyze();
231 check();
232 }
233
234 void check() {
235 boolean badActual = !constructorKind.matches(argumentKind);
236
237 boolean badArity = constructorKind != ConstructorKind.NON_GENERIC &&
238 useTypeArgumentKind != TypeArgumentKind.NONE &&
239 useTypeArgArity != TypeArgArity.ONE;
240
241 boolean badMethodTypeArg = constructorKind != ConstructorKind.NON_GENERIC &&
242 !useTypeArgumentKind.matches(argumentKind);
243
244 boolean badExplicitParams = (useTypeArgumentKind != TypeArgumentKind.NONE &&
245 diamondTypeArgumentKind == TypeArgumentKind.NONE) ||
246 !boundKind.matches(diamondTypeArgumentKind);
247
248 boolean badGenericType = !boundKind.matches(declTypeArgumentKind) ||
249 !diamondTypeArgumentKind.matches(declTypeArgumentKind);
250
251 boolean shouldFail = badActual || badArity ||
252 badMethodTypeArg || badExplicitParams || badGenericType;
253
254 if (shouldFail != diagChecker.errorFound) {
255 throw new Error("invalid diagnostics for source:\n" +
256 source.getCharContent(true) +
257 "\nFound error: " + diagChecker.errorFound +
258 "\nExpected error: " + shouldFail);
259 }
260 }
261
262 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
263
264 boolean errorFound;
265
266 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
267 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
268 errorFound = true;
269 }
270 }
271 }
272 }

mercurial