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 package java.lang.reflect.code.type;
 27 
 28 import java.lang.constant.ClassDesc;
 29 import java.lang.constant.MethodTypeDesc;
 30 import java.lang.reflect.code.op.CoreOp;
 31 import java.lang.reflect.code.type.impl.MethodRefImpl;
 32 import java.lang.invoke.MethodHandle;
 33 import java.lang.invoke.MethodHandles;
 34 import java.lang.invoke.MethodType;
 35 import java.lang.reflect.Executable;
 36 import java.lang.reflect.Method;
 37 import java.lang.reflect.code.TypeElement;
 38 import java.util.List;
 39 import java.util.Optional;
 40 
 41 import static java.lang.reflect.code.type.FunctionType.functionType;
 42 
 43 /**
 44  * The symbolic reference to a Java method.
 45  */
 46 // @@@ require invoke kind:
 47 //    special, static, virtual
 48 //    interface_special, interface_static, interface_virtual
 49 //  Otherwise it is not possible to generate correct bytecode invoke instruction with
 50 //  a symbolic reference to a method or an interface method, specifically a
 51 //  constant pool entry of CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info.
 52 //
 53 //  We can infer the kind, if we can resolve the types and lookup the declared method
 54 public sealed interface MethodRef extends TypeVarRef.Owner permits MethodRefImpl {
 55 
 56     TypeElement refType();
 57 
 58     String name();
 59 
 60     FunctionType type();
 61 
 62     // Resolutions and model access
 63 
 64     Executable resolveToMember(MethodHandles.Lookup l) throws ReflectiveOperationException;
 65 
 66     MethodHandle resolveToHandle(MethodHandles.Lookup l) throws ReflectiveOperationException;
 67 
 68     Optional<CoreOp.FuncOp> codeModel(MethodHandles.Lookup l) throws ReflectiveOperationException;
 69 
 70     // Factories
 71 
 72     static MethodRef method(Executable e) {
 73         return method(e.getDeclaringClass(), e.getName(),
 74                 e instanceof Method m ? m.getReturnType() : e.getDeclaringClass(),
 75                 e.getParameterTypes());
 76     }
 77 
 78     static MethodRef method(Class<?> refType, String name, MethodType mt) {
 79         return method(refType, name, mt.returnType(), mt.parameterList());
 80     }
 81 
 82     static MethodRef method(Class<?> refType, String name, Class<?> retType, Class<?>... params) {
 83         return method(refType, name, retType, List.of(params));
 84     }
 85 
 86     static MethodRef method(Class<?> refType, String name, Class<?> retType, List<Class<?>> params) {
 87         return method(JavaType.type(refType), name, JavaType.type(retType), params.stream().map(JavaType::type).toList());
 88     }
 89 
 90 
 91     static MethodRef method(TypeElement refType, String name, FunctionType type) {
 92         return new MethodRefImpl(refType, name, type);
 93     }
 94 
 95     static MethodRef method(TypeElement refType, String name, TypeElement retType, TypeElement... params) {
 96         return method(refType, name, functionType(retType, params));
 97     }
 98 
 99     static MethodRef method(TypeElement refType, String name, TypeElement retType, List<? extends TypeElement> params) {
100         return method(refType, name, functionType(retType, params));
101     }
102 
103     // Copied code in jdk.compiler module throws UOE
104     static MethodRef ofString(String s) {
105 /*__throw new UnsupportedOperationException();__*/        return java.lang.reflect.code.parser.impl.DescParser.parseMethodRef(s);
106     }
107 
108 
109     // MethodTypeDesc factories
110     // @@@ Where else to place them?
111 
112     static FunctionType ofNominalDescriptor(MethodTypeDesc d) {
113         return FunctionType.functionType(
114                 JavaType.type(d.returnType()),
115                 d.parameterList().stream().map(JavaType::type).toList());
116     }
117 
118     static MethodTypeDesc toNominalDescriptor(FunctionType t) {
119         return MethodTypeDesc.of(
120                 toClassDesc(t.returnType()),
121                 t.parameterTypes().stream().map(MethodRef::toClassDesc).toList());
122     }
123 
124     private static ClassDesc toClassDesc(TypeElement e) {
125         if (!(e instanceof JavaType jt)) {
126             throw new IllegalArgumentException();
127         }
128 
129         return jt.toNominalDescriptor();
130     }
131 }