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:
Alexander Udalov
2015-11-05 19:32:02 +03:00
parent 7d32524754
commit 1576160390
17 changed files with 203 additions and 72 deletions
@@ -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();
}
}