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:"java.lang.Object" = invoke %4 @java.ref:"java.util.Objects::requireNonNull(java.lang.Object):java.lang.Object";
210 %6 : java.type:"LocalClassTest::Inner" = new %5 @java.ref:"LocalClassTest::Inner::(LocalClassTest)";
211 return %6;
212 };
213 %7 : Var<java.type:"java.util.function.Supplier<LocalClassTest::Inner>"> = var %3 @"aNew";
214 return;
215 };
216 """)
217 void testExplicitInner(LocalClassTest test) {
218 Supplier<Inner> aNew = (@Reflect Supplier<Inner>) () -> test.new Inner();
219 }
220
221 @Reflect
222 @IR("""
223 func @"testLocalInMethod" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
224 %1 : java.type:"java.util.function.Supplier<LocalClassTest::$1L>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::$1L" -> {
225 %2 : java.type:"LocalClassTest::$1L" = new %0 @java.ref:"LocalClassTest::$1L::(LocalClassTest)";
226 return %2;
227 };
228 %3 : Var<java.type:"java.util.function.Supplier<LocalClassTest::$1L>"> = var %1 @"aNew";
229 return;
230 };
231 """)
232 void testLocalInMethod() {
233 class L { }
234 Supplier<L> aNew = (@Reflect Supplier<L>) () -> new L();
235 }
236
237 @Reflect
238 @IR("""
239 func @"testLocalInLambda" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
240 %1 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Object" -> {
241 %2 : java.type:"LocalClassTest::$2L" = new %0 @java.ref:"LocalClassTest::$2L::(LocalClassTest)";
242 return %2;
243 };
244 %3 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %1 @"aNew";
245 return;
246 };
247 """)
248 void testLocalInLambda() {
249 Supplier<Object> aNew = (@Reflect Supplier<Object>) () -> {
250 class L { }
251 return new L();
252 };
253 }
254
255 @Reflect
256 @IR("""
257 func @"testLocalInMethodWithCaptures" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
258 %1 : java.type:"java.lang.String" = constant @"Foo";
259 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
260 %3 : java.type:"java.util.function.Supplier<LocalClassTest::$3L>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::$3L" -> {
261 %4 : java.type:"java.lang.String" = var.load %2;
262 %5 : java.type:"LocalClassTest::$3L" = new %0 %4 @java.ref:"LocalClassTest::$3L::(LocalClassTest, java.lang.String)";
263 return %5;
264 };
265 %6 : Var<java.type:"java.util.function.Supplier<LocalClassTest::$3L>"> = var %3 @"aNew";
266 return;
267 };
268 """)
269 void testLocalInMethodWithCaptures() {
270 String s = "Foo";
271 class L {
272 String s() {
273 return s;
274 }
275 }
276 Supplier<L> aNew = (@Reflect Supplier<L>) () -> new L();
277 }
278
279 @Reflect
280 @IR("""
281 func @"testLocalInLambdaWithCaptures" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
282 %1 : java.type:"java.lang.String" = constant @"Foo";
283 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
284 %3 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Object" -> {
285 %4 : java.type:"java.lang.String" = var.load %2;
286 %5 : java.type:"LocalClassTest::$4L" = new %0 %4 @java.ref:"LocalClassTest::$4L::(LocalClassTest, java.lang.String)";
287 return %5;
288 };
289 %6 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %3 @"aNew";
290 return;
291 };
292 """)
293 void testLocalInLambdaWithCaptures() {
294 String s = "Foo";
295 Supplier<Object> aNew = (@Reflect Supplier<Object>) () -> {
296 class L {
297 String s() {
298 return s;
299 }
300 }
301 return new L();
302 };
303 }
304
305 @Reflect
306 @IR("""
307 func @"testAnonInLambda" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
308 %1 : java.type:"java.util.function.Supplier<java.lang.Object>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Object" -> {
309 %2 : java.type:"LocalClassTest::$5" = new %0 @java.ref:"LocalClassTest::$5::(LocalClassTest)";
310 return %2;
311 };
312 %3 : Var<java.type:"java.util.function.Supplier<java.lang.Object>"> = var %1 @"so";
313 return;
314 };
315 """)
316 void testAnonInLambda() {
317 Supplier<Object> so = () -> new Object() { };
318 }
319 }