JS: report inline suspend functions to IC

* Also inline suspend lambda'a
* Also use correct JsName's in exported suspend inline fun's
* Also use less unused imports
This commit is contained in:
Anton Bannykh
2018-11-01 20:23:45 +03:00
parent 82268cd95d
commit 59009430e5
13 changed files with 81 additions and 8 deletions
@@ -291,6 +291,11 @@ public class IncrementalJsCompilerRunnerTestGenerated extends AbstractIncrementa
runTest("jps-plugin/testData/incremental/pureKotlin/inlinePropertyOnTopLevel/");
}
@TestMetadata("inlineSuspendFunctionChanged")
public void testInlineSuspendFunctionChanged() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/inlineSuspendFunctionChanged/");
}
@TestMetadata("inlineTwoFunctionsOneChanged")
public void testInlineTwoFunctionsOneChanged() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/inlineTwoFunctionsOneChanged/");
@@ -291,6 +291,11 @@ public class IncrementalJvmCompilerRunnerTestGenerated extends AbstractIncrement
runTest("jps-plugin/testData/incremental/pureKotlin/inlinePropertyOnTopLevel/");
}
@TestMetadata("inlineSuspendFunctionChanged")
public void testInlineSuspendFunctionChanged() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/inlineSuspendFunctionChanged/");
}
@TestMetadata("inlineTwoFunctionsOneChanged")
public void testInlineTwoFunctionsOneChanged() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/inlineTwoFunctionsOneChanged/");
@@ -4,7 +4,6 @@
// WITH_RUNTIME
// WITH_COROUTINES
// NO_CHECK_LAMBDA_INLINING
// IGNORE_BACKEND: JS
suspend inline fun crossinlineMe(crossinline c: suspend () -> Unit) {
val l: suspend () -> Unit = { c() }
@@ -870,6 +870,11 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
runTest("jps-plugin/testData/incremental/pureKotlin/inlinePropertyOnTopLevel/");
}
@TestMetadata("inlineSuspendFunctionChanged")
public void testInlineSuspendFunctionChanged() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/inlineSuspendFunctionChanged/");
}
@TestMetadata("inlineTwoFunctionsOneChanged")
public void testInlineTwoFunctionsOneChanged() throws Exception {
runTest("jps-plugin/testData/incremental/pureKotlin/inlineTwoFunctionsOneChanged/");
@@ -0,0 +1,22 @@
================ 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/useInline.kt
Exit code: ADDITIONAL_PASS_REQUIRED
------------------------------------------
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/inline/UseInlineKt.class
End of files
Compiling files:
src/useInline.kt
End of files
Exit code: OK
------------------------------------------
@@ -0,0 +1,5 @@
package inline
fun dontUseF() {
println("Don't use f")
}
@@ -0,0 +1,6 @@
package inline
inline suspend fun f(body: () -> Unit) {
println("i'm inline suspend function")
body()
}
@@ -0,0 +1,6 @@
package inline
inline suspend fun f(body: () -> Unit) {
body()
println("i'm inline suspend function")
}
@@ -0,0 +1,5 @@
package inline
suspend fun useF() {
f { println("useF") }
}
@@ -47,12 +47,14 @@ class CoroutineTransformer : JsVisitorWithContextImpl() {
if (function?.coroutineMetadata != null) {
val name = ((lhs as? JsNameRef)?.name ?: function.name)?.ident
additionalStatementsByNode[x] = CoroutineFunctionTransformer(function, name).transform()
function.coroutineMetadata = null
return false
}
}
else if (expression is JsFunction) {
if (expression.coroutineMetadata != null) {
additionalStatementsByNode[x] = CoroutineFunctionTransformer(expression, expression.name?.ident).transform()
expression.coroutineMetadata = null
return false
}
}
@@ -74,6 +76,7 @@ class CoroutineTransformer : JsVisitorWithContextImpl() {
if (function?.coroutineMetadata != null) {
val name = x.name.ident
additionalStatementsByNode[x] = CoroutineFunctionTransformer(function, name).transform()
function.coroutineMetadata = null
return false
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.js.inline.util.rewriters
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.coroutineMetadata
class NameReplacingVisitor(private val replaceMap: Map<JsName, JsExpression>) : JsVisitorWithContextImpl() {
@@ -43,6 +44,16 @@ class NameReplacingVisitor(private val replaceMap: Map<JsName, JsExpression>) :
override fun endVisit(x: JsParameter, ctx: JsContext<*>) = applyToNamedNode(x)
override fun visit(x: JsFunction, ctx: JsContext<*>): Boolean {
x.coroutineMetadata?.let { coroutineMetadata ->
x.coroutineMetadata = coroutineMetadata.copy(
baseClassRef = accept(coroutineMetadata.baseClassRef.deepCopy()),
suspendObjectRef = accept(coroutineMetadata.suspendObjectRef.deepCopy())
)
}
return super.visit(x, ctx)
}
private fun applyToNamedNode(x: HasName) {
while (true) {
val replacement = replaceMap[x.name]
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.js.translate.callTranslator
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -32,8 +31,6 @@ import org.jetbrains.kotlin.js.translate.reference.CallExpressionTranslator
import org.jetbrains.kotlin.js.translate.utils.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.Call.CallType
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtWhenConditionInRange
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsName
import org.jetbrains.kotlin.js.backend.ast.metadata.coroutineMetadata
import org.jetbrains.kotlin.js.backend.ast.metadata.isInlineableCoroutineBody
import org.jetbrains.kotlin.js.descriptorUtils.shouldBeExported
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata
import org.jetbrains.kotlin.js.translate.expression.translateAndAliasParameters
@@ -100,17 +101,20 @@ abstract class AbstractDeclarationVisitor : TranslatorVisitor<Unit>() {
else {
null
}
addFunction(descriptor, functionAndContext?.first, expression)
if (descriptor.isSuspend && descriptor.isInline && descriptor.shouldBeExported(context.config) && functionAndContext != null) {
val exportFunction = functionAndContext.first as JsFunction
exportFunction.fillCoroutineMetadata(context, descriptor, exportFunction.coroutineMetadata!!.hasController)
addFunction(descriptor, exportFunction, expression)
val innerContext = functionAndContext.second
val inlineFunction = functionAndContext.first.deepCopy() as JsFunction
inlineFunction.name = null
inlineFunction.coroutineMetadata = null
inlineFunction.isInlineableCoroutineBody = true
val metadata = InlineMetadata.compose(inlineFunction, descriptor, innerContext)
val functionWithMetadata = metadata.functionWithMetadata(context, descriptor.source.getPsi())
context.addDeclarationStatement(functionWithMetadata.makeStmt())
context.addDeclarationStatement(innerContext.wrapWithInlineMetadata(context, inlineFunction, descriptor).makeStmt())
} else {
addFunction(descriptor, functionAndContext?.first, expression)
}
}