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.
  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 import org.testng.Assert;
 25 import org.testng.annotations.DataProvider;
 26 import org.testng.annotations.Test;
 27 
 28 import java.lang.invoke.MethodHandles;
 29 import java.lang.reflect.code.op.CoreOp;
 30 import java.lang.reflect.code.type.FieldRef;
 31 import java.lang.reflect.code.type.MethodRef;
 32 import java.lang.reflect.code.type.RecordTypeRef;
 33 import java.lang.runtime.CodeReflection;
 34 import java.util.Optional;
 35 
 36 /*
 37  * @test
 38  * @run testng TestReferences
 39  */
 40 
 41 public class TestReferences {
 42 
 43     @DataProvider
 44     public Object[][] methodRefs() {
 45         return new Object[][]{
 46                 {"a::b()void", "a", "b"},
 47                 {"a.b::c(int)int", "a.b", "c"},
 48                 {"a.b.c::d(int, int)int", "a.b.c", "d"},
 49                 {"a::b(Func<String, Number>, Entry<List<String>, val>, int, long)void", "a", "b"},
 50                 {"java.io.PrintStream::println(java.lang.String)void", "java.io.PrintStream", "println"},
 51                 {"MethodReferenceTest$A::m(java.lang.Object)java.lang.Object", "MethodReferenceTest$A", "m"},
 52                 {"MethodReferenceTest$X::<new>(int)MethodReferenceTest$X", "MethodReferenceTest$X", "<new>"},
 53                 {"MethodReferenceTest$A[]::<new>(int)MethodReferenceTest$A[]", "MethodReferenceTest$A[]", "<new>"}
 54         };
 55     }
 56 
 57     @Test(dataProvider = "methodRefs")
 58     public void testMethodRef(String mds, String refType, String name) {
 59         MethodRef mr = MethodRef.ofString(mds);
 60         Assert.assertEquals(mr.toString(), mds);
 61         Assert.assertEquals(mr.refType().toString(), refType);
 62         Assert.assertEquals(mr.name(), name);
 63     }
 64 
 65 
 66     @DataProvider
 67     public Object[][] fieldRefs() {
 68         return new Object[][]{
 69                 {"a.b::c()int", "a.b", "c", "int"},
 70                 {"a.b.c::d()int", "a.b.c", "d", "int"},
 71                 {"java.lang.System::out()java.io.PrintStream", "java.lang.System", "out", "java.io.PrintStream"},
 72         };
 73     }
 74 
 75     @Test(dataProvider = "fieldRefs")
 76     public void testFieldRef(String fds, String refType, String name, String type) {
 77         FieldRef fr = FieldRef.ofString(fds);
 78         Assert.assertEquals(fr.toString(), fds);
 79         Assert.assertEquals(fr.refType().toString(), refType);
 80         Assert.assertEquals(fr.name(), name);
 81         Assert.assertEquals(fr.type().toString(), type);
 82     }
 83 
 84 
 85     @DataProvider
 86     public Object[][] recordTypeRefs() {
 87         return new Object[][]{
 88                 {"()A"},
 89                 {"(B b)A"},
 90                 {"(B b, C c)A"},
 91                 {"(p.Func<String, Number> f, Entry<List<String>, val> e, int i, long l)p.A<R>"},
 92         };
 93     }
 94 
 95     @Test(dataProvider = "recordTypeRefs")
 96     public void testRecordTypeRef(String rtds) {
 97         RecordTypeRef rtr = RecordTypeRef.ofString(rtds);
 98         Assert.assertEquals(rtr.toString(), rtds);
 99     }
100 
101 
102     @CodeReflection
103     static void x() {}
104 
105     @Test
106     public void testAccessCodeModel() throws ReflectiveOperationException {
107         MethodRef xr = MethodRef.method(TestReferences.class, "x", void.class);
108         Optional<CoreOp.FuncOp> m = xr.codeModel(MethodHandles.lookup());
109         Assert.assertTrue(m.isPresent());
110     }
111 }