test/tools/javac/lambda/TestSelfRef.java

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

mercurial