All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.teavm.model.MethodReference Maven / Gradle / Ivy

There is a newer version: 0.10.2
Show newest version
/*
 *  Copyright 2013 Alexey Andreev.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.teavm.model;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Stream;

/**
 * 

Specifies a fully qualified name of a method, including its name, class name, parameter types * and return value type. This class overloads equals and hashCode * so that any two references to one method are considered equal.

* *

Though in Java language it is enough to have only parameter types to uniquely identify * a method, JVM uses return value as well. Java generates bridge methods to make * adjust the JVM's behavior.

* * @author Alexey Andreev */ public class MethodReference implements Serializable { private String className; private MethodDescriptor descriptor; private transient int hash; public MethodReference(String className, MethodDescriptor descriptor) { this.className = className; this.descriptor = descriptor; } /** *

Creates a new reference to a method.

* *

For example, here is how you should call this constructor to create a reference to * the Integer.valueOf(int) method: * *

     * new MethodReference("java.lang.Integer", "valueOf",
     *         ValueType.INT, ValueType.object("java.lang.Integer"))
     * 
* * @param className the name of the class that owns the method. * @param name the name of the method. * @param signature descriptor of a method, as described in VM spec. The last element is * a type of a returning value, and all the remaining elements are types of arguments. */ public MethodReference(String className, String name, ValueType... signature) { this(className, new MethodDescriptor(name, signature)); } public MethodReference(Class cls, String name, Class... signature) { this(cls.getName(), name, convertSignature(signature)); } private static ValueType[] convertSignature(Class... signature) { ValueType[] types = new ValueType[signature.length]; for (int i = 0; i < types.length; ++i) { types[i] = ValueType.parse(signature[i]); } return types; } public String getClassName() { return className; } public MethodDescriptor getDescriptor() { return descriptor; } public int parameterCount() { return descriptor.parameterCount(); } public ValueType parameterType(int index) { return descriptor.parameterType(index); } public ValueType[] getParameterTypes() { return descriptor.getParameterTypes(); } public ValueType[] getSignature() { return descriptor.getSignature(); } public ValueType getReturnType() { return descriptor.getResultType(); } public String getName() { return descriptor.getName(); } @Override public int hashCode() { if (hash == 0) { hash = (className.hashCode() * 31 + descriptor.hashCode()) * 17; if (hash == 0) { hash++; } } return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof MethodReference)) { return false; } MethodReference other = (MethodReference) obj; return className.equals(other.className) && descriptor.equals(other.descriptor); } @Override @JsonValue public String toString() { return className + "." + getDescriptor().toString(); } @JsonCreator public static MethodReference parse(String string) { MethodReference reference = parseIfPossible(string); if (reference == null) { throw new IllegalArgumentException("Illegal method reference: " + string); } return reference; } public static MethodReference parseIfPossible(String string) { int index = string.lastIndexOf('.'); if (index < 1) { return null; } String className = string.substring(0, index); MethodDescriptor desc = MethodDescriptor.parseIfPossible(string.substring(index + 1)); return desc != null ? new MethodReference(className, desc) : null; } public static MethodReference parse(Method method) { ValueType[] signature = Stream.concat(Arrays.stream(method.getParameterTypes()).map(ValueType::parse), Stream.of(ValueType.parse(method.getReturnType()))).toArray(ValueType[]::new); return new MethodReference(method.getDeclaringClass().getName(), method.getName(), signature); } public String signatureToString() { return getDescriptor().signatureToString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy