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 : java.type:"java.lang.String" = var.load %2;
110 %5 : java.type:"LocalClassTest::$3Foo" = new %0 %4 @java.ref:"LocalClassTest::$3Foo::(LocalClassTest, java.lang.String)";
111 %6 : java.type:"java.lang.String" = invoke %5 @java.ref:"LocalClassTest::$3Foo::m():java.lang.String";
112 return %6;
113 };
114 """)
115 String testLocalCaptureParamAndField(String s) {
116 final String localConst = "Hello!";
117 class Foo {
118 String m() { return localConst + s + nonConstString + CONST_STRING; }
119 }
120 return new Foo().m();
121 }
122
123 @Reflect
124 @IR("""
125 func @"testAnonCaptureParamAndField" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
126 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
127 %3 : java.type:"java.lang.String" = constant @"Hello!";
128 %4 : java.type:"java.lang.String" = var.load %2;
129 %5 : java.type:"LocalClassTest::$3" = new %0 %4 @java.ref:"LocalClassTest::$3::(LocalClassTest, java.lang.String)";
130 %6 : java.type:"java.lang.String" = invoke %5 @java.ref:"LocalClassTest::$3::m():java.lang.String";
131 return %6;
132 };
133 """)
134 String testAnonCaptureParamAndField(String s) {
135 final String localConst = "Hello!";
136 return new Object() {
137 String m() { return localConst + s + nonConstString + CONST_STRING; }
138 }.m();
139 }
140
141 @Reflect
142 @IR("""
143 func @"testLocalDependency" (%0 : java.type:"LocalClassTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
144 %3 : Var<java.type:"int"> = var %1 @"s";
145 %4 : Var<java.type:"int"> = var %2 @"i";
146 %5 : java.type:"int" = var.load %3;
147 %6 : java.type:"int" = var.load %4;
148 %7 : java.type:"LocalClassTest::$1Bar" = new %0 %5 %6 @java.ref:"LocalClassTest::$1Bar::(LocalClassTest, int, int)";
149 return;
150 };
151 """)
152 void testLocalDependency(int s, int i) {
153 class Foo {
154 int i() { return i; }
155 }
156 class Bar {
157 int s() { return s; }
158 Foo foo() { return new Foo(); }
159 }
160 new Bar();
161 }
162
163 @Reflect
164 @IR("""
165 func @"testAnonDependency" (%0 : java.type:"LocalClassTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
166 %3 : Var<java.type:"int"> = var %1 @"s";
167 %4 : Var<java.type:"int"> = var %2 @"i";
168 %5 : java.type:"int" = var.load %3;
169 %6 : java.type:"int" = var.load %4;
170 %7 : java.type:"LocalClassTest::$4" = new %0 %5 %6 @java.ref:"LocalClassTest::$4::(LocalClassTest, int, int)";
171 return;
172 };
173 """)
174 void testAnonDependency(int s, int i) {
175 class Foo {
176 int i() { return i; }
177 }
178 new Object() {
179 int s() { return s; }
180 Foo foo() { return new Foo(); }
181 };
182 }
183
184 class Inner { }
185
186 @Reflect
187 @IR("""
188 func @"testImplicitInner" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
189 %1 : java.type:"java.util.function.Supplier<LocalClassTest::Inner>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::Inner" -> {
190 %2 : java.type:"LocalClassTest::Inner" = new %0 @java.ref:"LocalClassTest::Inner::(LocalClassTest)";
191 return %2;
192 };
193 %3 : Var<java.type:"java.util.function.Supplier<LocalClassTest::Inner>"> = var %1 @"aNew";
194 return;
195 };
196 """)
197 void testImplicitInner() {
198 Supplier<Inner> aNew = (@Reflect Supplier<Inner>) () -> new Inner();
199 }
200
201 @Reflect
202 @IR("""
203 func @"testExplicitInner" (%0 : java.type:"LocalClassTest", %1 : java.type:"LocalClassTest")java.type:"void" -> {
204 %2 : Var<java.type:"LocalClassTest"> = var %1 @"test";
205 %3 : java.type:"java.util.function.Supplier<LocalClassTest::Inner>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::Inner" -> {
206 %4 : java.type:"LocalClassTest" = var.load %2;
207 %5 : java.type:"java.lang.Object" = invoke %4 @java.ref:"java.util.Objects::requireNonNull(java.lang.Object):java.lang.Object";
208 %6 : java.type:"LocalClassTest::Inner" = new %4 @java.ref:"LocalClassTest::Inner::(LocalClassTest)";
209 return %6;
210 };
211 %7 : Var<java.type:"java.util.function.Supplier<LocalClassTest::Inner>"> = var %3 @"aNew";
212 return;
213 };
214 """)
215 void testExplicitInner(LocalClassTest test) {
216 Supplier<Inner> aNew = (@Reflect Supplier<Inner>) () -> test.new Inner();
217 }
218
219 @Reflect
220 @IR("""
221 func @"testLocalInMethod" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
222 %1 : java.type:"java.util.function.Supplier<LocalClassTest::$1L>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::$1L" -> {
223 %2 : java.type:"LocalClassTest::$1L" = new %0 @java.ref:"LocalClassTest::$1L::(LocalClassTest)";
224 return %2;
225 };
226 %3 : Var<java.type:"java.util.function.Supplier<LocalClassTest::$1L>"> = var %1 @"aNew";
227 return;
228 };
229 """)
230 void testLocalInMethod() {
231 class L { }
232 Supplier<L> aNew = (@Reflect Supplier<L>) () -> new L();
233 }
234
235 @Reflect
236 @IR("""
237 func @"testLocalInLambda" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
238 %1 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Object" -> {
239 %2 : java.type:"LocalClassTest::$2L" = new %0 @java.ref:"LocalClassTest::$2L::(LocalClassTest)";
240 return %2;
241 };
242 %3 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %1 @"aNew";
243 return;
244 };
245 """)
246 void testLocalInLambda() {
247 Supplier<Object> aNew = (@Reflect Supplier<Object>) () -> {
248 class L { }
249 return new L();
250 };
251 }
252
253 @Reflect
254 @IR("""
255 func @"testLocalInMethodWithCaptures" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
256 %1 : java.type:"java.lang.String" = constant @"Foo";
257 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
258 %3 : java.type:"java.util.function.Supplier<LocalClassTest::$3L>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::$3L" -> {
259 %4 : java.type:"java.lang.String" = var.load %2;
260 %5 : java.type:"LocalClassTest::$3L" = new %0 %4 @java.ref:"LocalClassTest::$3L::(LocalClassTest, java.lang.String)";
261 return %5;
262 };
263 %6 : Var<java.type:"java.util.function.Supplier<LocalClassTest::$3L>"> = var %3 @"aNew";
264 return;
265 };
266 """)
267 void testLocalInMethodWithCaptures() {
268 String s = "Foo";
269 class L {
270 String s() {
271 return s;
272 }
273 }
274 Supplier<L> aNew = (@Reflect Supplier<L>) () -> new L();
275 }
276
277 @Reflect
278 @IR("""
279 func @"testLocalInLambdaWithCaptures" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
280 %1 : java.type:"java.lang.String" = constant @"Foo";
281 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
282 %3 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Object" -> {
283 %4 : java.type:"java.lang.String" = var.load %2;
284 %5 : java.type:"LocalClassTest::$4L" = new %0 %4 @java.ref:"LocalClassTest::$4L::(LocalClassTest, java.lang.String)";
285 return %5;
286 };
287 %6 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %3 @"aNew";
288 return;
289 };
290 """)
291 void testLocalInLambdaWithCaptures() {
292 String s = "Foo";
293 Supplier<Object> aNew = (@Reflect Supplier<Object>) () -> {
294 class L {
295 String s() {
296 return s;
297 }
298 }
299 return new L();
300 };
301 }
302
303 @Reflect
304 @IR("""
305 func @"testAnonInLambda" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
306 %1 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Object" -> {
307 %2 : java.type:"LocalClassTest::$5" = new %0 @java.ref:"LocalClassTest::$5::(LocalClassTest)";
308 return %2;
309 };
310 %3 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %1 @"so";
311 return;
312 };
313 """)
314 void testAnonInLambda() {
315 Supplier<Object> so = () -> new Object() { };
316 }
317 }