test/tools/javac/lambda/TestSelfRef.java

Sat, 19 Oct 2013 17:43:09 +0100

author
vromero
date
Sat, 19 Oct 2013 17:43:09 +0100
changeset 2148
c4292590fc70
parent 1415
01c9d4161882
child 2525
2eb010b6cb22
permissions
-rw-r--r--

8024809: javac, some lambda programs are rejected by flow analysis
Reviewed-by: jjg, dlsmith

mcimadamore@1415 1 /*
vromero@2148 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
mcimadamore@1415 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@1415 4 *
mcimadamore@1415 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@1415 6 * under the terms of the GNU General Public License version 2 only, as
mcimadamore@1415 7 * published by the Free Software Foundation.
mcimadamore@1415 8 *
mcimadamore@1415 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@1415 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@1415 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@1415 12 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@1415 13 * accompanied this code).
mcimadamore@1415 14 *
mcimadamore@1415 15 * You should have received a copy of the GNU General Public License version
mcimadamore@1415 16 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@1415 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@1415 18 *
mcimadamore@1415 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mcimadamore@1415 20 * or visit www.oracle.com if you need additional information or have any
mcimadamore@1415 21 * questions.
mcimadamore@1415 22 */
mcimadamore@1415 23
mcimadamore@1415 24 /*
mcimadamore@1415 25 * @test
mcimadamore@1415 26 * @bug 8003280
mcimadamore@1415 27 * @summary Add lambda tests
mcimadamore@1415 28 * Check that self/forward references from lambda expressions behave
mcimadamore@1415 29 * consistently w.r.t. local inner classes
mcimadamore@1415 30 */
mcimadamore@1415 31
mcimadamore@1415 32 import java.net.URI;
mcimadamore@1415 33 import java.util.Arrays;
mcimadamore@1415 34 import javax.tools.Diagnostic;
mcimadamore@1415 35 import javax.tools.JavaCompiler;
mcimadamore@1415 36 import javax.tools.JavaFileObject;
mcimadamore@1415 37 import javax.tools.SimpleJavaFileObject;
mcimadamore@1415 38 import javax.tools.StandardJavaFileManager;
mcimadamore@1415 39 import javax.tools.ToolProvider;
vromero@2148 40 import com.sun.source.util.JavacTask;
mcimadamore@1415 41
mcimadamore@1415 42 public class TestSelfRef {
mcimadamore@1415 43
mcimadamore@1415 44 static int checkCount = 0;
mcimadamore@1415 45
mcimadamore@1415 46 enum RefKind {
mcimadamore@1415 47 SELF_LAMBDA("SAM s = x->{ System.out.println(s); };", true, false),
mcimadamore@1415 48 FORWARD_LAMBDA("SAM s = x->{ System.out.println(f); };\nObject f = null;", false, true),
mcimadamore@1415 49 SELF_ANON("Object s = new Object() { void test() { System.out.println(s); } };", true, false),
mcimadamore@1415 50 FORWARD_ANON("Object s = new Object() { void test() { System.out.println(f); } }; Object f = null;", false, true);
mcimadamore@1415 51
mcimadamore@1415 52 String refStr;
mcimadamore@1415 53 boolean selfRef;
mcimadamore@1415 54 boolean forwardRef;
mcimadamore@1415 55
mcimadamore@1415 56 private RefKind(String refStr, boolean selfRef, boolean forwardRef) {
mcimadamore@1415 57 this.refStr = refStr;
mcimadamore@1415 58 this.selfRef = selfRef;
mcimadamore@1415 59 this.forwardRef = forwardRef;
mcimadamore@1415 60 }
mcimadamore@1415 61 }
mcimadamore@1415 62
mcimadamore@1415 63 enum EnclosingKind {
mcimadamore@1415 64 TOPLEVEL("class C { #S }"),
mcimadamore@1415 65 MEMBER_INNER("class Outer { class C { #S } }"),
mcimadamore@1415 66 NESTED_INNER("class Outer { static class C { #S } }");
mcimadamore@1415 67
mcimadamore@1415 68 String enclStr;
mcimadamore@1415 69
mcimadamore@1415 70 private EnclosingKind(String enclStr) {
mcimadamore@1415 71 this.enclStr = enclStr;
mcimadamore@1415 72 }
mcimadamore@1415 73 }
mcimadamore@1415 74
mcimadamore@1415 75 enum InnerKind {
mcimadamore@1415 76 NONE("#R"),
mcimadamore@1415 77 LOCAL_NONE("class Local { #R }"),
mcimadamore@1415 78 LOCAL_MTH("class Local { void test() { #R } }"),
mcimadamore@1415 79 ANON_NONE("new Object() { #R };"),
mcimadamore@1415 80 ANON_MTH("new Object() { void test() { #R } };");
mcimadamore@1415 81
mcimadamore@1415 82 String innerStr;
mcimadamore@1415 83
mcimadamore@1415 84 private InnerKind(String innerStr) {
mcimadamore@1415 85 this.innerStr = innerStr;
mcimadamore@1415 86 }
mcimadamore@1415 87
mcimadamore@1415 88 boolean inMethodContext(SiteKind sk) {
mcimadamore@1415 89 switch (this) {
mcimadamore@1415 90 case LOCAL_MTH:
mcimadamore@1415 91 case ANON_MTH: return true;
mcimadamore@1415 92 case NONE: return sk != SiteKind.NONE;
mcimadamore@1415 93 default:
mcimadamore@1415 94 return false;
mcimadamore@1415 95 }
mcimadamore@1415 96 }
mcimadamore@1415 97 }
mcimadamore@1415 98
mcimadamore@1415 99 enum SiteKind {
mcimadamore@1415 100 NONE("#I"),
mcimadamore@1415 101 STATIC_INIT("static { #I }"),
mcimadamore@1415 102 INSTANCE_INIT("{ #I }"),
mcimadamore@1415 103 CONSTRUCTOR("C() { #I }"),
mcimadamore@1415 104 METHOD("void test() { #I }");
mcimadamore@1415 105
mcimadamore@1415 106 String siteStr;
mcimadamore@1415 107
mcimadamore@1415 108 private SiteKind(String siteStr) {
mcimadamore@1415 109 this.siteStr = siteStr;
mcimadamore@1415 110 }
mcimadamore@1415 111 }
mcimadamore@1415 112
mcimadamore@1415 113 public static void main(String... args) throws Exception {
mcimadamore@1415 114
mcimadamore@1415 115 //create default shared JavaCompiler - reused across multiple compilations
mcimadamore@1415 116 JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
mcimadamore@1415 117 StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
mcimadamore@1415 118
mcimadamore@1415 119 for (EnclosingKind ek : EnclosingKind.values()) {
mcimadamore@1415 120 for (SiteKind sk : SiteKind.values()) {
mcimadamore@1415 121 if (sk == SiteKind.STATIC_INIT && ek == EnclosingKind.MEMBER_INNER)
mcimadamore@1415 122 continue;
mcimadamore@1415 123 for (InnerKind ik : InnerKind.values()) {
mcimadamore@1415 124 if (ik != InnerKind.NONE && sk == SiteKind.NONE)
mcimadamore@1415 125 break;
mcimadamore@1415 126 for (RefKind rk : RefKind.values()) {
mcimadamore@1415 127 new TestSelfRef(ek, sk, ik, rk).run(comp, fm);
mcimadamore@1415 128 }
mcimadamore@1415 129 }
mcimadamore@1415 130 }
mcimadamore@1415 131 }
mcimadamore@1415 132 System.out.println("Total check executed: " + checkCount);
mcimadamore@1415 133 }
mcimadamore@1415 134
mcimadamore@1415 135 EnclosingKind ek;
mcimadamore@1415 136 SiteKind sk;
mcimadamore@1415 137 InnerKind ik;
mcimadamore@1415 138 RefKind rk;
mcimadamore@1415 139 JavaSource source;
mcimadamore@1415 140 DiagnosticChecker diagChecker;
mcimadamore@1415 141
mcimadamore@1415 142 TestSelfRef(EnclosingKind ek, SiteKind sk, InnerKind ik, RefKind rk) {
mcimadamore@1415 143 this.ek = ek;
mcimadamore@1415 144 this.sk = sk;
mcimadamore@1415 145 this.ik = ik;
mcimadamore@1415 146 this.rk = rk;
mcimadamore@1415 147 this.source = new JavaSource();
mcimadamore@1415 148 this.diagChecker = new DiagnosticChecker();
mcimadamore@1415 149 }
mcimadamore@1415 150
mcimadamore@1415 151 class JavaSource extends SimpleJavaFileObject {
mcimadamore@1415 152
mcimadamore@1415 153 String bodyTemplate = "interface SAM { void test(Object o); }\n#B";
mcimadamore@1415 154 String source;
mcimadamore@1415 155
mcimadamore@1415 156 public JavaSource() {
mcimadamore@1415 157 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
mcimadamore@1415 158 source = bodyTemplate.replace("#B",
mcimadamore@1415 159 ek.enclStr.replace("#S", sk.siteStr.replace("#I", ik.innerStr.replace("#R", rk.refStr))));
mcimadamore@1415 160 }
mcimadamore@1415 161
mcimadamore@1415 162 @Override
mcimadamore@1415 163 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
mcimadamore@1415 164 return source;
mcimadamore@1415 165 }
mcimadamore@1415 166 }
mcimadamore@1415 167
mcimadamore@1415 168 void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
mcimadamore@1415 169 JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
mcimadamore@1415 170 null, null, Arrays.asList(source));
mcimadamore@1415 171 try {
mcimadamore@1415 172 ct.analyze();
mcimadamore@1415 173 } catch (Throwable ex) {
mcimadamore@1415 174 throw new AssertionError("Error thron when compiling the following code:\n" + source.getCharContent(true));
mcimadamore@1415 175 }
mcimadamore@1415 176 check();
mcimadamore@1415 177 }
mcimadamore@1415 178
vromero@2148 179 boolean isErrorExpected() {
vromero@2148 180 //illegal forward ref
vromero@2148 181 boolean result = ik.inMethodContext(sk) && (rk.selfRef || rk.forwardRef);
vromero@2148 182 result |= (rk == RefKind.SELF_LAMBDA || rk == RefKind.FORWARD_LAMBDA);
vromero@2148 183 return result;
vromero@2148 184 }
vromero@2148 185
mcimadamore@1415 186 void check() {
vromero@2148 187 checkCount++;
vromero@2148 188 boolean errorExpected = isErrorExpected();
mcimadamore@1415 189 if (diagChecker.errorFound != errorExpected) {
mcimadamore@1415 190 throw new Error("invalid diagnostics for source:\n" +
mcimadamore@1415 191 source.getCharContent(true) +
mcimadamore@1415 192 "\nFound error: " + diagChecker.errorFound +
mcimadamore@1415 193 "\nExpected error: " + errorExpected);
mcimadamore@1415 194 }
mcimadamore@1415 195 }
mcimadamore@1415 196
mcimadamore@1415 197 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
mcimadamore@1415 198
mcimadamore@1415 199 boolean errorFound;
mcimadamore@1415 200
mcimadamore@1415 201 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
mcimadamore@1415 202 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
mcimadamore@1415 203 errorFound = true;
mcimadamore@1415 204 }
mcimadamore@1415 205 }
mcimadamore@1415 206 }
mcimadamore@1415 207 }

mercurial