[JS IR] Fill source info in codegen
#KT-46551 In Progress
This commit is contained in:
committed by
teamcityserver
parent
64c6d852de
commit
5a3efc1a98
+21
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -40,7 +40,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
|
||||
override fun visitVararg(expression: IrVararg, context: JsGenerationContext): JsExpression {
|
||||
assert(expression.elements.none { it is IrSpreadElement })
|
||||
return JsArrayLiteral(expression.elements.map { it.accept(this, context) })
|
||||
return JsArrayLiteral(expression.elements.map { it.accept(this, context) }).withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitExpressionBody(body: IrExpressionBody, context: JsGenerationContext): JsExpression =
|
||||
@@ -64,7 +64,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
is IrConstKind.Char -> throw IllegalStateException("Char const should have been lowered at this point")
|
||||
is IrConstKind.Float -> JsDoubleLiteral(toDoubleConst(kind.valueOf(expression)))
|
||||
is IrConstKind.Double -> JsDoubleLiteral(kind.valueOf(expression))
|
||||
}
|
||||
}.withSource(expression, context)
|
||||
}
|
||||
|
||||
private fun toDoubleConst(f: Float) = if (f.isInfinite() || f.isNaN()) f.toDouble() else f.toString().toDouble()
|
||||
@@ -94,19 +94,19 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
return JsNameRef(
|
||||
field.getJsNameOrKotlinName().identifier,
|
||||
context.getNameForClass(fieldParent).makeRef()
|
||||
)
|
||||
).withSource(expression, context)
|
||||
}
|
||||
|
||||
if (fieldParent is IrClass && fieldParent.isInline) {
|
||||
return expression.receiver!!.accept(this, context)
|
||||
return expression.receiver!!.accept(this, context).withSource(expression, context)
|
||||
}
|
||||
val fieldName = context.getNameForField(field)
|
||||
return JsNameRef(fieldName, expression.receiver?.accept(this, context))
|
||||
return JsNameRef(fieldName, expression.receiver?.accept(this, context)).withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue, context: JsGenerationContext): JsExpression {
|
||||
if (expression.symbol.owner.isThisReceiver()) return JsThisRef()
|
||||
return context.getNameForValueDeclaration(expression.symbol.owner).makeRef()
|
||||
if (expression.symbol.owner.isThisReceiver()) return JsThisRef().withSource(expression, context)
|
||||
return context.getNameForValueDeclaration(expression.symbol.owner).makeRef().withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitGetObjectValue(expression: IrGetObjectValue, context: JsGenerationContext): JsExpression {
|
||||
@@ -114,20 +114,20 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
assert(obj.kind == ClassKind.OBJECT)
|
||||
assert(obj.isEffectivelyExternal()) { "Non external IrGetObjectValue must be lowered" }
|
||||
|
||||
return context.getRefForExternalClass(obj)
|
||||
return context.getRefForExternalClass(obj).withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitSetField(expression: IrSetField, context: JsGenerationContext): JsExpression {
|
||||
val fieldName = context.getNameForField(expression.symbol.owner)
|
||||
val dest = JsNameRef(fieldName, expression.receiver?.accept(this, context))
|
||||
val source = expression.value.accept(this, context)
|
||||
return jsAssignment(dest, source)
|
||||
return jsAssignment(dest, source).withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitSetValue(expression: IrSetValue, context: JsGenerationContext): JsExpression {
|
||||
val ref = JsNameRef(context.getNameForValueDeclaration(expression.symbol.owner))
|
||||
val value = expression.value.accept(this, context)
|
||||
return JsBinaryOperation(JsBinaryOperator.ASG, ref, value)
|
||||
return JsBinaryOperation(JsBinaryOperator.ASG, ref, value).withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, context: JsGenerationContext): JsExpression {
|
||||
@@ -143,14 +143,14 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
assert(constructor.isPrimary) {
|
||||
"Delegation to secondary inline constructors must be lowered into simple function calls"
|
||||
}
|
||||
return JsBinaryOperation(JsBinaryOperator.ASG, thisRef, arguments.single())
|
||||
return JsBinaryOperation(JsBinaryOperator.ASG, thisRef, arguments.single()).withSource(expression, context)
|
||||
}
|
||||
|
||||
return if (context.staticContext.backendContext.es6mode) {
|
||||
JsInvocation(JsNameRef("super"), arguments)
|
||||
} else {
|
||||
JsInvocation(callFuncRef, listOf(thisRef) + arguments)
|
||||
}
|
||||
}.withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitConstructorCall(expression: IrConstructorCall, context: JsGenerationContext): JsExpression {
|
||||
@@ -190,7 +190,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
val ref = context.getNameForClass(klass).makeRef()
|
||||
JsNew(ref, arguments)
|
||||
}
|
||||
}
|
||||
}.withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall, context: JsGenerationContext): JsExpression {
|
||||
@@ -200,7 +200,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
|
||||
val lastStatement = statements.last()
|
||||
if (statements.size == 1) {
|
||||
if (lastStatement is JsExpressionStatement) return lastStatement.expression
|
||||
if (lastStatement is JsExpressionStatement) return lastStatement.expression.withSource(expression, context)
|
||||
}
|
||||
|
||||
val newStatements = statements.toMutableList()
|
||||
@@ -216,10 +216,10 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
}
|
||||
|
||||
val syntheticFunction = JsFunction(emptyScope, JsBlock(newStatements), "")
|
||||
return JsInvocation(syntheticFunction)
|
||||
return JsInvocation(syntheticFunction).withSource(expression, context)
|
||||
|
||||
}
|
||||
return translateCall(expression, context, this)
|
||||
return translateCall(expression, context, this).withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitWhen(expression: IrWhen, context: JsGenerationContext): JsExpression {
|
||||
@@ -239,11 +239,11 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
return when (expression.operator) {
|
||||
IrTypeOperator.REINTERPRET_CAST -> expression.argument.accept(this, data)
|
||||
else -> error("All type operator calls except REINTERPRET_CAST should be lowered at this point: ${expression.operator}")
|
||||
}
|
||||
}.withSource(expression, data)
|
||||
}
|
||||
|
||||
override fun visitDynamicMemberExpression(expression: IrDynamicMemberExpression, data: JsGenerationContext): JsExpression =
|
||||
JsNameRef(expression.memberName, expression.receiver.accept(this, data))
|
||||
JsNameRef(expression.memberName, expression.receiver.accept(this, data)).withSource(expression, data)
|
||||
|
||||
override fun visitDynamicOperatorExpression(expression: IrDynamicOperatorExpression, data: JsGenerationContext): JsExpression =
|
||||
when (expression.operator) {
|
||||
@@ -294,7 +294,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
)
|
||||
|
||||
else -> error("Unexpected operator ${expression.operator}: ${expression.render()}")
|
||||
}
|
||||
}.withSource(expression, data)
|
||||
|
||||
override fun visitRawFunctionReference(expression: IrRawFunctionReference, data: JsGenerationContext): JsExpression {
|
||||
val name = when (val function = expression.symbol.owner) {
|
||||
@@ -302,7 +302,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
is IrSimpleFunction -> data.getNameForStaticFunction(function)
|
||||
else -> error("Unexpected function kind")
|
||||
}
|
||||
return JsNameRef(name)
|
||||
return JsNameRef(name).withSource(expression, data)
|
||||
}
|
||||
|
||||
private fun prefixOperation(operator: JsUnaryOperator, expression: IrDynamicOperatorExpression, data: JsGenerationContext) =
|
||||
|
||||
+14
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -38,15 +38,15 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
}
|
||||
|
||||
override fun visitExpression(expression: IrExpression, context: JsGenerationContext): JsStatement {
|
||||
return JsExpressionStatement(expression.accept(IrElementToJsExpressionTransformer(), context))
|
||||
return expression.accept(IrElementToJsExpressionTransformer(), context).makeStmt()
|
||||
}
|
||||
|
||||
override fun visitBreak(jump: IrBreak, context: JsGenerationContext): JsStatement {
|
||||
return JsBreak(context.getNameForLoop(jump.loop)?.let { JsNameRef(it) })
|
||||
return JsBreak(context.getNameForLoop(jump.loop)?.let { JsNameRef(it) }).withSource(jump, context)
|
||||
}
|
||||
|
||||
override fun visitContinue(jump: IrContinue, context: JsGenerationContext): JsStatement {
|
||||
return JsContinue(context.getNameForLoop(jump.loop)?.let { JsNameRef(it) })
|
||||
return JsContinue(context.getNameForLoop(jump.loop)?.let { JsNameRef(it) }).withSource(jump, context)
|
||||
}
|
||||
|
||||
private fun IrExpression.maybeOptimizeIntoSwitch(context: JsGenerationContext, transformer: (JsExpression) -> JsStatement): JsStatement {
|
||||
@@ -62,20 +62,21 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
val fieldName = context.getNameForField(expression.symbol.owner)
|
||||
val expressionTransformer = IrElementToJsExpressionTransformer()
|
||||
val dest = JsNameRef(fieldName, expression.receiver?.accept(expressionTransformer, context))
|
||||
return expression.value.maybeOptimizeIntoSwitch(context) { jsAssignment(dest, it).makeStmt() }
|
||||
return expression.value.maybeOptimizeIntoSwitch(context) { jsAssignment(dest, it).withSource(expression, context).makeStmt() }
|
||||
}
|
||||
|
||||
override fun visitSetValue(expression: IrSetValue, context: JsGenerationContext): JsStatement {
|
||||
val ref = JsNameRef(context.getNameForValueDeclaration(expression.symbol.owner))
|
||||
return expression.value.maybeOptimizeIntoSwitch(context) { JsBinaryOperation(JsBinaryOperator.ASG, ref, it).makeStmt() }
|
||||
return expression.value
|
||||
.maybeOptimizeIntoSwitch(context) { jsAssignment(ref, it).withSource(expression, context).makeStmt() }
|
||||
}
|
||||
|
||||
override fun visitReturn(expression: IrReturn, context: JsGenerationContext): JsStatement {
|
||||
return expression.value.maybeOptimizeIntoSwitch(context) { JsReturn(it) }
|
||||
return expression.value.maybeOptimizeIntoSwitch(context) { JsReturn(it) }.withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitThrow(expression: IrThrow, context: JsGenerationContext): JsStatement {
|
||||
return expression.value.maybeOptimizeIntoSwitch(context) { JsThrow(it) }
|
||||
return expression.value.maybeOptimizeIntoSwitch(context) { JsThrow(it) }.withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitVariable(declaration: IrVariable, context: JsGenerationContext): JsStatement {
|
||||
@@ -90,11 +91,11 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
}
|
||||
|
||||
SwitchOptimizer(context, transformer).tryOptimize(value)?.let {
|
||||
return JsBlock(JsVars(JsVars.JsVar(varName)), it)
|
||||
return JsBlock(JsVars(JsVars.JsVar(varName)), it).withSource(declaration, context)
|
||||
}
|
||||
}
|
||||
|
||||
return jsVar(varName, value, context)
|
||||
return jsVar(varName, value, context).withSource(declaration, context)
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, context: JsGenerationContext): JsStatement {
|
||||
@@ -109,12 +110,12 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
val statements = translateJsCodeIntoStatementList(expression.getValueArgument(0) ?: error("JsCode is expected"))!!
|
||||
return when (statements.size) {
|
||||
0 -> JsEmpty
|
||||
1 -> statements.single()
|
||||
1 -> statements.single().withSource(expression, data)
|
||||
// TODO: use transparent block (e.g. JsCompositeBlock)
|
||||
else -> JsBlock(statements)
|
||||
}
|
||||
}
|
||||
return translateCall(expression, data, IrElementToJsExpressionTransformer()).makeStmt()
|
||||
return translateCall(expression, data, IrElementToJsExpressionTransformer()).withSource(expression, data).makeStmt()
|
||||
}
|
||||
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, context: JsGenerationContext): JsStatement {
|
||||
@@ -157,3 +158,4 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
return label?.let { JsLabel(it, loopStatement) } ?: loopStatement
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock
|
||||
|
||||
class IrFileToJsTransformer : BaseIrElementToJsNodeTransformer<JsBlock, JsGenerationContext> {
|
||||
override fun visitFile(declaration: IrFile, data: JsGenerationContext): JsBlock {
|
||||
val fileContext = data.newDeclaration()
|
||||
val fileContext = data.newFile(declaration)
|
||||
val block = JsGlobalBlock()
|
||||
|
||||
declaration.declarations.forEach {
|
||||
@@ -21,4 +21,4 @@ class IrFileToJsTransformer : BaseIrElementToJsNodeTransformer<JsBlock, JsGenera
|
||||
|
||||
return block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -136,6 +136,7 @@ class IrModuleToJsTransformer(
|
||||
globalNameScope = namer.globalNames
|
||||
)
|
||||
val rootContext = JsGenerationContext(
|
||||
currentFile = null,
|
||||
currentFunction = null,
|
||||
staticContext = staticContext,
|
||||
localNames = LocalNameGenerator(NameScope.EmptyScope)
|
||||
|
||||
+25
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
|
||||
import org.jetbrains.kotlin.backend.common.ir.isSuspend
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsStatementOrigins
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
@@ -480,3 +482,25 @@ object JsAstUtils {
|
||||
return JsVars(JsVars.JsVar(name, expr))
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <T : JsNode> T.withSource(node: IrElement, context: JsGenerationContext): T {
|
||||
addSourceInfoIfNeed(node, context)
|
||||
return this
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun <T : JsNode> T.addSourceInfoIfNeed(node: IrElement, context: JsGenerationContext) {
|
||||
if (!context.staticContext.genSourcemaps) return
|
||||
|
||||
if (node.startOffset == UNDEFINED_OFFSET || node.endOffset == UNDEFINED_OFFSET) return
|
||||
|
||||
val fileEntry = context.currentFile?.fileEntry ?: return
|
||||
|
||||
val path = fileEntry.name
|
||||
val startLine = fileEntry.getLineNumber(node.startOffset)
|
||||
val startColumn = fileEntry.getColumnNumber(node.startOffset)
|
||||
|
||||
// TODO maybe it's better to fix in JsExpressionStatement
|
||||
val locationTarget = if (this is JsExpressionStatement) this.expression else this
|
||||
locationTarget.source = JsLocation(path, startLine, startColumn)
|
||||
}
|
||||
|
||||
+15
-2
@@ -1,14 +1,16 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.ir.backend.js.utils
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.isSuspend
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsName
|
||||
@@ -24,12 +26,23 @@ val emptyScope: JsScope
|
||||
}
|
||||
|
||||
class JsGenerationContext(
|
||||
val currentFile: IrFile?,
|
||||
val currentFunction: IrFunction?,
|
||||
val staticContext: JsStaticContext,
|
||||
val localNames: LocalNameGenerator? = null
|
||||
): IrNamer by staticContext {
|
||||
fun newFile(file: IrFile? = null, func: IrFunction? = null, localNames: LocalNameGenerator? = null): JsGenerationContext {
|
||||
return JsGenerationContext(
|
||||
currentFile = file,
|
||||
currentFunction = func,
|
||||
staticContext = staticContext,
|
||||
localNames = localNames,
|
||||
)
|
||||
}
|
||||
|
||||
fun newDeclaration(func: IrFunction? = null, localNames: LocalNameGenerator? = null): JsGenerationContext {
|
||||
return JsGenerationContext(
|
||||
currentFile = currentFile,
|
||||
currentFunction = func,
|
||||
staticContext = staticContext,
|
||||
localNames = localNames,
|
||||
@@ -66,4 +79,4 @@ class JsGenerationContext(
|
||||
}
|
||||
|
||||
fun checkIfJsCode(symbol: IrFunctionSymbol): Boolean = symbol == staticContext.backendContext.intrinsics.jsCode
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIntrinsicTransfo
|
||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIrClassModel
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
|
||||
|
||||
class JsStaticContext(
|
||||
@@ -22,4 +23,6 @@ class JsStaticContext(
|
||||
val coroutineImplDeclaration = backendContext.ir.symbols.coroutineImpl.owner
|
||||
|
||||
val initializerBlock = JsGlobalBlock()
|
||||
}
|
||||
|
||||
val genSourcemaps = backendContext.configuration.getBoolean(JSConfigurationKeys.SOURCE_MAP)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user