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