[JS] Extract sourcemap generating related files to a separate module
It's required to reuse the same infrastructure in the new backend.
This commit is contained in:
committed by
TeamCityServer
parent
a63c179227
commit
a908e5576d
@@ -0,0 +1,17 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":js:js.ast"))
|
||||
compileOnly(project(":js:js.parser")) // TODO remove, required for JSON AST
|
||||
compileOnly(project(":js:js.frontend")) // TODO remove
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
compileOnly(intellijDep()) { includeJars("trove4j") }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" {}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.js.sourceMap;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsLocation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public final class PsiUtils {
|
||||
|
||||
private PsiUtils() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsLocation extractLocationFromPsi(@NotNull PsiElement element, @NotNull SourceFilePathResolver pathResolver)
|
||||
throws IOException {
|
||||
PsiFile psiFile = element.getContainingFile();
|
||||
int offset = element.getNode().getStartOffset();
|
||||
Document document = psiFile.getViewProvider().getDocument();
|
||||
assert document != null;
|
||||
int sourceLine = document.getLineNumber(offset);
|
||||
int sourceColumn = offset - document.getLineStartOffset(sourceLine);
|
||||
|
||||
File file = new File(psiFile.getViewProvider().getVirtualFile().getPath());
|
||||
return new JsLocation(pathResolver.getPathRelativeToSourceRoots(file), sourceLine, sourceColumn);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.js.sourceMap
|
||||
|
||||
import java.io.File
|
||||
|
||||
class RelativePathCalculator(baseDir: File) {
|
||||
private val baseDirPath = generateSequence(baseDir.canonicalFile) { it.parentFile }.toList().asReversed()
|
||||
|
||||
fun calculateRelativePathTo(file: File): String? {
|
||||
val path = generateSequence(file.canonicalFile) { it.parentFile }.toList().asReversed()
|
||||
if (baseDirPath[0] != path[0]) return null
|
||||
|
||||
val commonLength = baseDirPath.zip(path).takeWhile { (first, second) -> first == second }.size
|
||||
|
||||
val sb = StringBuilder()
|
||||
for (i in commonLength until baseDirPath.size) {
|
||||
sb.append("../")
|
||||
}
|
||||
for (i in commonLength until path.size) {
|
||||
sb.append(path[i].name).append('/')
|
||||
}
|
||||
sb.setLength(sb.lastIndex)
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.js.sourceMap;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys;
|
||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SourceFilePathResolver {
|
||||
@NotNull
|
||||
private final Set<File> sourceRoots;
|
||||
|
||||
@Nullable
|
||||
private final RelativePathCalculator outputDirPathResolver;
|
||||
|
||||
@NotNull
|
||||
private final Map<File, String> cache = new HashMap<>();
|
||||
|
||||
public SourceFilePathResolver(@NotNull List<File> sourceRoots) {
|
||||
this(sourceRoots, null);
|
||||
}
|
||||
|
||||
public SourceFilePathResolver(@NotNull List<File> sourceRoots, @Nullable File outputDir) {
|
||||
this.sourceRoots = new HashSet<>();
|
||||
for (File sourceRoot : sourceRoots) {
|
||||
this.sourceRoots.add(sourceRoot.getAbsoluteFile());
|
||||
}
|
||||
|
||||
outputDirPathResolver = outputDir != null ? new RelativePathCalculator(outputDir) : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPathRelativeToSourceRoots(@NotNull File file) throws IOException {
|
||||
String path = cache.get(file);
|
||||
if (path == null) {
|
||||
path = calculatePathRelativeToSourceRoots(file);
|
||||
cache.put(file, path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String calculatePathRelativeToSourceRoots(@NotNull File file) throws IOException {
|
||||
String pathRelativeToOutput = calculatePathRelativeToOutput(file);
|
||||
if (pathRelativeToOutput != null) return pathRelativeToOutput;
|
||||
|
||||
List<String> parts = new ArrayList<>();
|
||||
File currentFile = file.getCanonicalFile();
|
||||
|
||||
while (currentFile != null) {
|
||||
if (sourceRoots.contains(currentFile)) {
|
||||
if (parts.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
Collections.reverse(parts);
|
||||
return StringUtil.join(parts, File.separator);
|
||||
}
|
||||
parts.add(currentFile.getName());
|
||||
currentFile = currentFile.getParentFile();
|
||||
}
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String calculatePathRelativeToOutput(@NotNull File file) {
|
||||
return outputDirPathResolver != null ? outputDirPathResolver.calculateRelativePathTo(file) : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static SourceFilePathResolver create(@NotNull JsConfig config) {
|
||||
List<File> sourceRoots = config.getSourceMapRoots().stream().map(File::new).collect(Collectors.toList());
|
||||
File outputDir = null;
|
||||
if (config.shouldGenerateRelativePathsInSourceMap()) {
|
||||
outputDir = config.getConfiguration().get(JSConfigurationKeys.OUTPUT_DIR);
|
||||
}
|
||||
return new SourceFilePathResolver(sourceRoots, outputDir);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* 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.js.sourceMap;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import kotlin.io.TextStreamsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.js.parser.sourcemaps.*;
|
||||
import org.jetbrains.kotlin.js.util.TextOutput;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SourceMap3Builder implements SourceMapBuilder {
|
||||
private final StringBuilder out = new StringBuilder(8192);
|
||||
private final File generatedFile;
|
||||
private final TextOutput textOutput;
|
||||
private final String pathPrefix;
|
||||
|
||||
private final TObjectIntHashMap<SourceKey> sources = new TObjectIntHashMap<SourceKey>() {
|
||||
@Override
|
||||
public int get(SourceKey key) {
|
||||
int index = index(key);
|
||||
return index < 0 ? -1 : _values[index];
|
||||
}
|
||||
};
|
||||
|
||||
private final List<String> orderedSources = new ArrayList<>();
|
||||
private final List<Supplier<Reader>> orderedSourceContentSuppliers = new ArrayList<>();
|
||||
|
||||
private int previousGeneratedColumn = -1;
|
||||
private int previousSourceIndex;
|
||||
private int previousSourceLine;
|
||||
private int previousSourceColumn;
|
||||
private int previousMappingOffset;
|
||||
private int previousPreviousSourceIndex;
|
||||
private int previousPreviousSourceLine;
|
||||
private int previousPreviousSourceColumn;
|
||||
private boolean currentMappingIsEmpty = true;
|
||||
|
||||
public SourceMap3Builder(File generatedFile, TextOutput textOutput, String pathPrefix) {
|
||||
this.generatedFile = generatedFile;
|
||||
this.textOutput = textOutput;
|
||||
this.pathPrefix = pathPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getOutFile() {
|
||||
return new File(generatedFile.getParentFile(), generatedFile.getName() + ".map");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String build() {
|
||||
@SuppressWarnings("unchecked")
|
||||
JsonObject json = new JsonObject();
|
||||
json.getProperties().put("version", new JsonNumber(3));
|
||||
json.getProperties().put("file", new JsonString(generatedFile.getName()));
|
||||
appendSources(json);
|
||||
appendSourcesContent(json);
|
||||
json.getProperties().put("names", new JsonArray());
|
||||
json.getProperties().put("mappings", new JsonString(out.toString()));
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
private void appendSources(JsonObject json) {
|
||||
JsonArray array = new JsonArray();
|
||||
for (String source : orderedSources) {
|
||||
array.getElements().add(new JsonString(pathPrefix + source));
|
||||
}
|
||||
json.getProperties().put("sources", array);
|
||||
}
|
||||
|
||||
private void appendSourcesContent(JsonObject json) {
|
||||
JsonArray array = new JsonArray();
|
||||
for (Supplier<Reader> contentSupplier : orderedSourceContentSuppliers) {
|
||||
Reader reader = contentSupplier.get();
|
||||
array.getElements().add(reader != null ? new JsonString(TextStreamsKt.readText(reader)) : JsonNull.INSTANCE);
|
||||
}
|
||||
json.getProperties().put("sourcesContent", array);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newLine() {
|
||||
out.append(';');
|
||||
previousGeneratedColumn = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skipLinesAtBeginning(int count) {
|
||||
out.insert(0, StringUtil.repeatSymbol(';', count));
|
||||
}
|
||||
|
||||
private int getSourceIndex(String source, Object identityObject, Supplier<Reader> contentSupplier) {
|
||||
SourceKey key = new SourceKey(source, identityObject);
|
||||
int sourceIndex = sources.get(key);
|
||||
if (sourceIndex == -1) {
|
||||
sourceIndex = orderedSources.size();
|
||||
sources.put(key, sourceIndex);
|
||||
orderedSources.add(source);
|
||||
orderedSourceContentSuppliers.add(contentSupplier);
|
||||
}
|
||||
|
||||
return sourceIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMapping(
|
||||
@NotNull String source, @Nullable Object identityObject, @NotNull Supplier<Reader> sourceContent,
|
||||
int sourceLine, int sourceColumn
|
||||
) {
|
||||
source = source.replace(File.separatorChar, '/');
|
||||
int sourceIndex = getSourceIndex(source, identityObject, sourceContent);
|
||||
|
||||
if (!currentMappingIsEmpty && previousSourceIndex == sourceIndex && previousSourceLine == sourceLine &&
|
||||
previousSourceColumn == sourceColumn) {
|
||||
return;
|
||||
}
|
||||
|
||||
startMapping();
|
||||
|
||||
Base64VLQ.encode(out, sourceIndex - previousSourceIndex);
|
||||
previousSourceIndex = sourceIndex;
|
||||
|
||||
Base64VLQ.encode(out, sourceLine - previousSourceLine);
|
||||
previousSourceLine = sourceLine;
|
||||
|
||||
Base64VLQ.encode(out, sourceColumn - previousSourceColumn);
|
||||
previousSourceColumn = sourceColumn;
|
||||
|
||||
currentMappingIsEmpty = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEmptyMapping() {
|
||||
if (!currentMappingIsEmpty) {
|
||||
startMapping();
|
||||
currentMappingIsEmpty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void startMapping() {
|
||||
boolean newGroupStarted = previousGeneratedColumn == -1;
|
||||
if (newGroupStarted) {
|
||||
previousGeneratedColumn = 0;
|
||||
}
|
||||
|
||||
int columnDiff = textOutput.getColumn() - previousGeneratedColumn;
|
||||
if (!newGroupStarted) {
|
||||
out.append(',');
|
||||
}
|
||||
|
||||
if (columnDiff > 0 || newGroupStarted) {
|
||||
Base64VLQ.encode(out, columnDiff);
|
||||
previousGeneratedColumn = textOutput.getColumn();
|
||||
|
||||
previousMappingOffset = out.length();
|
||||
previousPreviousSourceIndex = previousSourceIndex;
|
||||
previousPreviousSourceLine = previousSourceLine;
|
||||
previousPreviousSourceColumn = previousSourceColumn;
|
||||
}
|
||||
else {
|
||||
out.setLength(previousMappingOffset);
|
||||
previousSourceIndex = previousPreviousSourceIndex;
|
||||
previousSourceLine = previousPreviousSourceLine;
|
||||
previousSourceColumn = previousPreviousSourceColumn;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLink() {
|
||||
textOutput.print("\n//# sourceMappingURL=");
|
||||
textOutput.print(generatedFile.getName());
|
||||
textOutput.print(".map\n");
|
||||
}
|
||||
|
||||
private static final class Base64VLQ {
|
||||
// A Base64 VLQ digit can represent 5 bits, so it is base-32.
|
||||
private static final int VLQ_BASE_SHIFT = 5;
|
||||
private static final int VLQ_BASE = 1 << VLQ_BASE_SHIFT;
|
||||
|
||||
// A mask of bits for a VLQ digit (11111), 31 decimal.
|
||||
private static final int VLQ_BASE_MASK = VLQ_BASE - 1;
|
||||
|
||||
// The continuation bit is the 6th bit.
|
||||
private static final int VLQ_CONTINUATION_BIT = VLQ_BASE;
|
||||
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private static final char[] BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();
|
||||
|
||||
private Base64VLQ() {
|
||||
}
|
||||
|
||||
private static int toVLQSigned(int value) {
|
||||
return value < 0 ? ((-value) << 1) + 1 : value << 1;
|
||||
}
|
||||
|
||||
public static void encode(StringBuilder out, int value) {
|
||||
value = toVLQSigned(value);
|
||||
do {
|
||||
int digit = value & VLQ_BASE_MASK;
|
||||
value >>>= VLQ_BASE_SHIFT;
|
||||
if (value > 0) {
|
||||
digit |= VLQ_CONTINUATION_BIT;
|
||||
}
|
||||
out.append(BASE64_MAP[digit]);
|
||||
}
|
||||
while (value > 0);
|
||||
}
|
||||
}
|
||||
|
||||
static final class SourceKey {
|
||||
private final String sourcePath;
|
||||
private final Object identityKey;
|
||||
|
||||
SourceKey(String sourcePath, Object identityKey) {
|
||||
this.sourcePath = sourcePath;
|
||||
this.identityKey = identityKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof SourceKey)) return false;
|
||||
|
||||
SourceKey key = (SourceKey) o;
|
||||
|
||||
if (!sourcePath.equals(key.sourcePath)) return false;
|
||||
if (identityKey != null ? !identityKey.equals(key.identityKey) : key.identityKey != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = sourcePath.hashCode();
|
||||
result = 31 * result + (identityKey != null ? identityKey.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.js.sourceMap;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface SourceMapBuilder extends SourceMapMappingConsumer {
|
||||
void skipLinesAtBeginning(int count);
|
||||
|
||||
void addLink();
|
||||
|
||||
File getOutFile();
|
||||
|
||||
String build();
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.js.sourceMap;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.js.backend.SourceLocationConsumer;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsLocation;
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsLocationWithSource;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SourceMapBuilderConsumer implements SourceLocationConsumer {
|
||||
@NotNull
|
||||
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
|
||||
public void newLine() {
|
||||
mappingConsumer.newLine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pushSourceInfo(@Nullable Object info) {
|
||||
sourceStack.add(info);
|
||||
addMapping(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popSourceInfo() {
|
||||
sourceStack.remove(sourceStack.size() - 1);
|
||||
Object sourceInfo = !sourceStack.isEmpty() ? sourceStack.get(sourceStack.size() - 1) : null;
|
||||
addMapping(sourceInfo);
|
||||
}
|
||||
|
||||
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 {
|
||||
path = pathResolver.getPathRelativeToSourceRoots(absFile);
|
||||
}
|
||||
catch (IOException e) {
|
||||
path = location.getFile();
|
||||
}
|
||||
}
|
||||
else {
|
||||
path = location.getFile();
|
||||
}
|
||||
mappingConsumer.addMapping(path, location.getIdentityObject(), contentSupplier,
|
||||
location.getStartLine(), location.getStartChar());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.js.sourceMap;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface SourceMapMappingConsumer {
|
||||
void newLine();
|
||||
|
||||
void addMapping(
|
||||
@NotNull String source, @Nullable Object sourceIdentity, @NotNull Supplier<Reader> sourceSupplier,
|
||||
int sourceLine, int sourceColumn
|
||||
);
|
||||
|
||||
void addEmptyMapping();
|
||||
}
|
||||
Reference in New Issue
Block a user