test/tools/javac/cast/intersection/IntersectionTypeCastTest.java

changeset 1482
954541f13717
parent 1436
f6f1fd261f57
child 1511
c7c41a044e7c
equal deleted inserted replaced
1481:d07340b61e6a 1482:954541f13717
1 /* 1 /*
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
23 23
24 /* 24 /*
25 * @test 25 * @test
26 * @bug 8002099 26 * @bug 8002099
27 * @summary Add support for intersection types in cast expression 27 * @summary Add support for intersection types in cast expression
28 * @library ../../lib
29 * @build JavacTestingAbstractThreadedTest
30 * @run main/timeout=360 IntersectionTypeCastTest
28 */ 31 */
29 32
30 import com.sun.source.util.JavacTask;
31 import com.sun.tools.javac.util.List;
32 import com.sun.tools.javac.util.ListBuffer;
33 import java.net.URI; 33 import java.net.URI;
34 import java.util.Arrays; 34 import java.util.Arrays;
35 import javax.tools.Diagnostic; 35 import javax.tools.Diagnostic;
36 import javax.tools.JavaCompiler; 36 import javax.tools.JavaCompiler;
37 import javax.tools.JavaFileObject; 37 import javax.tools.JavaFileObject;
38 import javax.tools.SimpleJavaFileObject; 38 import javax.tools.SimpleJavaFileObject;
39 import javax.tools.StandardJavaFileManager;
40 import javax.tools.ToolProvider; 39 import javax.tools.ToolProvider;
41 40
42 public class IntersectionTypeCastTest { 41 import com.sun.source.util.JavacTask;
43 42 import com.sun.tools.javac.util.List;
44 static int checkCount = 0; 43 import com.sun.tools.javac.util.ListBuffer;
44
45 public class IntersectionTypeCastTest
46 extends JavacTestingAbstractThreadedTest
47 implements Runnable {
45 48
46 interface Type { 49 interface Type {
47 boolean subtypeOf(Type that); 50 boolean subtypeOf(Type that);
48 String asString(); 51 String asString();
49 boolean isClass(); 52 boolean isClass();
57 60
58 String declStr; 61 String declStr;
59 String typeStr; 62 String typeStr;
60 InterfaceKind superInterface; 63 InterfaceKind superInterface;
61 64
62 InterfaceKind(String declStr, String typeStr, InterfaceKind superInterface) { 65 InterfaceKind(String declStr, String typeStr,
66 InterfaceKind superInterface) {
63 this.declStr = declStr; 67 this.declStr = declStr;
64 this.typeStr = typeStr; 68 this.typeStr = typeStr;
65 this.superInterface = superInterface; 69 this.superInterface = superInterface;
66 } 70 }
67 71
68 @Override 72 @Override
69 public boolean subtypeOf(Type that) { 73 public boolean subtypeOf(Type that) {
70 return this == that || superInterface == that || that == ClassKind.OBJECT; 74 return this == that || superInterface == that ||
75 that == ClassKind.OBJECT;
71 } 76 }
72 77
73 @Override 78 @Override
74 public String asString() { 79 public String asString() {
75 return typeStr; 80 return typeStr;
86 } 91 }
87 } 92 }
88 93
89 enum ClassKind implements Type { 94 enum ClassKind implements Type {
90 OBJECT(null, "Object"), 95 OBJECT(null, "Object"),
91 CA("#M class CA implements A { }\n", "CA", InterfaceKind.A), 96 CA("#M class CA implements A { }\n", "CA",
92 CB("#M class CB implements B { }\n", "CB", InterfaceKind.B), 97 InterfaceKind.A),
93 CAB("#M class CAB implements A, B { }\n", "CAB", InterfaceKind.A, InterfaceKind.B), 98 CB("#M class CB implements B { }\n", "CB",
94 CC("#M class CC implements C { }\n", "CC", InterfaceKind.C, InterfaceKind.A), 99 InterfaceKind.B),
95 CCA("#M class CCA implements C, A { }\n", "CCA", InterfaceKind.C, InterfaceKind.A), 100 CAB("#M class CAB implements A, B { }\n", "CAB",
96 CCB("#M class CCB implements C, B { }\n", "CCB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B), 101 InterfaceKind.A, InterfaceKind.B),
97 CCAB("#M class CCAB implements C, A, B { }\n", "CCAB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B); 102 CC("#M class CC implements C { }\n", "CC",
103 InterfaceKind.C, InterfaceKind.A),
104 CCA("#M class CCA implements C, A { }\n", "CCA",
105 InterfaceKind.C, InterfaceKind.A),
106 CCB("#M class CCB implements C, B { }\n", "CCB",
107 InterfaceKind.C, InterfaceKind.A, InterfaceKind.B),
108 CCAB("#M class CCAB implements C, A, B { }\n", "CCAB",
109 InterfaceKind.C, InterfaceKind.A, InterfaceKind.B);
98 110
99 String declTemplate; 111 String declTemplate;
100 String typeStr; 112 String typeStr;
101 List<InterfaceKind> superInterfaces; 113 List<InterfaceKind> superInterfaces;
102 114
103 ClassKind(String declTemplate, String typeStr, InterfaceKind... superInterfaces) { 115 ClassKind(String declTemplate, String typeStr,
116 InterfaceKind... superInterfaces) {
104 this.declTemplate = declTemplate; 117 this.declTemplate = declTemplate;
105 this.typeStr = typeStr; 118 this.typeStr = typeStr;
106 this.superInterfaces = List.from(superInterfaces); 119 this.superInterfaces = List.from(superInterfaces);
107 } 120 }
108 121
112 ""; 125 "";
113 } 126 }
114 127
115 @Override 128 @Override
116 public boolean subtypeOf(Type that) { 129 public boolean subtypeOf(Type that) {
117 return this == that || superInterfaces.contains(that) || that == OBJECT; 130 return this == that || superInterfaces.contains(that) ||
131 that == OBJECT;
118 } 132 }
119 133
120 @Override 134 @Override
121 public String asString() { 135 public String asString() {
122 return typeStr; 136 return typeStr;
168 this.kind = kind; 182 this.kind = kind;
169 this.types = types; 183 this.types = types;
170 } 184 }
171 185
172 String getCast() { 186 String getCast() {
173 String temp = kind.castTemplate.replaceAll("#C", types[0].asString()); 187 String temp = kind.castTemplate.replaceAll("#C",
188 types[0].asString());
174 for (int i = 0; i < kind.interfaceBounds ; i++) { 189 for (int i = 0; i < kind.interfaceBounds ; i++) {
175 temp = temp.replace(String.format("#I%d", i), types[i + 1].asString()); 190 temp = temp.replace(String.format("#I%d", i),
191 types[i + 1].asString());
176 } 192 }
177 return temp; 193 return temp;
178 } 194 }
179 195
180 boolean hasDuplicateTypes() { 196 boolean hasDuplicateTypes() {
193 for (Type t2 : that.types) { 209 for (Type t2 : that.types) {
194 boolean compat = 210 boolean compat =
195 t1.subtypeOf(t2) || 211 t1.subtypeOf(t2) ||
196 t2.subtypeOf(t1) || 212 t2.subtypeOf(t1) ||
197 (t1.isInterface() && t2.isInterface()) || //side-cast (1) 213 (t1.isInterface() && t2.isInterface()) || //side-cast (1)
198 (mod == ModifierKind.NONE && (t1.isInterface() != t2.isInterface())); //side-cast (2) 214 (mod == ModifierKind.NONE &&
215 (t1.isInterface() != t2.isInterface())); //side-cast (2)
199 if (!compat) return false; 216 if (!compat) return false;
200 } 217 }
201 } 218 }
202 return true; 219 return true;
203 } 220 }
204 } 221 }
205 222
206 public static void main(String... args) throws Exception { 223 public static void main(String... args) throws Exception {
207 //create default shared JavaCompiler - reused across multiple compilations
208 JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
209 StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
210
211 for (ModifierKind mod : ModifierKind.values()) { 224 for (ModifierKind mod : ModifierKind.values()) {
212 for (CastInfo cast1 : allCastInfo()) { 225 for (CastInfo cast1 : allCastInfo()) {
213 for (CastInfo cast2 : allCastInfo()) { 226 for (CastInfo cast2 : allCastInfo()) {
214 new IntersectionTypeCastTest(mod, cast1, cast2).run(comp, fm); 227 pool.execute(
228 new IntersectionTypeCastTest(mod, cast1, cast2));
215 } 229 }
216 } 230 }
217 } 231 }
218 System.out.println("Total check executed: " + checkCount); 232 checkAfterExec();
219 } 233 }
220 234
221 static List<CastInfo> allCastInfo() { 235 static List<CastInfo> allCastInfo() {
222 ListBuffer<CastInfo> buf = ListBuffer.lb(); 236 ListBuffer<CastInfo> buf = ListBuffer.lb();
223 for (CastKind kind : CastKind.values()) { 237 for (CastKind kind : CastKind.values()) {
233 buf.append(new CastInfo(kind, clazz, intf1)); 247 buf.append(new CastInfo(kind, clazz, intf1));
234 continue; 248 continue;
235 } else { 249 } else {
236 for (InterfaceKind intf2 : InterfaceKind.values()) { 250 for (InterfaceKind intf2 : InterfaceKind.values()) {
237 if (kind.interfaceBounds == 2) { 251 if (kind.interfaceBounds == 2) {
238 buf.append(new CastInfo(kind, clazz, intf1, intf2)); 252 buf.append(
253 new CastInfo(kind, clazz, intf1, intf2));
239 continue; 254 continue;
240 } else { 255 } else {
241 for (InterfaceKind intf3 : InterfaceKind.values()) { 256 for (InterfaceKind intf3 : InterfaceKind.values()) {
242 buf.append(new CastInfo(kind, clazz, intf1, intf2, intf3)); 257 buf.append(
258 new CastInfo(kind, clazz, intf1,
259 intf2, intf3));
243 continue; 260 continue;
244 } 261 }
245 } 262 }
246 } 263 }
247 } 264 }
263 this.cast2 = cast2; 280 this.cast2 = cast2;
264 this.source = new JavaSource(); 281 this.source = new JavaSource();
265 this.diagChecker = new DiagnosticChecker(); 282 this.diagChecker = new DiagnosticChecker();
266 } 283 }
267 284
285 @Override
286 public void run() {
287 final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
288
289 JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker,
290 Arrays.asList("-XDallowIntersectionTypes"),
291 null, Arrays.asList(source));
292 try {
293 ct.analyze();
294 } catch (Throwable ex) {
295 throw new AssertionError("Error thrown when compiling the following code:\n" +
296 source.getCharContent(true));
297 }
298 check();
299 }
300
268 class JavaSource extends SimpleJavaFileObject { 301 class JavaSource extends SimpleJavaFileObject {
269 302
270 String bodyTemplate = "class Test {\n" + 303 String bodyTemplate = "class Test {\n" +
271 " void test() {\n" + 304 " void test() {\n" +
272 " Object o = #C1#C2null;\n" + 305 " Object o = #C1#C2null;\n" +
280 source += ck.getDecl(mod); 313 source += ck.getDecl(mod);
281 } 314 }
282 for (InterfaceKind ik : InterfaceKind.values()) { 315 for (InterfaceKind ik : InterfaceKind.values()) {
283 source += ik.declStr; 316 source += ik.declStr;
284 } 317 }
285 source += bodyTemplate.replaceAll("#C1", cast1.getCast()).replaceAll("#C2", cast2.getCast()); 318 source += bodyTemplate.replaceAll("#C1", cast1.getCast()).
319 replaceAll("#C2", cast2.getCast());
286 } 320 }
287 321
288 @Override 322 @Override
289 public CharSequence getCharContent(boolean ignoreEncodingErrors) { 323 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
290 return source; 324 return source;
291 } 325 }
292 } 326 }
293 327
294 void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
295 JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
296 Arrays.asList("-XDallowIntersectionTypes"), null, Arrays.asList(source));
297 try {
298 ct.analyze();
299 } catch (Throwable ex) {
300 throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
301 }
302 check();
303 }
304
305 void check() { 328 void check() {
306 checkCount++; 329 checkCount.incrementAndGet();
307 330
308 boolean errorExpected = cast1.hasDuplicateTypes() || cast2.hasDuplicateTypes(); 331 boolean errorExpected = cast1.hasDuplicateTypes() ||
332 cast2.hasDuplicateTypes();
309 333
310 errorExpected |= !cast2.compatibleWith(mod, cast1); 334 errorExpected |= !cast2.compatibleWith(mod, cast1);
311 335
312 if (errorExpected != diagChecker.errorFound) { 336 if (errorExpected != diagChecker.errorFound) {
313 throw new Error("invalid diagnostics for source:\n" + 337 throw new Error("invalid diagnostics for source:\n" +
315 "\nFound error: " + diagChecker.errorFound + 339 "\nFound error: " + diagChecker.errorFound +
316 "\nExpected error: " + errorExpected); 340 "\nExpected error: " + errorExpected);
317 } 341 }
318 } 342 }
319 343
320 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { 344 static class DiagnosticChecker
345 implements javax.tools.DiagnosticListener<JavaFileObject> {
321 346
322 boolean errorFound; 347 boolean errorFound;
323 348
324 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 349 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
325 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { 350 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
326 errorFound = true; 351 errorFound = true;
327 } 352 }
328 } 353 }
329 } 354 }
355
330 } 356 }

mercurial