test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java

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

author
mcimadamore
date
Mon, 21 Jan 2013 20:14:39 +0000
changeset 1511
c7c41a044e7c
parent 1436
f6f1fd261f57
child 1678
c635a966ce84
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 /*
mcimadamore@1436 2 * Copyright (c) 2012, 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
mcimadamore@1436 28 */
mcimadamore@1436 29
mcimadamore@1436 30 import com.sun.source.util.JavacTask;
mcimadamore@1436 31 import com.sun.tools.javac.util.List;
mcimadamore@1436 32 import com.sun.tools.javac.util.ListBuffer;
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.StandardJavaFileManager;
mcimadamore@1436 40 import javax.tools.ToolProvider;
mcimadamore@1436 41
mcimadamore@1436 42 public class IntersectionTargetTypeTest {
mcimadamore@1436 43
mcimadamore@1436 44 static int checkCount = 0;
mcimadamore@1436 45
mcimadamore@1436 46 enum BoundKind {
mcimadamore@1436 47 INTF,
mcimadamore@1436 48 CLASS,
mcimadamore@1436 49 SAM,
mcimadamore@1436 50 ZAM;
mcimadamore@1436 51 }
mcimadamore@1436 52
mcimadamore@1436 53 enum MethodKind {
mcimadamore@1436 54 NONE,
mcimadamore@1436 55 ABSTRACT,
mcimadamore@1436 56 DEFAULT;
mcimadamore@1436 57 }
mcimadamore@1436 58
mcimadamore@1436 59 enum TypeKind {
mcimadamore@1436 60 A("interface A { }\n", "A", BoundKind.ZAM),
mcimadamore@1436 61 B("interface B { default void m() { } }\n", "B", BoundKind.ZAM),
mcimadamore@1436 62 C("interface C { void m(); }\n", "C", BoundKind.SAM),
mcimadamore@1436 63 D("interface D extends B { }\n", "D", BoundKind.ZAM),
mcimadamore@1436 64 E("interface E extends C { }\n", "E", BoundKind.SAM),
mcimadamore@1436 65 F("interface F extends C { void g(); }\n", "F", BoundKind.INTF),
mcimadamore@1436 66 G("interface G extends B { void g(); }\n", "G", BoundKind.SAM),
mcimadamore@1436 67 H("interface H extends A { void g(); }\n", "H", BoundKind.SAM),
mcimadamore@1436 68 OBJECT("", "Object", BoundKind.CLASS),
mcimadamore@1436 69 STRING("", "String", BoundKind.CLASS);
mcimadamore@1436 70
mcimadamore@1436 71 String declStr;
mcimadamore@1436 72 String typeStr;
mcimadamore@1436 73 BoundKind boundKind;
mcimadamore@1436 74
mcimadamore@1436 75 private TypeKind(String declStr, String typeStr, BoundKind boundKind) {
mcimadamore@1436 76 this.declStr = declStr;
mcimadamore@1436 77 this.typeStr = typeStr;
mcimadamore@1436 78 this.boundKind = boundKind;
mcimadamore@1436 79 }
mcimadamore@1436 80
mcimadamore@1436 81 boolean compatibleSupertype(TypeKind tk) {
mcimadamore@1436 82 if (tk == this) return true;
mcimadamore@1436 83 switch (tk) {
mcimadamore@1436 84 case B:
mcimadamore@1436 85 return this != C && this != E && this != F;
mcimadamore@1436 86 case C:
mcimadamore@1436 87 return this != B && this != C && this != D && this != G;
mcimadamore@1436 88 case D: return compatibleSupertype(B);
mcimadamore@1436 89 case E:
mcimadamore@1436 90 case F: return compatibleSupertype(C);
mcimadamore@1436 91 case G: return compatibleSupertype(B);
mcimadamore@1436 92 case H: return compatibleSupertype(A);
mcimadamore@1436 93 default:
mcimadamore@1436 94 return true;
mcimadamore@1436 95 }
mcimadamore@1436 96 }
mcimadamore@1436 97 }
mcimadamore@1436 98
mcimadamore@1436 99 enum CastKind {
mcimadamore@1436 100 ONE_ARY("(#B0)", 1),
mcimadamore@1436 101 TWO_ARY("(#B0 & #B1)", 2),
mcimadamore@1436 102 THREE_ARY("(#B0 & #B1 & #B2)", 3);
mcimadamore@1436 103
mcimadamore@1436 104 String castTemplate;
mcimadamore@1436 105 int nbounds;
mcimadamore@1436 106
mcimadamore@1436 107 CastKind(String castTemplate, int nbounds) {
mcimadamore@1436 108 this.castTemplate = castTemplate;
mcimadamore@1436 109 this.nbounds = nbounds;
mcimadamore@1436 110 }
mcimadamore@1436 111 }
mcimadamore@1436 112
mcimadamore@1436 113 enum ExpressionKind {
mcimadamore@1436 114 LAMBDA("()->{}", true),
mcimadamore@1436 115 MREF("this::m", true),
mcimadamore@1436 116 //COND_LAMBDA("(true ? ()->{} : ()->{})", true), re-enable if spec allows this
mcimadamore@1436 117 //COND_MREF("(true ? this::m : this::m)", true),
mcimadamore@1436 118 STANDALONE("null", false);
mcimadamore@1436 119
mcimadamore@1436 120 String exprString;
mcimadamore@1436 121 boolean isFunctional;
mcimadamore@1436 122
mcimadamore@1436 123 private ExpressionKind(String exprString, boolean isFunctional) {
mcimadamore@1436 124 this.exprString = exprString;
mcimadamore@1436 125 this.isFunctional = isFunctional;
mcimadamore@1436 126 }
mcimadamore@1436 127 }
mcimadamore@1436 128
mcimadamore@1436 129 static class CastInfo {
mcimadamore@1436 130 CastKind kind;
mcimadamore@1436 131 TypeKind[] types;
mcimadamore@1436 132
mcimadamore@1436 133 CastInfo(CastKind kind, TypeKind... types) {
mcimadamore@1436 134 this.kind = kind;
mcimadamore@1436 135 this.types = types;
mcimadamore@1436 136 }
mcimadamore@1436 137
mcimadamore@1436 138 String getCast() {
mcimadamore@1436 139 String temp = kind.castTemplate;
mcimadamore@1436 140 for (int i = 0; i < kind.nbounds ; i++) {
mcimadamore@1436 141 temp = temp.replace(String.format("#B%d", i), types[i].typeStr);
mcimadamore@1436 142 }
mcimadamore@1436 143 return temp;
mcimadamore@1436 144 }
mcimadamore@1436 145
mcimadamore@1436 146 boolean wellFormed() {
mcimadamore@1436 147 //check for duplicate types
mcimadamore@1436 148 for (int i = 0 ; i < types.length ; i++) {
mcimadamore@1436 149 for (int j = 0 ; j < types.length ; j++) {
mcimadamore@1436 150 if (i != j && types[i] == types[j]) {
mcimadamore@1436 151 return false;
mcimadamore@1436 152 }
mcimadamore@1436 153 }
mcimadamore@1436 154 }
mcimadamore@1436 155 //check that classes only appear as first bound
mcimadamore@1436 156 boolean classOk = true;
mcimadamore@1436 157 for (int i = 0 ; i < types.length ; i++) {
mcimadamore@1436 158 if (types[i].boundKind == BoundKind.CLASS &&
mcimadamore@1436 159 !classOk) {
mcimadamore@1436 160 return false;
mcimadamore@1436 161 }
mcimadamore@1436 162 classOk = false;
mcimadamore@1436 163 }
mcimadamore@1436 164 //check that supertypes are mutually compatible
mcimadamore@1436 165 for (int i = 0 ; i < types.length ; i++) {
mcimadamore@1436 166 for (int j = 0 ; j < types.length ; j++) {
mcimadamore@1436 167 if (!types[i].compatibleSupertype(types[j]) && i != j) {
mcimadamore@1436 168 return false;
mcimadamore@1436 169 }
mcimadamore@1436 170 }
mcimadamore@1436 171 }
mcimadamore@1436 172 return true;
mcimadamore@1436 173 }
mcimadamore@1436 174 }
mcimadamore@1436 175
mcimadamore@1436 176 public static void main(String... args) throws Exception {
mcimadamore@1436 177 //create default shared JavaCompiler - reused across multiple compilations
mcimadamore@1436 178 JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
mcimadamore@1436 179 StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
mcimadamore@1436 180
mcimadamore@1436 181 for (CastInfo cInfo : allCastInfo()) {
mcimadamore@1436 182 for (ExpressionKind ek : ExpressionKind.values()) {
mcimadamore@1436 183 new IntersectionTargetTypeTest(cInfo, ek).run(comp, fm);
mcimadamore@1436 184 }
mcimadamore@1436 185 }
mcimadamore@1436 186 System.out.println("Total check executed: " + checkCount);
mcimadamore@1436 187 }
mcimadamore@1436 188
mcimadamore@1436 189 static List<CastInfo> allCastInfo() {
mcimadamore@1436 190 ListBuffer<CastInfo> buf = ListBuffer.lb();
mcimadamore@1436 191 for (CastKind kind : CastKind.values()) {
mcimadamore@1436 192 for (TypeKind b1 : TypeKind.values()) {
mcimadamore@1436 193 if (kind.nbounds == 1) {
mcimadamore@1436 194 buf.append(new CastInfo(kind, b1));
mcimadamore@1436 195 continue;
mcimadamore@1436 196 } else {
mcimadamore@1436 197 for (TypeKind b2 : TypeKind.values()) {
mcimadamore@1436 198 if (kind.nbounds == 2) {
mcimadamore@1436 199 buf.append(new CastInfo(kind, b1, b2));
mcimadamore@1436 200 continue;
mcimadamore@1436 201 } else {
mcimadamore@1436 202 for (TypeKind b3 : TypeKind.values()) {
mcimadamore@1436 203 buf.append(new CastInfo(kind, b1, b2, b3));
mcimadamore@1436 204 }
mcimadamore@1436 205 }
mcimadamore@1436 206 }
mcimadamore@1436 207 }
mcimadamore@1436 208 }
mcimadamore@1436 209 }
mcimadamore@1436 210 return buf.toList();
mcimadamore@1436 211 }
mcimadamore@1436 212
mcimadamore@1436 213 CastInfo cInfo;
mcimadamore@1436 214 ExpressionKind ek;
mcimadamore@1436 215 JavaSource source;
mcimadamore@1436 216 DiagnosticChecker diagChecker;
mcimadamore@1436 217
mcimadamore@1436 218 IntersectionTargetTypeTest(CastInfo cInfo, ExpressionKind ek) {
mcimadamore@1436 219 this.cInfo = cInfo;
mcimadamore@1436 220 this.ek = ek;
mcimadamore@1436 221 this.source = new JavaSource();
mcimadamore@1436 222 this.diagChecker = new DiagnosticChecker();
mcimadamore@1436 223 }
mcimadamore@1436 224
mcimadamore@1436 225 class JavaSource extends SimpleJavaFileObject {
mcimadamore@1436 226
mcimadamore@1436 227 String bodyTemplate = "class Test {\n" +
mcimadamore@1436 228 " void m() { }\n" +
mcimadamore@1436 229 " void test() {\n" +
mcimadamore@1436 230 " Object o = #C#E;\n" +
mcimadamore@1436 231 " } }";
mcimadamore@1436 232
mcimadamore@1436 233 String source = "";
mcimadamore@1436 234
mcimadamore@1436 235 public JavaSource() {
mcimadamore@1436 236 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
mcimadamore@1436 237 for (TypeKind tk : TypeKind.values()) {
mcimadamore@1436 238 source += tk.declStr;
mcimadamore@1436 239 }
mcimadamore@1436 240 source += bodyTemplate.replaceAll("#C", cInfo.getCast()).replaceAll("#E", ek.exprString);
mcimadamore@1436 241 }
mcimadamore@1436 242
mcimadamore@1436 243 @Override
mcimadamore@1436 244 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
mcimadamore@1436 245 return source;
mcimadamore@1436 246 }
mcimadamore@1436 247 }
mcimadamore@1436 248
mcimadamore@1436 249 void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
mcimadamore@1436 250 JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
mcimadamore@1511 251 null, null, Arrays.asList(source));
mcimadamore@1436 252 try {
mcimadamore@1436 253 ct.analyze();
mcimadamore@1436 254 } catch (Throwable ex) {
mcimadamore@1436 255 throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
mcimadamore@1436 256 }
mcimadamore@1436 257 check();
mcimadamore@1436 258 }
mcimadamore@1436 259
mcimadamore@1436 260 void check() {
mcimadamore@1436 261 checkCount++;
mcimadamore@1436 262
mcimadamore@1436 263 boolean errorExpected = !cInfo.wellFormed();
mcimadamore@1436 264
mcimadamore@1436 265 if (ek.isFunctional) {
mcimadamore@1436 266 //first bound must be a SAM
mcimadamore@1436 267 errorExpected |= cInfo.types[0].boundKind != BoundKind.SAM;
mcimadamore@1436 268 if (cInfo.types.length > 1) {
mcimadamore@1436 269 //additional bounds must be ZAMs
mcimadamore@1436 270 for (int i = 1; i < cInfo.types.length; i++) {
mcimadamore@1436 271 errorExpected |= cInfo.types[i].boundKind != BoundKind.ZAM;
mcimadamore@1436 272 }
mcimadamore@1436 273 }
mcimadamore@1436 274 }
mcimadamore@1436 275
mcimadamore@1436 276 if (errorExpected != diagChecker.errorFound) {
mcimadamore@1436 277 throw new Error("invalid diagnostics for source:\n" +
mcimadamore@1436 278 source.getCharContent(true) +
mcimadamore@1436 279 "\nFound error: " + diagChecker.errorFound +
mcimadamore@1436 280 "\nExpected error: " + errorExpected);
mcimadamore@1436 281 }
mcimadamore@1436 282 }
mcimadamore@1436 283
mcimadamore@1436 284 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
mcimadamore@1436 285
mcimadamore@1436 286 boolean errorFound;
mcimadamore@1436 287
mcimadamore@1436 288 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
mcimadamore@1436 289 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
mcimadamore@1436 290 errorFound = true;
mcimadamore@1436 291 }
mcimadamore@1436 292 }
mcimadamore@1436 293 }
mcimadamore@1436 294 }

mercurial