1 /*
2 * Copyright (c) 2024, 2026, 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 * @summary Smoke test for code reflection with local class creation expressions.
27 * @modules jdk.incubator.code
28 * @build LocalClassTest
29 * @build CodeReflectionTester
30 * @run main CodeReflectionTester LocalClassTest
31 */
32
33 import jdk.incubator.code.Reflect;
34
35 import java.util.function.Supplier;
36
37 public class LocalClassTest {
38
39 final static String CONST_STRING = "Hello!";
40 String nonConstString = "Hello!";
41
42 @Reflect
43 @IR("""
44 func @"testLocalNoCapture" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
45 %1 : java.type:"LocalClassTest::$1Foo" = new %0 @java.ref:"LocalClassTest::$1Foo::(LocalClassTest)";
46 invoke %1 @java.ref:"LocalClassTest::$1Foo::m():void";
47 return;
48 };
49 """)
50 void testLocalNoCapture() {
51 class Foo {
52 void m() { }
53 }
54 new Foo().m();
55 }
56
57 @Reflect
58 @IR("""
59 func @"testAnonNoCapture" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
60 %1 : java.type:"LocalClassTest::$1" = new %0 @java.ref:"LocalClassTest::$1::(LocalClassTest)";
61 invoke %1 @java.ref:"LocalClassTest::$1::m():void";
62 return;
63 };
64 """)
65 void testAnonNoCapture() {
66 new Object() {
67 void m() { }
68 }.m();
69 }
70
71 @Reflect
72 @IR("""
73 func @"testLocalCaptureParam" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
74 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
75 %3 : java.type:"java.lang.String" = var.load %2;
76 %4 : java.type:"LocalClassTest::$2Foo" = new %0 %3 @java.ref:"LocalClassTest::$2Foo::(LocalClassTest, java.lang.String)";
77 %5 : java.type:"java.lang.String" = invoke %4 @java.ref:"LocalClassTest::$2Foo::m():java.lang.String";
78 return %5;
79 };
80 """)
81 String testLocalCaptureParam(String s) {
82 class Foo {
83 String m() { return s; }
84 }
85 return new Foo().m();
86 }
87
88 @Reflect
89 @IR("""
90 func @"testAnonCaptureParam" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
91 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
92 %3 : java.type:"java.lang.String" = var.load %2;
93 %4 : java.type:"LocalClassTest::$2" = new %0 %3 @java.ref:"LocalClassTest::$2::(LocalClassTest, java.lang.String)";
94 %5 : java.type:"java.lang.String" = invoke %4 @java.ref:"LocalClassTest::$2::m():java.lang.String";
95 return %5;
96 };
97 """)
98 String testAnonCaptureParam(String s) {
99 return new Object() {
100 String m() { return s; }
101 }.m();
102 }
103
104 @Reflect
105 @IR("""
106 func @"testLocalCaptureParamAndField" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
107 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
108 %3 : java.type:"java.lang.String" = constant @"Hello!";
109 %4 : Var<java.type:"java.lang.String"> = var %3 @"localConst";
110 %5 : java.type:"java.lang.String" = var.load %2;
111 %6 : java.type:"LocalClassTest::$3Foo" = new %0 %5 @java.ref:"LocalClassTest::$3Foo::(LocalClassTest, java.lang.String)";
112 %7 : java.type:"java.lang.String" = invoke %6 @java.ref:"LocalClassTest::$3Foo::m():java.lang.String";
113 return %7;
114 };
115 """)
116 String testLocalCaptureParamAndField(String s) {
117 final String localConst = "Hello!";
118 class Foo {
119 String m() { return localConst + s + nonConstString + CONST_STRING; }
120 }
121 return new Foo().m();
122 }
123
124 @Reflect
125 @IR("""
126 func @"testAnonCaptureParamAndField" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
127 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
128 %3 : java.type:"java.lang.String" = constant @"Hello!";
129 %4 : Var<java.type:"java.lang.String"> = var %3 @"localConst";
130 %5 : java.type:"java.lang.String" = var.load %2;
131 %6 : java.type:"LocalClassTest::$3" = new %0 %5 @java.ref:"LocalClassTest::$3::(LocalClassTest, java.lang.String)";
132 %7 : java.type:"java.lang.String" = invoke %6 @java.ref:"LocalClassTest::$3::m():java.lang.String";
133 return %7;
134 };
135 """)
136 String testAnonCaptureParamAndField(String s) {
137 final String localConst = "Hello!";
138 return new Object() {
139 String m() { return localConst + s + nonConstString + CONST_STRING; }
140 }.m();
141 }
142
143 @Reflect
144 @IR("""
145 func @"testLocalDependency" (%0 : java.type:"LocalClassTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
146 %3 : Var<java.type:"int"> = var %1 @"s";
147 %4 : Var<java.type:"int"> = var %2 @"i";
148 %5 : java.type:"int" = var.load %3;
149 %6 : java.type:"int" = var.load %4;
150 %7 : java.type:"LocalClassTest::$1Bar" = new %0 %5 %6 @java.ref:"LocalClassTest::$1Bar::(LocalClassTest, int, int)";
151 return;
152 };
153 """)
154 void testLocalDependency(int s, int i) {
155 class Foo {
156 int i() { return i; }
157 }
158 class Bar {
159 int s() { return s; }
160 Foo foo() { return new Foo(); }
161 }
162 new Bar();
163 }
164
165 @Reflect
166 @IR("""
167 func @"testAnonDependency" (%0 : java.type:"LocalClassTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
168 %3 : Var<java.type:"int"> = var %1 @"s";
169 %4 : Var<java.type:"int"> = var %2 @"i";
170 %5 : java.type:"int" = var.load %3;
171 %6 : java.type:"int" = var.load %4;
172 %7 : java.type:"LocalClassTest::$4" = new %0 %5 %6 @java.ref:"LocalClassTest::$4::(LocalClassTest, int, int)";
173 return;
174 };
175 """)
176 void testAnonDependency(int s, int i) {
177 class Foo {
178 int i() { return i; }
179 }
180 new Object() {
181 int s() { return s; }
182 Foo foo() { return new Foo(); }
183 };
184 }
185
186 class Inner { }
187
188 @Reflect
189 @IR("""
190 func @"testImplicitInner" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
191 %1 : java.type:"java.util.function.Supplier<LocalClassTest::Inner>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::Inner" -> {
192 %2 : java.type:"LocalClassTest::Inner" = new %0 @java.ref:"LocalClassTest::Inner::(LocalClassTest)";
193 return %2;
194 };
195 %3 : Var<java.type:"java.util.function.Supplier<LocalClassTest::Inner>"> = var %1 @"aNew";
196 return;
197 };
198 """)
199 void testImplicitInner() {
200 Supplier<Inner> aNew = (@Reflect Supplier<Inner>) () -> new Inner();
201 }
202
203 @Reflect
204 @IR("""
205 func @"testExplicitInner" (%0 : java.type:"LocalClassTest", %1 : java.type:"LocalClassTest")java.type:"void" -> {
206 %2 : Var<java.type:"LocalClassTest"> = var %1 @"test";
207 %3 : java.type:"java.util.function.Supplier<LocalClassTest::Inner>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::Inner" -> {
208 %4 : java.type:"LocalClassTest" = var.load %2;
209 %5 : java.type:"LocalClassTest::Inner" = new %4 @java.ref:"LocalClassTest::Inner::(LocalClassTest)";
210 return %5;
211 };
212 %6 : Var<java.type:"java.util.function.Supplier<LocalClassTest::Inner>"> = var %3 @"aNew";
213 return;
214 };
215 """)
216 void testExplicitInner(LocalClassTest test) {
217 Supplier<Inner> aNew = (@Reflect Supplier<Inner>) () -> test.new Inner();
218 }
219
220 @Reflect
221 @IR("""
222 func @"testLocalInMethod" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
223 %1 : java.type:"java.util.function.Supplier<LocalClassTest::$1L>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::$1L" -> {
224 %2 : java.type:"LocalClassTest::$1L" = new %0 @java.ref:"LocalClassTest::$1L::(LocalClassTest)";
225 return %2;
226 };
227 %3 : Var<java.type:"java.util.function.Supplier<LocalClassTest::$1L>"> = var %1 @"aNew";
228 return;
229 };
230 """)
231 void testLocalInMethod() {
232 class L { }
233 Supplier<L> aNew = (@Reflect Supplier<L>) () -> new L();
234 }
235
236 @Reflect
237 @IR("""
238 func @"testLocalInLambda" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
239 %1 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Object" -> {
240 %2 : java.type:"LocalClassTest::$2L" = new %0 @java.ref:"LocalClassTest::$2L::(LocalClassTest)";
241 return %2;
242 };
243 %3 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %1 @"aNew";
244 return;
245 };
246 """)
247 void testLocalInLambda() {
248 Supplier<Object> aNew = (@Reflect Supplier<Object>) () -> {
249 class L { }
250 return new L();
251 };
252 }
253
254 @Reflect
255 @IR("""
256 func @"testLocalInMethodWithCaptures" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
257 %1 : java.type:"java.lang.String" = constant @"Foo";
258 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
259 %3 : java.type:"java.util.function.Supplier<LocalClassTest::$3L>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::$3L" -> {
260 %4 : java.type:"java.lang.String" = var.load %2;
261 %5 : java.type:"LocalClassTest::$3L" = new %0 %4 @java.ref:"LocalClassTest::$3L::(LocalClassTest, java.lang.String)";
262 return %5;
263 };
264 %6 : Var<java.type:"java.util.function.Supplier<LocalClassTest::$3L>"> = var %3 @"aNew";
265 return;
266 };
267 """)
268 void testLocalInMethodWithCaptures() {
269 String s = "Foo";
270 class L {
271 String s() {
272 return s;
273 }
274 }
275 Supplier<L> aNew = (@Reflect Supplier<L>) () -> new L();
276 }
277
278 @Reflect
279 @IR("""
280 func @"testLocalInLambdaWithCaptures" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
281 %1 : java.type:"java.lang.String" = constant @"Foo";
282 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
283 %3 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Object" -> {
284 %4 : java.type:"java.lang.String" = var.load %2;
285 %5 : java.type:"LocalClassTest::$4L" = new %0 %4 @java.ref:"LocalClassTest::$4L::(LocalClassTest, java.lang.String)";
286 return %5;
287 };
288 %6 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %3 @"aNew";
289 return;
290 };
291 """)
292 void testLocalInLambdaWithCaptures() {
293 String s = "Foo";
294 Supplier<Object> aNew = (@Reflect Supplier<Object>) () -> {
295 class L {
296 String s() {
297 return s;
298 }
299 }
300 return new L();
301 };
302 }
303
304 @Reflect
305 @IR("""
306 func @"testAnonInLambda" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
307 %1 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Object" -> {
308 %2 : java.type:"LocalClassTest::$5" = new %0 @java.ref:"LocalClassTest::$5::(LocalClassTest)";
309 return %2;
310 };
311 %3 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %1 @"so";
312 return;
313 };
314 """)
315 void testAnonInLambda() {
316 Supplier<Object> so = () -> new Object() { };
317 }
318 }