Support crossinline suspend lambda as parameter of inline function
Use fake continuation instead of ALOAD 0 while inlining Do not generate state machine for inner lambdas and inner objects, which capture crossinline suspend lambda. #KT-19159: Fixed
This commit is contained in:
Generated
+1
@@ -53,6 +53,7 @@
|
||||
<component name="SuppressABINotification">
|
||||
<option name="modulesWithSuppressedNotConfigured">
|
||||
<set>
|
||||
<option value="backend.src" />
|
||||
<option value="kotlin-stdlib-common" />
|
||||
<option value="kotlin-stdlib-js" />
|
||||
<option value="kotlin-test-common" />
|
||||
|
||||
@@ -2343,7 +2343,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
@NotNull CallGenerator callGenerator,
|
||||
@NotNull ArgumentGenerator argumentGenerator
|
||||
) {
|
||||
boolean isSuspendNoInlineCall = CoroutineCodegenUtilKt.isSuspendNoInlineCall(resolvedCall);
|
||||
boolean isSuspendNoInlineCall = CoroutineCodegenUtilKt.isSuspendNoInlineCall(resolvedCall, this);
|
||||
boolean isConstructor = resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor;
|
||||
if (!(callableMethod instanceof IntrinsicWithSpecialReceiver)) {
|
||||
putReceiverAndInlineMarkerIfNeeded(callableMethod, resolvedCall, receiver, isSuspendNoInlineCall, isConstructor);
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
@@ -61,10 +62,7 @@ import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
@@ -642,6 +640,10 @@ public class FunctionCodegen {
|
||||
mv.visitLabel(methodEnd);
|
||||
|
||||
Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
|
||||
|
||||
if (functionDescriptor instanceof AnonymousFunctionDescriptor && functionDescriptor.isSuspend()) {
|
||||
functionDescriptor = CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(functionDescriptor, typeMapper.getBindingContext());
|
||||
}
|
||||
generateLocalVariableTable(
|
||||
mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind(), typeMapper,
|
||||
(functionFakeIndex >= 0 ? 1 : 0) + (lambdaFakeIndex >= 0 ? 1 : 0)
|
||||
|
||||
+58
-13
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.binding;
|
||||
@@ -25,6 +14,7 @@ import kotlin.collections.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.ReflectionTypes;
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor;
|
||||
import org.jetbrains.kotlin.cfg.WhenChecker;
|
||||
import org.jetbrains.kotlin.codegen.*;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
@@ -51,6 +41,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue;
|
||||
import org.jetbrains.kotlin.resolve.constants.NullValue;
|
||||
@@ -314,8 +305,25 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
nameStack.push(name);
|
||||
|
||||
if (CoroutineUtilKt.isSuspendLambda(functionDescriptor)) {
|
||||
SimpleFunctionDescriptor jvmSuspendFunctionView =
|
||||
CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(
|
||||
(SimpleFunctionDescriptor) functionDescriptor
|
||||
);
|
||||
|
||||
bindingTrace.record(
|
||||
CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW,
|
||||
functionDescriptor,
|
||||
jvmSuspendFunctionView
|
||||
);
|
||||
closure.setSuspend(true);
|
||||
closure.setSuspendLambda();
|
||||
if (capturesCrossinlineSuspendLambda(functionLiteral)) {
|
||||
bindingTrace.record(
|
||||
CodegenBinding.CAPTURES_CROSSINLINE_SUSPEND_LAMBDA,
|
||||
functionDescriptor,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
super.visitLambdaExpression(lambdaExpression);
|
||||
@@ -323,6 +331,35 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
classStack.pop();
|
||||
}
|
||||
|
||||
// If inner lambda captures crossinline suspend lambda, it is unsafe to generate state machine for it.
|
||||
private boolean capturesCrossinlineSuspendLambda(@NotNull PsiElement psiNode) {
|
||||
PsiElement[] children = psiNode.getChildren();
|
||||
boolean res = false;
|
||||
for (PsiElement child : children) {
|
||||
if (child instanceof KtCallElement) {
|
||||
KtExpression callee = ((KtCallElement) child).getCalleeExpression();
|
||||
Call call = bindingContext.get(CALL, callee);
|
||||
ResolvedCall<?> resolvedCall = bindingContext.get(RESOLVED_CALL, call);
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
VariableAsFunctionResolvedCall variableAsFunction = (VariableAsFunctionResolvedCall) resolvedCall;
|
||||
VariableDescriptor variableDescriptor = variableAsFunction.getVariableCall().getResultingDescriptor();
|
||||
CallableDescriptor callableDescriptor = ((ResolvedCall) variableAsFunction).getResultingDescriptor();
|
||||
if (variableDescriptor instanceof ValueParameterDescriptor &&
|
||||
((ValueParameterDescriptor) variableDescriptor).isCrossinline() &&
|
||||
callableDescriptor instanceof FunctionDescriptor &&
|
||||
((FunctionDescriptor) callableDescriptor).isSuspend()) {
|
||||
FunctionDescriptor enclosingDescriptor =
|
||||
bindingContext.get(ENCLOSING_SUSPEND_FUNCTION_FOR_SUSPEND_FUNCTION_CALL, resolvedCall.getCall());
|
||||
assert(enclosingDescriptor != null);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
res = res || capturesCrossinlineSuspendLambda(child);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression) {
|
||||
ResolvedCall<?> referencedFunction = CallUtilKt.getResolvedCall(expression.getCallableReference(), bindingContext);
|
||||
@@ -537,6 +574,14 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
MutableClosure closure = recordClosure(classDescriptor, name);
|
||||
closure.setSuspend(true);
|
||||
|
||||
if (capturesCrossinlineSuspendLambda(function)) {
|
||||
bindingTrace.record(
|
||||
CodegenBinding.CAPTURES_CROSSINLINE_SUSPEND_LAMBDA,
|
||||
functionDescriptor,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
super.visitNamedFunction(function);
|
||||
|
||||
if (nameForClassOrPackageMember != null) {
|
||||
|
||||
@@ -52,6 +52,9 @@ public class CodegenBinding {
|
||||
public static final WritableSlice<FunctionDescriptor, FunctionDescriptor> SUSPEND_FUNCTION_TO_JVM_VIEW =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<FunctionDescriptor, Boolean> CAPTURES_CROSSINLINE_SUSPEND_LAMBDA =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<ValueParameterDescriptor, ValueParameterDescriptor> PARAMETER_SYNONYM =
|
||||
Slices.createSimpleSlice();
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.codegen.context.PackageContext
|
||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||
import org.jetbrains.kotlin.codegen.inline.ReificationArgument
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
@@ -50,6 +51,11 @@ import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.util.Textifier
|
||||
import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import java.io.StringWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
|
||||
fun generateIsCheck(
|
||||
@@ -424,3 +430,13 @@ inline fun FrameMap.evaluateOnce(
|
||||
leaveTemp(asType)
|
||||
}
|
||||
}
|
||||
|
||||
// Handy debugging routine. Print all instructions from methodNode.
|
||||
fun MethodNode.textifyMethodNode(): String {
|
||||
val text = Textifier()
|
||||
val tmv = TraceMethodVisitor(text)
|
||||
this.instructions.asSequence().forEach { it.accept(tmv) }
|
||||
val sw = StringWriter()
|
||||
text.print(PrintWriter(sw))
|
||||
return "$sw"
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class InlineLambdaContext(
|
||||
contextKind: OwnerKind,
|
||||
parentContext: CodegenContext<*>,
|
||||
closure: MutableClosure?,
|
||||
private val isCrossInline: Boolean,
|
||||
val isCrossInline: Boolean,
|
||||
private val isPropertyReference: Boolean
|
||||
) : MethodContext(functionDescriptor, contextKind, parentContext, closure, false) {
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_SUSPEND_LAMBDA
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
|
||||
@@ -127,7 +129,8 @@ class CoroutineCodegenForLambda private constructor(
|
||||
element: KtElement,
|
||||
private val closureContext: ClosureContext,
|
||||
classBuilder: ClassBuilder,
|
||||
private val originalSuspendFunctionDescriptor: FunctionDescriptor
|
||||
private val originalSuspendFunctionDescriptor: FunctionDescriptor,
|
||||
private val forInline: Boolean
|
||||
) : AbstractCoroutineCodegen(
|
||||
outerExpressionCodegen, element, closureContext, classBuilder,
|
||||
userDataForDoResume = mapOf(INITIAL_SUSPEND_DESCRIPTOR_FOR_DO_RESUME to originalSuspendFunctionDescriptor)
|
||||
@@ -300,13 +303,14 @@ class CoroutineCodegenForLambda private constructor(
|
||||
object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) {
|
||||
|
||||
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
|
||||
if (forInline) return super.wrapMethodVisitor(mv, access, name, desc)
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { v },
|
||||
element = element,
|
||||
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = v.thisName,
|
||||
isForNamedFunction = false
|
||||
mv, access, name, desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { v },
|
||||
lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0,
|
||||
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = v.thisName,
|
||||
isForNamedFunction = false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -336,7 +340,9 @@ class CoroutineCodegenForLambda private constructor(
|
||||
originalSuspendLambdaDescriptor, expressionCodegen, expressionCodegen.state.typeMapper
|
||||
),
|
||||
classBuilder,
|
||||
originalSuspendLambdaDescriptor
|
||||
originalSuspendLambdaDescriptor,
|
||||
// Local suspend lambdas, which call crossinline suspend parameters of containing functions must be generated after inlining
|
||||
expressionCodegen.bindingContext[CAPTURES_CROSSINLINE_SUSPEND_LAMBDA, originalSuspendLambdaDescriptor] == true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+63
-39
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import com.intellij.util.containers.Stack
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
@@ -28,7 +27,6 @@ import org.jetbrains.kotlin.codegen.optimization.common.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
@@ -53,7 +51,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
obtainClassBuilderForCoroutineState: () -> ClassBuilder,
|
||||
private val isForNamedFunction: Boolean,
|
||||
private val shouldPreserveClassInitialization: Boolean,
|
||||
private val element: KtElement,
|
||||
private val lineNumber: Int,
|
||||
// It's only matters for named functions, may differ from '!isStatic(access)' in case of DefaultImpls
|
||||
private val needDispatchReceiver: Boolean = false,
|
||||
// May differ from containingClassInternalName in case of DefaultImpls
|
||||
@@ -67,6 +65,8 @@ class CoroutineTransformerMethodVisitor(
|
||||
private var exceptionIndex = if (isForNamedFunction) -1 else 2
|
||||
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
removeFakeContinuationConstructorCall(methodNode)
|
||||
|
||||
val suspensionPoints = collectSuspensionPoints(methodNode)
|
||||
|
||||
// First instruction in the method node may change in case of named function
|
||||
@@ -78,11 +78,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
ReturnUnitMethodTransformer.transform(containingClassInternalName, methodNode)
|
||||
|
||||
if (allSuspensionPointsAreTailCalls(containingClassInternalName, methodNode, suspensionPoints)) {
|
||||
continuationIndex =
|
||||
if (isStatic(methodNode.access))
|
||||
Type.getArgumentTypes(methodNode.desc).size - 1
|
||||
else
|
||||
Type.getArgumentTypes(methodNode.desc).size
|
||||
continuationIndex = getLastParameterIndex(methodNode.desc, methodNode.access)
|
||||
replaceFakeContinuationsWithRealOnes(methodNode, continuationIndex)
|
||||
|
||||
dropSuspensionMarkers(methodNode, suspensionPoints)
|
||||
@@ -125,7 +121,6 @@ class CoroutineTransformerMethodVisitor(
|
||||
val startLabel = LabelNode()
|
||||
val defaultLabel = LabelNode()
|
||||
val tableSwitchLabel = LabelNode()
|
||||
val lineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0
|
||||
|
||||
// tableswitch(this.label)
|
||||
insertBefore(
|
||||
@@ -161,12 +156,15 @@ class CoroutineTransformerMethodVisitor(
|
||||
methodNode.removeEmptyCatchBlocks()
|
||||
}
|
||||
|
||||
private fun replaceFakeContinuationsWithRealOnes(methodNode: MethodNode, continuationIndex: Int) {
|
||||
val fakeContinuations = methodNode.instructions.asSequence().filter(::isFakeContinuationMarker)
|
||||
for (fakeContinuation in fakeContinuations) {
|
||||
methodNode.instructions.removeAll(listOf(fakeContinuation.previous.previous, fakeContinuation.previous))
|
||||
methodNode.instructions.set(fakeContinuation, VarInsnNode(Opcodes.ALOAD, continuationIndex))
|
||||
private fun removeFakeContinuationConstructorCall(methodNode: MethodNode) {
|
||||
val seq = methodNode.instructions.asSequence()
|
||||
val first = seq.firstOrNull(::isBeforeFakeContinuationConstructorCallMarker)?.previous ?: return
|
||||
val last = seq.firstOrNull(::isAfterFakeContinuationConstructorCallMarker).sure {
|
||||
"BeforeFakeContinuationConstructorCallMarker without AfterFakeContinuationConstructorCallMarker"
|
||||
}
|
||||
val toRemove = InsnSequence(first, last).toList()
|
||||
methodNode.instructions.removeAll(toRemove)
|
||||
methodNode.instructions.set(last, InsnNode(Opcodes.ACONST_NULL))
|
||||
}
|
||||
|
||||
private fun createInsnForReadingLabel() =
|
||||
@@ -285,30 +283,13 @@ class CoroutineTransformerMethodVisitor(
|
||||
|
||||
visitLabel(createStateInstance)
|
||||
|
||||
anew(objectTypeForState)
|
||||
dup()
|
||||
|
||||
val parameterTypesAndIndices =
|
||||
getParameterTypesIndicesForCoroutineConstructor(
|
||||
methodNode.desc,
|
||||
methodNode.access,
|
||||
needDispatchReceiver, internalNameForDispatchReceiver ?: containingClassInternalName
|
||||
)
|
||||
for ((type, index) in parameterTypesAndIndices) {
|
||||
load(index, type)
|
||||
}
|
||||
|
||||
invokespecial(
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"<init>",
|
||||
Type.getMethodDescriptor(
|
||||
Type.VOID_TYPE,
|
||||
*getParameterTypesForCoroutineConstructor(
|
||||
methodNode.desc, needDispatchReceiver,
|
||||
internalNameForDispatchReceiver ?: containingClassInternalName
|
||||
)
|
||||
),
|
||||
false
|
||||
generateContinuationConstructorCall(
|
||||
objectTypeForState,
|
||||
methodNode,
|
||||
needDispatchReceiver,
|
||||
internalNameForDispatchReceiver,
|
||||
containingClassInternalName,
|
||||
classBuilderForCoroutineState
|
||||
)
|
||||
|
||||
visitVarInsn(Opcodes.ASTORE, continuationIndex)
|
||||
@@ -501,7 +482,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
): LabelNode {
|
||||
val continuationLabel = LabelNode()
|
||||
val continuationLabelAfterLoadedResult = LabelNode()
|
||||
val suspendElementLineNumber = CodegenUtil.getLineNumberForElement(element, false) ?: 0
|
||||
val suspendElementLineNumber = lineNumber
|
||||
val nextLineNumberNode = suspension.suspensionCallEnd.findNextOrNull { it is LineNumberNode } as? LineNumberNode
|
||||
with(methodNode.instructions) {
|
||||
// Save state
|
||||
@@ -616,6 +597,41 @@ class CoroutineTransformerMethodVisitor(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun InstructionAdapter.generateContinuationConstructorCall(
|
||||
objectTypeForState: Type?,
|
||||
methodNode: MethodNode,
|
||||
needDispatchReceiver: Boolean,
|
||||
internalNameForDispatchReceiver: String?,
|
||||
containingClassInternalName: String,
|
||||
classBuilderForCoroutineState: ClassBuilder
|
||||
) {
|
||||
anew(objectTypeForState)
|
||||
dup()
|
||||
|
||||
val parameterTypesAndIndices =
|
||||
getParameterTypesIndicesForCoroutineConstructor(
|
||||
methodNode.desc,
|
||||
methodNode.access,
|
||||
needDispatchReceiver, internalNameForDispatchReceiver ?: containingClassInternalName
|
||||
)
|
||||
for ((type, index) in parameterTypesAndIndices) {
|
||||
load(index, type)
|
||||
}
|
||||
|
||||
invokespecial(
|
||||
classBuilderForCoroutineState.thisName,
|
||||
"<init>",
|
||||
Type.getMethodDescriptor(
|
||||
Type.VOID_TYPE,
|
||||
*getParameterTypesForCoroutineConstructor(
|
||||
methodNode.desc, needDispatchReceiver,
|
||||
internalNameForDispatchReceiver ?: containingClassInternalName
|
||||
)
|
||||
),
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
private fun InstructionAdapter.generateResumeWithExceptionCheck(exceptionIndex: Int) {
|
||||
// Check if resumeWithException has been called
|
||||
load(exceptionIndex, AsmTypes.OBJECT_TYPE)
|
||||
@@ -803,3 +819,11 @@ private fun AbstractInsnNode?.isInvisibleInDebugVarInsn(methodNode: MethodNode):
|
||||
|
||||
private val SAFE_OPCODES =
|
||||
((Opcodes.DUP..Opcodes.DUP2_X2) + Opcodes.NOP + Opcodes.POP + Opcodes.POP2 + (Opcodes.IFEQ..Opcodes.GOTO)).toSet()
|
||||
|
||||
internal fun replaceFakeContinuationsWithRealOnes(methodNode: MethodNode, continuationIndex: Int) {
|
||||
val fakeContinuations = methodNode.instructions.asSequence().filter(::isFakeContinuationMarker).toList()
|
||||
for (fakeContinuation in fakeContinuations) {
|
||||
methodNode.instructions.removeAll(listOf(fakeContinuation.previous.previous, fakeContinuation.previous))
|
||||
methodNode.instructions.set(fakeContinuation, VarInsnNode(Opcodes.ALOAD, continuationIndex))
|
||||
}
|
||||
}
|
||||
+56
-10
@@ -16,9 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy
|
||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationConstructorCallMarker
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -30,6 +34,8 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
class SuspendFunctionGenerationStrategy(
|
||||
state: GenerationState,
|
||||
@@ -39,7 +45,6 @@ class SuspendFunctionGenerationStrategy(
|
||||
private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode
|
||||
) : FunctionGenerationStrategy.CodegenBased(state) {
|
||||
|
||||
private lateinit var transformer: CoroutineTransformerMethodVisitor
|
||||
private lateinit var codegen: ExpressionCodegen
|
||||
|
||||
private val classBuilderForCoroutineState by lazy {
|
||||
@@ -57,16 +62,22 @@ class SuspendFunctionGenerationStrategy(
|
||||
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
|
||||
if (access and Opcodes.ACC_ABSTRACT != 0) return mv
|
||||
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState,
|
||||
isForNamedFunction = true,
|
||||
element = declaration,
|
||||
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null,
|
||||
internalNameForDispatchReceiver = containingClassInternalNameOrNull()
|
||||
).also {
|
||||
transformer = it
|
||||
if (state.bindingContext[CodegenBinding.CAPTURES_CROSSINLINE_SUSPEND_LAMBDA, originalSuspendDescriptor] == true) {
|
||||
return AddConstructorCallForCoroutineRegeneration(
|
||||
mv, access, name, desc, null, null, this::classBuilderForCoroutineState,
|
||||
containingClassInternalName,
|
||||
originalSuspendDescriptor.dispatchReceiverParameter != null,
|
||||
containingClassInternalNameOrNull()
|
||||
)
|
||||
}
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState,
|
||||
isForNamedFunction = true,
|
||||
lineNumber = CodegenUtil.getLineNumberForElement(declaration, false) ?: 0,
|
||||
shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null,
|
||||
internalNameForDispatchReceiver = containingClassInternalNameOrNull()
|
||||
)
|
||||
}
|
||||
|
||||
private fun containingClassInternalNameOrNull() =
|
||||
@@ -76,4 +87,39 @@ class SuspendFunctionGenerationStrategy(
|
||||
this.codegen = codegen
|
||||
codegen.returnExpression(declaration.bodyExpression ?: error("Function has no body: " + declaration.getElementTextWithContext()))
|
||||
}
|
||||
|
||||
// When we generate named suspend function for the use as inline site, we do not generate state machine.
|
||||
// So, there will be no way to remember the name of generated continuation in such case.
|
||||
// In order to keep generated continuation for named suspend function, we just generate construction call, which is going to be
|
||||
// removed during inlining.
|
||||
// The continuation itself will be regenerated and used as a container for the coroutine's locals.
|
||||
private class AddConstructorCallForCoroutineRegeneration(
|
||||
delegate: MethodVisitor,
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
signature: String?,
|
||||
exceptions: Array<out String>?,
|
||||
obtainClassBuilderForCoroutineState: () -> ClassBuilder,
|
||||
private val containingClassInternalName: String,
|
||||
private val needDispatchReceiver: Boolean,
|
||||
private val internalNameForDispatchReceiver: String?
|
||||
) : TransformationMethodVisitor(delegate, access, name, desc, signature, exceptions) {
|
||||
private val classBuilderForCoroutineState: ClassBuilder by lazy(obtainClassBuilderForCoroutineState)
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
val objectTypeForState = Type.getObjectType(classBuilderForCoroutineState.thisName)
|
||||
methodNode.instructions.insert(withInstructionAdapter {
|
||||
addFakeContinuationConstructorCallMarker(this, true)
|
||||
generateContinuationConstructorCall(
|
||||
objectTypeForState,
|
||||
methodNode,
|
||||
needDispatchReceiver,
|
||||
internalNameForDispatchReceiver,
|
||||
containingClassInternalName,
|
||||
classBuilderForCoroutineState
|
||||
)
|
||||
addFakeContinuationConstructorCallMarker(this, false)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-5
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.coroutines
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationMarker
|
||||
@@ -175,13 +176,18 @@ private fun NewResolvedCallImpl<VariableDescriptor>.asDummyOldResolvedCall(bindi
|
||||
)
|
||||
}
|
||||
|
||||
fun ResolvedCall<*>.isSuspendNoInlineCall(): Boolean {
|
||||
val isCrossinline =
|
||||
safeAs<VariableAsFunctionResolvedCall>()?.variableCall?.resultingDescriptor?.safeAs<ValueParameterDescriptor>()?.isCrossinline
|
||||
?: false
|
||||
fun ResolvedCall<*>.isSuspendNoInlineCall(codegen: ExpressionCodegen): Boolean {
|
||||
var isCrossinline = false
|
||||
var isInlineLambda = false
|
||||
if (this is VariableAsFunctionResolvedCall) {
|
||||
variableCall.resultingDescriptor.safeAs<ValueParameterDescriptor>()?.let {
|
||||
isCrossinline = it.isCrossinline
|
||||
isInlineLambda = !isCrossinline && !it.isNoinline && codegen.context.functionDescriptor.isInline
|
||||
}
|
||||
}
|
||||
return resultingDescriptor.safeAs<FunctionDescriptor>()
|
||||
?.let {
|
||||
val inline = it.isInline || isCrossinline
|
||||
val inline = it.isInline || isCrossinline || isInlineLambda
|
||||
it.isSuspend && (!inline || it.isBuiltInSuspendCoroutineOrReturnInJvm() || it.isBuiltInSuspendCoroutineUninterceptedOrReturnInJvm())
|
||||
} == true
|
||||
}
|
||||
|
||||
+111
-5
@@ -21,15 +21,17 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.coroutines.COROUTINE_IMPL_ASM_TYPE
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable
|
||||
import org.jetbrains.kotlin.codegen.writeKotlinMetadata
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.load.kotlin.header.ReadKotlinClassHeaderAnnotationVisitor
|
||||
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||
import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.load.kotlin.header.ReadKotlinClassHeaderAnnotationVisitor
|
||||
import org.jetbrains.kotlin.protobuf.MessageLite
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.Companion.NO_ORIGIN
|
||||
@@ -41,7 +43,8 @@ import java.util.*
|
||||
class AnonymousObjectTransformer(
|
||||
transformationInfo: AnonymousObjectTransformationInfo,
|
||||
private val inliningContext: InliningContext,
|
||||
private val isSameModule: Boolean
|
||||
private val isSameModule: Boolean,
|
||||
private val continuationClassName: String?
|
||||
) : ObjectTransformer<AnonymousObjectTransformationInfo>(transformationInfo, inliningContext.state) {
|
||||
|
||||
private val oldObjectType = Type.getObjectType(transformationInfo.oldClassName)
|
||||
@@ -138,12 +141,39 @@ class AnonymousObjectTransformer(
|
||||
val additionalFakeParams = extractParametersMappingAndPatchConstructor(
|
||||
constructor!!, allCapturedParamBuilder, constructorParamBuilder,transformationInfo, parentRemapper
|
||||
)
|
||||
|
||||
val capturesCrossinlineSuspend = (!inliningContext.isInliningLambda || inliningContext.isContinuation) &&
|
||||
inliningContext.expressionMap.values.any { lambda ->
|
||||
lambda is PsiExpressionLambda && lambda.isCrossInline && lambda.invokeMethodDescriptor.isSuspend
|
||||
}
|
||||
|
||||
val deferringMethods = ArrayList<DeferredMethodVisitor>()
|
||||
|
||||
generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, parentRemapper, additionalFakeParams)
|
||||
|
||||
val isLambdaAlreadyGeneratedAndNotGoingToBeInlined = transformationInfo.oldClassName.contains("\$\$special\$\$inlined")
|
||||
|
||||
val hasLambdasToInline =
|
||||
((parentRemapper is RegeneratedLambdaFieldRemapper) && parentRemapper.recapturedLambdas.isNotEmpty()) || transformationInfo.capturedLambdasToInline.isNotEmpty()
|
||||
|
||||
for (next in methodsToTransform) {
|
||||
val deferringVisitor = newMethod(classBuilder, next)
|
||||
// Generate state machine for
|
||||
// 1) doResume method of suspend lambda
|
||||
// 2) Suspend named function
|
||||
// Iff it captures crossinline suspend lambda
|
||||
val generateStateMachineForLambda =
|
||||
next.name == "doResume" && capturesCrossinlineSuspend && inliningContext.isContinuation &&
|
||||
!isLambdaAlreadyGeneratedAndNotGoingToBeInlined && hasLambdasToInline
|
||||
val continuationClassName = findFakeContinuationConstructorClassName(next)
|
||||
val generateStateMachineForNamedFunction =
|
||||
capturesCrossinlineSuspend && !inliningContext.isContinuation && continuationClassName != null
|
||||
|
||||
val deferringVisitor =
|
||||
when {
|
||||
generateStateMachineForLambda -> newStateMachineForLambda(classBuilder, next)
|
||||
generateStateMachineForNamedFunction -> newStateMachineForNamedFunction(classBuilder, next, continuationClassName!!)
|
||||
else -> newMethod(classBuilder, next)
|
||||
}
|
||||
val funResult = inlineMethodAndUpdateGlobalResult(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false)
|
||||
|
||||
val returnType = Type.getReturnType(next.desc)
|
||||
@@ -160,6 +190,21 @@ class AnonymousObjectTransformer(
|
||||
deferringMethods.forEach { method ->
|
||||
removeFinallyMarkers(method.intermediate)
|
||||
method.visitEnd()
|
||||
|
||||
// During regeneration of named suspend functions, which capture crossinline suspend lambda, we need to spill the variables
|
||||
// into continuation object.
|
||||
// In order to do this, we reuse class builder, which regenerates continuation object.
|
||||
if (capturesCrossinlineSuspend &&
|
||||
!inliningContext.isContinuation &&
|
||||
inliningContext is RegeneratedClassContext
|
||||
) {
|
||||
val continuationClassName = findFakeContinuationConstructorClassName(method.intermediate)
|
||||
if (continuationClassName != null) {
|
||||
inliningContext.continuationBuilders
|
||||
.remove(continuationClassName)
|
||||
?.let(ClassBuilder::done)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SourceMapper.flushToClassBuilder(sourceMapper, classBuilder)
|
||||
@@ -177,7 +222,12 @@ class AnonymousObjectTransformer(
|
||||
|
||||
writeOuterInfo(visitor)
|
||||
|
||||
classBuilder.done()
|
||||
if (continuationClassName == transformationInfo.oldClassName) {
|
||||
assert(inliningContext.parent?.parent is RegeneratedClassContext)
|
||||
(inliningContext.parent?.parent as RegeneratedClassContext).continuationBuilders[continuationClassName] = classBuilder
|
||||
} else {
|
||||
classBuilder.done()
|
||||
}
|
||||
|
||||
return transformationResult
|
||||
}
|
||||
@@ -390,6 +440,55 @@ class AnonymousObjectTransformer(
|
||||
}
|
||||
}
|
||||
|
||||
private fun newStateMachineForLambda(builder: ClassBuilder, original: MethodNode): DeferredMethodVisitor {
|
||||
return DeferredMethodVisitor(
|
||||
MethodNode(
|
||||
original.access, original.name, original.desc, original.signature,
|
||||
ArrayUtil.toStringArray(original.exceptions)
|
||||
)
|
||||
) {
|
||||
CoroutineTransformerMethodVisitor(
|
||||
builder.newMethod(
|
||||
NO_ORIGIN, original.access, original.name, original.desc, original.signature,
|
||||
ArrayUtil.toStringArray(original.exceptions)
|
||||
), original.access, original.name, original.desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { builder },
|
||||
lineNumber = 0, // <- TODO
|
||||
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = builder.thisName,
|
||||
isForNamedFunction = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun newStateMachineForNamedFunction(
|
||||
builder: ClassBuilder,
|
||||
original: MethodNode,
|
||||
continuationClassName: String
|
||||
): DeferredMethodVisitor {
|
||||
assert(inliningContext is RegeneratedClassContext)
|
||||
return DeferredMethodVisitor(
|
||||
MethodNode(
|
||||
original.access, original.name, original.desc, original.signature,
|
||||
ArrayUtil.toStringArray(original.exceptions)
|
||||
)
|
||||
) {
|
||||
CoroutineTransformerMethodVisitor(
|
||||
builder.newMethod(
|
||||
NO_ORIGIN, original.access, original.name, original.desc, original.signature,
|
||||
ArrayUtil.toStringArray(original.exceptions)
|
||||
), original.access, original.name, original.desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
|
||||
lineNumber = 0, // <- TODO
|
||||
shouldPreserveClassInitialization = state.constructorCallNormalizationMode.shouldPreserveClassInitialization,
|
||||
containingClassInternalName = builder.thisName,
|
||||
isForNamedFunction = true,
|
||||
needDispatchReceiver = true,
|
||||
internalNameForDispatchReceiver = builder.thisName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractParametersMappingAndPatchConstructor(
|
||||
constructor: MethodNode,
|
||||
capturedParamBuilder: ParametersBuilder,
|
||||
@@ -535,3 +634,10 @@ class AnonymousObjectTransformer(
|
||||
private fun isFirstDeclSiteLambdaFieldRemapper(parentRemapper: FieldRemapper): Boolean =
|
||||
parentRemapper !is RegeneratedLambdaFieldRemapper && parentRemapper !is InlinedLambdaRemapper
|
||||
}
|
||||
|
||||
internal fun findFakeContinuationConstructorClassName(node: MethodNode): String? {
|
||||
val marker = node.instructions.asSequence().firstOrNull(::isBeforeFakeContinuationConstructorCallMarker) ?: return null
|
||||
val new = marker.next
|
||||
assert(new?.opcode == Opcodes.NEW)
|
||||
return (new as TypeInsnNode).desc
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
@@ -41,11 +42,13 @@ class RegeneratedClassContext(
|
||||
override val callSiteInfo: InlineCallSiteInfo
|
||||
) : InliningContext(
|
||||
parent, expressionMap, state, nameGenerator, typeRemapper, lambdaInfo, true
|
||||
)
|
||||
) {
|
||||
val continuationBuilders: MutableMap<String, ClassBuilder> = hashMapOf()
|
||||
}
|
||||
|
||||
open class InliningContext(
|
||||
val parent: InliningContext?,
|
||||
private val expressionMap: Map<Int, LambdaInfo>,
|
||||
val expressionMap: Map<Int, LambdaInfo>,
|
||||
val state: GenerationState,
|
||||
val nameGenerator: NameGenerator,
|
||||
val typeRemapper: TypeRemapper,
|
||||
@@ -55,7 +58,7 @@ open class InliningContext(
|
||||
|
||||
val isInliningLambda = lambdaInfo != null
|
||||
|
||||
val internalNameToAnonymousObjectTransformationInfo = hashMapOf<String, AnonymousObjectTransformationInfo>()
|
||||
private val internalNameToAnonymousObjectTransformationInfo = hashMapOf<String, AnonymousObjectTransformationInfo>()
|
||||
|
||||
var isContinuation: Boolean = false
|
||||
|
||||
@@ -64,6 +67,14 @@ open class InliningContext(
|
||||
val root: RootInliningContext
|
||||
get() = if (isRoot) this as RootInliningContext else parent!!.root
|
||||
|
||||
fun findAnonymousObjectTransformationInfo(internalName: String, searchInParent: Boolean = true): AnonymousObjectTransformationInfo? =
|
||||
internalNameToAnonymousObjectTransformationInfo[internalName]
|
||||
?: if (searchInParent) parent?.findAnonymousObjectTransformationInfo(internalName, searchInParent) else null
|
||||
|
||||
fun recordIfNotPresent(internalName: String, info: AnonymousObjectTransformationInfo) {
|
||||
internalNameToAnonymousObjectTransformationInfo.putIfAbsent(internalName, info)
|
||||
}
|
||||
|
||||
fun subInlineLambda(lambdaInfo: LambdaInfo): InliningContext =
|
||||
subInline(
|
||||
nameGenerator.subGenerator("lambda"),
|
||||
@@ -104,8 +115,4 @@ open class InliningContext(
|
||||
get() {
|
||||
return parent!!.callSiteInfo
|
||||
}
|
||||
|
||||
fun findAnonymousObjectTransformationInfo(internalName: String): AnonymousObjectTransformationInfo? {
|
||||
return root.internalNameToAnonymousObjectTransformationInfo[internalName]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
@@ -9,18 +9,23 @@ import org.jetbrains.kotlin.backend.jvm.codegen.IrExpressionLambda
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ClosureCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_ASM_TYPE
|
||||
import org.jetbrains.kotlin.codegen.coroutines.replaceFakeContinuationsWithRealOnes
|
||||
import org.jetbrains.kotlin.codegen.inline.FieldRemapper.Companion.foldName
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.optimization.ApiVersionCallsPreprocessingMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.FixStackWithLabelNormalizationMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.isMeaningful
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -159,7 +164,11 @@ class MethodInliner(
|
||||
currentTypeMapping,
|
||||
inlineCallSiteInfo
|
||||
)
|
||||
val transformer = transformationInfo!!.createTransformer(childInliningContext, isSameModule)
|
||||
val transformer = transformationInfo!!.createTransformer(
|
||||
childInliningContext,
|
||||
isSameModule,
|
||||
findFakeContinuationConstructorClassName(node)
|
||||
)
|
||||
|
||||
val transformResult = transformer.doTransform(nodeRemapper)
|
||||
result.merge(transformResult)
|
||||
@@ -308,7 +317,7 @@ class MethodInliner(
|
||||
//TODO: add new inner class also for other contexts
|
||||
if (inliningContext.parent is RegeneratedClassContext) {
|
||||
inliningContext.parent.typeRemapper.addAdditionalMappings(
|
||||
transformationInfo!!.oldClassName, transformationInfo!!.newClassName
|
||||
transformationInfo!!.oldClassName, transformationInfo!!.newClassName
|
||||
)
|
||||
}
|
||||
|
||||
@@ -319,7 +328,7 @@ class MethodInliner(
|
||||
}
|
||||
}
|
||||
else if ((!inliningContext.isInliningLambda || isDefaultLambdaWithReification(inliningContext.lambdaInfo!!)) &&
|
||||
ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) {
|
||||
ReifiedTypeInliner.isNeedClassReificationMarker(MethodInsnNode(opcode, owner, name, desc, false))) {
|
||||
//we shouldn't process here content of inlining lambda it should be reified at external level except default lambdas
|
||||
}
|
||||
else {
|
||||
@@ -443,6 +452,8 @@ class MethodInliner(
|
||||
|
||||
preprocessNodeBeforeInline(processingNode, labelOwner)
|
||||
|
||||
replaceContinuationAccessesWithFakeContinuationsIfNeeded(processingNode)
|
||||
|
||||
val sources = analyzeMethodNodeBeforeInline(processingNode)
|
||||
|
||||
val toDelete = SmartSet.create<AbstractInsnNode>()
|
||||
@@ -584,6 +595,67 @@ class MethodInliner(
|
||||
return processingNode
|
||||
}
|
||||
|
||||
// Replace ALOAD 0
|
||||
// with
|
||||
// ICONST fakeContinuationMarker
|
||||
// INVOKESTATIC InlineMarker.mark
|
||||
// ACONST_NULL
|
||||
// iff this ALOAD 0 is continuation and one of the following conditions is met
|
||||
// 1) it is passed as the last parameter to suspending function
|
||||
// 2) it is ASTORE'd right after
|
||||
// 3) it is passed to invoke of lambda
|
||||
private fun replaceContinuationAccessesWithFakeContinuationsIfNeeded(processingNode: MethodNode) {
|
||||
val lambdaInfo = inliningContext.lambdaInfo ?: return
|
||||
if (!lambdaInfo.invokeMethodDescriptor.isSuspend) return
|
||||
val aload0s = processingNode.instructions.asSequence().filter { it.opcode == Opcodes.ALOAD && it.safeAs<VarInsnNode>()?.`var` == 0 }
|
||||
// Expected pattern here:
|
||||
// ALOAD 0
|
||||
// ICONST_0
|
||||
// INVOKESTATIC InlineMarker.mark
|
||||
// INVOKE* suspendingFunction(..., Continuation;)Ljava/lang/Object;
|
||||
val continuationAsParameterAload0s =
|
||||
aload0s.filter { it.next?.next?.let(::isBeforeSuspendMarker) == true && isSuspendCall(it.next?.next?.next) }
|
||||
replaceContinuationsWithFakeOnes(continuationAsParameterAload0s, processingNode)
|
||||
// Expected pattern here:
|
||||
// ALOAD 0
|
||||
// ASTORE N
|
||||
// This pattern may occur after multiple inlines
|
||||
val continuationToStoreAload0s = aload0s.filter { it.next?.opcode == Opcodes.ASTORE }
|
||||
replaceContinuationsWithFakeOnes(continuationToStoreAload0s, processingNode)
|
||||
// Expected pattern here:
|
||||
// ALOAD 0
|
||||
// INVOKEINTERFACE kotlin/jvm/functions/FunctionN.invoke (...,Ljava/lang/Object;)Ljava/lang/Object;
|
||||
val continuationAsLambdaParameterAload0s = aload0s.filter { isLambdaCall(it.next) }
|
||||
replaceContinuationsWithFakeOnes(continuationAsLambdaParameterAload0s, processingNode)
|
||||
}
|
||||
|
||||
private fun isLambdaCall(invoke: AbstractInsnNode?): Boolean {
|
||||
if (invoke?.opcode != Opcodes.INVOKEINTERFACE) return false
|
||||
invoke as MethodInsnNode
|
||||
if (!invoke.owner.startsWith("kotlin/jvm/functions/Function")) return false
|
||||
if (invoke.name != "invoke") return false
|
||||
if (Type.getReturnType(invoke.desc) != OBJECT_TYPE) return false
|
||||
return Type.getArgumentTypes(invoke.desc).let { it.isNotEmpty() && it.last() == OBJECT_TYPE }
|
||||
}
|
||||
|
||||
private fun replaceContinuationsWithFakeOnes(
|
||||
continuations: Sequence<AbstractInsnNode>,
|
||||
node: MethodNode
|
||||
) {
|
||||
for (toReplace in continuations) {
|
||||
insertNodeBefore(createFakeContinuationMethodNodeForInline(), node, toReplace)
|
||||
node.instructions.remove(toReplace)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSuspendCall(invoke: AbstractInsnNode?): Boolean {
|
||||
if (invoke !is MethodInsnNode) return false
|
||||
// We can't have suspending constructors.
|
||||
assert(invoke.opcode != Opcodes.INVOKESPECIAL)
|
||||
if (Type.getReturnType(invoke.desc) != OBJECT_TYPE) return false
|
||||
return Type.getArgumentTypes(invoke.desc).let { it.isNotEmpty() && it.last() == CONTINUATION_ASM_TYPE }
|
||||
}
|
||||
|
||||
private fun preprocessNodeBeforeInline(node: MethodNode, labelOwner: LabelOwner) {
|
||||
try {
|
||||
FixStackWithLabelNormalizationMethodTransformer().transform("fake", node)
|
||||
@@ -635,7 +707,6 @@ class MethodInliner(
|
||||
needReification: Boolean,
|
||||
capturesAnonymousObjectThatMustBeRegenerated: Boolean
|
||||
): AnonymousObjectTransformationInfo {
|
||||
val memoizeAnonymousObject = inliningContext.findAnonymousObjectTransformationInfo(anonymousType) == null
|
||||
|
||||
val info = AnonymousObjectTransformationInfo(
|
||||
anonymousType, needReification, lambdaMapping,
|
||||
@@ -647,8 +718,16 @@ class MethodInliner(
|
||||
capturesAnonymousObjectThatMustBeRegenerated
|
||||
)
|
||||
|
||||
if (memoizeAnonymousObject) {
|
||||
inliningContext.root.internalNameToAnonymousObjectTransformationInfo.put(anonymousType, info)
|
||||
val memoizeAnonymousObject = inliningContext.findAnonymousObjectTransformationInfo(anonymousType)
|
||||
if (memoizeAnonymousObject == null ||
|
||||
//anonymous object could be inlined in several context without transformation (keeps same class name)
|
||||
// and on further inlining such code some of such cases would be transformed and some not,
|
||||
// so we should distinguish one classes from another more clearly
|
||||
!memoizeAnonymousObject.shouldRegenerate(isSameModule) &&
|
||||
info.shouldRegenerate(isSameModule)
|
||||
) {
|
||||
|
||||
inliningContext.recordIfNotPresent(anonymousType, info)
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
@@ -43,7 +43,7 @@ class SamWrapperTransformationInfo(override val oldClassName: String, private va
|
||||
|
||||
override fun canRemoveAfterTransformation() = false
|
||||
|
||||
override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean) =
|
||||
override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean, continuationClassName: String?) =
|
||||
SamWrapperTransformer(this, inliningContext)
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ interface TransformationInfo {
|
||||
|
||||
fun canRemoveAfterTransformation(): Boolean
|
||||
|
||||
fun createTransformer(inliningContext: InliningContext, sameModule: Boolean): ObjectTransformer<*>
|
||||
fun createTransformer(inliningContext: InliningContext, sameModule: Boolean, continuationClassName: String?): ObjectTransformer<*>
|
||||
}
|
||||
|
||||
class WhenMappingTransformationInfo(
|
||||
@@ -52,7 +52,7 @@ class WhenMappingTransformationInfo(
|
||||
|
||||
override fun canRemoveAfterTransformation(): Boolean = true
|
||||
|
||||
override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean): ObjectTransformer<*> =
|
||||
override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean, continuationClassName: String?): ObjectTransformer<*> =
|
||||
WhenMappingTransformer(this, inliningContext)
|
||||
|
||||
companion object {
|
||||
@@ -103,6 +103,10 @@ class AnonymousObjectTransformationInfo internal constructor(
|
||||
return !isStaticOrigin
|
||||
}
|
||||
|
||||
override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean): ObjectTransformer<*> =
|
||||
AnonymousObjectTransformer(this, inliningContext, sameModule)
|
||||
override fun createTransformer(
|
||||
inliningContext: InliningContext,
|
||||
sameModule: Boolean,
|
||||
continuationClassName: String?
|
||||
): ObjectTransformer<*> =
|
||||
AnonymousObjectTransformer(this, inliningContext, sameModule, continuationClassName)
|
||||
}
|
||||
|
||||
@@ -84,6 +84,8 @@ private const val INLINE_MARKER_BEFORE_SUSPEND_ID = 0
|
||||
private const val INLINE_MARKER_AFTER_SUSPEND_ID = 1
|
||||
private const val INLINE_MARKER_RETURNS_UNIT = 2
|
||||
private const val INLINE_MARKER_FAKE_CONTINUATION = 3
|
||||
private const val INLINE_MARKER_BEFORE_FAKE_CONTINUATION_CONSTRUCTOR_CALL = 4
|
||||
private const val INLINE_MARKER_AFTER_FAKE_CONTINUATION_CONSTRUCTOR_CALL = 5
|
||||
private val INTRINSIC_ARRAY_CONSTRUCTOR_TYPE = AsmUtil.asmTypeByClassId(classId)
|
||||
|
||||
internal fun getMethodNode(
|
||||
@@ -295,6 +297,13 @@ internal fun insertNodeBefore(from: MethodNode, to: MethodNode, beforeNode: Abst
|
||||
|
||||
internal fun createEmptyMethodNode() = MethodNode(API, 0, "fake", "()V", null, null)
|
||||
|
||||
internal fun createFakeContinuationMethodNodeForInline(): MethodNode {
|
||||
val methodNode = createEmptyMethodNode()
|
||||
val v = InstructionAdapter(methodNode)
|
||||
addFakeContinuationMarker(v)
|
||||
return methodNode
|
||||
}
|
||||
|
||||
internal fun firstLabelInChain(node: LabelNode): LabelNode {
|
||||
var curNode = node
|
||||
while (curNode.previous is LabelNode) {
|
||||
@@ -425,6 +434,15 @@ internal fun addSuspendMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
||||
)
|
||||
}
|
||||
|
||||
internal fun addFakeContinuationConstructorCallMarker(v: InstructionAdapter, isStartNotEnd: Boolean) {
|
||||
v.iconst(if (isStartNotEnd) INLINE_MARKER_BEFORE_FAKE_CONTINUATION_CONSTRUCTOR_CALL else INLINE_MARKER_AFTER_FAKE_CONTINUATION_CONSTRUCTOR_CALL)
|
||||
v.visitMethodInsn(
|
||||
Opcodes.INVOKESTATIC, INLINE_MARKER_CLASS_NAME,
|
||||
"mark",
|
||||
"(I)V", false
|
||||
)
|
||||
}
|
||||
|
||||
private fun addReturnsUnitMarker(v: InstructionAdapter) {
|
||||
v.iconst(INLINE_MARKER_RETURNS_UNIT)
|
||||
v.visitMethodInsn(
|
||||
@@ -454,6 +472,10 @@ internal fun isAfterSuspendMarker(insn: AbstractInsnNode) = isSuspendMarker(insn
|
||||
internal fun isReturnsUnitMarker(insn: AbstractInsnNode) = isSuspendMarker(insn, INLINE_MARKER_RETURNS_UNIT)
|
||||
internal fun isFakeContinuationMarker(insn: AbstractInsnNode) =
|
||||
insn.previous != null && isSuspendMarker(insn.previous, INLINE_MARKER_FAKE_CONTINUATION) && insn.opcode == Opcodes.ACONST_NULL
|
||||
internal fun isBeforeFakeContinuationConstructorCallMarker(insn: AbstractInsnNode) =
|
||||
isSuspendMarker(insn, INLINE_MARKER_BEFORE_FAKE_CONTINUATION_CONSTRUCTOR_CALL)
|
||||
internal fun isAfterFakeContinuationConstructorCallMarker(insn: AbstractInsnNode) =
|
||||
isSuspendMarker(insn, INLINE_MARKER_AFTER_FAKE_CONTINUATION_CONSTRUCTOR_CALL)
|
||||
|
||||
private fun isSuspendMarker(insn: AbstractInsnNode, id: Int) =
|
||||
isInlineMarker(insn, "mark") && insn.previous.intConstant == id
|
||||
|
||||
@@ -201,6 +201,7 @@ public interface Errors {
|
||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, KtModifierKeywordToken> ILLEGAL_INLINE_PARAMETER_MODIFIER = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory0<KtParameter> INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtParameter> REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE = DiagnosticFactory0.create(WARNING);
|
||||
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory2<KtAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE = DiagnosticFactory1.create(WARNING);
|
||||
|
||||
+2
-1
@@ -122,7 +122,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(DEPRECATED_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is deprecated inside ''{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(ILLEGAL_INLINE_PARAMETER_MODIFIER, "Modifier ''{0}'' is allowed only for function parameters of an inline function", TO_STRING);
|
||||
MAP.put(INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, "Inline lambda parameters of suspend function type are not fully supported. Add 'noinline' modifier.");
|
||||
MAP.put(INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, "Inline lambda parameters of suspend function type are not supported. Add 'noinline' or 'crossinline' modifier.");
|
||||
MAP.put(REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE, "Redundant suspend modifier of inline lambda parameters of suspend function type.");
|
||||
MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING);
|
||||
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET, "This annotation is not applicable to target ''{0}'' and use site target ''@{1}''", TO_STRING, TO_STRING);
|
||||
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE,
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.calls.checkers
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
@@ -239,7 +240,7 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
|
||||
val containingDeclaration = descriptor.getContainingDeclaration()
|
||||
val isInvoke = descriptor.getName() == OperatorNameConventions.INVOKE &&
|
||||
containingDeclaration is ClassDescriptor &&
|
||||
containingDeclaration.defaultType.isFunctionType
|
||||
(containingDeclaration.defaultType.isFunctionType || containingDeclaration.defaultType.isSuspendFunctionType)
|
||||
|
||||
return isInvoke || InlineUtil.isInline(descriptor)
|
||||
}
|
||||
|
||||
+9
-3
@@ -32,16 +32,22 @@ object InlineParameterChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
if (declaration is KtFunction) {
|
||||
val inline = declaration.hasModifier(KtTokens.INLINE_KEYWORD)
|
||||
val suspend = declaration.hasModifier(KtTokens.SUSPEND_KEYWORD)
|
||||
for (parameter in declaration.valueParameters) {
|
||||
val parameterDescriptor = context.trace.get(BindingContext.VALUE_PARAMETER, parameter)
|
||||
if (!inline || (parameterDescriptor != null && !parameterDescriptor.type.isBuiltinFunctionalType)) {
|
||||
parameter.reportIncorrectInline(KtTokens.NOINLINE_KEYWORD, context.trace)
|
||||
parameter.reportIncorrectInline(KtTokens.CROSSINLINE_KEYWORD, context.trace)
|
||||
}
|
||||
|
||||
if (inline && !parameter.hasModifier(KtTokens.NOINLINE_KEYWORD) &&
|
||||
parameterDescriptor?.type?.isSuspendFunctionType == true) {
|
||||
context.trace.report(Errors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED.on(parameter))
|
||||
!parameter.hasModifier(KtTokens.CROSSINLINE_KEYWORD) &&
|
||||
parameterDescriptor?.type?.isSuspendFunctionType == true
|
||||
) {
|
||||
if (suspend) {
|
||||
context.trace.report(Errors.REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE.on(parameter))
|
||||
} else {
|
||||
context.trace.report(Errors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED.on(parameter))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ public class InlineUtil {
|
||||
public static boolean isInlineParameterExceptNullability(@NotNull ParameterDescriptor valueParameterOrReceiver) {
|
||||
return !(valueParameterOrReceiver instanceof ValueParameterDescriptor
|
||||
&& ((ValueParameterDescriptor) valueParameterOrReceiver).isNoinline()) &&
|
||||
FunctionTypesKt.isFunctionType(valueParameterOrReceiver.getOriginal().getType());
|
||||
(FunctionTypesKt.isFunctionType(valueParameterOrReceiver.getOriginal().getType()) ||
|
||||
FunctionTypesKt.isSuspendFunctionType(valueParameterOrReceiver.getOriginal().getType()));
|
||||
}
|
||||
|
||||
public static boolean isInlineParameter(@NotNull ParameterDescriptor valueParameterOrReceiver) {
|
||||
@@ -55,7 +56,7 @@ public class InlineUtil {
|
||||
}
|
||||
|
||||
public static boolean isPropertyWithAllAccessorsAreInline(@NotNull DeclarationDescriptor descriptor) {
|
||||
if (!(descriptor instanceof PropertyDescriptor)) return false;
|
||||
if (!(descriptor instanceof PropertyDescriptor)) return false;
|
||||
|
||||
PropertyGetterDescriptor getter = ((PropertyDescriptor) descriptor).getGetter();
|
||||
if (getter == null || !getter.isInline()) return false;
|
||||
|
||||
+8
-1
@@ -35,7 +35,11 @@ fun builderConsumer(c: suspend () -> Consumer): Consumer {
|
||||
}
|
||||
|
||||
class Container {
|
||||
var y: String = "FAIL 1"
|
||||
var y: String = "FAIL 0"
|
||||
|
||||
val consumer0 = crossInlineBuilderConsumer { s ->
|
||||
y = s
|
||||
}
|
||||
|
||||
val consumer1 = crossInlineBuilderConsumer { s ->
|
||||
builder {
|
||||
@@ -108,6 +112,9 @@ class Container {
|
||||
|
||||
fun box(): String {
|
||||
val c = Container()
|
||||
c.consumer0.consume("OK")
|
||||
if (c.y != "OK") return c.y
|
||||
c.y = "FAIL 1"
|
||||
c.consumer1.consume("OK")
|
||||
if (c.y != "OK") return c.y
|
||||
c.y = "FAIL 2"
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
suspend inline fun test1(c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
val a = 1
|
||||
test2 {
|
||||
val b = 2
|
||||
test1 {
|
||||
val c = a + b // 3
|
||||
run {
|
||||
val a = c + 1 // 4
|
||||
test1 {
|
||||
val b = c + c // 6
|
||||
test2 {
|
||||
val c = b - a // 2
|
||||
res = "${calculate()} $a$b$c"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK 462") return res
|
||||
return "OK"
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
inline suspend fun foo(crossinline a: suspend () -> Unit, crossinline b: suspend () -> Unit) {
|
||||
var x = "OK"
|
||||
bar { x; a(); b() }
|
||||
}
|
||||
|
||||
inline suspend fun bar(crossinline l: suspend () -> Unit) {
|
||||
val c : suspend () -> Unit = { l() }
|
||||
c()
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
fun box(): String {
|
||||
var y = "fail"
|
||||
builder {
|
||||
foo({ y = "O" }) { y += "K" }
|
||||
}
|
||||
return y
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
}
|
||||
|
||||
val defaultController = Controller()
|
||||
|
||||
suspend inline fun test1(controller: Controller = defaultController, crossinline c: suspend Controller.() -> Unit) {
|
||||
controller.c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(controller: Controller = defaultController, crossinline c: suspend Controller.() -> Unit) {
|
||||
val l : suspend () -> Unit = {
|
||||
controller.c()
|
||||
}
|
||||
l()
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun test3(controller: Controller = defaultController, crossinline c: suspend Controller.() -> Unit) {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
controller.c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
builder {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (defaultController.res != "OK") return defaultController.res
|
||||
defaultController.res = "FAIL 2"
|
||||
builder {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (defaultController.res != "OK") return defaultController.res
|
||||
defaultController.res = "FAIL 3"
|
||||
builder {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (defaultController.res != "OK") return defaultController.res
|
||||
val controller = Controller()
|
||||
controller.res = "FAIL 4"
|
||||
builder {
|
||||
test1(controller) {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 5"
|
||||
builder {
|
||||
test2(controller) {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 6"
|
||||
builder {
|
||||
test3(controller) {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
}
|
||||
|
||||
val defaultController = Controller()
|
||||
|
||||
suspend inline fun test(controller: Controller = defaultController, c: suspend Controller.() -> Unit) {
|
||||
controller.c()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
builder {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (defaultController.res != "OK") return defaultController.res
|
||||
val controller = Controller()
|
||||
controller.res = "FAIL 2"
|
||||
builder {
|
||||
test(controller) {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
inline fun test1(crossinline runner: suspend () -> Unit) {
|
||||
val l : suspend () -> Unit = { runner() }
|
||||
builder { l() }
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
inline fun test2(crossinline c: suspend () -> Unit) {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
builder { sr.run() }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL 1"
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 2"
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 3"
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 4"
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 5"
|
||||
test1 {
|
||||
test2 {
|
||||
test1 {
|
||||
test2 {
|
||||
test1 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Start coroutine call is possible
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
inline fun test1(noinline c: suspend () -> Unit) {
|
||||
val l : suspend () -> Unit = { c() }
|
||||
builder { l() }
|
||||
}
|
||||
|
||||
val EmptyContinuation = object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
inline fun test2(noinline c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
inline fun test3(noinline c: suspend () -> Unit) {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
builder { sr.run() }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL 1"
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 2"
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 3"
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 4"
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 5"
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 6"
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 7"
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun test1(c: () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test3(crossinline c: suspend() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test4(crossinline c: suspend() -> Unit) {
|
||||
val l : suspend () -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun test5(crossinline c: suspend() -> Unit) {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
import kotlin.coroutines.experimental.jvm.internal.*
|
||||
|
||||
object EmptyContinuation: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
var continuationChanged = true
|
||||
var savedContinuation: Continuation<Unit>? = null
|
||||
|
||||
suspend inline fun saveContinuation() = suspendCoroutineUninterceptedOrReturn<Unit> { c ->
|
||||
savedContinuation = c
|
||||
Unit
|
||||
}
|
||||
|
||||
suspend inline fun checkContinuation(continuation: Continuation<Unit>) = suspendCoroutineUninterceptedOrReturn<Unit> { c ->
|
||||
continuationChanged = (continuation !== c)
|
||||
Unit
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
builder {
|
||||
saveContinuation()
|
||||
test1 {
|
||||
checkContinuation(savedContinuation!!)
|
||||
}
|
||||
}
|
||||
if (continuationChanged) return "FAIL 1"
|
||||
continuationChanged = true
|
||||
builder {
|
||||
saveContinuation()
|
||||
test2 {
|
||||
checkContinuation(savedContinuation!!)
|
||||
}
|
||||
}
|
||||
if (continuationChanged) return "FAIL 2"
|
||||
continuationChanged = true
|
||||
builder {
|
||||
saveContinuation()
|
||||
test3 {
|
||||
checkContinuation(savedContinuation!!)
|
||||
}
|
||||
}
|
||||
if (continuationChanged) return "FAIL 3"
|
||||
continuationChanged = false
|
||||
builder {
|
||||
saveContinuation()
|
||||
test4 {
|
||||
checkContinuation(savedContinuation!!)
|
||||
}
|
||||
}
|
||||
if (!continuationChanged) return "FAIL 4"
|
||||
continuationChanged = false
|
||||
builder {
|
||||
saveContinuation()
|
||||
test5 {
|
||||
checkContinuation(savedContinuation!!)
|
||||
}
|
||||
}
|
||||
if (!continuationChanged) return "FAIL 5"
|
||||
return "OK"
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
|
||||
suspend inline fun test1(crossinline c: () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(crossinline c: () -> Unit) {
|
||||
val l = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test3(crossinline c: () -> Unit) {
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend () -> Unit) {
|
||||
builder { c() }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 3"
|
||||
builder {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 4"
|
||||
builder {
|
||||
test1 {
|
||||
transform {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 5"
|
||||
builder {
|
||||
test2 {
|
||||
transform {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 6"
|
||||
builder {
|
||||
test3 {
|
||||
transform {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
suspend inline fun test1(crossinline c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun test3(crossinline c: suspend () -> Unit) {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 3"
|
||||
builder {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 4"
|
||||
builder {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 5"
|
||||
builder {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 6"
|
||||
builder {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 7"
|
||||
builder {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test1 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
|
||||
suspend inline fun test1(noinline c: () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(noinline c: () -> Unit) {
|
||||
val l = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test3(noinline c: () -> Unit) {
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend () -> Unit) {
|
||||
builder { c() }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 3"
|
||||
builder {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 4"
|
||||
builder {
|
||||
test1 {
|
||||
transform {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 5"
|
||||
builder {
|
||||
test2 {
|
||||
transform {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
|
||||
res = "FAIL 6"
|
||||
builder {
|
||||
test3 {
|
||||
transform {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
// Start coroutine call is possible
|
||||
// Block is allowed to be called directly inside inline function
|
||||
|
||||
suspend inline fun test1(noinline c: suspend () -> Unit) {
|
||||
val l : suspend () -> Unit = { c() }
|
||||
builder { l() }
|
||||
}
|
||||
|
||||
object EmptyContinuation: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
suspend inline fun test2(noinline c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend inline fun test3(noinline c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun test4(noinline c: suspend () -> Unit) {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 3"
|
||||
builder {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 4"
|
||||
builder {
|
||||
test4 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 5"
|
||||
builder {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 6"
|
||||
builder {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 7"
|
||||
builder {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 8"
|
||||
builder {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 9"
|
||||
builder {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test4 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
suspend inline fun test(c: () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend () -> Unit) {
|
||||
builder { c() }
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
builder {
|
||||
test {
|
||||
transform {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
suspend inline fun test(c: suspend () -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
var res = "FAIL 1"
|
||||
builder {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (res != "OK") return res
|
||||
res = "FAIL 2"
|
||||
builder {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
object Result {
|
||||
var a: String = ""
|
||||
var b: Int = 0
|
||||
}
|
||||
|
||||
suspend inline fun inlineMe(c: suspend () -> Unit) {
|
||||
var a = ""
|
||||
var b = 0
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
b++
|
||||
a += "a"
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
c()
|
||||
r.run()
|
||||
Result.a = a
|
||||
Result.b = b
|
||||
}
|
||||
suspend inline fun noinlineMe(noinline c: suspend () -> Unit) {
|
||||
var a = ""
|
||||
var b = 0
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
b += 2
|
||||
a += "b"
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
c()
|
||||
r.run()
|
||||
Result.a += a
|
||||
Result.b += b
|
||||
}
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
var a = ""
|
||||
var b = 0
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
b += 3
|
||||
a += "c"
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
c()
|
||||
r.run()
|
||||
Result.a += a
|
||||
Result.b += b
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun dummy() {
|
||||
val local0 = 0
|
||||
val local1 = 0
|
||||
val local2 = 0
|
||||
val local3 = 0
|
||||
val local4 = 0
|
||||
val local5 = 0
|
||||
val local6 = 0
|
||||
val local7 = 0
|
||||
val local8 = 0
|
||||
val local9 = 0
|
||||
val local10 = 0
|
||||
val local11 = 0
|
||||
val local12 = 0
|
||||
val local13 = 0
|
||||
val local14 = 0
|
||||
val local15 = 0
|
||||
val local16 = 0
|
||||
val local17 = 0
|
||||
val local18 = 0
|
||||
val local19 = 0
|
||||
val local20 = 0
|
||||
val local21 = 0
|
||||
val local22 = 0
|
||||
}
|
||||
|
||||
suspend fun inlineSite() {
|
||||
inlineMe {
|
||||
dummy()
|
||||
dummy()
|
||||
}
|
||||
if (Result.a != "aa" || Result.b != 2) throw RuntimeException("FAIL 1")
|
||||
noinlineMe {
|
||||
dummy()
|
||||
dummy()
|
||||
}
|
||||
if (Result.a != "aabb" || Result.b != 6) throw RuntimeException("FAIL 2")
|
||||
crossinlineMe {
|
||||
dummy()
|
||||
dummy()
|
||||
}
|
||||
if (Result.a != "aabbcc" || Result.b != 12) throw RuntimeException("FAIL 3")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
inlineSite()
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun inlineMe(c: suspend () -> Unit) {
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
}
|
||||
suspend inline fun noinlineMe(noinline c: suspend () -> Unit) {
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
}
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
var k = 0;
|
||||
|
||||
suspend fun calculateI() {
|
||||
i++
|
||||
}
|
||||
|
||||
suspend fun calculateJ() {
|
||||
j++
|
||||
}
|
||||
|
||||
suspend fun calculateK() {
|
||||
k++
|
||||
}
|
||||
|
||||
suspend fun inlineSite() {
|
||||
inlineMe {
|
||||
calculateI()
|
||||
calculateI()
|
||||
}
|
||||
noinlineMe {
|
||||
calculateJ()
|
||||
calculateJ()
|
||||
}
|
||||
crossinlineMe {
|
||||
calculateK()
|
||||
calculateK()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
inlineSite()
|
||||
}
|
||||
if (i != 10) return "FAIL I"
|
||||
if (j != 10) return "FAIL J"
|
||||
if (k != 10) return "FAIL K"
|
||||
return "OK"
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
inline fun test1(crossinline runner: suspend Controller.() -> Unit) {
|
||||
val l : suspend Controller.() -> Unit = { runner() }
|
||||
builder(this) { l() }
|
||||
}
|
||||
|
||||
inline fun test2(crossinline c: suspend Controller.() -> Unit) {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
builder(this) { sr.run() }
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
val controller = Controller()
|
||||
controller.test1 {
|
||||
res = calculate()
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 2"
|
||||
controller.test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 3"
|
||||
controller.test2 {
|
||||
res = calculate()
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 4"
|
||||
controller.test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 5"
|
||||
controller.test1 {
|
||||
test2 {
|
||||
test1 {
|
||||
test2 {
|
||||
test1 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Start coroutine call is possible
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
val EmptyContinuation = object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
inline fun test1(noinline c: suspend Controller.() -> Unit) {
|
||||
val l : suspend Controller.() -> Unit = { c() }
|
||||
builder(this) { l() }
|
||||
}
|
||||
|
||||
inline fun test2(noinline c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(this, EmptyContinuation)
|
||||
}
|
||||
|
||||
inline fun test3(noinline c: suspend Controller.() -> Unit) {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
builder(this) { sr.run() }
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, EmptyContinuation)
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
val controller = Controller()
|
||||
controller.test1 {
|
||||
res = calculate()
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 2"
|
||||
controller.test2 {
|
||||
res = "OK"
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 3"
|
||||
controller.test3 {
|
||||
res = "OK"
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 4"
|
||||
controller.test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 5"
|
||||
controller.test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 6"
|
||||
controller.test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 7"
|
||||
controller.test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test1(crossinline c: Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(crossinline c: Controller.() -> Unit) {
|
||||
val l = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test3(crossinline c: Controller.() -> Unit) {
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend Controller.() -> Unit) {
|
||||
builder(this) { c() }
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller : Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun box() : String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 2"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 3"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 4"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
transform {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 5"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
transform {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 6"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
transform {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test1(crossinline c: suspend Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(crossinline c: suspend Controller.() -> Unit) {
|
||||
val l: suspend Controller.() -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test3(crossinline c: suspend Controller.() -> Unit) {
|
||||
val sr = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 2"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 3"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 4"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 5"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 6"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 7"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test1 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test1(noinline c: Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test2(noinline c: Controller.() -> Unit) {
|
||||
val l = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test3(noinline c: Controller.() -> Unit) {
|
||||
val r = object: Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
r.run()
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend Controller.() -> Unit) {
|
||||
builder(this) { c() }
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun box() : String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 2"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 3"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 4"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
transform {
|
||||
test1 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 5"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
transform {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
|
||||
controller.res = "FAIL 6"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
transform {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// Are suspend calls possible inside lambda matching to the parameter
|
||||
// Start coroutine call is possible
|
||||
// Block is allowed to be called directly inside inline function
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
object EmptyContinuation: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test1(noinline c: suspend Controller.() -> Unit) {
|
||||
val l : suspend Controller.() -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun test2(noinline c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(this, EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend inline fun test3(noinline c: suspend Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
suspend inline fun test4(noinline c: suspend Controller.() -> Unit) {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, EmptyContinuation)
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box(): String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 2"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 3"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 4"
|
||||
builder(controller) {
|
||||
test4 {
|
||||
res = "OK"
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 5"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 6"
|
||||
builder(controller) {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
test2 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 7"
|
||||
builder(controller) {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
test3 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 8"
|
||||
builder(controller) {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
test4 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 9"
|
||||
builder(controller) {
|
||||
test1 {
|
||||
test2 {
|
||||
test3 {
|
||||
test4 {
|
||||
test1 {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test(c: Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
|
||||
inline fun transform(crossinline c: suspend Controller.() -> Unit) {
|
||||
builder(this) { c() }
|
||||
}
|
||||
}
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
builder(controller) {
|
||||
test {
|
||||
transform {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// FILE: test.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
class Controller {
|
||||
var res = "FAIL 1"
|
||||
|
||||
suspend inline fun test(c: suspend Controller.() -> Unit) {
|
||||
c()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(controller: Controller, c: suspend Controller.() -> Unit) {
|
||||
c.startCoroutine(controller, object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() : String {
|
||||
val controller = Controller()
|
||||
builder(controller) {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
if (controller.res != "OK") return controller.res
|
||||
controller.res = "FAIL 2"
|
||||
builder(controller) {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
test {
|
||||
res = calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return controller.res
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL"
|
||||
return "OK"
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = {
|
||||
val l1 : suspend () -> Unit = {
|
||||
c()
|
||||
}
|
||||
l1()
|
||||
}
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL $i"
|
||||
return "OK"
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = "OK"
|
||||
builder {
|
||||
crossinlineMe {
|
||||
res = "FAIL 1"
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL 2"
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
val l : suspend () -> Unit = {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
val l : suspend () -> Unit = {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
l()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
l()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL $i"
|
||||
return "OK"
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = {
|
||||
c()
|
||||
}
|
||||
l()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
val l : suspend () -> Unit = {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
val l : suspend () -> Unit = {
|
||||
val sr = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
l()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
l()
|
||||
}
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL $i"
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
o.run()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL $i"
|
||||
return "OK"
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
val o1 = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
o1.run()
|
||||
}
|
||||
}
|
||||
o.run()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL $i"
|
||||
return "OK"
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run1()
|
||||
suspend fun run2()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) {
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run1() {
|
||||
c1()
|
||||
}
|
||||
override suspend fun run2() {
|
||||
c2()
|
||||
}
|
||||
}
|
||||
o.run1()
|
||||
o.run2()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
|
||||
suspend fun incrementI() {
|
||||
i++
|
||||
}
|
||||
|
||||
suspend fun incrementJ() {
|
||||
j++
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe({ incrementI() }) { incrementJ() }
|
||||
}
|
||||
if (i != 1) return "FAIL i $i"
|
||||
if (j != 1) return "FAIL i $i"
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+58
@@ -0,0 +1,58 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
o.run()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var res = "OK"
|
||||
builder {
|
||||
crossinlineMe {
|
||||
res = "FAIL 1"
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL 2"
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutineOrReturn<Unit> {
|
||||
i++
|
||||
COROUTINE_SUSPENDED
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
if (i != 1) return "FAIL"
|
||||
return "OK"
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
|
||||
val l: suspend () -> Unit = { c() }
|
||||
l()
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe2(crossinline c: suspend () -> Unit) {
|
||||
crossinlineMe { c(); c() }
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
var result = "FAIL"
|
||||
var i = 0
|
||||
var finished = false
|
||||
|
||||
var proceed: () -> Unit = {}
|
||||
|
||||
suspend fun suspendHere() = suspendCoroutine<Unit> { c ->
|
||||
i++
|
||||
proceed = { c.resume(Unit) }
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
val continuation = object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
proceed = {
|
||||
result = "OK"
|
||||
finished = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
c.startCoroutine(continuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
crossinlineMe2 {
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
suspendHere()
|
||||
}
|
||||
}
|
||||
for (counter in 0 until 10) {
|
||||
if (i != counter + 1) return "Expected ${counter + 1}, got $i"
|
||||
proceed()
|
||||
}
|
||||
if (i != 10) return "FAIL $i"
|
||||
if (finished) return "resume on root continuation is called"
|
||||
proceed()
|
||||
if (!finished) return "resume on root continuation is not called"
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
// FILE: inlined.kt
|
||||
// WITH_RUNTIME
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
|
||||
suspend inline fun inlineMe(c: suspend (String) -> String, d: suspend () -> String): String {
|
||||
return c(try { d() } catch (e: Exception) { "Exception 1 ${e.message}" })
|
||||
}
|
||||
|
||||
suspend inline fun noinlineMe(noinline c: suspend (String) -> String, noinline d: suspend () -> String): String {
|
||||
return c(try { d() } catch (e: Exception) { "Exception 1 ${e.message}" })
|
||||
}
|
||||
|
||||
suspend inline fun crossinlineMe(crossinline c: suspend (String) -> String, crossinline d: suspend () -> String): String {
|
||||
return c(try { d() } catch (e: Exception) { "Exception 1 ${e.message}" })
|
||||
}
|
||||
|
||||
// FILE: inlineSite.kt
|
||||
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(object: Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = EmptyCoroutineContext
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
throw exception
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
suspend fun yieldString(s: String) = s
|
||||
|
||||
suspend fun throwException(s: String): String {
|
||||
throw RuntimeException(s)
|
||||
}
|
||||
|
||||
suspend fun inlineSite() {
|
||||
var res = inlineMe({ it }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 1: $res")
|
||||
|
||||
res = inlineMe({ it }) { throwException("OK") }
|
||||
if (res != "Exception 1 OK") throw RuntimeException("FAIL 2: $res")
|
||||
|
||||
res = noinlineMe({ it }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 3: $res")
|
||||
|
||||
res = noinlineMe({ it }) { throwException("OK") }
|
||||
if (res != "Exception 1 OK") throw RuntimeException("FAIL 4: $res")
|
||||
|
||||
res = crossinlineMe({ it }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 5: $res")
|
||||
|
||||
res = crossinlineMe({ it }) { throwException("OK") }
|
||||
if (res != "Exception 1 OK") throw RuntimeException("FAIL 6: $res")
|
||||
|
||||
res = inlineMe({ try {yieldString(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 7: $res")
|
||||
|
||||
res = inlineMe({ try {throwException(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "Exception 2 OK") throw RuntimeException("FAIL 8: $res")
|
||||
|
||||
res = noinlineMe({ try {yieldString(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 9: $res")
|
||||
|
||||
res = noinlineMe({ try {throwException(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "Exception 2 OK") throw RuntimeException("FAIL 10: $res")
|
||||
|
||||
res = crossinlineMe({ try {yieldString(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "OK") throw RuntimeException("FAIL 11: $res")
|
||||
|
||||
res = crossinlineMe({ try {throwException(it) } catch (e: Exception) { yieldString("Exception 2 $it") } }) { yieldString("OK") }
|
||||
if (res != "Exception 2 OK") throw RuntimeException("FAIL 12: $res")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
inlineSite()
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
// SKIP_TXT
|
||||
inline fun foo(crossinline <!WRONG_MODIFIER_TARGET!>suspend<!> <!UNUSED_PARAMETER!>c<!>: () -> Unit) {}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
// Function is NOT suspend
|
||||
// parameter is crossinline
|
||||
// parameter is NOT suspend
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls NOT possible inside lambda matching to the parameter
|
||||
|
||||
inline fun test(crossinline c: () -> Unit) {
|
||||
c()
|
||||
val o = object: Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
val l = { c() }
|
||||
c.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>startCoroutine<!>(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
test {
|
||||
<!ILLEGAL_SUSPEND_FUNCTION_CALL!>calculate<!>()
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -NOTHING_TO_INLINE
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
// Function is NOT suspend
|
||||
// parameter is crossinline
|
||||
// parameter is suspend
|
||||
// Block is NOT allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
inline fun test(crossinline c: suspend () -> Unit) {
|
||||
<!ILLEGAL_SUSPEND_FUNCTION_CALL!>c<!>()
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
val l: suspend () -> Unit = { c() }
|
||||
<!USAGE_IS_NOT_INLINABLE!>c<!>.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
test {
|
||||
calculate()
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -NOTHING_TO_INLINE
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
// Function is NOT suspend
|
||||
// parameter is noinline
|
||||
// parameter is NOT suspend
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls NOT possible inside lambda matching to the parameter
|
||||
inline fun test(noinline c: () -> Unit) {
|
||||
c()
|
||||
val o = object: Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
val l = { c() }
|
||||
c.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>startCoroutine<!>(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
test {
|
||||
<!ILLEGAL_SUSPEND_FUNCTION_CALL!>calculate<!>()
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -NOTHING_TO_INLINE
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
// Function is NOT suspend
|
||||
// parameter is noinline
|
||||
// parameter is suspend
|
||||
// Block is NOT allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is possible to call startCoroutine on the parameter
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
inline fun test(noinline c: suspend () -> Unit) {
|
||||
<!ILLEGAL_SUSPEND_FUNCTION_CALL!>c<!>()
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
val l: suspend () -> Unit = { c() }
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
test {
|
||||
calculate()
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
// Function is NOT suspend
|
||||
// parameter is inline
|
||||
// parameter is NOT suspend
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is NOT allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
inline fun test(c: () -> Unit) {
|
||||
c()
|
||||
val o = object : Runnable {
|
||||
override fun run() {
|
||||
<!NON_LOCAL_RETURN_NOT_ALLOWED!>c<!>()
|
||||
}
|
||||
}
|
||||
val l = { <!NON_LOCAL_RETURN_NOT_ALLOWED!>c<!>() }
|
||||
c.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>startCoroutine<!>(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
builder {
|
||||
test {
|
||||
calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -NOTHING_TO_INLINE -UNUSED_PARAMETER
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
// Function is NOT suspend
|
||||
// parameter is inline
|
||||
// parameter is suspend
|
||||
// Block is NOT allowed to be called inside the body of owner inline function
|
||||
// Block is NOT allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
|
||||
inline fun test(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>c: suspend () -> Unit<!>) {
|
||||
<!ILLEGAL_SUSPEND_FUNCTION_CALL!>c<!>()
|
||||
val o = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
<!NON_LOCAL_RETURN_NOT_ALLOWED!>c<!>()
|
||||
}
|
||||
}
|
||||
val l: suspend () -> Unit = { <!NON_LOCAL_RETURN_NOT_ALLOWED!>c<!>() }
|
||||
<!USAGE_IS_NOT_INLINABLE!>c<!>.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
test {
|
||||
calculate()
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
// Function is suspend
|
||||
// parameter is crossinline
|
||||
// parameter is NOT suspend
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls NOT possible inside lambda matching to the parameter
|
||||
suspend inline fun test(crossinline c: () -> Unit) {
|
||||
c()
|
||||
val o = object : Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
val l = { c() }
|
||||
c.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>startCoroutine<!>(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
builder {
|
||||
test {
|
||||
<!NON_LOCAL_SUSPENSION_POINT!>calculate<!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -NOTHING_TO_INLINE
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
// Function is suspend
|
||||
// parameter is crossinline
|
||||
// parameter is suspend
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
suspend inline fun test(crossinline c: suspend () -> Unit) {
|
||||
c()
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
val l: suspend () -> Unit = { c() }
|
||||
<!USAGE_IS_NOT_INLINABLE!>c<!>.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
builder {
|
||||
test {
|
||||
calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -NOTHING_TO_INLINE
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
// Function is suspend
|
||||
// parameter is noinline
|
||||
// parameter is NOT suspend
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls NOT possible inside lambda matching to the parameter
|
||||
suspend inline fun test(noinline c: () -> Unit) {
|
||||
c()
|
||||
val o = object : Runnable {
|
||||
override fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
val l = { c() }
|
||||
c.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>startCoroutine<!>(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
builder {
|
||||
test {
|
||||
<!NON_LOCAL_SUSPENSION_POINT!>calculate<!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -NOTHING_TO_INLINE -UNUSED_PARAMETER
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
// Function is suspend
|
||||
// parameter is noinline
|
||||
// parameter is suspend
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is possible to call startCoroutine on the parameter
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
suspend inline fun test(noinline c: suspend () -> Unit) {
|
||||
c()
|
||||
val o = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c()
|
||||
}
|
||||
}
|
||||
val l: suspend () -> Unit = { c() }
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
builder {
|
||||
test {
|
||||
calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
// Function is suspend
|
||||
// parameter is inline
|
||||
// parameter is NOT suspend
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is NOT allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
suspend inline fun test(c: () -> Unit) {
|
||||
c()
|
||||
val o = object: Runnable {
|
||||
override fun run() {
|
||||
<!NON_LOCAL_RETURN_NOT_ALLOWED!>c<!>()
|
||||
}
|
||||
}
|
||||
val l = { <!NON_LOCAL_RETURN_NOT_ALLOWED!>c<!>() }
|
||||
c.<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>startCoroutine<!>(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun builder(c: suspend () -> Unit) {}
|
||||
|
||||
fun box() {
|
||||
builder {
|
||||
test {
|
||||
calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfSuspend.kt
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -NOTHING_TO_INLINE
|
||||
// SKIP_TXT
|
||||
import kotlin.coroutines.experimental.*
|
||||
import kotlin.coroutines.experimental.intrinsics.*
|
||||
|
||||
open class EmptyContinuation(override val context: CoroutineContext = EmptyCoroutineContext) : Continuation<Any?> {
|
||||
companion object : EmptyContinuation()
|
||||
override fun resume(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>data<!>: Any?) {}
|
||||
override fun resumeWithException(exception: Throwable) { throw exception }
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
// Function is suspend
|
||||
// parameter is inline
|
||||
// parameter is suspend
|
||||
// Block is allowed to be called inside the body of owner inline function
|
||||
// Block is NOT allowed to be called from nested classes/lambdas (as common crossinlines)
|
||||
// It is NOT possible to call startCoroutine on the parameter
|
||||
// suspend calls possible inside lambda matching to the parameter
|
||||
suspend inline fun test(<!REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE!>c: suspend () -> Unit<!>) {
|
||||
c()
|
||||
val o = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
<!NON_LOCAL_RETURN_NOT_ALLOWED!>c<!>()
|
||||
}
|
||||
}
|
||||
val l: suspend () -> Unit = { <!NON_LOCAL_RETURN_NOT_ALLOWED!>c<!>() }
|
||||
<!USAGE_IS_NOT_INLINABLE!>c<!>.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
}
|
||||
|
||||
suspend fun calculate() = "OK"
|
||||
|
||||
fun box() {
|
||||
builder {
|
||||
test {
|
||||
calculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -1,18 +1,18 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// SKIP_TXT
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo1(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>x: suspend () -> Unit<!>) {}
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo2(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>crossinline x: suspend () -> Unit<!>) {}
|
||||
inline fun foo1(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>x: suspend () -> Unit<!>) {}
|
||||
inline fun foo2(crossinline x: suspend () -> Unit) {}
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo3(noinline x: suspend () -> Unit) {}
|
||||
<!NOTHING_TO_INLINE!>inline<!> fun foo4(<!INCOMPATIBLE_MODIFIERS!>noinline<!> <!INCOMPATIBLE_MODIFIERS!>crossinline<!> x: suspend () -> Unit) {}
|
||||
|
||||
suspend inline fun bar1(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>x: suspend () -> Unit<!>) {}
|
||||
suspend inline fun bar2(<!INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED!>crossinline x: suspend () -> Unit<!>) {}
|
||||
suspend inline fun bar1(<!REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE!>x: suspend () -> Unit<!>) {}
|
||||
suspend inline fun bar2(crossinline x: suspend () -> Unit) {}
|
||||
suspend inline fun bar3(noinline x: suspend () -> Unit) {}
|
||||
suspend inline fun bar4(<!INCOMPATIBLE_MODIFIERS!>noinline<!> <!INCOMPATIBLE_MODIFIERS!>crossinline<!> x: suspend () -> Unit) {}
|
||||
|
||||
suspend fun baz() {
|
||||
foo1 {
|
||||
<!RETURN_NOT_ALLOWED!>return@baz<!>
|
||||
return@baz
|
||||
}
|
||||
|
||||
foo2 {
|
||||
@@ -28,7 +28,7 @@ suspend fun baz() {
|
||||
}
|
||||
|
||||
bar1 {
|
||||
<!RETURN_NOT_ALLOWED!>return@baz<!>
|
||||
return@baz
|
||||
}
|
||||
|
||||
bar2 {
|
||||
|
||||
+246
@@ -3391,6 +3391,252 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Suspend extends AbstractIrBlackBoxInlineCodegenTest {
|
||||
public void testAllFilesPresentInSuspend() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("capturedVariables.kt")
|
||||
public void testCapturedVariables() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/capturedVariables.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt")
|
||||
public void testCrossinlineSuspendLambdaInsideCrossinlineSuspendLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineOrdinaryOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineOrdinaryOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendContinuation.kt")
|
||||
public void testInlineSuspendContinuation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendContinuation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
|
||||
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
|
||||
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfOrdinary.kt")
|
||||
public void testInlineSuspendOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfSuspend.kt")
|
||||
public void testInlineSuspendOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleLocals.kt")
|
||||
public void testMultipleLocals() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/multipleLocals.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleSuspensionPoints.kt")
|
||||
public void testMultipleSuspensionPoints() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("tryCatchStackTransform.kt")
|
||||
public void testTryCatchStackTransform() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class DefaultParameter extends AbstractIrBlackBoxInlineCodegenTest {
|
||||
public void testAllFilesPresentInDefaultParameter() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/defaultParameter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultValueCrossinline.kt")
|
||||
public void testDefaultValueCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter/defaultValueCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultValueInline.kt")
|
||||
public void testDefaultValueInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter/defaultValueInline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/receiver")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Receiver extends AbstractIrBlackBoxInlineCodegenTest {
|
||||
public void testAllFilesPresentInReceiver() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/receiver"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineOrdinaryOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineOrdinaryOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
|
||||
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
|
||||
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfOrdinary.kt")
|
||||
public void testInlineSuspendOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfSuspend.kt")
|
||||
public void testInlineSuspendOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class StateMachine extends AbstractIrBlackBoxInlineCodegenTest {
|
||||
public void testAllFilesPresentInStateMachine() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambda.kt")
|
||||
public void testInnerLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambdaInsideLambda.kt")
|
||||
public void testInnerLambdaInsideLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambdaWithoutCrossinline.kt")
|
||||
public void testInnerLambdaWithoutCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaWithoutCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerMadness.kt")
|
||||
public void testInnerMadness() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerMadness.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerMadnessCallSite.kt")
|
||||
public void testInnerMadnessCallSite() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerMadnessCallSite.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObject.kt")
|
||||
public void testInnerObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectInsideInnerObject.kt")
|
||||
public void testInnerObjectInsideInnerObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectInsideInnerObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectSeveralFunctions.kt")
|
||||
public void testInnerObjectSeveralFunctions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectSeveralFunctions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectWithoutCapturingCrossinline.kt")
|
||||
public void testInnerObjectWithoutCapturingCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectWithoutCapturingCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("normalInline.kt")
|
||||
public void testNormalInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/normalInline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("numberOfSuspentions.kt")
|
||||
public void testNumberOfSuspentions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/numberOfSuspentions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/syntheticAccessors")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+246
@@ -3391,6 +3391,252 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Suspend extends AbstractIrCompileKotlinAgainstInlineKotlinTest {
|
||||
public void testAllFilesPresentInSuspend() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("capturedVariables.kt")
|
||||
public void testCapturedVariables() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/capturedVariables.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt")
|
||||
public void testCrossinlineSuspendLambdaInsideCrossinlineSuspendLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineOrdinaryOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineOrdinaryOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendContinuation.kt")
|
||||
public void testInlineSuspendContinuation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendContinuation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
|
||||
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
|
||||
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfOrdinary.kt")
|
||||
public void testInlineSuspendOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfSuspend.kt")
|
||||
public void testInlineSuspendOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleLocals.kt")
|
||||
public void testMultipleLocals() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/multipleLocals.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleSuspensionPoints.kt")
|
||||
public void testMultipleSuspensionPoints() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("tryCatchStackTransform.kt")
|
||||
public void testTryCatchStackTransform() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class DefaultParameter extends AbstractIrCompileKotlinAgainstInlineKotlinTest {
|
||||
public void testAllFilesPresentInDefaultParameter() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/defaultParameter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultValueCrossinline.kt")
|
||||
public void testDefaultValueCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter/defaultValueCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultValueInline.kt")
|
||||
public void testDefaultValueInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter/defaultValueInline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/receiver")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Receiver extends AbstractIrCompileKotlinAgainstInlineKotlinTest {
|
||||
public void testAllFilesPresentInReceiver() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/receiver"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineOrdinaryOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineOrdinaryOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
|
||||
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
|
||||
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfOrdinary.kt")
|
||||
public void testInlineSuspendOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfSuspend.kt")
|
||||
public void testInlineSuspendOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class StateMachine extends AbstractIrCompileKotlinAgainstInlineKotlinTest {
|
||||
public void testAllFilesPresentInStateMachine() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambda.kt")
|
||||
public void testInnerLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambdaInsideLambda.kt")
|
||||
public void testInnerLambdaInsideLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambdaWithoutCrossinline.kt")
|
||||
public void testInnerLambdaWithoutCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaWithoutCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerMadness.kt")
|
||||
public void testInnerMadness() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerMadness.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerMadnessCallSite.kt")
|
||||
public void testInnerMadnessCallSite() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerMadnessCallSite.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObject.kt")
|
||||
public void testInnerObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectInsideInnerObject.kt")
|
||||
public void testInnerObjectInsideInnerObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectInsideInnerObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectSeveralFunctions.kt")
|
||||
public void testInnerObjectSeveralFunctions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectSeveralFunctions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectWithoutCapturingCrossinline.kt")
|
||||
public void testInnerObjectWithoutCapturingCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectWithoutCapturingCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("normalInline.kt")
|
||||
public void testNormalInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/normalInline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("numberOfSuspentions.kt")
|
||||
public void testNumberOfSuspentions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/numberOfSuspentions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/syntheticAccessors")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+87
@@ -1551,6 +1551,93 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InlineCrossinline extends AbstractDiagnosticsTestWithStdLib {
|
||||
public void testAllFilesPresentInInlineCrossinline() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinlineSuspendValueParameter.kt")
|
||||
public void testCrossinlineSuspendValueParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/crossinlineSuspendValueParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineOrdinary.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineOrdinary.kt")
|
||||
public void testInlineOrdinaryOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfOrdinary.kt")
|
||||
public void testInlineOrdinaryOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfSuspend.kt")
|
||||
public void testInlineOrdinaryOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
|
||||
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
|
||||
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfOrdinary.kt")
|
||||
public void testInlineSuspendOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfSuspend.kt")
|
||||
public void testInlineSuspendOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
Generated
+87
@@ -1551,6 +1551,93 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InlineCrossinline extends AbstractDiagnosticsTestWithStdLibUsingJavac {
|
||||
public void testAllFilesPresentInInlineCrossinline() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinlineSuspendValueParameter.kt")
|
||||
public void testCrossinlineSuspendValueParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/crossinlineSuspendValueParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineOrdinary.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineOrdinary.kt")
|
||||
public void testInlineOrdinaryOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfOrdinary.kt")
|
||||
public void testInlineOrdinaryOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfSuspend.kt")
|
||||
public void testInlineOrdinaryOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineOrdinaryOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
|
||||
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
|
||||
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfOrdinary.kt")
|
||||
public void testInlineSuspendOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfSuspend.kt")
|
||||
public void testInlineSuspendOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/inlineCrossinline/inlineSuspendOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/coroutines/restrictSuspension")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+246
@@ -3391,6 +3391,252 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Suspend extends AbstractBlackBoxInlineCodegenTest {
|
||||
public void testAllFilesPresentInSuspend() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("capturedVariables.kt")
|
||||
public void testCapturedVariables() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/capturedVariables.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt")
|
||||
public void testCrossinlineSuspendLambdaInsideCrossinlineSuspendLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineOrdinaryOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineOrdinaryOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendContinuation.kt")
|
||||
public void testInlineSuspendContinuation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendContinuation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
|
||||
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
|
||||
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfOrdinary.kt")
|
||||
public void testInlineSuspendOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfSuspend.kt")
|
||||
public void testInlineSuspendOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleLocals.kt")
|
||||
public void testMultipleLocals() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/multipleLocals.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleSuspensionPoints.kt")
|
||||
public void testMultipleSuspensionPoints() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("tryCatchStackTransform.kt")
|
||||
public void testTryCatchStackTransform() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class DefaultParameter extends AbstractBlackBoxInlineCodegenTest {
|
||||
public void testAllFilesPresentInDefaultParameter() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/defaultParameter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultValueCrossinline.kt")
|
||||
public void testDefaultValueCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter/defaultValueCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultValueInline.kt")
|
||||
public void testDefaultValueInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter/defaultValueInline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/receiver")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Receiver extends AbstractBlackBoxInlineCodegenTest {
|
||||
public void testAllFilesPresentInReceiver() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/receiver"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineOrdinaryOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineOrdinaryOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
|
||||
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
|
||||
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfOrdinary.kt")
|
||||
public void testInlineSuspendOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfSuspend.kt")
|
||||
public void testInlineSuspendOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class StateMachine extends AbstractBlackBoxInlineCodegenTest {
|
||||
public void testAllFilesPresentInStateMachine() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambda.kt")
|
||||
public void testInnerLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambdaInsideLambda.kt")
|
||||
public void testInnerLambdaInsideLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambdaWithoutCrossinline.kt")
|
||||
public void testInnerLambdaWithoutCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaWithoutCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerMadness.kt")
|
||||
public void testInnerMadness() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerMadness.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerMadnessCallSite.kt")
|
||||
public void testInnerMadnessCallSite() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerMadnessCallSite.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObject.kt")
|
||||
public void testInnerObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectInsideInnerObject.kt")
|
||||
public void testInnerObjectInsideInnerObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectInsideInnerObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectSeveralFunctions.kt")
|
||||
public void testInnerObjectSeveralFunctions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectSeveralFunctions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectWithoutCapturingCrossinline.kt")
|
||||
public void testInnerObjectWithoutCapturingCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectWithoutCapturingCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("normalInline.kt")
|
||||
public void testNormalInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/normalInline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("numberOfSuspentions.kt")
|
||||
public void testNumberOfSuspentions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/numberOfSuspentions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/syntheticAccessors")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Generated
+246
@@ -3391,6 +3391,252 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Suspend extends AbstractCompileKotlinAgainstInlineKotlinTest {
|
||||
public void testAllFilesPresentInSuspend() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("capturedVariables.kt")
|
||||
public void testCapturedVariables() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/capturedVariables.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt")
|
||||
public void testCrossinlineSuspendLambdaInsideCrossinlineSuspendLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineOrdinaryOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineOrdinaryOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendContinuation.kt")
|
||||
public void testInlineSuspendContinuation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendContinuation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
|
||||
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
|
||||
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfOrdinary.kt")
|
||||
public void testInlineSuspendOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfSuspend.kt")
|
||||
public void testInlineSuspendOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/inlineSuspendOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleLocals.kt")
|
||||
public void testMultipleLocals() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/multipleLocals.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleSuspensionPoints.kt")
|
||||
public void testMultipleSuspensionPoints() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("tryCatchStackTransform.kt")
|
||||
public void testTryCatchStackTransform() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/tryCatchStackTransform.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class DefaultParameter extends AbstractCompileKotlinAgainstInlineKotlinTest {
|
||||
public void testAllFilesPresentInDefaultParameter() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/defaultParameter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultValueCrossinline.kt")
|
||||
public void testDefaultValueCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter/defaultValueCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultValueInline.kt")
|
||||
public void testDefaultValueInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/defaultParameter/defaultValueInline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/receiver")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Receiver extends AbstractCompileKotlinAgainstInlineKotlinTest {
|
||||
public void testAllFilesPresentInReceiver() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/receiver"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfCrossinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineOrdinaryOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineOrdinaryOfNoinlineSuspend.kt")
|
||||
public void testInlineOrdinaryOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineOrdinaryOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfCrossinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfCrossinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfCrossinlineSuspend.kt")
|
||||
public void testInlineSuspendOfCrossinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfCrossinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineOrdinary.kt")
|
||||
public void testInlineSuspendOfNoinlineOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfNoinlineOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfNoinlineSuspend.kt")
|
||||
public void testInlineSuspendOfNoinlineSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfNoinlineSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfOrdinary.kt")
|
||||
public void testInlineSuspendOfOrdinary() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfOrdinary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inlineSuspendOfSuspend.kt")
|
||||
public void testInlineSuspendOfSuspend() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/receiver/inlineSuspendOfSuspend.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class StateMachine extends AbstractCompileKotlinAgainstInlineKotlinTest {
|
||||
public void testAllFilesPresentInStateMachine() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/suspend/stateMachine"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambda.kt")
|
||||
public void testInnerLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambdaInsideLambda.kt")
|
||||
public void testInnerLambdaInsideLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaInsideLambda.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerLambdaWithoutCrossinline.kt")
|
||||
public void testInnerLambdaWithoutCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaWithoutCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerMadness.kt")
|
||||
public void testInnerMadness() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerMadness.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerMadnessCallSite.kt")
|
||||
public void testInnerMadnessCallSite() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerMadnessCallSite.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObject.kt")
|
||||
public void testInnerObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectInsideInnerObject.kt")
|
||||
public void testInnerObjectInsideInnerObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectInsideInnerObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectSeveralFunctions.kt")
|
||||
public void testInnerObjectSeveralFunctions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectSeveralFunctions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerObjectWithoutCapturingCrossinline.kt")
|
||||
public void testInnerObjectWithoutCapturingCrossinline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/innerObjectWithoutCapturingCrossinline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("normalInline.kt")
|
||||
public void testNormalInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/normalInline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("numberOfSuspentions.kt")
|
||||
public void testNumberOfSuspentions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/suspend/stateMachine/numberOfSuspentions.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/syntheticAccessors")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user