Generate state-machine even if the object is going to be transformed
This fixes Java interop of inline functions, which use coroutines. However, we cannot transform the state-machine. Thus, we generate a $$forInline counterpart for suspend functions (similar to inline suspend functions) and invokeSuspend$$forInline for lambdas if these coroutines are going to transformed (i.e. are declared inside inline functions). During transformation we just skip method with state-machine and transform the $$forInline counterpart. Of course, if inline site is inline itself, we generate both state-machine version (which will be dropped during the next transformation) and $$forInline version. Consequently, the final version of the coroutines will not have $$forInline counterpart. Unfortunately, since CompileKotlinAgainstInlineKotlin tests do not allow java sources, the tests for the interop are usual box tests. #KT-30707 Fixed
This commit is contained in:
@@ -125,7 +125,8 @@ public class FunctionCodegen {
|
||||
CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
|
||||
function,
|
||||
v.getThisName(),
|
||||
state.getConstructorCallNormalizationMode()
|
||||
state.getConstructorCallNormalizationMode(),
|
||||
this
|
||||
);
|
||||
} else {
|
||||
strategy = new SuspendInlineFunctionGenerationStrategy(
|
||||
@@ -1642,4 +1643,9 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Map<DeclarationDescriptor, EnclosedValueDescriptor> getCaptureVariables() {
|
||||
return owner.closure == null ? null : owner.closure.getCaptureVariables();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
@@ -462,10 +465,8 @@ class CoroutineCodegenForLambda private constructor(
|
||||
object : FunctionGenerationStrategy.FunctionDefault(state, element as KtDeclarationWithBody) {
|
||||
|
||||
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
|
||||
val addEndLabelMethodVisitor = AddEndLabelMethodVisitor(mv, access, name, desc, endLabel)
|
||||
if (forInline) return super.wrapMethodVisitor(addEndLabelMethodVisitor, access, name, desc)
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
addEndLabelMethodVisitor, access, name, desc, null, null,
|
||||
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { v },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
@@ -474,6 +475,17 @@ class CoroutineCodegenForLambda private constructor(
|
||||
isForNamedFunction = false,
|
||||
languageVersionSettings = languageVersionSettings
|
||||
)
|
||||
return if (forInline) AddEndLabelMethodVisitor(
|
||||
MethodNodeCopyingMethodVisitor(
|
||||
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
stateMachineBuilder, access, name, desc, v.thisName,
|
||||
isCapturedSuspendLambda = { isCapturedSuspendLambda(closure.captureVariables, it.name) }
|
||||
), access, name, desc,
|
||||
newMethod = { origin, newAccess, newName, newDesc ->
|
||||
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||
}
|
||||
), access, name, desc, endLabel
|
||||
) else AddEndLabelMethodVisitor(stateMachineBuilder, access, name, desc, endLabel)
|
||||
}
|
||||
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
@@ -516,13 +528,22 @@ class CoroutineCodegenForLambda private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun isCapturedSuspendLambda(captureVariables: Map<DeclarationDescriptor, EnclosedValueDescriptor>, name: String): Boolean {
|
||||
for ((param, value) in captureVariables) {
|
||||
if (param !is ValueParameterDescriptor) continue
|
||||
if (value.fieldName != name) continue
|
||||
return param.type.isSuspendFunctionTypeOrSubtype
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private class AddEndLabelMethodVisitor(
|
||||
delegate: MethodVisitor,
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
private val endLabel: Label
|
||||
): TransformationMethodVisitor(delegate, access, name, desc, null, null) {
|
||||
) : TransformationMethodVisitor(delegate, access, name, desc, null, null) {
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
methodNode.instructions.add(
|
||||
withInstructionAdapter {
|
||||
|
||||
+2
-1
@@ -48,6 +48,7 @@ private const val COROUTINES_METADATA_VERSION_JVM_NAME = "v"
|
||||
|
||||
const val SUSPEND_FUNCTION_CONTINUATION_PARAMETER = "\$completion"
|
||||
const val SUSPEND_CALL_RESULT_NAME = "\$result"
|
||||
const val ILLEGAL_STATE_ERROR_MESSAGE = "call to 'resume' before 'invoke' with coroutine"
|
||||
|
||||
class CoroutineTransformerMethodVisitor(
|
||||
delegate: MethodVisitor,
|
||||
@@ -176,7 +177,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
insert(last, defaultLabel)
|
||||
|
||||
insert(last, withInstructionAdapter {
|
||||
AsmUtil.genThrow(this, "java/lang/IllegalStateException", "call to 'resume' before 'invoke' with coroutine")
|
||||
AsmUtil.genThrow(this, "java/lang/IllegalStateException", ILLEGAL_STATE_ERROR_MESSAGE)
|
||||
areturn(Type.VOID_TYPE)
|
||||
})
|
||||
}
|
||||
|
||||
+40
-21
@@ -5,12 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
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.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.inline.addFakeContinuationConstructorCallMarker
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
@@ -22,17 +20,19 @@ import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
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
|
||||
|
||||
open class SuspendFunctionGenerationStrategy(
|
||||
state: GenerationState,
|
||||
protected val originalSuspendDescriptor: FunctionDescriptor,
|
||||
protected val declaration: KtFunction,
|
||||
private val containingClassInternalName: String,
|
||||
private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode
|
||||
state: GenerationState,
|
||||
protected val originalSuspendDescriptor: FunctionDescriptor,
|
||||
protected val declaration: KtFunction,
|
||||
private val containingClassInternalName: String,
|
||||
private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode,
|
||||
protected val functionCodegen: FunctionCodegen
|
||||
) : FunctionGenerationStrategy.CodegenBased(state) {
|
||||
|
||||
private lateinit var codegen: ExpressionCodegen
|
||||
@@ -45,7 +45,7 @@ open class SuspendFunctionGenerationStrategy(
|
||||
declaration.containingFile
|
||||
).also {
|
||||
val coroutineCodegen =
|
||||
CoroutineCodegenForNamedFunction.create(it, codegen, originalSuspendDescriptor, declaration)
|
||||
CoroutineCodegenForNamedFunction.create(it, codegen, originalSuspendDescriptor, declaration)
|
||||
coroutineCodegen.generate()
|
||||
}
|
||||
}
|
||||
@@ -53,16 +53,7 @@ open class SuspendFunctionGenerationStrategy(
|
||||
override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor {
|
||||
if (access and Opcodes.ACC_ABSTRACT != 0) return mv
|
||||
|
||||
if (state.bindingContext[CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, originalSuspendDescriptor] == true) {
|
||||
return AddConstructorCallForCoroutineRegeneration(
|
||||
mv, access, name, desc, null, null, this::classBuilderForCoroutineState,
|
||||
containingClassInternalName,
|
||||
originalSuspendDescriptor.dispatchReceiverParameter != null,
|
||||
containingClassInternalNameOrNull(),
|
||||
languageVersionSettings
|
||||
)
|
||||
}
|
||||
return CoroutineTransformerMethodVisitor(
|
||||
val stateMachineBuilder = CoroutineTransformerMethodVisitor(
|
||||
mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState,
|
||||
isForNamedFunction = true,
|
||||
element = declaration,
|
||||
@@ -72,10 +63,37 @@ open class SuspendFunctionGenerationStrategy(
|
||||
internalNameForDispatchReceiver = containingClassInternalNameOrNull(),
|
||||
languageVersionSettings = languageVersionSettings
|
||||
)
|
||||
|
||||
val forInline = state.bindingContext[CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, originalSuspendDescriptor] == true
|
||||
// Yegor Bugayenko style
|
||||
return if (forInline)
|
||||
AddConstructorCallForCoroutineRegeneration(
|
||||
MethodNodeCopyingMethodVisitor(
|
||||
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
stateMachineBuilder,
|
||||
access, name, desc, containingClassInternalName,
|
||||
isCapturedSuspendLambda = {
|
||||
isCapturedSuspendLambda(
|
||||
functionCodegen.captureVariables.sure {
|
||||
"Anonymous object should have closure"
|
||||
},
|
||||
it.name
|
||||
)
|
||||
}
|
||||
), access, name, desc,
|
||||
newMethod = { origin, newAccess, newName, newDesc ->
|
||||
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||
}
|
||||
), access, name, desc, null, null, this::classBuilderForCoroutineState,
|
||||
containingClassInternalName,
|
||||
originalSuspendDescriptor.dispatchReceiverParameter != null,
|
||||
containingClassInternalNameOrNull(),
|
||||
languageVersionSettings
|
||||
) else stateMachineBuilder
|
||||
}
|
||||
|
||||
private fun containingClassInternalNameOrNull() =
|
||||
originalSuspendDescriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let(state.typeMapper::mapClass)?.internalName
|
||||
originalSuspendDescriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let(state.typeMapper::mapClass)?.internalName
|
||||
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
this.codegen = codegen
|
||||
@@ -115,6 +133,7 @@ open class SuspendFunctionGenerationStrategy(
|
||||
languageVersionSettings
|
||||
)
|
||||
addFakeContinuationConstructorCallMarker(this, false)
|
||||
pop() // Otherwise stack-transformation breaks
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+28
-53
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* Copyright 2010-2019 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.
|
||||
*/
|
||||
|
||||
@@ -9,12 +9,12 @@ import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
||||
import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy
|
||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
@@ -29,13 +29,14 @@ class SuspendInlineFunctionGenerationStrategy(
|
||||
declaration: KtFunction,
|
||||
containingClassInternalName: String,
|
||||
constructorCallNormalizationMode: JVMConstructorCallNormalizationMode,
|
||||
private val codegen: FunctionCodegen
|
||||
codegen: FunctionCodegen
|
||||
) : SuspendFunctionGenerationStrategy(
|
||||
state,
|
||||
originalSuspendDescriptor,
|
||||
declaration,
|
||||
containingClassInternalName,
|
||||
constructorCallNormalizationMode
|
||||
constructorCallNormalizationMode,
|
||||
codegen
|
||||
) {
|
||||
private val defaultStrategy = FunctionGenerationStrategy.FunctionDefault(state, declaration)
|
||||
|
||||
@@ -43,16 +44,10 @@ class SuspendInlineFunctionGenerationStrategy(
|
||||
if (access and Opcodes.ACC_ABSTRACT != 0) return mv
|
||||
|
||||
return MethodNodeCopyingMethodVisitor(
|
||||
super.wrapMethodVisitor(mv, access, name, desc),
|
||||
access,
|
||||
name,
|
||||
desc = desc,
|
||||
signature = null,
|
||||
exceptions = null,
|
||||
codegen = codegen,
|
||||
declaration = declaration,
|
||||
originalSuspendDescriptor = originalSuspendDescriptor,
|
||||
isReleaseCoroutines = state.languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
|
||||
super.wrapMethodVisitor(mv, access, name, desc), access, name, desc,
|
||||
newMethod = { origin, newAccess, newName, newDesc ->
|
||||
functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||
}, keepAccess = false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -60,46 +55,26 @@ class SuspendInlineFunctionGenerationStrategy(
|
||||
super.doGenerateBody(codegen, signature)
|
||||
defaultStrategy.doGenerateBody(codegen, signature)
|
||||
}
|
||||
}
|
||||
|
||||
private class MethodNodeCopyingMethodVisitor(
|
||||
delegate: MethodVisitor,
|
||||
private val access: Int,
|
||||
private val name: String,
|
||||
private val desc: String,
|
||||
private val signature: String?,
|
||||
private val exceptions: Array<out String>?,
|
||||
private val codegen: FunctionCodegen,
|
||||
private val declaration: KtFunction,
|
||||
private val originalSuspendDescriptor: FunctionDescriptor,
|
||||
private val isReleaseCoroutines: Boolean
|
||||
) : TransformationMethodVisitor(
|
||||
delegate,
|
||||
calculateAccessForInline(access),
|
||||
"$name\$\$forInline",
|
||||
desc,
|
||||
signature,
|
||||
exceptions
|
||||
) {
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
val newMethodNode = codegen.newMethod(
|
||||
OtherOrigin(declaration, getOrCreateJvmSuspendFunctionView(originalSuspendDescriptor, isReleaseCoroutines)),
|
||||
calculateAccessForInline(access), "$name\$\$forInline", desc, signature, exceptions
|
||||
)
|
||||
methodNode.instructions.resetLabels()
|
||||
methodNode.accept(newMethodNode)
|
||||
}
|
||||
class MethodNodeCopyingMethodVisitor(
|
||||
delegate: MethodVisitor, private val access: Int, private val name: String, private val desc: String,
|
||||
private val newMethod: (JvmDeclarationOrigin, Int, String, String) -> MethodVisitor,
|
||||
private val keepAccess: Boolean = true
|
||||
) : TransformationMethodVisitor(
|
||||
delegate, calculateAccessForInline(access, keepAccess), "$name$FOR_INLINE_SUFFIX", desc, null, null
|
||||
) {
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
val newMethodNode = newMethod(
|
||||
JvmDeclarationOrigin.NO_ORIGIN, calculateAccessForInline(access, keepAccess), "$name$FOR_INLINE_SUFFIX", desc
|
||||
)
|
||||
methodNode.instructions.resetLabels()
|
||||
methodNode.accept(newMethodNode)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun calculateAccessForInline(access: Int): Int {
|
||||
var accessForInline = access
|
||||
if (accessForInline and Opcodes.ACC_PUBLIC != 0) {
|
||||
accessForInline = accessForInline xor Opcodes.ACC_PUBLIC
|
||||
}
|
||||
if (accessForInline and Opcodes.ACC_PROTECTED != 0) {
|
||||
accessForInline = accessForInline xor Opcodes.ACC_PROTECTED
|
||||
}
|
||||
return accessForInline or Opcodes.ACC_PRIVATE
|
||||
}
|
||||
private fun calculateAccessForInline(access: Int, keepAccess: Boolean): Int =
|
||||
if (keepAccess) access
|
||||
else access or Opcodes.ACC_PRIVATE and Opcodes.ACC_PUBLIC.inv() and Opcodes.ACC_PROTECTED.inv()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-3
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.coroutines.DEBUG_METADATA_ANNOTATION_ASM_TYPE
|
||||
import org.jetbrains.kotlin.codegen.coroutines.isCapturedSuspendLambda
|
||||
import org.jetbrains.kotlin.codegen.coroutines.isCoroutineSuperClass
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable
|
||||
@@ -67,6 +69,8 @@ class AnonymousObjectTransformer(
|
||||
// Empty inner class info because no inner classes are used in kotlin.Metadata and its arguments
|
||||
val innerClassesInfo = FileBasedKotlinClass.InnerClassesInfo()
|
||||
return FileBasedKotlinClass.convertAnnotationVisitor(metadataReader, desc, innerClassesInfo)
|
||||
} else if (desc == DEBUG_METADATA_ANNOTATION_ASM_TYPE.descriptor) {
|
||||
return null
|
||||
}
|
||||
return super.visitAnnotation(desc, visible)
|
||||
}
|
||||
@@ -135,12 +139,13 @@ class AnonymousObjectTransformer(
|
||||
classBuilder,
|
||||
methodsToTransform,
|
||||
superClassName,
|
||||
additionalFakeParams
|
||||
allCapturedParamBuilder.listCaptured()
|
||||
)
|
||||
for (next in methodsToTransform) {
|
||||
loop@for (next in methodsToTransform) {
|
||||
val deferringVisitor =
|
||||
when {
|
||||
coroutineTransformer.shouldTransform(next) -> coroutineTransformer.newMethod(next)
|
||||
coroutineTransformer.shouldSkip(next) -> continue@loop
|
||||
coroutineTransformer.shouldGenerateStateMachine(next) -> coroutineTransformer.newMethod(next)
|
||||
else -> newMethod(classBuilder, next)
|
||||
}
|
||||
val funResult = inlineMethodAndUpdateGlobalResult(parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false)
|
||||
@@ -479,6 +484,11 @@ class AnonymousObjectTransformer(
|
||||
alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false),
|
||||
alreadyAddedParam != null
|
||||
)
|
||||
if (info is PsiExpressionLambda && info.captureVariables.any { it.value.fieldName == desc.fieldName }) {
|
||||
recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend(
|
||||
isCapturedSuspendLambda(info.captureVariables, desc.fieldName)
|
||||
)
|
||||
}
|
||||
val composed = StackValue.field(
|
||||
desc.type,
|
||||
oldObjectType, /*TODO owner type*/
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructors
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
@@ -575,7 +576,7 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
|
||||
// 2) for inliner: with mangled name and without state machine
|
||||
private fun mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor: FunctionDescriptor, asmMethod: Method): Method {
|
||||
if (!functionDescriptor.isSuspend) return asmMethod
|
||||
return Method("${asmMethod.name}\$\$forInline", asmMethod.descriptor)
|
||||
return Method("${asmMethod.name}$FOR_INLINE_SUFFIX", asmMethod.descriptor)
|
||||
}
|
||||
|
||||
private fun getDirectMemberAndCallableFromObject(functionDescriptor: FunctionDescriptor): CallableMemberDescriptor {
|
||||
|
||||
@@ -307,4 +307,6 @@ class PsiExpressionLambda(
|
||||
|
||||
val isPropertyReference: Boolean
|
||||
get() = propertyReferenceInfo != null
|
||||
|
||||
val captureVariables = closure.captureVariables
|
||||
}
|
||||
+38
-15
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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 2010-2019 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;
|
||||
@@ -29,9 +18,13 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.commons.*;
|
||||
import org.jetbrains.org.objectweb.asm.commons.FieldRemapper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RemappingClassBuilder extends DelegatingClassBuilder {
|
||||
private final ClassBuilder builder;
|
||||
private final Remapper remapper;
|
||||
private final Map<String, FieldVisitor> spilledCoroutineVariables = new HashMap<>();
|
||||
|
||||
public RemappingClassBuilder(@NotNull ClassBuilder builder, @NotNull Remapper remapper) {
|
||||
this.builder = builder;
|
||||
@@ -68,9 +61,39 @@ public class RemappingClassBuilder extends DelegatingClassBuilder {
|
||||
@Nullable String signature,
|
||||
@Nullable Object value
|
||||
) {
|
||||
return new FieldRemapper(
|
||||
builder.newField(origin, access, name, remapper.mapDesc(desc), remapper.mapSignature(signature, true), value), remapper
|
||||
if (spilledCoroutineVariables.containsKey(name)) return spilledCoroutineVariables.get(name);
|
||||
|
||||
FieldRemapper field = new FieldRemapper(
|
||||
builder.newField(origin, access, name, this.remapper.mapDesc(desc), this.remapper.mapSignature(signature, true), value),
|
||||
this.remapper
|
||||
);
|
||||
if (isSpilledCoroutineVariableName(name)) {
|
||||
spilledCoroutineVariables.put(name, field);
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
private static boolean isSpilledCoroutineVariableName(String name) {
|
||||
if (name.length() < 3) return false;
|
||||
switch (name.charAt(0)) {
|
||||
case 'L':
|
||||
case 'Z':
|
||||
case 'C':
|
||||
case 'B':
|
||||
case 'S':
|
||||
case 'I':
|
||||
case 'F':
|
||||
case 'J':
|
||||
case 'D':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (name.charAt(1) != '$') return false;
|
||||
for (int i = 2; i < name.length(); ++i) {
|
||||
if (!Character.isDigit(name.charAt(i))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+80
-53
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.codegen.inline.coroutines
|
||||
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.CAPTURED_THIS_FIELD
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.coroutines.*
|
||||
@@ -16,7 +17,6 @@ import org.jetbrains.kotlin.codegen.optimization.common.asSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
@@ -29,6 +29,8 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||
|
||||
const val NOINLINE_CALL_MARKER = "NOINLINE_CALL_MARKER"
|
||||
|
||||
const val FOR_INLINE_SUFFIX = "\$\$forInline"
|
||||
|
||||
class CoroutineTransformer(
|
||||
private val inliningContext: InliningContext,
|
||||
private val classBuilder: ClassBuilder,
|
||||
@@ -37,24 +39,20 @@ class CoroutineTransformer(
|
||||
private val capturedParams: List<CapturedParamInfo>
|
||||
) {
|
||||
private val state = inliningContext.state
|
||||
// If we inline into inline function, we should generate both method with state-machine for Java interop and method without
|
||||
// state-machine for further transformation/inlining.
|
||||
private val generateForInline = inliningContext.callSiteInfo.isInlineOrInsideInline
|
||||
|
||||
fun shouldTransform(node: MethodNode): Boolean {
|
||||
// Never generate state-machine for objects, which are going to be retransformed
|
||||
// See innerObjectRetransformation.kt
|
||||
if (inliningContext.callSiteInfo.isInlineOrInsideInline) return false
|
||||
fun shouldSkip(node: MethodNode): Boolean = methods.any { it.name == node.name + FOR_INLINE_SUFFIX && it.desc == node.desc }
|
||||
|
||||
fun shouldGenerateStateMachine(node: MethodNode): Boolean {
|
||||
// Continuations are similar to lambdas from bird's view, but we should never generate state machine for them
|
||||
if (isContinuationNotLambda()) return false
|
||||
val crossinlineParam = crossinlineLambda()
|
||||
if (inliningContext.isInliningLambda && !inliningContext.isContinuation) return false
|
||||
return when {
|
||||
isSuspendFunction(node) -> true
|
||||
isSuspendLambda(node) -> {
|
||||
if (isStateMachine(node)) return false
|
||||
val functionDescriptor =
|
||||
crossinlineParam?.invokeMethodDescriptor?.containingDeclaration as? FunctionDescriptor ?: return true
|
||||
!functionDescriptor.isInline
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
// The method does not have state-machine, but should. Generate it
|
||||
if (node.name.endsWith(FOR_INLINE_SUFFIX)) return true
|
||||
// there can be suspend lambdas inside inline functions, which do not
|
||||
// capture crossinline lambdas, thus, there is no need to transform them
|
||||
return isSuspendFunctionWithFakeConstructorCall(node) || (isSuspendLambda(node) && !isStateMachine(node))
|
||||
}
|
||||
|
||||
private fun isContinuationNotLambda(): Boolean = inliningContext.isContinuation &&
|
||||
@@ -66,7 +64,7 @@ class CoroutineTransformer(
|
||||
}?.cast()
|
||||
|
||||
private fun isStateMachine(node: MethodNode): Boolean =
|
||||
node.instructions.asSequence().any { it.opcode == Opcodes.INVOKESTATIC && (it as MethodInsnNode).name == "getCOROUTINE_SUSPENDED" }
|
||||
node.instructions.asSequence().any { insn -> insn is LdcInsnNode && insn.cst == ILLEGAL_STATE_ERROR_MESSAGE }
|
||||
|
||||
private fun isSuspendLambda(node: MethodNode) = isResumeImpl(node)
|
||||
|
||||
@@ -83,28 +81,29 @@ class CoroutineTransformer(
|
||||
}
|
||||
newStateMachineForLambda(node, element)
|
||||
}
|
||||
isSuspendFunction(node) -> newStateMachineForNamedFunction(node, element)
|
||||
isSuspendFunctionWithFakeConstructorCall(node) -> newStateMachineForNamedFunction(node, element)
|
||||
else -> error("no need to generate state maching for ${node.name}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun isResumeImpl(node: MethodNode): Boolean =
|
||||
state.languageVersionSettings.isResumeImplMethodName(node.name) &&
|
||||
state.languageVersionSettings.isResumeImplMethodName(node.name.removeSuffix(FOR_INLINE_SUFFIX)) &&
|
||||
inliningContext.isContinuation
|
||||
|
||||
private fun isSuspendFunction(node: MethodNode): Boolean = findFakeContinuationConstructorClassName(node) != null
|
||||
private fun isSuspendFunctionWithFakeConstructorCall(node: MethodNode): Boolean = findFakeContinuationConstructorClassName(node) != null
|
||||
|
||||
private fun newStateMachineForLambda(node: MethodNode, element: KtElement): DeferredMethodVisitor {
|
||||
val name = node.name.removeSuffix(FOR_INLINE_SUFFIX)
|
||||
return DeferredMethodVisitor(
|
||||
MethodNode(
|
||||
node.access, node.name, node.desc, node.signature,
|
||||
node.access, name, node.desc, node.signature,
|
||||
ArrayUtil.toStringArray(node.exceptions)
|
||||
)
|
||||
) {
|
||||
surroundNoinlineCallsWithMarkersIfNeeded(
|
||||
val stateMachineBuilder = surroundNoinlineCallsWithMarkersIfNeeded(
|
||||
node,
|
||||
CoroutineTransformerMethodVisitor(
|
||||
createNewMethodFrom(node), node.access, node.name, node.desc, null, null,
|
||||
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { classBuilder },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
@@ -114,22 +113,36 @@ class CoroutineTransformer(
|
||||
isForNamedFunction = false
|
||||
)
|
||||
)
|
||||
|
||||
if (generateForInline)
|
||||
MethodNodeCopyingMethodVisitor(
|
||||
delegate = stateMachineBuilder,
|
||||
access = node.access,
|
||||
name = name,
|
||||
desc = node.desc,
|
||||
newMethod = { origin, newAccess, newName, newDesc ->
|
||||
classBuilder.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||
}
|
||||
)
|
||||
else
|
||||
stateMachineBuilder
|
||||
}
|
||||
}
|
||||
|
||||
private fun newStateMachineForNamedFunction(node: MethodNode, element: KtElement): DeferredMethodVisitor {
|
||||
val name = node.name.removeSuffix(FOR_INLINE_SUFFIX)
|
||||
val continuationClassName = findFakeContinuationConstructorClassName(node)
|
||||
assert(inliningContext is RegeneratedClassContext)
|
||||
return DeferredMethodVisitor(
|
||||
MethodNode(
|
||||
node.access, node.name, node.desc, node.signature,
|
||||
node.access, name, node.desc, node.signature,
|
||||
ArrayUtil.toStringArray(node.exceptions)
|
||||
)
|
||||
) {
|
||||
surroundNoinlineCallsWithMarkersIfNeeded(
|
||||
val stateMachineBuilder = surroundNoinlineCallsWithMarkersIfNeeded(
|
||||
node,
|
||||
CoroutineTransformerMethodVisitor(
|
||||
createNewMethodFrom(node), node.access, node.name, node.desc, null, null,
|
||||
createNewMethodFrom(node, name), node.access, name, node.desc, null, null,
|
||||
obtainClassBuilderForCoroutineState = { (inliningContext as RegeneratedClassContext).continuationBuilders[continuationClassName]!! },
|
||||
element = element,
|
||||
diagnostics = state.diagnostics,
|
||||
@@ -141,30 +154,33 @@ class CoroutineTransformer(
|
||||
internalNameForDispatchReceiver = classBuilder.thisName
|
||||
)
|
||||
)
|
||||
|
||||
if (generateForInline)
|
||||
MethodNodeCopyingMethodVisitor(
|
||||
stateMachineBuilder, node.access, name, node.desc,
|
||||
newMethod = { origin, newAccess, newName, newDesc ->
|
||||
classBuilder.newMethod(origin, newAccess, newName, newDesc, null, null)
|
||||
}
|
||||
)
|
||||
else
|
||||
stateMachineBuilder
|
||||
}
|
||||
}
|
||||
|
||||
private fun surroundNoinlineCallsWithMarkersIfNeeded(node: MethodNode, delegate: MethodVisitor): MethodVisitor =
|
||||
if (capturedParams.any { (it.functionalArgument as? NonInlineableArgumentForInlineableParameterCalledInSuspend)?.isSuspend == true })
|
||||
if (capturedParams.any { it.functionalArgument?.isSuspendLambda() == true })
|
||||
SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
delegate,
|
||||
node.access,
|
||||
node.name,
|
||||
node.desc,
|
||||
classBuilder.thisName,
|
||||
capturedParams
|
||||
delegate, node.access, node.name, node.desc, classBuilder.thisName, this::isCapturedSuspendLambda
|
||||
)
|
||||
else
|
||||
delegate
|
||||
|
||||
private fun createNewMethodFrom(node: MethodNode): MethodVisitor {
|
||||
private fun isCapturedSuspendLambda(field: FieldInsnNode): Boolean =
|
||||
capturedParams.find { it.newFieldName == field.name }?.functionalArgument?.isSuspendLambda() == true
|
||||
|
||||
private fun createNewMethodFrom(node: MethodNode, name: String): MethodVisitor {
|
||||
return classBuilder.newMethod(
|
||||
JvmDeclarationOrigin.NO_ORIGIN,
|
||||
node.access,
|
||||
node.name,
|
||||
node.desc,
|
||||
node.signature,
|
||||
ArrayUtil.toStringArray(node.exceptions)
|
||||
JvmDeclarationOrigin.NO_ORIGIN, node.access, name, node.desc, node.signature, ArrayUtil.toStringArray(node.exceptions)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -193,13 +209,10 @@ class CoroutineTransformer(
|
||||
}
|
||||
}
|
||||
|
||||
private class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
delegate: MethodVisitor,
|
||||
access: Int,
|
||||
name: String,
|
||||
desc: String,
|
||||
val thisName: String,
|
||||
val capturedParams: List<CapturedParamInfo>
|
||||
class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
delegate: MethodVisitor, access: Int, name: String, desc: String,
|
||||
private val thisName: String,
|
||||
private val isCapturedSuspendLambda: (FieldInsnNode) -> Boolean
|
||||
) : TransformationMethodVisitor(delegate, access, name, desc, null, null) {
|
||||
override fun performTransformations(methodNode: MethodNode) {
|
||||
fun AbstractInsnNode.index() = methodNode.instructions.indexOf(this)
|
||||
@@ -213,7 +226,7 @@ private class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
insn as MethodInsnNode
|
||||
if (!isInvokeOnLambda(insn.owner, insn.name)) continue
|
||||
val frame = sourceFrames[insn.index()]
|
||||
val receiver = findReceiverOfInvoke(frame, insn).takeIf { it?.isNoinlineSuspendLambda(insn) == true } as? FieldInsnNode ?: continue
|
||||
val receiver = findReceiverOfInvoke(frame, insn).takeIf { it?.isSuspendLambda(insn) == true } as? FieldInsnNode ?: continue
|
||||
val aload = receiver.findPreviousOrNull { it.opcode != Opcodes.GETFIELD } ?: error("GETFIELD cannot be the first instruction")
|
||||
assert(aload.opcode == Opcodes.ALOAD) { "Before GETFIELD there shall be ALOAD" }
|
||||
noinlineInvokes.add(insn to aload)
|
||||
@@ -222,15 +235,29 @@ private class SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor(
|
||||
surroundInvokesWithSuspendMarkers(methodNode, noinlineInvokes)
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.isNoinlineSuspendLambda(invoke: MethodInsnNode): Boolean {
|
||||
private fun AbstractInsnNode.isSuspendLambda(invoke: MethodInsnNode): Boolean {
|
||||
if (opcode != Opcodes.GETFIELD) return false
|
||||
this as FieldInsnNode
|
||||
if (owner != thisName || desc != "L${invoke.owner};") return false
|
||||
val functionalArgument = capturedParams.find { it.newFieldName == name }?.functionalArgument ?: return false
|
||||
return functionalArgument is NonInlineableArgumentForInlineableParameterCalledInSuspend && functionalArgument.isSuspend
|
||||
if (desc != "L${invoke.owner};") return false
|
||||
var current: FieldInsnNode? = this
|
||||
// Unroll the battery of
|
||||
// GETFIELD <outer1>.this$0 L<outer2>;
|
||||
// GETFIELD <outer2>.this$0 L<outer3>;
|
||||
// ...
|
||||
// GETFIELD <outerN>.$action Lkotlin/jvm/functions/FunctionM;
|
||||
while (current != null) {
|
||||
if (current.owner == thisName) break
|
||||
if (current.previous?.opcode != Opcodes.GETFIELD || current.previous.cast<FieldInsnNode>().name != CAPTURED_THIS_FIELD) return false
|
||||
current = current.previous as FieldInsnNode
|
||||
}
|
||||
return isCapturedSuspendLambda(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FunctionalArgument.isSuspendLambda(): Boolean =
|
||||
(this is NonInlineableArgumentForInlineableParameterCalledInSuspend && isSuspend) ||
|
||||
(this is PsiExpressionLambda && invokeMethodDescriptor.isSuspend)
|
||||
|
||||
fun surroundInvokesWithSuspendMarkers(
|
||||
methodNode: MethodNode,
|
||||
noinlineInvokes: List<Pair<AbstractInsnNode, AbstractInsnNode>>
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
// CHECK_STATE_MACHINE
|
||||
|
||||
// FILE: inlineMe.kt
|
||||
|
||||
package test
|
||||
|
||||
inline fun inlineMe(crossinline c: suspend () -> Unit) = suspend { c(); c() }
|
||||
|
||||
inline fun inlineMe2(crossinline c: suspend () -> Unit) = inlineMe { c(); c() }
|
||||
|
||||
inline fun inlineMe3(crossinline c: suspend () -> Unit) = suspend {
|
||||
var sr = inlineMe {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
sr()
|
||||
sr = inlineMe {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
sr()
|
||||
}
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
import test.InlineMeKt;
|
||||
import helpers.CoroutineUtilKt;
|
||||
import helpers.EmptyContinuation;
|
||||
import kotlin.Unit;
|
||||
|
||||
public class A {
|
||||
public static Object call() {
|
||||
return InlineMeKt.inlineMe((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call2() {
|
||||
return InlineMeKt.inlineMe2((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call3() {
|
||||
return InlineMeKt.inlineMe3((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import test.*
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(CheckStateMachineContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
(A.call() as (suspend () -> Unit))()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call2() as (suspend () -> Unit))()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call3() as (suspend () -> Unit))()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe2 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe3 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}()
|
||||
}
|
||||
StateMachineChecker.check(16)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// NO_CHECK_LAMBDA_INLINING
|
||||
// CHECK_STATE_MACHINE
|
||||
|
||||
// FILE: inlineMe.kt
|
||||
|
||||
package test
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run()
|
||||
}
|
||||
|
||||
inline fun inlineMe(crossinline c: suspend () -> Unit) = object : SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
c(); c()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun inlineMe2(crossinline c: suspend () -> Unit) = inlineMe { c(); c() }
|
||||
|
||||
inline fun inlineMe3(crossinline c: suspend () -> Unit) = object: SuspendRunnable {
|
||||
override suspend fun run() {
|
||||
var sr = inlineMe {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
sr.run()
|
||||
sr = inlineMe {
|
||||
c()
|
||||
c()
|
||||
}
|
||||
sr.run()
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: A.java
|
||||
|
||||
import test.InlineMeKt;
|
||||
import helpers.CoroutineUtilKt;
|
||||
import helpers.EmptyContinuation;
|
||||
import kotlin.Unit;
|
||||
|
||||
public class A {
|
||||
public static Object call() {
|
||||
return InlineMeKt.inlineMe((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call2() {
|
||||
return InlineMeKt.inlineMe2((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
public static Object call3() {
|
||||
return InlineMeKt.inlineMe3((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation));
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
|
||||
import test.*
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(CheckStateMachineContinuation)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
builder {
|
||||
(A.call() as SuspendRunnable).run()
|
||||
}
|
||||
StateMachineChecker.check(2)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call2() as SuspendRunnable).run()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
(A.call3() as SuspendRunnable).run()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run()
|
||||
}
|
||||
StateMachineChecker.check(4)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe2 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run()
|
||||
}
|
||||
StateMachineChecker.check(8)
|
||||
StateMachineChecker.reset()
|
||||
|
||||
builder {
|
||||
inlineMe3 {
|
||||
StateMachineChecker.suspendHere()
|
||||
StateMachineChecker.suspendHere()
|
||||
}.run()
|
||||
}
|
||||
StateMachineChecker.check(16)
|
||||
return "OK"
|
||||
}
|
||||
+47
@@ -1,5 +1,12 @@
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field L$5: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1
|
||||
@@ -10,7 +17,12 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 {
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1
|
||||
@@ -28,6 +40,7 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$box$1$filter$$inlined$source$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -38,11 +51,18 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1 {
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
|
||||
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$box$1$fold$$inlined$consumeEach$1
|
||||
@@ -60,6 +80,7 @@ public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1 {
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -119,6 +140,11 @@ public final class CrossinlineKt$box$1$invokeSuspend$$inlined$filter$1 {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$box$1$invokeSuspend$$inlined$fold$1
|
||||
@@ -173,11 +199,19 @@ public final class CrossinlineKt$consumeEach$2 {
|
||||
inner class CrossinlineKt$consumeEach$2$send$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$filter$$inlined$source$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field L$5: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1
|
||||
@@ -188,7 +222,12 @@ public final class CrossinlineKt$filter$$inlined$source$1$1 {
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$filter$$inlined$source$1$lambda$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1$lambda$1
|
||||
@@ -206,6 +245,7 @@ public final class CrossinlineKt$filter$$inlined$source$1$lambda$1 {
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$filter$$inlined$source$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -216,6 +256,7 @@ public final class CrossinlineKt$filter$$inlined$source$1 {
|
||||
inner class CrossinlineKt$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$1
|
||||
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -238,6 +279,7 @@ public final class CrossinlineKt$fold$$inlined$consumeEach$1 {
|
||||
inner class CrossinlineKt$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -271,7 +313,11 @@ public final class CrossinlineKt$range$$inlined$source$1 {
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class CrossinlineKt$source$1$consume$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: CrossinlineKt$source$1
|
||||
@@ -287,6 +333,7 @@ public final class CrossinlineKt$source$1 {
|
||||
inner class CrossinlineKt$source$1
|
||||
inner class CrossinlineKt$source$1$consume$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
+41
@@ -56,6 +56,11 @@ public final class CrossinlineKt$box$1$doResume$$inlined$filter$1 {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$doResume$$inlined$fold$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$doResume$$inlined$fold$1
|
||||
@@ -79,6 +84,12 @@ public final class CrossinlineKt$box$1$doResume$$inlined$fold$1 {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field L$5: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1
|
||||
@@ -92,6 +103,10 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$1 {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1
|
||||
@@ -111,6 +126,7 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1 {
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$box$1$filter$$inlined$source$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -121,11 +137,17 @@ public final class CrossinlineKt$box$1$filter$$inlined$source$1 {
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$box$1$filter$$inlined$source$1$1
|
||||
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$box$1$fold$$inlined$consumeEach$1
|
||||
@@ -145,6 +167,7 @@ public final class CrossinlineKt$box$1$fold$$inlined$consumeEach$1 {
|
||||
inner class CrossinlineKt$box$1$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -183,11 +206,18 @@ public final class CrossinlineKt$consumeEach$2 {
|
||||
inner class CrossinlineKt$consumeEach$2$send$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$filter$$inlined$source$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field L$4: java.lang.Object
|
||||
field L$5: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1
|
||||
@@ -201,6 +231,10 @@ public final class CrossinlineKt$filter$$inlined$source$1$1 {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$filter$$inlined$source$1$lambda$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$filter$$inlined$source$1$lambda$1
|
||||
@@ -220,6 +254,7 @@ public final class CrossinlineKt$filter$$inlined$source$1$lambda$1 {
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$lambda$1$1
|
||||
public method <init>(p0: Sink, p1: CrossinlineKt$filter$$inlined$source$1): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -230,6 +265,7 @@ public final class CrossinlineKt$filter$$inlined$source$1 {
|
||||
inner class CrossinlineKt$filter$$inlined$source$1
|
||||
inner class CrossinlineKt$filter$$inlined$source$1$1
|
||||
public method <init>(p0: SourceCrossinline, p1: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -254,6 +290,7 @@ public final class CrossinlineKt$fold$$inlined$consumeEach$1 {
|
||||
inner class CrossinlineKt$fold$$inlined$consumeEach$1$1
|
||||
public method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void
|
||||
public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void
|
||||
public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -289,6 +326,9 @@ public final class CrossinlineKt$range$$inlined$source$1 {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class CrossinlineKt$source$1$consume$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: CrossinlineKt$source$1
|
||||
@@ -306,6 +346,7 @@ public final class CrossinlineKt$source$1 {
|
||||
inner class CrossinlineKt$source$1
|
||||
inner class CrossinlineKt$source$1$consume$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method consume$$forInline(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method consume(@org.jetbrains.annotations.NotNull p0: Sink, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
Vendored
+13
@@ -64,6 +64,10 @@ public final class flow/InnerObjectRetransformationKt$check$$inlined$flow$1 {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$flowWith$1
|
||||
@@ -110,6 +114,7 @@ public final class flow/InnerObjectRetransformationKt$collect$2 {
|
||||
inner class flow/InnerObjectRetransformationKt$collect$2
|
||||
inner class flow/InnerObjectRetransformationKt$collect$2$emit$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method emit$$forInline(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method emit(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -130,6 +135,7 @@ public final class flow/InnerObjectRetransformationKt$flow$1 {
|
||||
inner class flow/InnerObjectRetransformationKt$flow$1
|
||||
inner class flow/InnerObjectRetransformationKt$flow$1$collect$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -151,11 +157,17 @@ public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1 {
|
||||
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1
|
||||
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1
|
||||
public method <init>(p0: flow.Flow, p1: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
field label: int
|
||||
synthetic field result: java.lang.Object
|
||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$2
|
||||
@@ -172,6 +184,7 @@ public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2 {
|
||||
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2
|
||||
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1
|
||||
public method <init>(p0: flow.Flow, p1: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
Vendored
+12
@@ -65,6 +65,10 @@ public final class flow/InnerObjectRetransformationKt$check$$inlined$flow$1 {
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt$check$$inlined$flowWith$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$check$$inlined$flowWith$1
|
||||
@@ -116,6 +120,7 @@ public final class flow/InnerObjectRetransformationKt$collect$2 {
|
||||
inner class flow/InnerObjectRetransformationKt$collect$2
|
||||
inner class flow/InnerObjectRetransformationKt$collect$2$emit$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method emit$$forInline(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method emit(@org.jetbrains.annotations.NotNull p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -138,6 +143,7 @@ public final class flow/InnerObjectRetransformationKt$flow$1 {
|
||||
inner class flow/InnerObjectRetransformationKt$flow$1
|
||||
inner class flow/InnerObjectRetransformationKt$flow$1$collect$1
|
||||
public method <init>(p0: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@@ -161,11 +167,16 @@ public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1 {
|
||||
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1
|
||||
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1
|
||||
public method <init>(p0: flow.Flow, p1: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1 {
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field L$3: java.lang.Object
|
||||
synthetic field data: java.lang.Object
|
||||
synthetic field exception: java.lang.Throwable
|
||||
synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$2
|
||||
@@ -184,6 +195,7 @@ public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2 {
|
||||
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2
|
||||
inner class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$2$1
|
||||
public method <init>(p0: flow.Flow, p1: kotlin.jvm.functions.Function2): void
|
||||
public @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.FlowCollector, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ final class CoroutineFieldsKt$box$1 {
|
||||
field J$0: long
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
private field p$: Controller
|
||||
inner class CoroutineFieldsKt$box$1
|
||||
method <init>(p0: kotlin.jvm.internal.Ref$ObjectRef, p1: COROUTINES_PACKAGE.Continuation): void
|
||||
|
||||
@@ -40,6 +40,7 @@ final class CoroutineFieldsKt$box$1 {
|
||||
field J$0: long
|
||||
field L$0: java.lang.Object
|
||||
field L$1: java.lang.Object
|
||||
field L$2: java.lang.Object
|
||||
field label: int
|
||||
private field p$: Controller
|
||||
inner class CoroutineFieldsKt$box$1
|
||||
|
||||
@@ -6,5 +6,8 @@ inline fun inlineMe(crossinline c: suspend () -> Int): suspend () -> Int {
|
||||
return i
|
||||
}
|
||||
|
||||
// invokeSuspend$$forInline : valueOf
|
||||
// invokeSuspend : boxInt
|
||||
|
||||
// 1 valueOf
|
||||
// 0 boxInt
|
||||
// 1 boxInt
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ fun main(args: Array<String>) {
|
||||
@BuilderInference
|
||||
suspend fun SequenceScope<Int>.awaitSeq(): Int = 42
|
||||
|
||||
// 1 LOCALVARIABLE a I L16 L.* 3
|
||||
// 1 LINENUMBER 8 L16
|
||||
// 1 LOCALVARIABLE a I L17 L.* 3
|
||||
// 1 LINENUMBER 8 L17
|
||||
// Adding ignore flags below the test since the test relies on line numbers.
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
|
||||
+3
-1
@@ -21,4 +21,6 @@ class Test {
|
||||
}
|
||||
}
|
||||
|
||||
// 4 TABLESWITCH
|
||||
// suspend lambdas: 4
|
||||
// suspend lambdas $$forInline: 1
|
||||
// 5 TABLESWITCH
|
||||
+37
@@ -7381,6 +7381,43 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/coroutines/javaInterop")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class JavaInterop extends AbstractBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
|
||||
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJavaInterop() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/javaInterop"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("returnLambda.kt")
|
||||
public void testReturnLambda_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines.experimental");
|
||||
}
|
||||
|
||||
@TestMetadata("returnLambda.kt")
|
||||
public void testReturnLambda_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("returnObject.kt")
|
||||
public void testReturnObject_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines.experimental");
|
||||
}
|
||||
|
||||
@TestMetadata("returnObject.kt")
|
||||
public void testReturnObject_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+37
@@ -7381,6 +7381,43 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/coroutines/javaInterop")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class JavaInterop extends AbstractLightAnalysisModeTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
|
||||
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJavaInterop() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/javaInterop"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("returnLambda.kt")
|
||||
public void testReturnLambda_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines.experimental");
|
||||
}
|
||||
|
||||
@TestMetadata("returnLambda.kt")
|
||||
public void testReturnLambda_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("returnObject.kt")
|
||||
public void testReturnObject_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines.experimental");
|
||||
}
|
||||
|
||||
@TestMetadata("returnObject.kt")
|
||||
public void testReturnObject_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+37
@@ -7381,6 +7381,43 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/coroutines/javaInterop")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class JavaInterop extends AbstractIrBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
|
||||
KotlinTestUtils.runTest(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JVM_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJavaInterop() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/javaInterop"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("returnLambda.kt")
|
||||
public void testReturnLambda_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines.experimental");
|
||||
}
|
||||
|
||||
@TestMetadata("returnLambda.kt")
|
||||
public void testReturnLambda_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("returnObject.kt")
|
||||
public void testReturnObject_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines.experimental");
|
||||
}
|
||||
|
||||
@TestMetadata("returnObject.kt")
|
||||
public void testReturnObject_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Generated
+27
@@ -5701,6 +5701,33 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/coroutines/javaInterop")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class JavaInterop extends AbstractIrJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
|
||||
KotlinTestUtils.runTest0(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJavaInterop() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/javaInterop"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("returnLambda.kt")
|
||||
public void testReturnLambda_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("returnObject.kt")
|
||||
public void testReturnObject_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+37
@@ -6441,6 +6441,43 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/coroutines/javaInterop")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class JavaInterop extends AbstractJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
private void runTestWithPackageReplacement(String testDataFilePath, String packageName) throws Exception {
|
||||
KotlinTestUtils.runTest0(filePath -> doTestWithCoroutinesPackageReplacement(filePath, packageName), TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJavaInterop() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/javaInterop"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("returnLambda.kt")
|
||||
public void testReturnLambda_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines.experimental");
|
||||
}
|
||||
|
||||
@TestMetadata("returnLambda.kt")
|
||||
public void testReturnLambda_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnLambda.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("returnObject.kt")
|
||||
public void testReturnObject_1_2() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines.experimental");
|
||||
}
|
||||
|
||||
@TestMetadata("returnObject.kt")
|
||||
public void testReturnObject_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user