Improve implementation of callable reference superclasses
Previously to use reflection on them, you had to wrap an already created object with a "Reflection.function" or "Reflection.propertyN" call, which the JVM back-end was doing. This was not optimal in several senses and current solution fixes that
This commit is contained in:
@@ -17,10 +17,7 @@
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.jvm.KotlinReflectionNotSupportedError;
|
||||
import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KDeclarationContainer;
|
||||
import kotlin.reflect.KParameter;
|
||||
import kotlin.reflect.KType;
|
||||
import kotlin.reflect.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
@@ -32,7 +29,11 @@ import java.util.Map;
|
||||
*
|
||||
* All methods from reflection API should be implemented here to throw informative exceptions (see KotlinReflectionNotSupportedError)
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "NullableProblems"})
|
||||
public abstract class CallableReference implements KCallable {
|
||||
protected KCallable reflected;
|
||||
|
||||
protected abstract KCallable computeReflected();
|
||||
|
||||
// The following methods provide the information identifying this callable, which is used by the reflection implementation.
|
||||
// They are supposed to be overridden in each subclass (each anonymous class generated for a callable reference).
|
||||
@@ -41,7 +42,7 @@ public abstract class CallableReference implements KCallable {
|
||||
* @return the class or package where the callable should be located, usually specified on the LHS of the '::' operator
|
||||
*/
|
||||
public KDeclarationContainer getOwner() {
|
||||
throw error();
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +50,7 @@ public abstract class CallableReference implements KCallable {
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
throw error();
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +62,7 @@ public abstract class CallableReference implements KCallable {
|
||||
* but only as a unique and unambiguous way to map a function/property descriptor to a string.
|
||||
*/
|
||||
public String getSignature() {
|
||||
throw error();
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
// The following methods are the stub implementations of reflection functions.
|
||||
@@ -69,30 +70,41 @@ public abstract class CallableReference implements KCallable {
|
||||
|
||||
@Override
|
||||
public List<KParameter> getParameters() {
|
||||
throw error();
|
||||
return getReflected().getParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KType getReturnType() {
|
||||
throw error();
|
||||
return getReflected().getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Annotation> getAnnotations() {
|
||||
throw error();
|
||||
return getReflected().getAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(@NotNull Object... args) {
|
||||
throw error();
|
||||
return getReflected().call(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object callBy(@NotNull Map args) {
|
||||
throw error();
|
||||
return getReflected().callBy(args);
|
||||
}
|
||||
|
||||
protected static Error error() {
|
||||
throw new KotlinReflectionNotSupportedError();
|
||||
public KCallable compute() {
|
||||
if (reflected == null) {
|
||||
reflected = computeReflected();
|
||||
}
|
||||
return reflected;
|
||||
}
|
||||
|
||||
protected KCallable getReflected() {
|
||||
compute();
|
||||
if (reflected == this) {
|
||||
throw new KotlinReflectionNotSupportedError();
|
||||
}
|
||||
return reflected;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,15 +17,20 @@
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.jvm.KotlinReflectionNotSupportedError;
|
||||
import kotlin.reflect.*;
|
||||
import kotlin.reflect.KDeclarationContainer;
|
||||
import kotlin.reflect.KFunction;
|
||||
import kotlin.reflect.KParameter;
|
||||
import kotlin.reflect.KType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings({"unchecked", "NullableProblems"})
|
||||
public class FunctionReference extends FunctionImpl implements KFunction {
|
||||
private final int arity;
|
||||
private KFunction reflected;
|
||||
|
||||
public FunctionReference(int arity) {
|
||||
this.arity = arity;
|
||||
@@ -39,56 +44,57 @@ public class FunctionReference extends FunctionImpl implements KFunction {
|
||||
// Most of the following methods are copies from CallableReference, since this class cannot inherit from it
|
||||
|
||||
public KDeclarationContainer getOwner() {
|
||||
throw error();
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
throw error();
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
throw error();
|
||||
throw new AbstractMethodError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<KParameter> getParameters() {
|
||||
throw error();
|
||||
return getReflected().getParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KType getReturnType() {
|
||||
throw error();
|
||||
return getReflected().getReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Annotation> getAnnotations() {
|
||||
throw error();
|
||||
return getReflected().getAnnotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object call(@NotNull Object... args) {
|
||||
throw error();
|
||||
return getReflected().call(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object callBy(@NotNull Map args) {
|
||||
throw error();
|
||||
}
|
||||
|
||||
protected static Error error() {
|
||||
throw new KotlinReflectionNotSupportedError();
|
||||
return getReflected().callBy(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (!(obj instanceof FunctionReference)) return false;
|
||||
|
||||
FunctionReference other = (FunctionReference) obj;
|
||||
return getOwner().equals(other.getOwner()) &&
|
||||
getName().equals(other.getName()) &&
|
||||
getSignature().equals(other.getSignature());
|
||||
if (obj instanceof FunctionReference) {
|
||||
FunctionReference other = (FunctionReference) obj;
|
||||
return getOwner().equals(other.getOwner()) &&
|
||||
getName().equals(other.getName()) &&
|
||||
getSignature().equals(other.getSignature());
|
||||
}
|
||||
if (obj instanceof KFunction) {
|
||||
compute();
|
||||
return obj.equals(reflected);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -98,9 +104,29 @@ public class FunctionReference extends FunctionImpl implements KFunction {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
compute();
|
||||
if (reflected != this) {
|
||||
return reflected.toString();
|
||||
}
|
||||
|
||||
// TODO: consider adding the class name to toString() for constructors
|
||||
return "<init>".equals(getName())
|
||||
? "constructor" + Reflection.REFLECTION_NOT_AVAILABLE
|
||||
: "function " + getName() + Reflection.REFLECTION_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
public KFunction compute() {
|
||||
if (reflected == null) {
|
||||
reflected = Reflection.function(this);
|
||||
}
|
||||
return reflected;
|
||||
}
|
||||
|
||||
private KFunction getReflected() {
|
||||
compute();
|
||||
if (reflected == this) {
|
||||
throw new KotlinReflectionNotSupportedError();
|
||||
}
|
||||
return reflected;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,27 +16,33 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KMutableProperty0;
|
||||
import kotlin.reflect.KProperty0;
|
||||
|
||||
public class MutablePropertyReference0 extends MutablePropertyReference implements KMutableProperty0 {
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.mutableProperty0(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get() {
|
||||
throw error();
|
||||
return ((KMutableProperty0) getReflected()).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Object value) {
|
||||
throw error();
|
||||
((KMutableProperty0) getReflected()).set(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KProperty0.Getter getGetter() {
|
||||
throw error();
|
||||
return ((KMutableProperty0) getReflected()).getGetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KMutableProperty0.Setter getSetter() {
|
||||
throw error();
|
||||
return ((KMutableProperty0) getReflected()).getSetter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,27 +16,33 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KMutableProperty1;
|
||||
import kotlin.reflect.KProperty1;
|
||||
|
||||
public class MutablePropertyReference1 extends MutablePropertyReference implements KMutableProperty1 {
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.mutableProperty1(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object receiver) {
|
||||
throw error();
|
||||
return ((KMutableProperty1) getReflected()).get(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Object receiver, Object value) {
|
||||
throw error();
|
||||
((KMutableProperty1) getReflected()).set(receiver, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KProperty1.Getter getGetter() {
|
||||
throw error();
|
||||
return ((KMutableProperty1) getReflected()).getGetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KMutableProperty1.Setter getSetter() {
|
||||
throw error();
|
||||
return ((KMutableProperty1) getReflected()).getSetter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,27 +16,33 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KMutableProperty2;
|
||||
import kotlin.reflect.KProperty2;
|
||||
|
||||
public class MutablePropertyReference2 extends MutablePropertyReference implements KMutableProperty2 {
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.mutableProperty2(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object receiver1, Object receiver2) {
|
||||
throw error();
|
||||
return ((KMutableProperty2) getReflected()).get(receiver1, receiver2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Object receiver1, Object receiver2, Object value) {
|
||||
throw error();
|
||||
((KMutableProperty2) getReflected()).set(receiver1, receiver2, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KProperty2.Getter getGetter() {
|
||||
throw error();
|
||||
return ((KMutableProperty2) getReflected()).getGetter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KMutableProperty2.Setter getSetter() {
|
||||
throw error();
|
||||
return ((KMutableProperty2) getReflected()).getSetter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,12 +22,17 @@ public abstract class PropertyReference extends CallableReference implements KPr
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (!(obj instanceof PropertyReference)) return false;
|
||||
|
||||
PropertyReference other = (PropertyReference) obj;
|
||||
return getOwner().equals(other.getOwner()) &&
|
||||
getName().equals(other.getName()) &&
|
||||
getSignature().equals(other.getSignature());
|
||||
if (obj instanceof PropertyReference) {
|
||||
PropertyReference other = (PropertyReference) obj;
|
||||
return getOwner().equals(other.getOwner()) &&
|
||||
getName().equals(other.getName()) &&
|
||||
getSignature().equals(other.getSignature());
|
||||
}
|
||||
if (obj instanceof KProperty) {
|
||||
compute();
|
||||
return obj.equals(reflected);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -37,6 +42,11 @@ public abstract class PropertyReference extends CallableReference implements KPr
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
compute();
|
||||
if (reflected != this) {
|
||||
return reflected.toString();
|
||||
}
|
||||
|
||||
return "property " + getName() + Reflection.REFLECTION_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,16 +16,22 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KProperty0;
|
||||
|
||||
public class PropertyReference0 extends PropertyReference implements KProperty0 {
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.property0(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get() {
|
||||
throw error();
|
||||
return ((KProperty0) getReflected()).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KProperty0.Getter getGetter() {
|
||||
throw error();
|
||||
return ((KProperty0) getReflected()).getGetter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,16 +16,22 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KProperty1;
|
||||
|
||||
public class PropertyReference1 extends PropertyReference implements KProperty1 {
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.property1(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object receiver) {
|
||||
throw error();
|
||||
return ((KProperty1) getReflected()).get(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KProperty1.Getter getGetter() {
|
||||
throw error();
|
||||
return ((KProperty1) getReflected()).getGetter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,16 +16,22 @@
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
|
||||
import kotlin.reflect.KCallable;
|
||||
import kotlin.reflect.KProperty2;
|
||||
|
||||
public class PropertyReference2 extends PropertyReference implements KProperty2 {
|
||||
@Override
|
||||
protected KCallable computeReflected() {
|
||||
return Reflection.property2(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(Object receiver1, Object receiver2) {
|
||||
throw error();
|
||||
return ((KProperty2) getReflected()).get(receiver1, receiver2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KProperty2.Getter getGetter() {
|
||||
throw error();
|
||||
return ((KProperty2) getReflected()).getGetter();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user