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 * @ignore Reflection on the contents of local classes is not supported.
27 * @summary Smoke test for code reflection with local class creation expressions.
28 * @modules jdk.incubator.code
29 * @build LocalClassTest
30 * @build CodeReflectionTester
31 * @run main CodeReflectionTester LocalClassTest
32 */
33
34 import jdk.incubator.code.Reflect;
35
36 import java.util.function.Supplier;
37
38 public class LocalClassTest {
39
40 final static String CONST_STRING = "Hello!";
41 String nonConstString = "Hello!";
42
43 @Reflect
44 @IR("""
45 func @"testLocalNoCapture" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
46 %1 : java.type:"LocalClassTest::$1Foo" = new %0 @java.ref:"LocalClassTest::$1Foo::(LocalClassTest)";
47 invoke %1 @java.ref:"LocalClassTest::$1Foo::m():void";
48 return;
49 };
50 """)
51 void testLocalNoCapture() {
52 class Foo {
53 void m() { }
54 }
55 new Foo().m();
56 }
57
58 @Reflect
59 @IR("""
60 func @"testAnonNoCapture" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
61 %1 : java.type:"LocalClassTest::$1" = new %0 @java.ref:"LocalClassTest::$1::(LocalClassTest)";
62 invoke %1 @java.ref:"LocalClassTest::$1::m():void";
63 return;
64 };
65 """)
66 void testAnonNoCapture() {
67 new Object() {
68 void m() { }
69 }.m();
70 }
71
72 @Reflect
73 @IR("""
74 func @"testLocalCaptureParam" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
75 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
76 %3 : java.type:"java.lang.String" = var.load %2;
77 %4 : java.type:"LocalClassTest::$2Foo" = new %0 %3 @java.ref:"LocalClassTest::$2Foo::(LocalClassTest, java.lang.String)";
78 %5 : java.type:"java.lang.String" = invoke %4 @java.ref:"LocalClassTest::$2Foo::m():java.lang.String";
79 return %5;
80 };
81 """)
82 String testLocalCaptureParam(String s) {
83 class Foo {
84 String m() { return s; }
85 }
86 return new Foo().m();
87 }
88
89 @Reflect
90 @IR("""
91 func @"testAnonCaptureParam" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
92 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
93 %3 : java.type:"java.lang.String" = var.load %2;
94 %4 : java.type:"LocalClassTest::$2" = new %0 %3 @java.ref:"LocalClassTest::$2::(LocalClassTest, java.lang.String)";
95 %5 : java.type:"java.lang.String" = invoke %4 @java.ref:"LocalClassTest::$2::m():java.lang.String";
96 return %5;
97 };
98 """)
99 String testAnonCaptureParam(String s) {
100 return new Object() {
101 String m() { return s; }
102 }.m();
103 }
104
105 @Reflect
106 @IR("""
107 func @"testLocalCaptureParamAndField" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
108 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
109 %3 : java.type:"java.lang.String" = constant @"Hello!";
110 %4 : Var<java.type:"java.lang.String"> = var %3 @"localConst";
111 %5 : java.type:"java.lang.String" = var.load %2;
112 %6 : java.type:"LocalClassTest::$3Foo" = new %0 %5 @java.ref:"LocalClassTest::$3Foo::(LocalClassTest, java.lang.String)";
113 %7 : java.type:"java.lang.String" = invoke %6 @java.ref:"LocalClassTest::$3Foo::m():java.lang.String";
114 return %7;
115 };
116 """)
117 String testLocalCaptureParamAndField(String s) {
118 final String localConst = "Hello!";
119 class Foo {
120 String m() { return localConst + s + nonConstString + CONST_STRING; }
121 }
122 return new Foo().m();
123 }
124
125 @Reflect
126 @IR("""
127 func @"testAnonCaptureParamAndField" (%0 : java.type:"LocalClassTest", %1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
128 %2 : Var<java.type:"java.lang.String"> = var %1 @"s";
129 %3 : java.type:"java.lang.String" = constant @"Hello!";
130 %4 : Var<java.type:"java.lang.String"> = var %3 @"localConst";
131 %5 : java.type:"java.lang.String" = var.load %2;
132 %6 : java.type:"LocalClassTest::$3" = new %0 %5 @java.ref:"LocalClassTest::$3::(LocalClassTest, java.lang.String)";
133 %7 : java.type:"java.lang.String" = invoke %6 @java.ref:"LocalClassTest::$3::m():java.lang.String";
134 return %7;
135 };
136 """)
137 String testAnonCaptureParamAndField(String s) {
138 final String localConst = "Hello!";
139 return new Object() {
140 String m() { return localConst + s + nonConstString + CONST_STRING; }
141 }.m();
142 }
143
144 @Reflect
145 @IR("""
146 func @"testLocalDependency" (%0 : java.type:"LocalClassTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
147 %3 : Var<java.type:"int"> = var %1 @"s";
148 %4 : Var<java.type:"int"> = var %2 @"i";
149 %5 : java.type:"int" = var.load %3;
150 %6 : java.type:"int" = var.load %4;
151 %7 : java.type:"LocalClassTest::$1Bar" = new %0 %5 %6 @java.ref:"LocalClassTest::$1Bar::(LocalClassTest, int, int)";
152 return;
153 };
154 """)
155 void testLocalDependency(int s, int i) {
156 class Foo {
157 int i() { return i; }
158 }
159 class Bar {
160 int s() { return s; }
161 Foo foo() { return new Foo(); }
162 }
163 new Bar();
164 }
165
166 @Reflect
167 @IR("""
168 func @"testAnonDependency" (%0 : java.type:"LocalClassTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
169 %3 : Var<java.type:"int"> = var %1 @"s";
170 %4 : Var<java.type:"int"> = var %2 @"i";
171 %5 : java.type:"int" = var.load %3;
172 %6 : java.type:"int" = var.load %4;
173 %7 : java.type:"LocalClassTest::$4" = new %0 %5 %6 @java.ref:"LocalClassTest::$4::(LocalClassTest, int, int)";
174 return;
175 };
176 """)
177 void testAnonDependency(int s, int i) {
178 class Foo {
179 int i() { return i; }
180 }
181 new Object() {
182 int s() { return s; }
183 Foo foo() { return new Foo(); }
184 };
185 }
186
187 class Inner { }
188
189 @Reflect
190 @IR("""
191 func @"testImplicitInner" (%0 : java.type:"LocalClassTest")java.type:"void" -> {
192 %1 : java.type:"java.util.function.Supplier<LocalClassTest::Inner>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::Inner" -> {
193 %2 : java.type:"LocalClassTest::Inner" = new %0 @java.ref:"LocalClassTest::Inner::(LocalClassTest)";
194 return %2;
195 };
196 %3 : Var<java.type:"java.util.function.Supplier<LocalClassTest::Inner>"> = var %1 @"aNew";
197 return;
198 };
199 """)
200 void testImplicitInner() {
201 Supplier<Inner> aNew = (@Reflect Supplier<Inner>) () -> new Inner();
202 }
203
204 @Reflect
205 @IR("""
206 func @"testExplicitInner" (%0 : java.type:"LocalClassTest", %1 : java.type:"LocalClassTest")java.type:"void" -> {
207 %2 : Var<java.type:"LocalClassTest"> = var %1 @"test";
208 %3 : java.type:"java.util.function.Supplier<LocalClassTest::Inner>" = lambda @lambda.isReflectable=true ()java.type:"LocalClassTest::Inner" -> {
209 %4 : java.type:"LocalClassTest" = var.load %2;
210 %5 : java.type:"LocalClassTest::Inner" = new %4 @java.ref:"LocalClassTest::Inner::(LocalClassTest)";
211 return %5;
212 };
213 %6 : 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 }