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

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

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

mercurial