1 /*
2 * Copyright (c) 2024, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 /*
27 * @test
28 * @summary Smoke test for code reflection with local class creation expressions.
29 * @modules jdk.incubator.code
30 * @build LocalClassTest
31 * @build CodeReflectionTester
32 * @run main CodeReflectionTester LocalClassTest
33 */
34
35 import jdk.incubator.code.Reflect;
36
37 import java.util.function.Supplier;
38
39 public class LocalClassTest {
40
41 final static String CONST_STRING = "Hello!";
42 String nonConstString = "Hello!";
43
44 @Reflect
45 @IR("""
46 func @"testLocalNoCapture" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
47 %1 : java.type:"LocalClassTest::$1Foo" = new %0 @java.ref:"LocalClassTest::$1Foo::(LocalClassTest)";
48 invoke %1 @java.ref:"LocalClassTest::$1Foo::m():void";
49 return;
50 };
51 """)
52 void testLocalNoCapture() {
53 class Foo {
54 void m() { }
55 }
56 new Foo().m();
57 }
58
59 @Reflect
60 @IR("""
61 func @"testAnonNoCapture" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
62 %1 : java.type:"LocalClassTest::$1" = new %0 @java.ref:"LocalClassTest::$1::(LocalClassTest)";
63 invoke %1 @java.ref:"LocalClassTest::$1::m():void";
64 return;
65 };
66 """)
67 void testAnonNoCapture() {
68 new Object() {
69 void m() { }
70 }.m();
71 }
72
73 @Reflect
74 @IR("""
75 func @"testLocalCaptureParam" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
76 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
77 %3 : java.type:"java.lang.String" = var.load %2;
78 %4 : java.type:"LocalClassTest::$2Foo" = new %0 %3 @java.ref:"LocalClassTest::$2Foo::(LocalClassTest, java.lang.String)";
79 %5 : java.type:"java.lang.String" = invoke %4 @java.ref:"LocalClassTest::$2Foo::m():java.lang.String";
80 return %5;
81 };
82 """)
83 String testLocalCaptureParam(String s) {
84 class Foo {
85 String m() { return s; }
86 }
87 return new Foo().m();
88 }
89
90 @Reflect
91 @IR("""
92 func @"testAnonCaptureParam" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
93 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
94 %3 : java.type:"java.lang.String" = var.load %2;
95 %4 : java.type:"LocalClassTest::$2" = new %0 %3 @java.ref:"LocalClassTest::$2::(LocalClassTest, java.lang.String)";
96 %5 : java.type:"java.lang.String" = invoke %4 @java.ref:"LocalClassTest::$2::m():java.lang.String";
97 return %5;
98 };
99 """)
100 String testAnonCaptureParam(String s) {
101 return new Object() {
102 String m() { return s; }
103 }.m();
104 }
105
106 @Reflect
107 @IR("""
108 func @"testLocalCaptureParamAndField" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
109 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
110 %3 : java.type:"java.lang.String" = constant @"Hello!";
111 %4 : Var<java.type:"java.lang.String"> = var %3 @"localConst";
112 %5 : java.type:"java.lang.String" = var.load %2;
113 %6 : java.type:"LocalClassTest::$3Foo" = new %0 %5 @java.ref:"LocalClassTest::$3Foo::(LocalClassTest, java.lang.String)";
114 %7 : java.type:"java.lang.String" = invoke %6 @java.ref:"LocalClassTest::$3Foo::m():java.lang.String";
115 return %7;
116 };
117 """)
118 String testLocalCaptureParamAndField(String s) {
119 final String localConst = "Hello!";
120 class Foo {
121 String m() { return localConst + s + nonConstString + CONST_STRING; }
122 }
123 return new Foo().m();
124 }
125
126 @Reflect
127 @IR("""
128 func @"testAnonCaptureParamAndField" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
129 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
130 %3 : java.type:"java.lang.String" = constant @"Hello!";
131 %4 : Var<java.type:"java.lang.String"> = var %3 @"localConst";
132 %5 : java.type:"java.lang.String" = var.load %2;
133 %6 : java.type:"LocalClassTest::$3" = new %0 %5 @java.ref:"LocalClassTest::$3::(LocalClassTest, java.lang.String)";
134 %7 : java.type:"java.lang.String" = invoke %6 @java.ref:"LocalClassTest::$3::m():java.lang.String";
135 return %7;
136 };
137 """)
138 String testAnonCaptureParamAndField(String s) {
139 final String localConst = "Hello!";
140 return new Object() {
141 String m() { return localConst + s + nonConstString + CONST_STRING; }
142 }.m();
143 }
144
145 @Reflect
146 @IR("""
147 func @"testLocalDependency" (%0 : java.type:"LocalClassTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
148 %3 : Var<java.type:"int"> = var %1 @"s";
149 %4 : Var<java.type:"int"> = var %2 @"i";
150 %5 : java.type:"int" = var.load %3;
151 %6 : java.type:"int" = var.load %4;
152 %7 : java.type:"LocalClassTest::$1Bar" = new %0 %5 %6 @java.ref:"LocalClassTest::$1Bar::(LocalClassTest, int, int)";
153 return;
154 };
155 """)
156 void testLocalDependency(int s, int i) {
157 class Foo {
158 int i() { return i; }
159 }
160 class Bar {
161 int s() { return s; }
162 Foo foo() { return new Foo(); }
163 }
164 new Bar();
165 }
166
167 @Reflect
168 @IR("""
169 func @"testAnonDependency" (%0 : java.type:"LocalClassTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
170 %3 : Var<java.type:"int"> = var %1 @"s";
171 %4 : Var<java.type:"int"> = var %2 @"i";
172 %5 : java.type:"int" = var.load %3;
173 %6 : java.type:"int" = var.load %4;
174 %7 : java.type:"LocalClassTest::$4" = new %0 %5 %6 @java.ref:"LocalClassTest::$4::(LocalClassTest, int, int)";
175 return;
176 };
177 """)
178 void testAnonDependency(int s, int i) {
179 class Foo {
180 int i() { return i; }
181 }
182 new Object() {
183 int s() { return s; }
184 Foo foo() { return new Foo(); }
185 };
186 }
187
188 class Inner { }
189
190 @Reflect
191 @IR("""
192 func @"testImplicitInner" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
193 %1 : java.type:"java.util.function.Supplier<LocalClassTest::Inner>" = lambda @lambda.isQuotable=true ()java.type:"LocalClassTest::Inner" -> {
194 %2 : java.type:"LocalClassTest::Inner" = new %0 @java.ref:"LocalClassTest::Inner::(LocalClassTest)";
195 return %2;
196 };
197 %3 : Var<java.type:"java.util.function.Supplier<LocalClassTest::Inner>"> = var %1 @"aNew";
198 return;
199 };
200 """)
201 void testImplicitInner() {
202 Supplier<Inner> aNew = (@Reflect Supplier<Inner>) () -> new Inner();
203 }
204
205 @Reflect
206 @IR("""
207 func @"testExplicitInner" (%0 : java.type:"LocalClassTest", %1 : java.type:"LocalClassTest")java.type:"void" -> {
208 %2 : Var<java.type:"LocalClassTest"> = var %1 @"test";
209 %3 : java.type:"java.util.function.Supplier<LocalClassTest::Inner>" = lambda @lambda.isQuotable=true ()java.type:"LocalClassTest::Inner" -> {
210 %4 : java.type:"LocalClassTest" = var.load %2;
211 %5 : java.type:"LocalClassTest::Inner" = new %4 @java.ref:"LocalClassTest::Inner::(LocalClassTest)";
212 return %5;
213 };
214 %6 : Var<java.type:"java.util.function.Supplier<LocalClassTest::Inner>"> = var %3 @"aNew";
215 return;
216 };
217 """)
218 void testExplicitInner(LocalClassTest test) {
219 Supplier<Inner> aNew = (@Reflect Supplier<Inner>) () -> test.new Inner();
220 }
221
222 @Reflect
223 @IR("""
224 func @"testLocalInMethod" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
225 %1 : java.type:"java.util.function.Supplier<LocalClassTest::$1L>" = lambda @lambda.isQuotable=true ()java.type:"LocalClassTest::$1L" -> {
226 %2 : java.type:"LocalClassTest::$1L" = new %0 @java.ref:"LocalClassTest::$1L::(LocalClassTest)";
227 return %2;
228 };
229 %3 : Var<java.type:"java.util.function.Supplier<LocalClassTest::$1L>"> = var %1 @"aNew";
230 return;
231 };
232 """)
233 void testLocalInMethod() {
234 class L { }
235 Supplier<L> aNew = (@Reflect Supplier<L>) () -> new L();
236 }
237
238 @Reflect
239 @IR("""
240 func @"testLocalInLambda" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
241 %1 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isQuotable=true ()java.type:"java.lang.Object" -> {
242 %2 : java.type:"LocalClassTest::$2L" = new %0 @java.ref:"LocalClassTest::$2L::(LocalClassTest)";
243 return %2;
244 };
245 %3 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %1 @"aNew";
246 return;
247 };
248 """)
249 void testLocalInLambda() {
250 Supplier<Object> aNew = (@Reflect Supplier<Object>) () -> {
251 class L { }
252 return new L();
253 };
254 }
255
256 @Reflect
257 @IR("""
258 func @"testLocalInMethodWithCaptures" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
259 %1 : java.type:"java.lang.String" = constant @"Foo";
260 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
261 %3 : java.type:"java.util.function.Supplier<LocalClassTest::$3L>" = lambda @lambda.isQuotable=true ()java.type:"LocalClassTest::$3L" -> {
262 %4 : java.type:"java.lang.String" = var.load %2;
263 %5 : java.type:"LocalClassTest::$3L" = new %0 %4 @java.ref:"LocalClassTest::$3L::(LocalClassTest, java.lang.String)";
264 return %5;
265 };
266 %6 : Var<java.type:"java.util.function.Supplier<LocalClassTest::$3L>"> = var %3 @"aNew";
267 return;
268 };
269 """)
270 void testLocalInMethodWithCaptures() {
271 String s = "Foo";
272 class L {
273 String s() {
274 return s;
275 }
276 }
277 Supplier<L> aNew = (@Reflect Supplier<L>) () -> new L();
278 }
279
280 @Reflect
281 @IR("""
282 func @"testLocalInLambdaWithCaptures" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
283 %1 : java.type:"java.lang.String" = constant @"Foo";
284 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
285 %3 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isQuotable=true ()java.type:"java.lang.Object" -> {
286 %4 : java.type:"java.lang.String" = var.load %2;
287 %5 : java.type:"LocalClassTest::$4L" = new %0 %4 @java.ref:"LocalClassTest::$4L::(LocalClassTest, java.lang.String)";
288 return %5;
289 };
290 %6 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %3 @"aNew";
291 return;
292 };
293 """)
294 void testLocalInLambdaWithCaptures() {
295 String s = "Foo";
296 Supplier<Object> aNew = (@Reflect Supplier<Object>) () -> {
297 class L {
298 String s() {
299 return s;
300 }
301 }
302 return new L();
303 };
304 }
305 }