Refactor generator of JS source map
- refactor pipeline for generation of source map - generate "empty" mappings for nodes that impossible to map to something reasonable - generate more accurate locations in source maps for specific JS AST nodes - for binary operation nodes parser now returns location of binary operator tokens instead of location of first operand - change completely how source map remapper works
This commit is contained in:
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.js.JavaScript
|
||||
import org.jetbrains.kotlin.js.backend.JsToStringGenerationVisitor
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.config.EcmaVersion
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
@@ -42,7 +43,6 @@ import org.jetbrains.kotlin.js.dce.InputFile
|
||||
import org.jetbrains.kotlin.js.facade.*
|
||||
import org.jetbrains.kotlin.js.parser.parse
|
||||
import org.jetbrains.kotlin.js.parser.sourcemaps.*
|
||||
import org.jetbrains.kotlin.js.sourceMap.JsSourceGenerationVisitor
|
||||
import org.jetbrains.kotlin.js.sourceMap.SourceFilePathResolver
|
||||
import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder
|
||||
import org.jetbrains.kotlin.js.test.utils.*
|
||||
@@ -430,8 +430,8 @@ abstract class BasicBoxTest(
|
||||
|
||||
val output = TextOutputImpl()
|
||||
val pathResolver = SourceFilePathResolver(mutableListOf(File(".")))
|
||||
val sourceMapBuilder = SourceMap3Builder(outputFile, output, "", SourceMapBuilderConsumer(pathResolver, false, false))
|
||||
generatedProgram.accept(JsSourceGenerationVisitor(output, sourceMapBuilder))
|
||||
val sourceMapBuilder = SourceMap3Builder(outputFile, output, "")
|
||||
generatedProgram.accept(JsToStringGenerationVisitor(output, SourceMapBuilderConsumer(sourceMapBuilder, pathResolver, false, false)))
|
||||
val code = output.toString()
|
||||
val generatedSourceMap = sourceMapBuilder.build()
|
||||
|
||||
@@ -446,7 +446,7 @@ abstract class BasicBoxTest(
|
||||
is SourceMapError -> error("Could not parse source map: ${sourceMapParseResult.message}")
|
||||
}
|
||||
|
||||
val remapper = SourceMapLocationRemapper(mapOf(outputFile.path to sourceMap))
|
||||
val remapper = SourceMapLocationRemapper(sourceMap)
|
||||
remapper.remap(parsedProgram)
|
||||
|
||||
val codeWithRemappedLines = parsedProgram.toStringWithLineNumbers()
|
||||
|
||||
@@ -16,15 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.test.optimizer
|
||||
|
||||
|
||||
import com.google.gwt.dev.js.rhino.CodePosition
|
||||
import com.google.gwt.dev.js.rhino.ErrorReporter
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.js.backend.JsToStringGenerationVisitor
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
||||
import org.jetbrains.kotlin.js.inline.clean.FunctionPostProcessor
|
||||
import org.jetbrains.kotlin.js.parser.parse
|
||||
import org.jetbrains.kotlin.js.sourceMap.JsSourceGenerationVisitor
|
||||
import org.jetbrains.kotlin.js.test.BasicBoxTest
|
||||
import org.jetbrains.kotlin.js.test.createScriptEngine
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
@@ -120,7 +119,7 @@ abstract class BasicOptimizerTest(private var basePath: String) {
|
||||
|
||||
private fun astToString(ast: List<JsStatement>): String {
|
||||
val output = TextOutputImpl()
|
||||
val visitor = JsSourceGenerationVisitor(output, null)
|
||||
val visitor = JsToStringGenerationVisitor(output)
|
||||
for (stmt in ast) {
|
||||
stmt.accept(visitor)
|
||||
}
|
||||
|
||||
+8
-52
@@ -16,64 +16,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.test.utils
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
|
||||
class AmbiguousAstSourcePropagation : RecursiveJsVisitor() {
|
||||
private var sourceDefined = false
|
||||
|
||||
override fun visitConditional(x: JsConditional) = acceptAll(x, x.testExpression, x.thenExpression, x.elseExpression)
|
||||
|
||||
override fun visitBinaryExpression(x: JsBinaryOperation) = acceptAll(x, x.arg1, x.arg2)
|
||||
|
||||
override fun visitPostfixOperation(x: JsPostfixOperation) = acceptAll(x, x.arg)
|
||||
|
||||
override fun visitArrayAccess(x: JsArrayAccess) = acceptAll(x, x.arrayExpression, x.indexExpression)
|
||||
|
||||
override fun visitPropertyInitializer(x: JsPropertyInitializer) = acceptAll(x, x.labelExpr, x.valueExpr)
|
||||
|
||||
override fun visitInvocation(invocation: JsInvocation) = acceptAll(invocation, invocation.qualifier,
|
||||
*invocation.arguments.toTypedArray())
|
||||
|
||||
override fun visitNameRef(nameRef: JsNameRef) {
|
||||
val qualifier = nameRef.qualifier
|
||||
if (qualifier != null) {
|
||||
acceptAll(nameRef, qualifier)
|
||||
}
|
||||
else {
|
||||
super.visitNameRef(nameRef)
|
||||
}
|
||||
}
|
||||
private var lastSource: Any? = null
|
||||
|
||||
override fun visitElement(node: JsNode) {
|
||||
val old = sourceDefined
|
||||
propagate(node)
|
||||
val source = node.source
|
||||
if (source == null && node is JsExpression) {
|
||||
node.source = lastSource
|
||||
}
|
||||
|
||||
sourceDefined = false
|
||||
val oldLastSource = lastSource
|
||||
lastSource = node.source
|
||||
super.visitElement(node)
|
||||
sourceDefined = old
|
||||
}
|
||||
|
||||
private fun acceptAll(node: JsNode, first: JsNode, vararg remaining: JsNode) {
|
||||
val old = sourceDefined
|
||||
propagate(node)
|
||||
|
||||
accept(first)
|
||||
|
||||
sourceDefined = false
|
||||
remaining.forEach { accept(it) }
|
||||
sourceDefined = old
|
||||
}
|
||||
|
||||
private fun propagate(node: JsNode) {
|
||||
if (!sourceDefined) {
|
||||
val source = node.source
|
||||
if (source is JsLocationWithSource || source is PsiElement) {
|
||||
sourceDefined = true
|
||||
}
|
||||
}
|
||||
else if (node !is JsExpressionStatement) {
|
||||
node.source = null
|
||||
}
|
||||
lastSource = oldLastSource
|
||||
}
|
||||
}
|
||||
@@ -87,10 +87,9 @@ class LineCollector : RecursiveJsVisitor() {
|
||||
|
||||
override fun visitDoWhile(x: JsDoWhile) {
|
||||
withStatement(x) {
|
||||
handleNodeLocation(x)
|
||||
x.body.accept(this)
|
||||
x.condition.accept(this)
|
||||
}
|
||||
x.body.accept(this)
|
||||
}
|
||||
|
||||
override fun visitFor(x: JsFor) {
|
||||
@@ -130,8 +129,8 @@ class LineCollector : RecursiveJsVisitor() {
|
||||
override fun visit(x: JsSwitch) {
|
||||
withStatement(x) {
|
||||
x.expression.accept(this)
|
||||
x.cases.forEach { accept(it) }
|
||||
}
|
||||
x.cases.forEach { accept(it) }
|
||||
}
|
||||
|
||||
override fun visitThrow(x: JsThrow) {
|
||||
@@ -140,6 +139,14 @@ class LineCollector : RecursiveJsVisitor() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitTry(x: JsTry) {
|
||||
withStatement(x) {
|
||||
x.tryBlock.acceptChildren(this)
|
||||
x.catches?.forEach { accept(it) }
|
||||
x.finallyBlock?.acceptChildren(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun withStatement(statement: JsStatement, action: () -> Unit) {
|
||||
val oldStatement = currentStatement
|
||||
currentStatement = statement
|
||||
|
||||
@@ -73,6 +73,11 @@ class LineOutputToStringVisitor(output: TextOutput, val lineCollector: LineColle
|
||||
super.visitReturn(x)
|
||||
}
|
||||
|
||||
override fun visitTry(x: JsTry) {
|
||||
printLineNumbers(x)
|
||||
super.visitTry(x)
|
||||
}
|
||||
|
||||
override fun visit(x: JsSwitch) {
|
||||
printLineNumbers(x)
|
||||
super.visit(x)
|
||||
|
||||
Reference in New Issue
Block a user