From 5a3efc1a98ed29434e02ec6cb64cecf09d00a764 Mon Sep 17 00:00:00 2001 From: Zalim Bashorov Date: Thu, 1 Jul 2021 21:24:26 +0300 Subject: [PATCH] [JS IR] Fill source info in codegen #KT-46551 In Progress --- .../IrElementToJsExpressionTransformer.kt | 42 +++++++++---------- .../IrElementToJsStatementTransformer.kt | 26 ++++++------ .../irToJs/IrFileToJsTransformer.kt | 6 +-- .../irToJs/IrModuleToJsTransformer.kt | 1 + .../js/transformers/irToJs/jsAstUtils.kt | 26 +++++++++++- .../backend/js/utils/JsGenerationContext.kt | 17 +++++++- .../ir/backend/js/utils/JsStaticContext.kt | 7 +++- 7 files changed, 84 insertions(+), 41 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt index 23b11138606..9890b348be5 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt @@ -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 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 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 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 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) = diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsStatementTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsStatementTransformer.kt index 4b5563f247c..91f48629289 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsStatementTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsStatementTransformer.kt @@ -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 JsStatement): JsStatement { @@ -62,20 +62,21 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer 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 { 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 T.withSource(node: IrElement, context: JsGenerationContext): T { + addSourceInfoIfNeed(node, context) + return this +} + +@Suppress("NOTHING_TO_INLINE") +private inline fun 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) +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt index 0ce3066d03f..5adb9cdee7b 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt @@ -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 -} \ No newline at end of file +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt index b4bc41721cc..e854a10efcf 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt @@ -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() -} \ No newline at end of file + + val genSourcemaps = backendContext.configuration.getBoolean(JSConfigurationKeys.SOURCE_MAP) +}