Inherit FunctionReference from CallableReference

This became possible now because FunctionImpl is no longer a class
This commit is contained in:
Alexander Udalov
2016-09-07 13:31:00 +03:00
parent a10cf8a931
commit d128827a34
4 changed files with 36 additions and 119 deletions
@@ -105,9 +105,4 @@ public class ReflectionFactoryImpl extends ReflectionFactory {
KDeclarationContainer owner = reference.getOwner(); KDeclarationContainer owner = reference.getOwner();
return owner instanceof KDeclarationContainerImpl ? ((KDeclarationContainerImpl) owner) : EmptyContainerForLocal.INSTANCE; return owner instanceof KDeclarationContainerImpl ? ((KDeclarationContainerImpl) owner) : EmptyContainerForLocal.INSTANCE;
} }
private static KDeclarationContainerImpl getOwner(FunctionReference reference) {
KDeclarationContainer owner = reference.getOwner();
return owner instanceof KDeclarationContainerImpl ? ((KDeclarationContainerImpl) owner) : EmptyContainerForLocal.INSTANCE;
}
} }
@@ -28,14 +28,36 @@ import java.util.Map;
/** /**
* A superclass for all classes generated by Kotlin compiler for callable references. * A superclass for all classes generated by Kotlin compiler for callable references.
* *
* All methods from reflection API should be implemented here to throw informative exceptions (see KotlinReflectionNotSupportedError) * All methods from KCallable should be implemented here and should delegate to the actual implementation, loaded dynamically
* and stored in the {@link CallableReference#reflected} field.
*/ */
@SuppressWarnings({"unchecked", "NullableProblems"}) @SuppressWarnings({"unchecked", "NullableProblems"})
public abstract class CallableReference implements KCallable { public abstract class CallableReference implements KCallable {
protected KCallable reflected; // This field is not volatile intentionally:
// 1) It's fine if the value is computed multiple times in different threads;
// 2) An uninitialized value cannot be observed in this field from other thread because only already initialized or safely initialized
// objects are written to it. The latter is guaranteed because both KFunctionImpl and KPropertyImpl have at least one final field.
private KCallable reflected;
protected abstract KCallable computeReflected(); protected abstract KCallable computeReflected();
public KCallable compute() {
KCallable result = reflected;
if (result == null) {
result = computeReflected();
reflected = result;
}
return result;
}
protected KCallable getReflected() {
KCallable result = compute();
if (result == this) {
throw new KotlinReflectionNotSupportedError();
}
return result;
}
// The following methods provide the information identifying this callable, which is used by the reflection implementation. // 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). // They are supposed to be overridden in each subclass (each anonymous class generated for a callable reference).
@@ -66,8 +88,8 @@ public abstract class CallableReference implements KCallable {
throw new AbstractMethodError(); throw new AbstractMethodError();
} }
// The following methods are the stub implementations of reflection functions. // The following methods are the delegating implementations of reflection functions. They are called when you're using reflection
// They are called when you're using reflection on a property reference without the reflection implementation in the classpath. // on a callable reference. Without kotlin-reflect.jar in the classpath, getReflected() throws an exception.
@Override @Override
public List<KParameter> getParameters() { public List<KParameter> getParameters() {
@@ -120,21 +142,4 @@ public abstract class CallableReference implements KCallable {
public boolean isAbstract() { public boolean isAbstract() {
return getReflected().isAbstract(); return getReflected().isAbstract();
} }
public KCallable compute() {
KCallable result = reflected;
if (result == null) {
result = computeReflected();
reflected = result;
}
return result;
}
protected KCallable getReflected() {
KCallable result = compute();
if (result == this) {
throw new KotlinReflectionNotSupportedError();
}
return result;
}
} }
@@ -16,19 +16,11 @@
package kotlin.jvm.internal; package kotlin.jvm.internal;
import kotlin.jvm.KotlinReflectionNotSupportedError; import kotlin.reflect.KCallable;
import kotlin.reflect.*; import kotlin.reflect.KFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation; public class FunctionReference extends CallableReference implements FunctionImpl, KFunction {
import java.util.List;
import java.util.Map;
@SuppressWarnings({"unchecked", "NullableProblems"})
public class FunctionReference implements FunctionImpl, KFunction {
private final int arity; private final int arity;
private KFunction reflected;
public FunctionReference(int arity) { public FunctionReference(int arity) {
this.arity = arity; this.arity = arity;
@@ -39,71 +31,14 @@ public class FunctionReference implements FunctionImpl, KFunction {
return arity; return arity;
} }
// Most of the following methods are copies from CallableReference, since this class cannot inherit from it @Override
protected KFunction getReflected() {
public KDeclarationContainer getOwner() { return (KFunction) super.getReflected();
throw new AbstractMethodError();
} }
@Override @Override
public String getName() { protected KCallable computeReflected() {
throw new AbstractMethodError(); return Reflection.function(this);
}
public String getSignature() {
throw new AbstractMethodError();
}
@Override
public List<KParameter> getParameters() {
return getReflected().getParameters();
}
@Override
public KType getReturnType() {
return getReflected().getReturnType();
}
@Override
public List<Annotation> getAnnotations() {
return getReflected().getAnnotations();
}
@NotNull
@Override
public List<KTypeParameter> getTypeParameters() {
return getReflected().getTypeParameters();
}
@Override
public Object call(@NotNull Object... args) {
return getReflected().call(args);
}
@Override
public Object callBy(@NotNull Map args) {
return getReflected().callBy(args);
}
@Nullable
@Override
public KVisibility getVisibility() {
return getReflected().getVisibility();
}
@Override
public boolean isFinal() {
return getReflected().isFinal();
}
@Override
public boolean isOpen() {
return getReflected().isOpen();
}
@Override
public boolean isAbstract() {
return getReflected().isAbstract();
} }
@Override @Override
@@ -158,7 +93,7 @@ public class FunctionReference implements FunctionImpl, KFunction {
@Override @Override
public String toString() { public String toString() {
KFunction reflected = compute(); KCallable reflected = compute();
if (reflected != this) { if (reflected != this) {
return reflected.toString(); return reflected.toString();
} }
@@ -168,21 +103,4 @@ public class FunctionReference implements FunctionImpl, KFunction {
? "constructor" + Reflection.REFLECTION_NOT_AVAILABLE ? "constructor" + Reflection.REFLECTION_NOT_AVAILABLE
: "function " + getName() + Reflection.REFLECTION_NOT_AVAILABLE; : "function " + getName() + Reflection.REFLECTION_NOT_AVAILABLE;
} }
public KFunction compute() {
KFunction result = reflected;
if (result == null) {
result = Reflection.function(this);
reflected = result;
}
return result;
}
private KFunction getReflected() {
KFunction result = compute();
if (result == this) {
throw new KotlinReflectionNotSupportedError();
}
return result;
}
} }
@@ -45,8 +45,7 @@ public abstract class PropertyReference extends CallableReference implements KPr
getSignature().equals(other.getSignature()); getSignature().equals(other.getSignature());
} }
if (obj instanceof KProperty) { if (obj instanceof KProperty) {
compute(); return obj.equals(compute());
return obj.equals(reflected);
} }
return false; return false;
} }