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

Mon, 21 Jan 2013 20:14:39 +0000

author
mcimadamore
date
Mon, 21 Jan 2013 20:14:39 +0000
changeset 1511
c7c41a044e7c
parent 1482
954541f13717
child 1520
5c956be64b9e
permissions
-rw-r--r--

8006566: Remove transient lambda-related guards from JavacParser
Summary: Remove transitional internal flag for allowing intersection types in cast
Reviewed-by: jjg

mcimadamore@1436 1 /*
vromero@1482 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
mcimadamore@1436 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@1436 4 *
mcimadamore@1436 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@1436 6 * under the terms of the GNU General Public License version 2 only, as
mcimadamore@1436 7 * published by the Free Software Foundation.
mcimadamore@1436 8 *
mcimadamore@1436 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@1436 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@1436 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@1436 12 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@1436 13 * accompanied this code).
mcimadamore@1436 14 *
mcimadamore@1436 15 * You should have received a copy of the GNU General Public License version
mcimadamore@1436 16 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@1436 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@1436 18 *
mcimadamore@1436 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mcimadamore@1436 20 * or visit www.oracle.com if you need additional information or have any
mcimadamore@1436 21 * questions.
mcimadamore@1436 22 */
mcimadamore@1436 23
mcimadamore@1436 24 /*
mcimadamore@1436 25 * @test
mcimadamore@1436 26 * @bug 8002099
mcimadamore@1436 27 * @summary Add support for intersection types in cast expression
vromero@1482 28 * @library ../../lib
vromero@1482 29 * @build JavacTestingAbstractThreadedTest
vromero@1482 30 * @run main/timeout=360 IntersectionTypeCastTest
mcimadamore@1436 31 */
mcimadamore@1436 32
mcimadamore@1436 33 import java.net.URI;
mcimadamore@1436 34 import java.util.Arrays;
mcimadamore@1436 35 import javax.tools.Diagnostic;
mcimadamore@1436 36 import javax.tools.JavaCompiler;
mcimadamore@1436 37 import javax.tools.JavaFileObject;
mcimadamore@1436 38 import javax.tools.SimpleJavaFileObject;
mcimadamore@1436 39 import javax.tools.ToolProvider;
mcimadamore@1436 40
vromero@1482 41 import com.sun.source.util.JavacTask;
vromero@1482 42 import com.sun.tools.javac.util.List;
vromero@1482 43 import com.sun.tools.javac.util.ListBuffer;
mcimadamore@1436 44
vromero@1482 45 public class IntersectionTypeCastTest
vromero@1482 46 extends JavacTestingAbstractThreadedTest
vromero@1482 47 implements Runnable {
mcimadamore@1436 48
mcimadamore@1436 49 interface Type {
mcimadamore@1436 50 boolean subtypeOf(Type that);
mcimadamore@1436 51 String asString();
mcimadamore@1436 52 boolean isClass();
mcimadamore@1436 53 boolean isInterface();
mcimadamore@1436 54 }
mcimadamore@1436 55
mcimadamore@1436 56 enum InterfaceKind implements Type {
mcimadamore@1436 57 A("interface A { }\n", "A", null),
mcimadamore@1436 58 B("interface B { }\n", "B", null),
mcimadamore@1436 59 C("interface C extends A { }\n", "C", A);
mcimadamore@1436 60
mcimadamore@1436 61 String declStr;
mcimadamore@1436 62 String typeStr;
mcimadamore@1436 63 InterfaceKind superInterface;
mcimadamore@1436 64
vromero@1482 65 InterfaceKind(String declStr, String typeStr,
vromero@1482 66 InterfaceKind superInterface) {
mcimadamore@1436 67 this.declStr = declStr;
mcimadamore@1436 68 this.typeStr = typeStr;
mcimadamore@1436 69 this.superInterface = superInterface;
mcimadamore@1436 70 }
mcimadamore@1436 71
mcimadamore@1436 72 @Override
mcimadamore@1436 73 public boolean subtypeOf(Type that) {
vromero@1482 74 return this == that || superInterface == that ||
vromero@1482 75 that == ClassKind.OBJECT;
mcimadamore@1436 76 }
mcimadamore@1436 77
mcimadamore@1436 78 @Override
mcimadamore@1436 79 public String asString() {
mcimadamore@1436 80 return typeStr;
mcimadamore@1436 81 }
mcimadamore@1436 82
mcimadamore@1436 83 @Override
mcimadamore@1436 84 public boolean isClass() {
mcimadamore@1436 85 return false;
mcimadamore@1436 86 }
mcimadamore@1436 87
mcimadamore@1436 88 @Override
mcimadamore@1436 89 public boolean isInterface() {
mcimadamore@1436 90 return true;
mcimadamore@1436 91 }
mcimadamore@1436 92 }
mcimadamore@1436 93
mcimadamore@1436 94 enum ClassKind implements Type {
mcimadamore@1436 95 OBJECT(null, "Object"),
vromero@1482 96 CA("#M class CA implements A { }\n", "CA",
vromero@1482 97 InterfaceKind.A),
vromero@1482 98 CB("#M class CB implements B { }\n", "CB",
vromero@1482 99 InterfaceKind.B),
vromero@1482 100 CAB("#M class CAB implements A, B { }\n", "CAB",
vromero@1482 101 InterfaceKind.A, InterfaceKind.B),
vromero@1482 102 CC("#M class CC implements C { }\n", "CC",
vromero@1482 103 InterfaceKind.C, InterfaceKind.A),
vromero@1482 104 CCA("#M class CCA implements C, A { }\n", "CCA",
vromero@1482 105 InterfaceKind.C, InterfaceKind.A),
vromero@1482 106 CCB("#M class CCB implements C, B { }\n", "CCB",
vromero@1482 107 InterfaceKind.C, InterfaceKind.A, InterfaceKind.B),
vromero@1482 108 CCAB("#M class CCAB implements C, A, B { }\n", "CCAB",
vromero@1482 109 InterfaceKind.C, InterfaceKind.A, InterfaceKind.B);
mcimadamore@1436 110
mcimadamore@1436 111 String declTemplate;
mcimadamore@1436 112 String typeStr;
mcimadamore@1436 113 List<InterfaceKind> superInterfaces;
mcimadamore@1436 114
vromero@1482 115 ClassKind(String declTemplate, String typeStr,
vromero@1482 116 InterfaceKind... superInterfaces) {
mcimadamore@1436 117 this.declTemplate = declTemplate;
mcimadamore@1436 118 this.typeStr = typeStr;
mcimadamore@1436 119 this.superInterfaces = List.from(superInterfaces);
mcimadamore@1436 120 }
mcimadamore@1436 121
mcimadamore@1436 122 String getDecl(ModifierKind mod) {
mcimadamore@1436 123 return declTemplate != null ?
mcimadamore@1436 124 declTemplate.replaceAll("#M", mod.modStr) :
mcimadamore@1436 125 "";
mcimadamore@1436 126 }
mcimadamore@1436 127
mcimadamore@1436 128 @Override
mcimadamore@1436 129 public boolean subtypeOf(Type that) {
vromero@1482 130 return this == that || superInterfaces.contains(that) ||
vromero@1482 131 that == OBJECT;
mcimadamore@1436 132 }
mcimadamore@1436 133
mcimadamore@1436 134 @Override
mcimadamore@1436 135 public String asString() {
mcimadamore@1436 136 return typeStr;
mcimadamore@1436 137 }
mcimadamore@1436 138
mcimadamore@1436 139 @Override
mcimadamore@1436 140 public boolean isClass() {
mcimadamore@1436 141 return true;
mcimadamore@1436 142 }
mcimadamore@1436 143
mcimadamore@1436 144 @Override
mcimadamore@1436 145 public boolean isInterface() {
mcimadamore@1436 146 return false;
mcimadamore@1436 147 }
mcimadamore@1436 148 }
mcimadamore@1436 149
mcimadamore@1436 150 enum ModifierKind {
mcimadamore@1436 151 NONE(""),
mcimadamore@1436 152 FINAL("final");
mcimadamore@1436 153
mcimadamore@1436 154 String modStr;
mcimadamore@1436 155
mcimadamore@1436 156 ModifierKind(String modStr) {
mcimadamore@1436 157 this.modStr = modStr;
mcimadamore@1436 158 }
mcimadamore@1436 159 }
mcimadamore@1436 160
mcimadamore@1436 161 enum CastKind {
mcimadamore@1436 162 CLASS("(#C)", 0),
mcimadamore@1436 163 INTERFACE("(#I0)", 1),
mcimadamore@1436 164 INTERSECTION2("(#C & #I0)", 1),
mcimadamore@1436 165 INTERSECTION3("(#C & #I0 & #I1)", 2);
mcimadamore@1436 166 //INTERSECTION4("(#C & #I0 & #I1 & #I2)", 3);
mcimadamore@1436 167
mcimadamore@1436 168 String castTemplate;
mcimadamore@1436 169 int interfaceBounds;
mcimadamore@1436 170
mcimadamore@1436 171 CastKind(String castTemplate, int interfaceBounds) {
mcimadamore@1436 172 this.castTemplate = castTemplate;
mcimadamore@1436 173 this.interfaceBounds = interfaceBounds;
mcimadamore@1436 174 }
mcimadamore@1436 175 }
mcimadamore@1436 176
mcimadamore@1436 177 static class CastInfo {
mcimadamore@1436 178 CastKind kind;
mcimadamore@1436 179 Type[] types;
mcimadamore@1436 180
mcimadamore@1436 181 CastInfo(CastKind kind, Type... types) {
mcimadamore@1436 182 this.kind = kind;
mcimadamore@1436 183 this.types = types;
mcimadamore@1436 184 }
mcimadamore@1436 185
mcimadamore@1436 186 String getCast() {
vromero@1482 187 String temp = kind.castTemplate.replaceAll("#C",
vromero@1482 188 types[0].asString());
mcimadamore@1436 189 for (int i = 0; i < kind.interfaceBounds ; i++) {
vromero@1482 190 temp = temp.replace(String.format("#I%d", i),
vromero@1482 191 types[i + 1].asString());
mcimadamore@1436 192 }
mcimadamore@1436 193 return temp;
mcimadamore@1436 194 }
mcimadamore@1436 195
mcimadamore@1436 196 boolean hasDuplicateTypes() {
mcimadamore@1436 197 for (int i = 0 ; i < types.length ; i++) {
mcimadamore@1436 198 for (int j = 0 ; j < types.length ; j++) {
mcimadamore@1436 199 if (i != j && types[i] == types[j]) {
mcimadamore@1436 200 return true;
mcimadamore@1436 201 }
mcimadamore@1436 202 }
mcimadamore@1436 203 }
mcimadamore@1436 204 return false;
mcimadamore@1436 205 }
mcimadamore@1436 206
mcimadamore@1436 207 boolean compatibleWith(ModifierKind mod, CastInfo that) {
mcimadamore@1436 208 for (Type t1 : types) {
mcimadamore@1436 209 for (Type t2 : that.types) {
mcimadamore@1436 210 boolean compat =
mcimadamore@1436 211 t1.subtypeOf(t2) ||
mcimadamore@1436 212 t2.subtypeOf(t1) ||
mcimadamore@1436 213 (t1.isInterface() && t2.isInterface()) || //side-cast (1)
vromero@1482 214 (mod == ModifierKind.NONE &&
vromero@1482 215 (t1.isInterface() != t2.isInterface())); //side-cast (2)
mcimadamore@1436 216 if (!compat) return false;
mcimadamore@1436 217 }
mcimadamore@1436 218 }
mcimadamore@1436 219 return true;
mcimadamore@1436 220 }
mcimadamore@1436 221 }
mcimadamore@1436 222
mcimadamore@1436 223 public static void main(String... args) throws Exception {
mcimadamore@1436 224 for (ModifierKind mod : ModifierKind.values()) {
mcimadamore@1436 225 for (CastInfo cast1 : allCastInfo()) {
mcimadamore@1436 226 for (CastInfo cast2 : allCastInfo()) {
vromero@1482 227 pool.execute(
vromero@1482 228 new IntersectionTypeCastTest(mod, cast1, cast2));
mcimadamore@1436 229 }
mcimadamore@1436 230 }
mcimadamore@1436 231 }
vromero@1482 232 checkAfterExec();
mcimadamore@1436 233 }
mcimadamore@1436 234
mcimadamore@1436 235 static List<CastInfo> allCastInfo() {
mcimadamore@1436 236 ListBuffer<CastInfo> buf = ListBuffer.lb();
mcimadamore@1436 237 for (CastKind kind : CastKind.values()) {
mcimadamore@1436 238 for (ClassKind clazz : ClassKind.values()) {
mcimadamore@1436 239 if (kind == CastKind.INTERFACE && clazz != ClassKind.OBJECT) {
mcimadamore@1436 240 continue;
mcimadamore@1436 241 } else if (kind.interfaceBounds == 0) {
mcimadamore@1436 242 buf.append(new CastInfo(kind, clazz));
mcimadamore@1436 243 continue;
mcimadamore@1436 244 } else {
mcimadamore@1436 245 for (InterfaceKind intf1 : InterfaceKind.values()) {
mcimadamore@1436 246 if (kind.interfaceBounds == 1) {
mcimadamore@1436 247 buf.append(new CastInfo(kind, clazz, intf1));
mcimadamore@1436 248 continue;
mcimadamore@1436 249 } else {
mcimadamore@1436 250 for (InterfaceKind intf2 : InterfaceKind.values()) {
mcimadamore@1436 251 if (kind.interfaceBounds == 2) {
vromero@1482 252 buf.append(
vromero@1482 253 new CastInfo(kind, clazz, intf1, intf2));
mcimadamore@1436 254 continue;
mcimadamore@1436 255 } else {
mcimadamore@1436 256 for (InterfaceKind intf3 : InterfaceKind.values()) {
vromero@1482 257 buf.append(
vromero@1482 258 new CastInfo(kind, clazz, intf1,
vromero@1482 259 intf2, intf3));
mcimadamore@1436 260 continue;
mcimadamore@1436 261 }
mcimadamore@1436 262 }
mcimadamore@1436 263 }
mcimadamore@1436 264 }
mcimadamore@1436 265 }
mcimadamore@1436 266 }
mcimadamore@1436 267 }
mcimadamore@1436 268 }
mcimadamore@1436 269 return buf.toList();
mcimadamore@1436 270 }
mcimadamore@1436 271
mcimadamore@1436 272 ModifierKind mod;
mcimadamore@1436 273 CastInfo cast1, cast2;
mcimadamore@1436 274 JavaSource source;
mcimadamore@1436 275 DiagnosticChecker diagChecker;
mcimadamore@1436 276
mcimadamore@1436 277 IntersectionTypeCastTest(ModifierKind mod, CastInfo cast1, CastInfo cast2) {
mcimadamore@1436 278 this.mod = mod;
mcimadamore@1436 279 this.cast1 = cast1;
mcimadamore@1436 280 this.cast2 = cast2;
mcimadamore@1436 281 this.source = new JavaSource();
mcimadamore@1436 282 this.diagChecker = new DiagnosticChecker();
mcimadamore@1436 283 }
mcimadamore@1436 284
vromero@1482 285 @Override
vromero@1482 286 public void run() {
vromero@1482 287 final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
vromero@1482 288
vromero@1482 289 JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker,
mcimadamore@1511 290 null, null, Arrays.asList(source));
vromero@1482 291 try {
vromero@1482 292 ct.analyze();
vromero@1482 293 } catch (Throwable ex) {
vromero@1482 294 throw new AssertionError("Error thrown when compiling the following code:\n" +
vromero@1482 295 source.getCharContent(true));
vromero@1482 296 }
vromero@1482 297 check();
vromero@1482 298 }
vromero@1482 299
mcimadamore@1436 300 class JavaSource extends SimpleJavaFileObject {
mcimadamore@1436 301
mcimadamore@1436 302 String bodyTemplate = "class Test {\n" +
mcimadamore@1436 303 " void test() {\n" +
mcimadamore@1436 304 " Object o = #C1#C2null;\n" +
mcimadamore@1436 305 " } }";
mcimadamore@1436 306
mcimadamore@1436 307 String source = "";
mcimadamore@1436 308
mcimadamore@1436 309 public JavaSource() {
mcimadamore@1436 310 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
mcimadamore@1436 311 for (ClassKind ck : ClassKind.values()) {
mcimadamore@1436 312 source += ck.getDecl(mod);
mcimadamore@1436 313 }
mcimadamore@1436 314 for (InterfaceKind ik : InterfaceKind.values()) {
mcimadamore@1436 315 source += ik.declStr;
mcimadamore@1436 316 }
vromero@1482 317 source += bodyTemplate.replaceAll("#C1", cast1.getCast()).
vromero@1482 318 replaceAll("#C2", cast2.getCast());
mcimadamore@1436 319 }
mcimadamore@1436 320
mcimadamore@1436 321 @Override
mcimadamore@1436 322 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
mcimadamore@1436 323 return source;
mcimadamore@1436 324 }
mcimadamore@1436 325 }
mcimadamore@1436 326
vromero@1482 327 void check() {
vromero@1482 328 checkCount.incrementAndGet();
mcimadamore@1436 329
vromero@1482 330 boolean errorExpected = cast1.hasDuplicateTypes() ||
vromero@1482 331 cast2.hasDuplicateTypes();
mcimadamore@1436 332
mcimadamore@1436 333 errorExpected |= !cast2.compatibleWith(mod, cast1);
mcimadamore@1436 334
mcimadamore@1436 335 if (errorExpected != diagChecker.errorFound) {
mcimadamore@1436 336 throw new Error("invalid diagnostics for source:\n" +
mcimadamore@1436 337 source.getCharContent(true) +
mcimadamore@1436 338 "\nFound error: " + diagChecker.errorFound +
mcimadamore@1436 339 "\nExpected error: " + errorExpected);
mcimadamore@1436 340 }
mcimadamore@1436 341 }
mcimadamore@1436 342
vromero@1482 343 static class DiagnosticChecker
vromero@1482 344 implements javax.tools.DiagnosticListener<JavaFileObject> {
mcimadamore@1436 345
mcimadamore@1436 346 boolean errorFound;
mcimadamore@1436 347
mcimadamore@1436 348 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
mcimadamore@1436 349 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
mcimadamore@1436 350 errorFound = true;
mcimadamore@1436 351 }
mcimadamore@1436 352 }
mcimadamore@1436 353 }
vromero@1482 354
mcimadamore@1436 355 }

mercurial