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  * @summary Smoke test for code reflection with local class creation expressions.
 29  * @modules jdk.incubator.code
 30  * @build LocalClassTest
 31  * @build CodeReflectionTester
 32  * @run main CodeReflectionTester LocalClassTest
 33  */
 34 
 35 import jdk.incubator.code.CodeReflection;
 36 
 37 public class LocalClassTest {
 38 
 39     final static String CONST_STRING = "Hello!";
 40     String nonConstString = "Hello!";
 41 
 42     @CodeReflection
 43     @IR("""
 44             func @"testLocalNoCapture" (%0 : LocalClassTest)void -> {
 45                 %1 : .<LocalClassTest, LocalClassTest$1Foo> = new %0 @"func<.<LocalClassTest, LocalClassTest$1Foo>, LocalClassTest>";
 46                 invoke %1 @".<LocalClassTest, 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     @CodeReflection
 58     @IR("""
 59             func @"testAnonNoCapture" (%0 : LocalClassTest)void -> {
 60                 %1 : .<LocalClassTest, LocalClassTest$1> = new %0 @"func<.<LocalClassTest, LocalClassTest$1>, LocalClassTest>";
 61                 invoke %1 @".<LocalClassTest, LocalClassTest$1>::m()void";
 62                 return;
 63             };
 64             """)
 65     void testAnonNoCapture() {
 66         new Object() {
 67             void m() { }
 68         }.m();
 69     }
 70 
 71     @CodeReflection
 72     @IR("""
 73             func @"testLocalCaptureParam" (%0 : LocalClassTest, %1 : java.lang.String)java.lang.String -> {
 74                 %2 : Var<java.lang.String> = var %1 @"s";
 75                 %3 : java.lang.String = var.load %2;
 76                 %4 : .<LocalClassTest, LocalClassTest$2Foo> = new %0 %3 @"func<.<LocalClassTest, LocalClassTest$2Foo>, LocalClassTest, java.lang.String>";
 77                 %5 : java.lang.String = invoke %4 @".<LocalClassTest, 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     @CodeReflection
 89     @IR("""
 90             func @"testAnonCaptureParam" (%0 : LocalClassTest, %1 : java.lang.String)java.lang.String -> {
 91                 %2 : Var<java.lang.String> = var %1 @"s";
 92                 %3 : java.lang.String = var.load %2;
 93                 %4 : .<LocalClassTest, LocalClassTest$2> = new %0 %3 @"func<.<LocalClassTest, LocalClassTest$2>, LocalClassTest, java.lang.String>";
 94                 %5 : java.lang.String = invoke %4 @".<LocalClassTest, 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     @CodeReflection
105     @IR("""
106             func @"testLocalCaptureParamAndField" (%0 : LocalClassTest, %1 : java.lang.String)java.lang.String -> {
107                 %2 : Var<java.lang.String> = var %1 @"s";
108                 %3 : java.lang.String = constant @"Hello!";
109                 %4 : Var<java.lang.String> = var %3 @"localConst";
110                 %5 : java.lang.String = var.load %2;
111                 %6 : .<LocalClassTest, LocalClassTest$3Foo> = new %0 %5 @"func<.<LocalClassTest, LocalClassTest$3Foo>, LocalClassTest, java.lang.String>";
112                 %7 : java.lang.String = invoke %6 @".<LocalClassTest, 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     @CodeReflection
125     @IR("""
126             func @"testAnonCaptureParamAndField" (%0 : LocalClassTest, %1 : java.lang.String)java.lang.String -> {
127                 %2 : Var<java.lang.String> = var %1 @"s";
128                 %3 : java.lang.String = constant @"Hello!";
129                 %4 : Var<java.lang.String> = var %3 @"localConst";
130                 %5 : java.lang.String = var.load %2;
131                 %6 : .<LocalClassTest, LocalClassTest$3> = new %0 %5 @"func<.<LocalClassTest, LocalClassTest$3>, LocalClassTest, java.lang.String>";
132                 %7 : java.lang.String = invoke %6 @".<LocalClassTest, 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     @CodeReflection
144     @IR("""
145             func @"testLocalDependency" (%0 : LocalClassTest, %1 : int, %2 : int)void -> {
146                 %3 : Var<int> = var %1 @"s";
147                 %4 : Var<int> = var %2 @"i";
148                 %5 : int = var.load %3;
149                 %6 : int = var.load %4;
150                 %7 : .<LocalClassTest, LocalClassTest$1Bar> = new %0 %5 %6 @"func<.<LocalClassTest, 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     @CodeReflection
166     @IR("""
167             func @"testAnonDependency" (%0 : LocalClassTest, %1 : int, %2 : int)void -> {
168                 %3 : Var<int> = var %1 @"s";
169                 %4 : Var<int> = var %2 @"i";
170                 %5 : int = var.load %3;
171                 %6 : int = var.load %4;
172                 %7 : .<LocalClassTest, LocalClassTest$4> = new %0 %5 %6 @"func<.<LocalClassTest, 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 }