Support bound callable references in codegen
This commit is contained in:
@@ -241,7 +241,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public StackValue putInstanceOnStack(@NotNull final ExpressionCodegen codegen) {
|
public StackValue putInstanceOnStack(@NotNull final ExpressionCodegen codegen, @Nullable final StackValue functionReferenceReceiver) {
|
||||||
return StackValue.operation(
|
return StackValue.operation(
|
||||||
functionReferenceTarget != null ? K_FUNCTION : asmType,
|
functionReferenceTarget != null ? K_FUNCTION : asmType,
|
||||||
new Function1<InstructionAdapter, Unit>() {
|
new Function1<InstructionAdapter, Unit>() {
|
||||||
@@ -254,7 +254,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
|||||||
v.anew(asmType);
|
v.anew(asmType);
|
||||||
v.dup();
|
v.dup();
|
||||||
|
|
||||||
codegen.pushClosureOnStack(classDescriptor, true, codegen.defaultCallGenerator);
|
codegen.pushClosureOnStack(classDescriptor, true, codegen.defaultCallGenerator, functionReferenceReceiver);
|
||||||
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
|
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import com.intellij.util.containers.Stack;
|
|||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlin.collections.CollectionsKt;
|
import kotlin.collections.CollectionsKt;
|
||||||
|
import kotlin.jvm.functions.Function0;
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -1418,7 +1419,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText();
|
assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText();
|
||||||
|
|
||||||
return genClosure(
|
return genClosure(
|
||||||
declaration, descriptor, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), samType, null
|
declaration, descriptor, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), samType, null, null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1428,7 +1429,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
@NotNull FunctionDescriptor descriptor,
|
@NotNull FunctionDescriptor descriptor,
|
||||||
@NotNull FunctionGenerationStrategy strategy,
|
@NotNull FunctionGenerationStrategy strategy,
|
||||||
@Nullable SamType samType,
|
@Nullable SamType samType,
|
||||||
@Nullable FunctionDescriptor functionReferenceTarget
|
@Nullable FunctionDescriptor functionReferenceTarget,
|
||||||
|
@Nullable StackValue functionReferenceReceiver
|
||||||
) {
|
) {
|
||||||
ClassBuilder cv = state.getFactory().newVisitor(
|
ClassBuilder cv = state.getFactory().newVisitor(
|
||||||
JvmDeclarationOriginKt.OtherOrigin(declaration, descriptor),
|
JvmDeclarationOriginKt.OtherOrigin(declaration, descriptor),
|
||||||
@@ -1448,7 +1450,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
propagateChildReifiedTypeParametersUsages(closureCodegen.getReifiedTypeParametersUsages());
|
propagateChildReifiedTypeParametersUsages(closureCodegen.getReifiedTypeParametersUsages());
|
||||||
}
|
}
|
||||||
|
|
||||||
return closureCodegen.putInstanceOnStack(this);
|
return closureCodegen.putInstanceOnStack(this, functionReferenceReceiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1466,7 +1468,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
v.anew(type);
|
v.anew(type);
|
||||||
v.dup();
|
v.dup();
|
||||||
|
|
||||||
pushClosureOnStack(classDescriptor, true, defaultCallGenerator);
|
pushClosureOnStack(classDescriptor, true, defaultCallGenerator, /* functionReferenceReceiver = */ null);
|
||||||
|
|
||||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||||
assert primaryConstructor != null : "There should be primary constructor for object literal";
|
assert primaryConstructor != null : "There should be primary constructor for object literal";
|
||||||
@@ -1510,7 +1512,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushClosureOnStack(@NotNull ClassDescriptor classDescriptor, boolean putThis, @NotNull CallGenerator callGenerator) {
|
public void pushClosureOnStack(
|
||||||
|
@NotNull ClassDescriptor classDescriptor,
|
||||||
|
boolean putThis,
|
||||||
|
@NotNull CallGenerator callGenerator,
|
||||||
|
@Nullable StackValue functionReferenceReceiver
|
||||||
|
) {
|
||||||
CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor);
|
CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor);
|
||||||
if (closure == null) return;
|
if (closure == null) return;
|
||||||
|
|
||||||
@@ -1528,7 +1535,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
KotlinType captureReceiver = closure.getCaptureReceiverType();
|
KotlinType captureReceiver = closure.getCaptureReceiverType();
|
||||||
if (captureReceiver != null) {
|
if (captureReceiver != null) {
|
||||||
Type asmType = typeMapper.mapType(captureReceiver);
|
Type asmType = typeMapper.mapType(captureReceiver);
|
||||||
StackValue.Local capturedReceiver = StackValue.local(AsmUtil.getReceiverIndex(context, context.getContextDescriptor()), asmType);
|
StackValue capturedReceiver =
|
||||||
|
functionReferenceReceiver != null ? functionReferenceReceiver :
|
||||||
|
StackValue.local(AsmUtil.getReceiverIndex(context, context.getContextDescriptor()), asmType);
|
||||||
callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++);
|
callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1545,9 +1554,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassNotAny(classDescriptor);
|
ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassNotAny(classDescriptor);
|
||||||
if (superClass != null) {
|
if (superClass != null) {
|
||||||
pushClosureOnStack(
|
pushClosureOnStack(
|
||||||
superClass,
|
superClass, putThis && closure.getCaptureThis() == null, callGenerator, /* functionReferenceReceiver = */ null
|
||||||
putThis && closure.getCaptureThis() == null,
|
|
||||||
callGenerator
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2852,17 +2859,28 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
@Override
|
@Override
|
||||||
public StackValue visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, StackValue data) {
|
public StackValue visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, StackValue data) {
|
||||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression.getCallableReference(), bindingContext);
|
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression.getCallableReference(), bindingContext);
|
||||||
|
|
||||||
|
KotlinType receiverExpressionType = expressionJetType(expression.getReceiverExpression());
|
||||||
|
Type receiverAsmType = receiverExpressionType != null ? asmType(receiverExpressionType) : null;
|
||||||
|
StackValue receiverValue = receiverExpressionType != null ? gen(expression.getReceiverExpression()) : null;
|
||||||
|
|
||||||
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
||||||
if (functionDescriptor != null) {
|
if (functionDescriptor != null) {
|
||||||
FunctionReferenceGenerationStrategy strategy = new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall);
|
FunctionReferenceGenerationStrategy strategy =
|
||||||
return genClosure(expression, functionDescriptor, strategy, null, (FunctionDescriptor) resolvedCall.getResultingDescriptor());
|
new FunctionReferenceGenerationStrategy(state, functionDescriptor, resolvedCall, receiverAsmType, null);
|
||||||
|
|
||||||
|
return genClosure(
|
||||||
|
expression, functionDescriptor, strategy, null,
|
||||||
|
(FunctionDescriptor) resolvedCall.getResultingDescriptor(), receiverValue
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
|
VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression);
|
||||||
if (variableDescriptor != null) {
|
if (variableDescriptor != null) {
|
||||||
return generatePropertyReference(expression, variableDescriptor,
|
return generatePropertyReference(
|
||||||
(VariableDescriptor) resolvedCall.getResultingDescriptor(),
|
expression, variableDescriptor, (VariableDescriptor) resolvedCall.getResultingDescriptor(),
|
||||||
resolvedCall.getDispatchReceiver());
|
resolvedCall.getDispatchReceiver(), receiverAsmType, receiverValue
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText());
|
throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText());
|
||||||
@@ -2873,7 +2891,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
@NotNull KtElement element,
|
@NotNull KtElement element,
|
||||||
@NotNull VariableDescriptor variableDescriptor,
|
@NotNull VariableDescriptor variableDescriptor,
|
||||||
@NotNull VariableDescriptor target,
|
@NotNull VariableDescriptor target,
|
||||||
@Nullable ReceiverValue dispatchReceiver
|
@Nullable ReceiverValue dispatchReceiver,
|
||||||
|
@Nullable final Type receiverAsmType,
|
||||||
|
@Nullable final StackValue receiverValue
|
||||||
) {
|
) {
|
||||||
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
ClassDescriptor classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
||||||
|
|
||||||
@@ -2885,11 +2905,18 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
PropertyReferenceCodegen codegen = new PropertyReferenceCodegen(
|
PropertyReferenceCodegen codegen = new PropertyReferenceCodegen(
|
||||||
state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION),
|
state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION),
|
||||||
element, classBuilder, target, dispatchReceiver
|
element, classBuilder, target, dispatchReceiver, receiverAsmType
|
||||||
);
|
);
|
||||||
codegen.generate();
|
codegen.generate();
|
||||||
|
|
||||||
return codegen.putInstanceOnStack();
|
return codegen.putInstanceOnStack(receiverValue == null ? null : new Function0<Unit>() {
|
||||||
|
@Override
|
||||||
|
public Unit invoke() {
|
||||||
|
assert receiverAsmType != null : "Receiver type should not be null when receiver value is not null: " + receiverValue;
|
||||||
|
receiverValue.put(receiverAsmType, v);
|
||||||
|
return Unit.INSTANCE;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -3524,8 +3551,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
@NotNull StackValue metadataVar
|
@NotNull StackValue metadataVar
|
||||||
) {
|
) {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
StackValue value =
|
StackValue value = generatePropertyReference(variable.getDelegate(), variableDescriptor, variableDescriptor, null, null, null);
|
||||||
generatePropertyReference(variable.getDelegate(), variableDescriptor, variableDescriptor, null);
|
|
||||||
value.put(K_PROPERTY0_TYPE, v);
|
value.put(K_PROPERTY0_TYPE, v);
|
||||||
metadataVar.storeSelector(K_PROPERTY0_TYPE, v);
|
metadataVar.storeSelector(K_PROPERTY0_TYPE, v);
|
||||||
}
|
}
|
||||||
@@ -3570,7 +3596,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
// Resolved call to local class constructor doesn't have dispatchReceiver, so we need to generate closure on stack
|
// Resolved call to local class constructor doesn't have dispatchReceiver, so we need to generate closure on stack
|
||||||
// See StackValue.receiver for more info
|
// See StackValue.receiver for more info
|
||||||
pushClosureOnStack(containingDeclaration, dispatchReceiver == null, defaultCallGenerator);
|
pushClosureOnStack(
|
||||||
|
containingDeclaration, dispatchReceiver == null, defaultCallGenerator, /* functionReferenceReceiver = */ null
|
||||||
|
);
|
||||||
|
|
||||||
constructor = SamCodegenUtil.resolveSamAdapter(constructor);
|
constructor = SamCodegenUtil.resolveSamAdapter(constructor);
|
||||||
CallableMethod method = typeMapper.mapToCallableMethod(constructor, false);
|
CallableMethod method = typeMapper.mapToCallableMethod(constructor, false);
|
||||||
|
|||||||
+24
-6
@@ -39,15 +39,24 @@ import java.util.*;
|
|||||||
public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased<FunctionDescriptor> {
|
public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased<FunctionDescriptor> {
|
||||||
private final ResolvedCall<?> resolvedCall;
|
private final ResolvedCall<?> resolvedCall;
|
||||||
private final FunctionDescriptor referencedFunction;
|
private final FunctionDescriptor referencedFunction;
|
||||||
|
private final Type receiverType; // non-null for bound references
|
||||||
|
private final StackValue receiverValue;
|
||||||
|
|
||||||
public FunctionReferenceGenerationStrategy(
|
public FunctionReferenceGenerationStrategy(
|
||||||
@NotNull GenerationState state,
|
@NotNull GenerationState state,
|
||||||
@NotNull FunctionDescriptor functionDescriptor,
|
@NotNull FunctionDescriptor functionDescriptor,
|
||||||
@NotNull ResolvedCall<?> resolvedCall
|
@NotNull ResolvedCall<?> resolvedCall,
|
||||||
|
@Nullable Type receiverType,
|
||||||
|
@Nullable StackValue receiverValue
|
||||||
) {
|
) {
|
||||||
super(state, functionDescriptor);
|
super(state, functionDescriptor);
|
||||||
this.resolvedCall = resolvedCall;
|
this.resolvedCall = resolvedCall;
|
||||||
this.referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
|
this.referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
|
||||||
|
this.receiverType = receiverType;
|
||||||
|
this.receiverValue = receiverValue;
|
||||||
|
assert receiverType != null || receiverValue == null
|
||||||
|
: "A receiver value is provided for unbound function reference. Either this is a bound reference and you forgot " +
|
||||||
|
"to pass receiverType, or you accidentally passed some receiverValue for a reference without receiver";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -142,7 +151,8 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
|||||||
|
|
||||||
private void computeAndSaveArguments(@NotNull List<? extends ValueArgument> fakeArguments, @NotNull ExpressionCodegen codegen) {
|
private void computeAndSaveArguments(@NotNull List<? extends ValueArgument> fakeArguments, @NotNull ExpressionCodegen codegen) {
|
||||||
int receivers = (referencedFunction.getDispatchReceiverParameter() != null ? 1 : 0) +
|
int receivers = (referencedFunction.getDispatchReceiverParameter() != null ? 1 : 0) +
|
||||||
(referencedFunction.getExtensionReceiverParameter() != null ? 1 : 0);
|
(referencedFunction.getExtensionReceiverParameter() != null ? 1 : 0) -
|
||||||
|
(receiverType != null ? 1 : 0);
|
||||||
|
|
||||||
List<ValueParameterDescriptor> parameters = CollectionsKt.drop(callableDescriptor.getValueParameters(), receivers);
|
List<ValueParameterDescriptor> parameters = CollectionsKt.drop(callableDescriptor.getValueParameters(), receivers);
|
||||||
for (int i = 0; i < parameters.size(); i++) {
|
for (int i = 0; i < parameters.size(); i++) {
|
||||||
@@ -163,14 +173,22 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
|||||||
) {
|
) {
|
||||||
if (receiver == null) return null;
|
if (receiver == null) return null;
|
||||||
|
|
||||||
KtExpression receiverExpression = KtPsiFactoryKt
|
KtExpression receiverExpression = KtPsiFactoryKt.KtPsiFactory(state.getProject()).createExpression("callableReferenceFakeReceiver");
|
||||||
.KtPsiFactory(state.getProject()).createExpression("callableReferenceFakeReceiver");
|
codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature, codegen));
|
||||||
codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature));
|
|
||||||
return ExpressionReceiver.Companion.create(receiverExpression, receiver.getType(), BindingContext.EMPTY);
|
return ExpressionReceiver.Companion.create(receiverExpression, receiver.getType(), BindingContext.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static StackValue.Local receiverParameterStackValue(@NotNull JvmMethodSignature signature) {
|
private StackValue receiverParameterStackValue(@NotNull JvmMethodSignature signature, @NotNull ExpressionCodegen codegen) {
|
||||||
|
if (receiverValue != null) return receiverValue;
|
||||||
|
|
||||||
|
if (receiverType != null) {
|
||||||
|
return StackValue.field(
|
||||||
|
receiverType, Type.getObjectType(codegen.getParentCodegen().getClassName()), AsmUtil.CAPTURED_RECEIVER_FIELD,
|
||||||
|
/* isStatic = */ false, StackValue.LOCAL_0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 0 is this (the callable reference class), 1 is the invoke() method's first parameter
|
// 0 is this (the callable reference class), 1 is the invoke() method's first parameter
|
||||||
return StackValue.local(1, signature.getAsmMethod().getArgumentTypes()[0]);
|
return StackValue.local(1, signature.getAsmMethod().getArgumentTypes()[0]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public class JvmRuntimeTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Collection<KotlinType> getSupertypesForFunctionReference(@NotNull FunctionDescriptor descriptor) {
|
public Collection<KotlinType> getSupertypesForFunctionReference(@NotNull FunctionDescriptor descriptor, boolean isBound) {
|
||||||
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
|
||||||
ReceiverParameterDescriptor dispatchReceiver = descriptor.getDispatchReceiverParameter();
|
ReceiverParameterDescriptor dispatchReceiver = descriptor.getDispatchReceiverParameter();
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ public class JvmRuntimeTypes {
|
|||||||
KotlinType functionType = FunctionTypeResolveUtilsKt.createFunctionType(
|
KotlinType functionType = FunctionTypeResolveUtilsKt.createFunctionType(
|
||||||
DescriptorUtilsKt.getBuiltIns(descriptor),
|
DescriptorUtilsKt.getBuiltIns(descriptor),
|
||||||
Annotations.Companion.getEMPTY(),
|
Annotations.Companion.getEMPTY(),
|
||||||
receiverType,
|
isBound ? null : receiverType,
|
||||||
ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters()),
|
ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters()),
|
||||||
descriptor.getReturnType()
|
descriptor.getReturnType()
|
||||||
);
|
);
|
||||||
@@ -115,13 +115,14 @@ public class JvmRuntimeTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public KotlinType getSupertypeForPropertyReference(@NotNull VariableDescriptorWithAccessors descriptor) {
|
public KotlinType getSupertypeForPropertyReference(@NotNull VariableDescriptorWithAccessors descriptor, boolean isBound) {
|
||||||
if (descriptor instanceof LocalVariableDescriptor) {
|
if (descriptor instanceof LocalVariableDescriptor) {
|
||||||
return (descriptor.isVar() ? mutableLocalVariableReference : localVariableReference).getDefaultType();
|
return (descriptor.isVar() ? mutableLocalVariableReference : localVariableReference).getDefaultType();
|
||||||
}
|
}
|
||||||
|
|
||||||
int arity = (descriptor.getExtensionReceiverParameter() != null ? 1 : 0) +
|
int arity = (descriptor.getExtensionReceiverParameter() != null ? 1 : 0) +
|
||||||
(descriptor.getDispatchReceiverParameter() != null ? 1 : 0);
|
(descriptor.getDispatchReceiverParameter() != null ? 1 : 0) -
|
||||||
|
(isBound ? 1 : 0);
|
||||||
return (descriptor.isVar() ? mutablePropertyReferences : propertyReferences).get(arity).getDefaultType();
|
return (descriptor.isVar() ? mutablePropertyReferences : propertyReferences).get(arity).getDefaultType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil.method
|
import org.jetbrains.kotlin.codegen.AsmUtil.method
|
||||||
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
import org.jetbrains.kotlin.codegen.context.ClassContext
|
import org.jetbrains.kotlin.codegen.context.ClassContext
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -46,7 +47,8 @@ class PropertyReferenceCodegen(
|
|||||||
expression: KtElement,
|
expression: KtElement,
|
||||||
classBuilder: ClassBuilder,
|
classBuilder: ClassBuilder,
|
||||||
private val target: VariableDescriptor,
|
private val target: VariableDescriptor,
|
||||||
dispatchReceiver: ReceiverValue?
|
dispatchReceiver: ReceiverValue?,
|
||||||
|
private val receiverType: Type? // non-null for bound references
|
||||||
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
|
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
|
||||||
private val classDescriptor = context.contextDescriptor
|
private val classDescriptor = context.contextDescriptor
|
||||||
private val asmType = typeMapper.mapClass(classDescriptor)
|
private val asmType = typeMapper.mapClass(classDescriptor)
|
||||||
@@ -55,7 +57,9 @@ class PropertyReferenceCodegen(
|
|||||||
private val extensionReceiverType = target.extensionReceiverParameter?.type
|
private val extensionReceiverType = target.extensionReceiverParameter?.type
|
||||||
|
|
||||||
private val receiverCount =
|
private val receiverCount =
|
||||||
(if (dispatchReceiverType != null) 1 else 0) + (if (extensionReceiverType != null) 1 else 0)
|
(if (dispatchReceiverType != null) 1 else 0) +
|
||||||
|
(if (extensionReceiverType != null) 1 else 0) -
|
||||||
|
(if (receiverType != null) 1 else 0)
|
||||||
|
|
||||||
// e.g. MutablePropertyReference0
|
// e.g. MutablePropertyReference0
|
||||||
private val superAsmType = typeMapper.mapClass(classDescriptor.getSuperClassNotAny().sure { "No super class for $classDescriptor" })
|
private val superAsmType = typeMapper.mapClass(classDescriptor.getSuperClassNotAny().sure { "No super class for $classDescriptor" })
|
||||||
@@ -63,6 +67,18 @@ class PropertyReferenceCodegen(
|
|||||||
// e.g. mutableProperty0(Lkotlin/jvm/internal/MutablePropertyReference0;)Lkotlin/reflect/KMutableProperty0;
|
// e.g. mutableProperty0(Lkotlin/jvm/internal/MutablePropertyReference0;)Lkotlin/reflect/KMutableProperty0;
|
||||||
private val wrapperMethod = getWrapperMethodForPropertyReference(target, receiverCount)
|
private val wrapperMethod = getWrapperMethodForPropertyReference(target, receiverCount)
|
||||||
|
|
||||||
|
private val closure = bindingContext.get(CodegenBinding.CLOSURE, classDescriptor)!!.apply {
|
||||||
|
assert((captureReceiverType != null) == (receiverType != null)) {
|
||||||
|
"Bound property reference can only be generated with the type of the receiver. " +
|
||||||
|
"Captured type = $captureReceiverType, actual type = $receiverType"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val constructorArgs = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, asmType).apply {
|
||||||
|
assert(size <= 1) { "Bound property reference should capture only one value: $this" }
|
||||||
|
}
|
||||||
|
private val constructor = method("<init>", Type.VOID_TYPE, *constructorArgs.map { it.fieldType }.toTypedArray())
|
||||||
|
|
||||||
override fun generateDeclaration() {
|
override fun generateDeclaration() {
|
||||||
v.defineClass(
|
v.defineClass(
|
||||||
element,
|
element,
|
||||||
@@ -79,12 +95,14 @@ class PropertyReferenceCodegen(
|
|||||||
|
|
||||||
// TODO: ImplementationBodyCodegen.markLineNumberForSyntheticFunction?
|
// TODO: ImplementationBodyCodegen.markLineNumberForSyntheticFunction?
|
||||||
override fun generateBody() {
|
override fun generateBody() {
|
||||||
generateConstInstance(asmType, wrapperMethod.returnType)
|
if (JvmCodegenUtil.isConst(closure)) {
|
||||||
|
generateConstInstance(asmType, wrapperMethod.returnType)
|
||||||
generateMethod("property reference init", 0, method("<init>", Type.VOID_TYPE)) {
|
|
||||||
load(0, OBJECT_TYPE)
|
|
||||||
invokespecial(superAsmType.internalName, "<init>", "()V", false)
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
AsmUtil.genClosureFields(closure, v, typeMapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
generateConstructor()
|
||||||
|
|
||||||
generateMethod("property reference getName", ACC_PUBLIC, method("getName", JAVA_STRING_TYPE)) {
|
generateMethod("property reference getName", ACC_PUBLIC, method("getName", JAVA_STRING_TYPE)) {
|
||||||
aconst(target.name.asString())
|
aconst(target.name.asString())
|
||||||
@@ -102,6 +120,18 @@ class PropertyReferenceCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateConstructor() {
|
||||||
|
generateMethod("property reference init", 0, constructor) {
|
||||||
|
constructorArgs.fold(1) {
|
||||||
|
i, fieldInfo ->
|
||||||
|
AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, i, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
load(0, OBJECT_TYPE)
|
||||||
|
invokespecial(superAsmType.internalName, "<init>", "()V", false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun generateAccessors() {
|
private fun generateAccessors() {
|
||||||
fun generateAccessor(method: Method, accessorBody: InstructionAdapter.(StackValue) -> Unit) {
|
fun generateAccessor(method: Method, accessorBody: InstructionAdapter.(StackValue) -> Unit) {
|
||||||
generateMethod("property reference $method", ACC_PUBLIC, method) {
|
generateMethod("property reference $method", ACC_PUBLIC, method) {
|
||||||
@@ -123,8 +153,14 @@ class PropertyReferenceCodegen(
|
|||||||
StackValue.singleton(containingObject, typeMapper).put(typeMapper.mapClass(containingObject), this)
|
StackValue.singleton(containingObject, typeMapper).put(typeMapper.mapClass(containingObject), this)
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((index, type) in listOfNotNull(dispatchReceiverType, extensionReceiverType).withIndex()) {
|
if (receiverType != null) {
|
||||||
StackValue.local(index + 1, OBJECT_TYPE).put(typeMapper.mapType(type), this)
|
StackValue.field(receiverType, asmType, AsmUtil.CAPTURED_RECEIVER_FIELD, /* isStatic = */ false, StackValue.LOCAL_0)
|
||||||
|
.put(receiverType, this)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for ((index, type) in listOfNotNull(dispatchReceiverType, extensionReceiverType).withIndex()) {
|
||||||
|
StackValue.local(index + 1, OBJECT_TYPE).put(typeMapper.mapType(type), this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val value = if (target is LocalVariableDescriptor) {
|
val value = if (target is LocalVariableDescriptor) {
|
||||||
@@ -166,10 +202,21 @@ class PropertyReferenceCodegen(
|
|||||||
writeSyntheticClassMetadata(v)
|
writeSyntheticClassMetadata(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putInstanceOnStack(): StackValue =
|
fun putInstanceOnStack(receiverValue: (() -> Unit)?): StackValue {
|
||||||
StackValue.operation(wrapperMethod.returnType) { iv ->
|
return StackValue.operation(wrapperMethod.returnType) { iv ->
|
||||||
|
if (JvmCodegenUtil.isConst(closure)) {
|
||||||
|
assert(receiverValue == null) { "No receiver expected for unbound property reference: $classDescriptor" }
|
||||||
iv.getstatic(asmType.internalName, JvmAbi.INSTANCE_FIELD, wrapperMethod.returnType.descriptor)
|
iv.getstatic(asmType.internalName, JvmAbi.INSTANCE_FIELD, wrapperMethod.returnType.descriptor)
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
assert(receiverValue != null) { "Receiver expected for bound property reference: $classDescriptor" }
|
||||||
|
iv.anew(asmType)
|
||||||
|
iv.dup()
|
||||||
|
receiverValue!!()
|
||||||
|
iv.invokespecial(asmType.internalName, "<init>", constructor.descriptor, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|||||||
+18
-7
@@ -288,17 +288,22 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
CallableDescriptor callableDescriptor;
|
CallableDescriptor callableDescriptor;
|
||||||
Collection<KotlinType> supertypes;
|
Collection<KotlinType> supertypes;
|
||||||
|
|
||||||
|
KtExpression receiverExpression = expression.getReceiverExpression();
|
||||||
|
KotlinType receiverType = receiverExpression != null ? bindingContext.getType(receiverExpression) : null;
|
||||||
|
|
||||||
if (target instanceof FunctionDescriptor) {
|
if (target instanceof FunctionDescriptor) {
|
||||||
callableDescriptor = bindingContext.get(FUNCTION, expression);
|
callableDescriptor = bindingContext.get(FUNCTION, expression);
|
||||||
if (callableDescriptor == null) return;
|
if (callableDescriptor == null) return;
|
||||||
|
|
||||||
supertypes = runtimeTypes.getSupertypesForFunctionReference((FunctionDescriptor) target);
|
supertypes = runtimeTypes.getSupertypesForFunctionReference((FunctionDescriptor) target, receiverType != null);
|
||||||
}
|
}
|
||||||
else if (target instanceof PropertyDescriptor) {
|
else if (target instanceof PropertyDescriptor) {
|
||||||
callableDescriptor = bindingContext.get(VARIABLE, expression);
|
callableDescriptor = bindingContext.get(VARIABLE, expression);
|
||||||
if (callableDescriptor == null) return;
|
if (callableDescriptor == null) return;
|
||||||
|
|
||||||
supertypes = Collections.singleton(runtimeTypes.getSupertypeForPropertyReference((PropertyDescriptor) target));
|
supertypes = Collections.singleton(
|
||||||
|
runtimeTypes.getSupertypeForPropertyReference((PropertyDescriptor) target, receiverType != null)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
@@ -306,7 +311,11 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
|
|
||||||
String name = inventAnonymousClassName();
|
String name = inventAnonymousClassName();
|
||||||
ClassDescriptor classDescriptor = recordClassForCallable(expression, callableDescriptor, supertypes, name);
|
ClassDescriptor classDescriptor = recordClassForCallable(expression, callableDescriptor, supertypes, name);
|
||||||
recordClosure(classDescriptor, name);
|
MutableClosure closure = recordClosure(classDescriptor, name);
|
||||||
|
|
||||||
|
if (receiverType != null) {
|
||||||
|
closure.setCaptureReceiverType(receiverType);
|
||||||
|
}
|
||||||
|
|
||||||
classStack.push(classDescriptor);
|
classStack.push(classDescriptor);
|
||||||
nameStack.push(name);
|
nameStack.push(name);
|
||||||
@@ -315,9 +324,11 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
classStack.pop();
|
classStack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recordClosure(@NotNull ClassDescriptor classDescriptor, @NotNull String name) {
|
@NotNull
|
||||||
CodegenBinding.recordClosure(bindingTrace, classDescriptor, peekFromStack(classStack), Type.getObjectType(name),
|
private MutableClosure recordClosure(@NotNull ClassDescriptor classDescriptor, @NotNull String name) {
|
||||||
fileClassesProvider);
|
return CodegenBinding.recordClosure(
|
||||||
|
bindingTrace, classDescriptor, peekFromStack(classStack), Type.getObjectType(name), fileClassesProvider
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recordLocalVariablePropertyMetadata(LocalVariableDescriptor variableDescriptor) {
|
private void recordLocalVariablePropertyMetadata(LocalVariableDescriptor variableDescriptor) {
|
||||||
@@ -369,7 +380,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
if (delegate != null && descriptor instanceof VariableDescriptorWithAccessors) {
|
if (delegate != null && descriptor instanceof VariableDescriptorWithAccessors) {
|
||||||
VariableDescriptorWithAccessors variableDescriptor = (VariableDescriptorWithAccessors) descriptor;
|
VariableDescriptorWithAccessors variableDescriptor = (VariableDescriptorWithAccessors) descriptor;
|
||||||
String name = inventAnonymousClassName();
|
String name = inventAnonymousClassName();
|
||||||
KotlinType supertype = runtimeTypes.getSupertypeForPropertyReference(variableDescriptor);
|
KotlinType supertype = runtimeTypes.getSupertypeForPropertyReference(variableDescriptor, /* bound = */ false);
|
||||||
ClassDescriptor classDescriptor = recordClassForCallable(delegate, variableDescriptor, Collections.singleton(supertype), name);
|
ClassDescriptor classDescriptor = recordClassForCallable(delegate, variableDescriptor, Collections.singleton(supertype), name);
|
||||||
recordClosure(classDescriptor, name);
|
recordClosure(classDescriptor, name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,8 @@ public class CodegenBinding {
|
|||||||
return classDescriptor.isInner() || !(classDescriptor.getContainingDeclaration() instanceof ClassDescriptor);
|
return classDescriptor.isInner() || !(classDescriptor.getContainingDeclaration() instanceof ClassDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void recordClosure(
|
@NotNull
|
||||||
|
static MutableClosure recordClosure(
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull ClassDescriptor classDescriptor,
|
@NotNull ClassDescriptor classDescriptor,
|
||||||
@Nullable ClassDescriptor enclosing,
|
@Nullable ClassDescriptor enclosing,
|
||||||
@@ -164,6 +165,8 @@ public class CodegenBinding {
|
|||||||
if (enclosing != null && !JvmCodegenUtil.isArgumentWhichWillBeInlined(trace.getBindingContext(), classDescriptor)) {
|
if (enclosing != null && !JvmCodegenUtil.isArgumentWhichWillBeInlined(trace.getBindingContext(), classDescriptor)) {
|
||||||
recordInnerClass(trace, enclosing, classDescriptor);
|
recordInnerClass(trace, enclosing, classDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return closure;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void recordInnerClass(
|
private static void recordInnerClass(
|
||||||
|
|||||||
@@ -33,11 +33,12 @@ public final class MutableClosure implements CalculatedClosure {
|
|||||||
private final CallableDescriptor enclosingFunWithReceiverDescriptor;
|
private final CallableDescriptor enclosingFunWithReceiverDescriptor;
|
||||||
|
|
||||||
private boolean captureThis;
|
private boolean captureThis;
|
||||||
private boolean captureReceiver;
|
private boolean captureEnclosingReceiver;
|
||||||
|
|
||||||
private Map<DeclarationDescriptor, EnclosedValueDescriptor> captureVariables;
|
private Map<DeclarationDescriptor, EnclosedValueDescriptor> captureVariables;
|
||||||
private Map<DeclarationDescriptor, Integer> parameterOffsetInConstructor;
|
private Map<DeclarationDescriptor, Integer> parameterOffsetInConstructor;
|
||||||
private List<Pair<String, Type>> recordedFields;
|
private List<Pair<String, Type>> recordedFields;
|
||||||
|
private KotlinType captureReceiverType;
|
||||||
|
|
||||||
MutableClosure(@NotNull ClassDescriptor classDescriptor, @Nullable ClassDescriptor enclosingClass) {
|
MutableClosure(@NotNull ClassDescriptor classDescriptor, @Nullable ClassDescriptor enclosingClass) {
|
||||||
this.enclosingClass = enclosingClass;
|
this.enclosingClass = enclosingClass;
|
||||||
@@ -72,7 +73,11 @@ public final class MutableClosure implements CalculatedClosure {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KotlinType getCaptureReceiverType() {
|
public KotlinType getCaptureReceiverType() {
|
||||||
if (captureReceiver) {
|
if (captureReceiverType != null) {
|
||||||
|
return captureReceiverType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (captureEnclosingReceiver) {
|
||||||
ReceiverParameterDescriptor parameter = getEnclosingReceiverDescriptor();
|
ReceiverParameterDescriptor parameter = getEnclosingReceiverDescriptor();
|
||||||
assert parameter != null : "Receiver parameter should exist in " + enclosingFunWithReceiverDescriptor;
|
assert parameter != null : "Receiver parameter should exist in " + enclosingFunWithReceiverDescriptor;
|
||||||
return parameter.getType();
|
return parameter.getType();
|
||||||
@@ -85,7 +90,7 @@ public final class MutableClosure implements CalculatedClosure {
|
|||||||
if (enclosingFunWithReceiverDescriptor == null) {
|
if (enclosingFunWithReceiverDescriptor == null) {
|
||||||
throw new IllegalStateException("Extension receiver parameter should exist");
|
throw new IllegalStateException("Extension receiver parameter should exist");
|
||||||
}
|
}
|
||||||
this.captureReceiver = true;
|
this.captureEnclosingReceiver = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -94,6 +99,10 @@ public final class MutableClosure implements CalculatedClosure {
|
|||||||
return captureVariables != null ? captureVariables : Collections.<DeclarationDescriptor, EnclosedValueDescriptor>emptyMap();
|
return captureVariables != null ? captureVariables : Collections.<DeclarationDescriptor, EnclosedValueDescriptor>emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCaptureReceiverType(@NotNull KotlinType type) {
|
||||||
|
this.captureReceiverType = type;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public List<Pair<String, Type>> getRecordedFields() {
|
public List<Pair<String, Type>> getRecordedFields() {
|
||||||
|
|||||||
@@ -490,16 +490,26 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
: state.getTypeMapper().mapImplementationOwner(descriptor).getInternalName()
|
: state.getTypeMapper().mapImplementationOwner(descriptor).getInternalName()
|
||||||
);
|
);
|
||||||
|
|
||||||
FunctionGenerationStrategy strategy =
|
FunctionGenerationStrategy strategy;
|
||||||
expression instanceof KtCallableReferenceExpression ?
|
if (expression instanceof KtCallableReferenceExpression) {
|
||||||
new FunctionReferenceGenerationStrategy(
|
KtCallableReferenceExpression callableReferenceExpression = (KtCallableReferenceExpression) expression;
|
||||||
state,
|
KtExpression receiverExpression = callableReferenceExpression.getReceiverExpression();
|
||||||
descriptor,
|
StackValue receiverValue =
|
||||||
CallUtilKt.getResolvedCallWithAssert(
|
receiverExpression != null && codegen.getBindingContext().getType(receiverExpression) != null
|
||||||
((KtCallableReferenceExpression) expression).getCallableReference(), codegen.getBindingContext()
|
? codegen.gen(receiverExpression)
|
||||||
)
|
: null;
|
||||||
) :
|
|
||||||
new FunctionGenerationStrategy.FunctionDefault(state, descriptor, (KtDeclarationWithBody) expression);
|
strategy = new FunctionReferenceGenerationStrategy(
|
||||||
|
state,
|
||||||
|
descriptor,
|
||||||
|
CallUtilKt.getResolvedCallWithAssert(callableReferenceExpression.getCallableReference(), codegen.getBindingContext()),
|
||||||
|
receiverValue != null ? receiverValue.type : null,
|
||||||
|
receiverValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strategy = new FunctionGenerationStrategy.FunctionDefault(state, descriptor, (KtDeclarationWithBody) expression);
|
||||||
|
}
|
||||||
|
|
||||||
FunctionCodegen.generateMethodBody(adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen);
|
FunctionCodegen.generateMethodBody(adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen);
|
||||||
|
|
||||||
@@ -735,7 +745,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
private void putClosureParametersOnStack() {
|
private void putClosureParametersOnStack() {
|
||||||
for (LambdaInfo next : expressionMap.values()) {
|
for (LambdaInfo next : expressionMap.values()) {
|
||||||
activeLambda = next;
|
activeLambda = next;
|
||||||
codegen.pushClosureOnStack(next.getClassDescriptor(), true, this);
|
codegen.pushClosureOnStack(next.getClassDescriptor(), true, this, /* functionReferenceReceiver = */ null);
|
||||||
}
|
}
|
||||||
activeLambda = null;
|
activeLambda = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
inline fun foo(x: () -> String) = x()
|
||||||
|
|
||||||
|
fun String.id() = this
|
||||||
|
|
||||||
|
fun box() = foo("OK"::id)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun box(): String {
|
||||||
|
val f = "KOTLIN"::get
|
||||||
|
return "${f(1)}${f(0)}"
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fun box(): String {
|
||||||
|
val f = "kotlin"::length
|
||||||
|
val result = f.get()
|
||||||
|
return if (result == 6) "OK" else "Fail: $result"
|
||||||
|
}
|
||||||
@@ -1438,6 +1438,42 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/callableReference"), Pattern.compile("^(.+)\\.kt$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/callableReference"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/callableReference/bound")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Bound extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInBound() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/callableReference/bound"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleFunction.kt")
|
||||||
|
public void testSimpleFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/bound/simpleFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleProperty.kt")
|
||||||
|
public void testSimpleProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/bound/simpleProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/callableReference/bound/inline")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Inline extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInInline() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/callableReference/bound/inline"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/callableReference/bound/inline/simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/callableReference/function")
|
@TestMetadata("compiler/testData/codegen/box/callableReference/function")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user