Preserve sources properly for coroutine parts

Otherwise incremental reporting leads to exception when inlining into coroutine body happens
This commit is contained in:
Denis Zharkov
2016-05-30 14:35:54 +03:00
parent 7dda2d9f62
commit 07592398c1
8 changed files with 82 additions and 9 deletions
@@ -84,11 +84,17 @@ class CoroutineCodegen(
val resumeFunctionDescriptor = val resumeFunctionDescriptor =
createSynthesizedImplementationByName( createSynthesizedImplementationByName(
"resume", interfaceSupertype = continuationSuperType, implementationClass = classDescriptor) "resume",
interfaceSupertype = continuationSuperType,
implementationClass = classDescriptor,
sourceElement = funDescriptor.source)
val resumeWithExceptionFunctionDescriptor = val resumeWithExceptionFunctionDescriptor =
createSynthesizedImplementationByName( createSynthesizedImplementationByName(
"resumeWithException", interfaceSupertype = continuationSuperType, implementationClass = classDescriptor) "resumeWithException",
interfaceSupertype = continuationSuperType,
implementationClass = classDescriptor,
sourceElement = funDescriptor.source)
// private fun resume(result, throwable) // private fun resume(result, throwable)
val combinedResumeFunctionDescriptor = val combinedResumeFunctionDescriptor =
@@ -96,6 +102,7 @@ class CoroutineCodegen(
.setVisibility(Visibilities.PRIVATE) .setVisibility(Visibilities.PRIVATE)
.setName(Name.identifier("doResume")) .setName(Name.identifier("doResume"))
.setCopyOverrides(false) .setCopyOverrides(false)
.setPreserveSourceElement()
.setValueParameters( .setValueParameters(
listOf( listOf(
resumeFunctionDescriptor.valueParameters[0].copy( resumeFunctionDescriptor.valueParameters[0].copy(
@@ -120,10 +127,11 @@ class CoroutineCodegen(
private fun createSynthesizedImplementationByName( private fun createSynthesizedImplementationByName(
name: String, name: String,
interfaceSupertype: KotlinType, interfaceSupertype: KotlinType,
implementationClass: ClassDescriptor implementationClass: ClassDescriptor,
sourceElement: SourceElement
): SimpleFunctionDescriptor { ): SimpleFunctionDescriptor {
val inSuperType = interfaceSupertype.memberScope.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).single() val inSuperType = interfaceSupertype.memberScope.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).single()
val result = inSuperType.newCopyBuilder().setOwner(implementationClass).setModality(Modality.FINAL).build()!! val result = inSuperType.newCopyBuilder().setSource(sourceElement).setOwner(implementationClass).setModality(Modality.FINAL).build()!!
result.setSingleOverridden(inSuperType) result.setSingleOverridden(inSuperType)
return result return result
@@ -174,7 +182,7 @@ class CoroutineCodegen(
} ?: return null } ?: return null
val descriptorWithContinuationReturnType = val descriptorWithContinuationReturnType =
originalCoroutineLambdaDescriptor.newCopyBuilder().setReturnType(continuationSupertype).build()!! originalCoroutineLambdaDescriptor.newCopyBuilder().setPreserveSourceElement().setReturnType(continuationSupertype).build()!!
val state = expressionCodegen.state val state = expressionCodegen.state
return CoroutineCodegen( return CoroutineCodegen(
@@ -55,7 +55,7 @@ class DeserializedSimpleFunctionDescriptor(
) : DeserializedCallableMemberDescriptor, ) : DeserializedCallableMemberDescriptor,
SimpleFunctionDescriptorImpl( SimpleFunctionDescriptorImpl(
containingDeclaration, original, annotations, name, kind, containingDeclaration, original, annotations, name, kind,
source ?: org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE) { source ?: SourceElement.NO_SOURCE) {
override fun createSubstitutedCopy( override fun createSubstitutedCopy(
newOwner: DeclarationDescriptor, newOwner: DeclarationDescriptor,
@@ -114,9 +114,10 @@ class DeserializedConstructorDescriptor(
override val proto: ProtoBuf.Constructor, override val proto: ProtoBuf.Constructor,
override val nameResolver: NameResolver, override val nameResolver: NameResolver,
override val typeTable: TypeTable, override val typeTable: TypeTable,
override val containerSource: SourceElement? override val containerSource: SourceElement?,
source: SourceElement? = null
) : DeserializedCallableMemberDescriptor, ) : DeserializedCallableMemberDescriptor,
ConstructorDescriptorImpl(containingDeclaration, original, annotations, isPrimary, kind, SourceElement.NO_SOURCE) { ConstructorDescriptorImpl(containingDeclaration, original, annotations, isPrimary, kind, source ?: SourceElement.NO_SOURCE) {
override fun createSubstitutedCopy( override fun createSubstitutedCopy(
newOwner: DeclarationDescriptor, newOwner: DeclarationDescriptor,
@@ -128,7 +129,7 @@ class DeserializedConstructorDescriptor(
): DeserializedConstructorDescriptor { ): DeserializedConstructorDescriptor {
return DeserializedConstructorDescriptor( return DeserializedConstructorDescriptor(
newOwner as ClassDescriptor, original as ConstructorDescriptor?, annotations, isPrimary, kind, newOwner as ClassDescriptor, original as ConstructorDescriptor?, annotations, isPrimary, kind,
proto, nameResolver, typeTable, source proto, nameResolver, typeTable, containerSource, source
) )
} }
@@ -1124,6 +1124,12 @@ public class ExperimentalIncrementalJpsTestGenerated extends AbstractExperimenta
doTest(fileName); doTest(fileName);
} }
@TestMetadata("coroutine")
public void testCoroutine() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/inlineFunCallSite/coroutine/");
doTest(fileName);
}
@TestMetadata("function") @TestMetadata("function")
public void testFunction() throws Exception { public void testFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/inlineFunCallSite/function/"); String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/inlineFunCallSite/function/");
@@ -1124,6 +1124,12 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("coroutine")
public void testCoroutine() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/inlineFunCallSite/coroutine/");
doTest(fileName);
}
@TestMetadata("function") @TestMetadata("function")
public void testFunction() throws Exception { public void testFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/inlineFunCallSite/function/"); String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/inlineFunCallSite/function/");
@@ -0,0 +1,24 @@
================ Step #1 =================
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/inline/InlineKt.class
End of files
Compiling files:
src/inline.kt
End of files
Marked as dirty by Kotlin:
src/usage.kt
Exit code: ADDITIONAL_PASS_REQUIRED
------------------------------------------
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/usage/Controller.class
out/production/module/usage/UsageKt$bar$1.class
out/production/module/usage/UsageKt.class
End of files
Compiling files:
src/usage.kt
End of files
Exit code: OK
------------------------------------------
@@ -0,0 +1,5 @@
package inline
inline fun f(x: Int): Int {
return x - 1
}
@@ -0,0 +1,5 @@
package inline
inline fun f(x: Int): Int {
return x + 1
}
@@ -0,0 +1,18 @@
package usage
fun async(coroutine x: Controller.() -> Continuation<Unit>) {
x(Controller()).resume(Unit)
}
class Controller {
suspend fun step(param: Int, next: Continuation<Int>) {
next.resume(param + 1)
}
}
fun bar() {
async {
val result = step(1)
inline.f(result)
}
}