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:
Ilmir Usmanov
2018-01-18 15:21:19 +03:00
parent 042ca55be7
commit 6854135077
80 changed files with 5214 additions and 144 deletions
+1
View File
@@ -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)
@@ -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
)
}
}
@@ -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))
}
}
@@ -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)
})
}
}
}
@@ -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
}
@@ -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);
@@ -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)
}
@@ -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;
@@ -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"
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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"
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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"
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -0,0 +1,2 @@
// SKIP_TXT
inline fun foo(crossinline <!WRONG_MODIFIER_TARGET!>suspend<!> <!UNUSED_PARAMETER!>c<!>: () -> Unit) {}
@@ -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<!>()
}
}
@@ -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()
}
}
@@ -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<!>()
}
}
@@ -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()
}
}
@@ -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()
}
}
}
@@ -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()
}
}
@@ -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<!>()
}
}
}
@@ -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()
}
}
}
@@ -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<!>()
}
}
}
@@ -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()
}
}
}
@@ -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()
}
}
}
@@ -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()
}
}
}
@@ -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 {
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)