[JS] J2K for SourceMapBuilderConsumer

This commit is contained in:
Sergej Jaskiewicz
2022-06-16 23:42:28 +03:00
committed by Space
parent 9f5f5bcab2
commit 54c2839a7f
@@ -2,124 +2,92 @@
* Copyright 2010-2021 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. * 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.js.sourceMap
package org.jetbrains.kotlin.js.sourceMap; import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.js.backend.SourceLocationConsumer
import org.jetbrains.kotlin.js.backend.ast.JsLocationWithSource
import org.jetbrains.kotlin.js.backend.ast.JsNode
import org.jetbrains.kotlin.resolve.calls.util.isFakePsiElement
import org.jetbrains.kotlin.utils.addToStdlib.popLast
import java.io.*
import java.nio.charset.StandardCharsets
import com.intellij.psi.PsiElement; class SourceMapBuilderConsumer(
import com.intellij.psi.PsiFile; private val sourceBaseDir: File,
import org.jetbrains.annotations.NotNull; private val mappingConsumer: SourceMapMappingConsumer,
import org.jetbrains.annotations.Nullable; private val pathResolver: SourceFilePathResolver,
import org.jetbrains.kotlin.js.backend.SourceLocationConsumer; private val provideCurrentModuleContent: Boolean,
import org.jetbrains.kotlin.js.backend.ast.JsLocation; private val provideExternalModuleContent: Boolean
import org.jetbrains.kotlin.js.backend.ast.JsLocationWithSource; ) : SourceLocationConsumer {
import org.jetbrains.kotlin.resolve.calls.util.CallUtilKt;
import java.io.*; private val sourceStack = mutableListOf<Any?>()
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
public class SourceMapBuilderConsumer implements SourceLocationConsumer { override fun newLine() {
@NotNull mappingConsumer.newLine()
private final File sourceBaseDir;
@NotNull
private final SourceMapMappingConsumer mappingConsumer;
@NotNull
private final SourceFilePathResolver pathResolver;
private final boolean provideCurrentModuleContent;
private final boolean provideExternalModuleContent;
@NotNull
private final List<Object> sourceStack = new ArrayList<>();
public SourceMapBuilderConsumer(
@NotNull File sourceBaseDir,
@NotNull SourceMapMappingConsumer mappingConsumer,
@NotNull SourceFilePathResolver pathResolver,
boolean provideCurrentModuleContent, boolean provideExternalModuleContent
) {
this.sourceBaseDir = sourceBaseDir;
this.mappingConsumer = mappingConsumer;
this.pathResolver = pathResolver;
this.provideCurrentModuleContent = provideCurrentModuleContent;
this.provideExternalModuleContent = provideExternalModuleContent;
} }
@Override override fun pushSourceInfo(info: Any?) {
public void newLine() { sourceStack.add(info)
mappingConsumer.newLine(); addMapping(info)
} }
@Override override fun popSourceInfo() {
public void pushSourceInfo(@Nullable Object info) { sourceStack.popLast()
sourceStack.add(info); addMapping(sourceStack.lastOrNull())
addMapping(info);
} }
@Override private fun addMapping(sourceInfo: Any?) {
public void popSourceInfo() { when (sourceInfo) {
sourceStack.remove(sourceStack.size() - 1); null -> mappingConsumer.addEmptyMapping()
Object sourceInfo = !sourceStack.isEmpty() ? sourceStack.get(sourceStack.size() - 1) : null; is PsiElement -> {
addMapping(sourceInfo); // This branch is only taken on the legacy backend
} if (sourceInfo.isFakePsiElement) return
private void addMapping(@Nullable Object sourceInfo) {
if (sourceInfo == null) {
mappingConsumer.addEmptyMapping();
}
if (sourceInfo instanceof PsiElement) {
PsiElement element = (PsiElement) sourceInfo;
if (CallUtilKt.isFakePsiElement(element)) return;
try {
JsLocation location = PsiUtils.extractLocationFromPsi(element, pathResolver);
PsiFile psiFile = element.getContainingFile();
File file = new File(psiFile.getViewProvider().getVirtualFile().getPath());
Supplier<Reader> contentSupplier;
if (provideCurrentModuleContent) {
contentSupplier = () -> {
try {
return new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));
}
catch (IOException e) {
return null;
}
};
}
else {
contentSupplier = () -> null;
}
mappingConsumer.addMapping(location.getFile(), null, contentSupplier, location.getStartLine(), location.getStartChar());
}
catch (IOException e) {
throw new RuntimeException("IO error occurred generating source maps", e);
}
}
else if (sourceInfo instanceof JsLocationWithSource) {
JsLocationWithSource location = (JsLocationWithSource) sourceInfo;
Supplier<Reader> contentSupplier = provideExternalModuleContent ? location.getSourceProvider()::invoke : () -> null;
String path;
File absFile = new File(location.getFile()).isAbsolute() ?
new File(location.getFile()) :
new File(sourceBaseDir, location.getFile());
if (absFile.isAbsolute()) {
try { try {
path = pathResolver.getPathRelativeToSourceRoots(absFile); val (sourceFilePath, startLine, startChar) = PsiUtils.extractLocationFromPsi(sourceInfo, pathResolver)
} val psiFile = sourceInfo.containingFile
catch (IOException e) { val file = File(psiFile.viewProvider.virtualFile.path)
path = location.getFile(); val contentSupplier = if (provideCurrentModuleContent) {
{
try {
InputStreamReader(FileInputStream(file), StandardCharsets.UTF_8)
} catch (e: IOException) {
null
}
}
} else {
{ null }
}
mappingConsumer.addMapping(sourceFilePath, null, contentSupplier, startLine, startChar)
} catch (e: IOException) {
throw RuntimeException("IO error occurred generating source maps", e)
} }
} }
else { is JsLocationWithSource -> {
path = location.getFile(); val contentSupplier = if (provideExternalModuleContent) sourceInfo.sourceProvider else {
{ null }
}
val sourceFile = File(sourceInfo.file)
val absFile = if (sourceFile.isAbsolute) sourceFile else File(sourceBaseDir, sourceInfo.file)
val path = if (absFile.isAbsolute) {
try {
pathResolver.getPathRelativeToSourceRoots(absFile)
} catch (e: IOException) {
sourceInfo.file
}
} else {
sourceInfo.file
}
mappingConsumer.addMapping(
path,
sourceInfo.identityObject,
contentSupplier,
sourceInfo.startLine,
sourceInfo.startChar
)
} }
mappingConsumer.addMapping(path, location.getIdentityObject(), contentSupplier, is JsNode -> { /* Can occur on legacy BE, not sure if it's a bug or not. */ }
location.getStartLine(), location.getStartChar()); else -> error("Unexpected sourceInfo: $sourceInfo")
} }
} }
} }