JS: generate paths in source maps relative to .map file location
See KT-19818
This commit is contained in:
@@ -251,8 +251,20 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File outputDir = outputFile.getParentFile();
|
||||||
|
if (outputDir == null) {
|
||||||
|
outputDir = outputFile.getAbsoluteFile().getParentFile();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
config.getConfiguration().put(JSConfigurationKeys.OUTPUT_DIR, outputDir.getCanonicalFile());
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
messageCollector.report(ERROR, "Could not resolve output directory", null);
|
||||||
|
return ExitCode.COMPILATION_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.getConfiguration().getBoolean(JSConfigurationKeys.SOURCE_MAP)) {
|
if (config.getConfiguration().getBoolean(JSConfigurationKeys.SOURCE_MAP)) {
|
||||||
checkDuplicateSourceFileNames(messageCollector, sourcesFiles, config.getSourceMapRoots());
|
checkDuplicateSourceFileNames(messageCollector, sourcesFiles, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainCallParameters mainCallParameters = createMainCallParameters(arguments.getMain());
|
MainCallParameters mainCallParameters = createMainCallParameters(arguments.getMain());
|
||||||
@@ -280,11 +292,6 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
|||||||
return ExitCode.COMPILATION_ERROR;
|
return ExitCode.COMPILATION_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
File outputDir = outputFile.getParentFile();
|
|
||||||
if (outputDir == null) {
|
|
||||||
outputDir = outputFile.getAbsoluteFile().getParentFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||||
|
|
||||||
OutputUtilsKt.writeAll(outputFiles, outputDir, messageCollector,
|
OutputUtilsKt.writeAll(outputFiles, outputDir, messageCollector,
|
||||||
@@ -296,12 +303,11 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
|||||||
private static void checkDuplicateSourceFileNames(
|
private static void checkDuplicateSourceFileNames(
|
||||||
@NotNull MessageCollector log,
|
@NotNull MessageCollector log,
|
||||||
@NotNull List<KtFile> sourceFiles,
|
@NotNull List<KtFile> sourceFiles,
|
||||||
@NotNull List<String> sourceRoots
|
@NotNull JsConfig config
|
||||||
) {
|
) {
|
||||||
if (sourceRoots.isEmpty()) return;
|
if (config.getSourceMapRoots().isEmpty()) return;
|
||||||
|
|
||||||
List<File> sourceRootFiles = sourceRoots.stream().map(File::new).collect(Collectors.toList());
|
SourceFilePathResolver pathResolver = SourceFilePathResolver.create(config);
|
||||||
SourceFilePathResolver pathResolver = new SourceFilePathResolver(sourceRootFiles);
|
|
||||||
Map<String, String> pathMap = new HashMap<>();
|
Map<String, String> pathMap = new HashMap<>();
|
||||||
Set<String> duplicatePaths = new HashSet<>();
|
Set<String> duplicatePaths = new HashSet<>();
|
||||||
|
|
||||||
@@ -357,11 +363,15 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
|||||||
configuration.put(JSConfigurationKeys.SOURCE_MAP_PREFIX, arguments.getSourceMapPrefix());
|
configuration.put(JSConfigurationKeys.SOURCE_MAP_PREFIX, arguments.getSourceMapPrefix());
|
||||||
}
|
}
|
||||||
|
|
||||||
String sourceMapSourceRoots = arguments.getSourceMapBaseDirs() != null ?
|
String sourceMapSourceRoots = arguments.getSourceMapBaseDirs();
|
||||||
arguments.getSourceMapBaseDirs() :
|
if (sourceMapSourceRoots == null && StringUtil.isNotEmpty(arguments.getSourceMapPrefix())) {
|
||||||
calculateSourceMapSourceRoot(messageCollector, arguments);
|
sourceMapSourceRoots = calculateSourceMapSourceRoot(messageCollector, arguments);
|
||||||
List<String> sourceMapSourceRootList = StringUtil.split(sourceMapSourceRoots, File.pathSeparator);
|
}
|
||||||
configuration.put(JSConfigurationKeys.SOURCE_MAP_SOURCE_ROOTS, sourceMapSourceRootList);
|
|
||||||
|
if (sourceMapSourceRoots != null) {
|
||||||
|
List<String> sourceMapSourceRootList = StringUtil.split(sourceMapSourceRoots, File.pathSeparator);
|
||||||
|
configuration.put(JSConfigurationKeys.SOURCE_MAP_SOURCE_ROOTS, sourceMapSourceRootList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (arguments.getSourceMapPrefix() != null) {
|
if (arguments.getSourceMapPrefix() != null) {
|
||||||
|
|||||||
+2
@@ -1,5 +1,7 @@
|
|||||||
$TESTDATA_DIR$/sourceMap.kt
|
$TESTDATA_DIR$/sourceMap.kt
|
||||||
-no-stdlib
|
-no-stdlib
|
||||||
-source-map
|
-source-map
|
||||||
|
-source-map-prefix
|
||||||
|
./
|
||||||
-output
|
-output
|
||||||
$TEMP_DIR$/out.js
|
$TEMP_DIR$/out.js
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
// EXISTS: out.js
|
// EXISTS: out.js
|
||||||
// CONTAINS: out.js.map, "sourceMap.kt"
|
// CONTAINS: out.js.map, "./sourceMap.kt"
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
$TESTDATA_DIR$/sourceMap.kt
|
$TESTDATA_DIR$/sourceMap.kt
|
||||||
-no-stdlib
|
-no-stdlib
|
||||||
-source-map
|
-source-map
|
||||||
|
-source-map-prefix
|
||||||
|
./
|
||||||
-source-map-embed-sources
|
-source-map-embed-sources
|
||||||
always
|
always
|
||||||
-output
|
-output
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
// EXISTS: out.js
|
// EXISTS: out.js
|
||||||
// CONTAINS: out.js.map, "sourceMap.kt"
|
// CONTAINS: out.js.map, "./sourceMap.kt"
|
||||||
// CONTAINS: out.js.map, "var log = \"\"\n\nfun foo(x: String) {
|
// CONTAINS: out.js.map, "var log = \"\"\n\nfun foo(x: String) {
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
$TESTDATA_DIR$/sourceMapRelativeRoot/lib/src/lib.kt
|
||||||
|
-no-stdlib
|
||||||
|
-source-map
|
||||||
|
-meta-info
|
||||||
|
-output
|
||||||
|
$TESTDATA_DIR$/sourceMapRelativeRoot/lib/out/lib.js
|
||||||
|
---
|
||||||
|
$TESTDATA_DIR$/sourceMapRelativeRoot/main/src/main.kt
|
||||||
|
-no-stdlib
|
||||||
|
-libraries
|
||||||
|
$TESTDATA_DIR$/sourceMapRelativeRoot/lib/out/
|
||||||
|
-source-map
|
||||||
|
-output
|
||||||
|
$TESTDATA_DIR$/sourceMapRelativeRoot/main/out/main.js
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
OK
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// EXISTS: $TESTDATA_DIR$/sourceMapRelativeRoot/lib/out/lib.js
|
||||||
|
// EXISTS: $TESTDATA_DIR$/sourceMapRelativeRoot/main/out/main.js
|
||||||
|
// CONTAINS: $TESTDATA_DIR$/sourceMapRelativeRoot/lib/out/lib.js.map, "../src/lib.kt"
|
||||||
|
// CONTAINS: $TESTDATA_DIR$/sourceMapRelativeRoot/main/out/main.js.map, "../src/main.kt"
|
||||||
|
// CONTAINS: $TESTDATA_DIR$/sourceMapRelativeRoot/main/out/main.js.map, "../../lib/src/lib.kt"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
out
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun foo() = 23
|
||||||
|
|
||||||
|
fun bar() = 42
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
fun box() = foo() + bar()
|
||||||
@@ -2,5 +2,7 @@ $TESTDATA_DIR$/sourceMapRoot/foo/file1.kt
|
|||||||
$TESTDATA_DIR$/sourceMapRoot/bar/file2.kt
|
$TESTDATA_DIR$/sourceMapRoot/bar/file2.kt
|
||||||
-no-stdlib
|
-no-stdlib
|
||||||
-source-map
|
-source-map
|
||||||
|
-source-map-prefix
|
||||||
|
./
|
||||||
-output
|
-output
|
||||||
$TEMP_DIR$/out.js
|
$TEMP_DIR$/out.js
|
||||||
|
|||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
// EXISTS: out.js
|
// EXISTS: out.js
|
||||||
// CONTAINS: out.js.map, "foo/file1.kt"
|
// CONTAINS: out.js.map, "./foo/file1.kt"
|
||||||
// CONTAINS: out.js.map, "bar/file2.kt"
|
// CONTAINS: out.js.map, "./bar/file2.kt"
|
||||||
|
|||||||
@@ -43,19 +43,29 @@ import org.junit.Assert;
|
|||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
||||||
@NotNull
|
private static final String TESTDATA_DIR = "$TESTDATA_DIR$";
|
||||||
|
|
||||||
public static Pair<String, ExitCode> executeCompilerGrabOutput(@NotNull CLITool<?> compiler, @NotNull List<String> args) {
|
public static Pair<String, ExitCode> executeCompilerGrabOutput(@NotNull CLITool<?> compiler, @NotNull List<String> args) {
|
||||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||||
PrintStream origErr = System.err;
|
PrintStream origErr = System.err;
|
||||||
try {
|
try {
|
||||||
System.setErr(new PrintStream(bytes));
|
System.setErr(new PrintStream(bytes));
|
||||||
ExitCode exitCode = CLITool.doMainNoExit(compiler, ArrayUtil.toStringArray(args));
|
ExitCode exitCode;
|
||||||
|
int index = 0;
|
||||||
|
do {
|
||||||
|
int next = args.subList(index, args.size()).indexOf("---");
|
||||||
|
if (next == -1) {
|
||||||
|
next = args.size();
|
||||||
|
}
|
||||||
|
exitCode = CLITool.doMainNoExit(compiler, ArrayUtil.toStringArray(args.subList(index, next)));
|
||||||
|
if (exitCode != ExitCode.OK) break;
|
||||||
|
index = next + 1;
|
||||||
|
} while (index < args.size());
|
||||||
return new Pair<>(bytes.toString("utf-8"), exitCode);
|
return new Pair<>(bytes.toString("utf-8"), exitCode);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
@@ -70,8 +80,8 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
|||||||
public static String getNormalizedCompilerOutput(@NotNull String pureOutput, @NotNull ExitCode exitCode, @NotNull String testDataDir) {
|
public static String getNormalizedCompilerOutput(@NotNull String pureOutput, @NotNull ExitCode exitCode, @NotNull String testDataDir) {
|
||||||
String testDataAbsoluteDir = new File(testDataDir).getAbsolutePath();
|
String testDataAbsoluteDir = new File(testDataDir).getAbsolutePath();
|
||||||
String normalizedOutputWithoutExitCode = StringUtil.convertLineSeparators(pureOutput)
|
String normalizedOutputWithoutExitCode = StringUtil.convertLineSeparators(pureOutput)
|
||||||
.replace(testDataAbsoluteDir, "$TESTDATA_DIR$")
|
.replace(testDataAbsoluteDir, TESTDATA_DIR)
|
||||||
.replace(FileUtil.toSystemIndependentName(testDataAbsoluteDir), "$TESTDATA_DIR$")
|
.replace(FileUtil.toSystemIndependentName(testDataAbsoluteDir), TESTDATA_DIR)
|
||||||
.replace(PathUtil.getKotlinPathsForDistDirectory().getHomePath().getAbsolutePath(), "$PROJECT_DIR$")
|
.replace(PathUtil.getKotlinPathsForDistDirectory().getHomePath().getAbsolutePath(), "$PROJECT_DIR$")
|
||||||
.replace("expected version is " + JvmMetadataVersion.INSTANCE, "expected version is $ABI_VERSION$")
|
.replace("expected version is " + JvmMetadataVersion.INSTANCE, "expected version is $ABI_VERSION$")
|
||||||
.replace("expected version is " + JsMetadataVersion.INSTANCE, "expected version is $ABI_VERSION$")
|
.replace("expected version is " + JsMetadataVersion.INSTANCE, "expected version is $ABI_VERSION$")
|
||||||
@@ -81,7 +91,7 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
|||||||
return normalizedOutputWithoutExitCode + exitCode + "\n";
|
return normalizedOutputWithoutExitCode + exitCode + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doTest(@NotNull String fileName, @NotNull CLITool<?> compiler) throws Exception {
|
private void doTest(@NotNull String fileName, @NotNull CLITool<?> compiler) {
|
||||||
System.setProperty("java.awt.headless", "true");
|
System.setProperty("java.awt.headless", "true");
|
||||||
Pair<String, ExitCode> outputAndExitCode = executeCompilerGrabOutput(compiler, readArgs(fileName, tmpdir.getPath()));
|
Pair<String, ExitCode> outputAndExitCode = executeCompilerGrabOutput(compiler, readArgs(fileName, tmpdir.getPath()));
|
||||||
String actual = getNormalizedCompilerOutput(
|
String actual = getNormalizedCompilerOutput(
|
||||||
@@ -93,17 +103,17 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
|||||||
|
|
||||||
File additionalTestConfig = new File(fileName.replaceFirst("\\.args$", ".test"));
|
File additionalTestConfig = new File(fileName.replaceFirst("\\.args$", ".test"));
|
||||||
if (additionalTestConfig.exists()) {
|
if (additionalTestConfig.exists()) {
|
||||||
doTestAdditionalChecks(additionalTestConfig);
|
doTestAdditionalChecks(additionalTestConfig, fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doTestAdditionalChecks(@NotNull File testConfigFile) throws IOException {
|
private void doTestAdditionalChecks(@NotNull File testConfigFile, @NotNull String argsFilePath) {
|
||||||
List<String> diagnostics = new ArrayList<>(0);
|
List<String> diagnostics = new ArrayList<>(0);
|
||||||
String content = FilesKt.readText(testConfigFile, Charsets.UTF_8);
|
String content = FilesKt.readText(testConfigFile, Charsets.UTF_8);
|
||||||
|
|
||||||
List<String> existsList = InTextDirectivesUtils.findListWithPrefixes(content, "// EXISTS: ");
|
List<String> existsList = InTextDirectivesUtils.findListWithPrefixes(content, "// EXISTS: ");
|
||||||
for (String fileName : existsList) {
|
for (String fileName : existsList) {
|
||||||
File file = new File(tmpdir, fileName);
|
File file = checkedPathToFile(fileName, argsFilePath);
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
diagnostics.add("File does not exist, but should: " + fileName);
|
diagnostics.add("File does not exist, but should: " + fileName);
|
||||||
}
|
}
|
||||||
@@ -114,7 +124,7 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
|||||||
|
|
||||||
List<String> absentList = InTextDirectivesUtils.findListWithPrefixes(content, "// ABSENT: ");
|
List<String> absentList = InTextDirectivesUtils.findListWithPrefixes(content, "// ABSENT: ");
|
||||||
for (String fileName : absentList) {
|
for (String fileName : absentList) {
|
||||||
File file = new File(tmpdir, fileName);
|
File file = checkedPathToFile(fileName, argsFilePath);
|
||||||
if (file.exists() && file.isFile()) {
|
if (file.exists() && file.isFile()) {
|
||||||
diagnostics.add("File exists, but shouldn't: " + fileName);
|
diagnostics.add("File exists, but shouldn't: " + fileName);
|
||||||
}
|
}
|
||||||
@@ -125,7 +135,7 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
|||||||
String[] parts = containsSpec.split(",", 2);
|
String[] parts = containsSpec.split(",", 2);
|
||||||
String fileName = parts[0].trim();
|
String fileName = parts[0].trim();
|
||||||
String contentToSearch = parts[1].trim();
|
String contentToSearch = parts[1].trim();
|
||||||
File file = new File(tmpdir, fileName);
|
File file = checkedPathToFile(fileName, argsFilePath);
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
diagnostics.add("File does not exist: " + fileName);
|
diagnostics.add("File does not exist: " + fileName);
|
||||||
}
|
}
|
||||||
@@ -147,7 +157,17 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static List<String> readArgs(@NotNull String argsFilePath, @NotNull String tempDir) throws IOException {
|
private File checkedPathToFile(@NotNull String path, @NotNull String argsFilePath) {
|
||||||
|
if (path.startsWith(TESTDATA_DIR + "/")) {
|
||||||
|
return new File(new File(argsFilePath).getParent(), path.substring(TESTDATA_DIR.length() + 1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new File(tmpdir, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static List<String> readArgs(@NotNull String argsFilePath, @NotNull String tempDir) {
|
||||||
List<String> lines = FilesKt.readLines(new File(argsFilePath), Charsets.UTF_8);
|
List<String> lines = FilesKt.readLines(new File(argsFilePath), Charsets.UTF_8);
|
||||||
|
|
||||||
return CollectionsKt.mapNotNull(lines, arg -> {
|
return CollectionsKt.mapNotNull(lines, arg -> {
|
||||||
@@ -163,7 +183,7 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
|||||||
|
|
||||||
return argsWithColonsReplaced
|
return argsWithColonsReplaced
|
||||||
.replace("$TEMP_DIR$", tempDir)
|
.replace("$TEMP_DIR$", tempDir)
|
||||||
.replace("$TESTDATA_DIR$", new File(argsFilePath).getParent())
|
.replace(TESTDATA_DIR, new File(argsFilePath).getParent())
|
||||||
.replace(
|
.replace(
|
||||||
"$FOREIGN_ANNOTATIONS_DIR$",
|
"$FOREIGN_ANNOTATIONS_DIR$",
|
||||||
new File(AbstractForeignAnnotationsTestKt.getFOREIGN_ANNOTATIONS_SOURCES_PATH()).getPath()
|
new File(AbstractForeignAnnotationsTestKt.getFOREIGN_ANNOTATIONS_SOURCES_PATH()).getPath()
|
||||||
@@ -171,15 +191,15 @@ public abstract class AbstractCliTest extends TestCaseWithTmpdir {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doJvmTest(@NotNull String fileName) throws Exception {
|
protected void doJvmTest(@NotNull String fileName) {
|
||||||
doTest(fileName, new K2JVMCompiler());
|
doTest(fileName, new K2JVMCompiler());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doJsTest(@NotNull String fileName) throws Exception {
|
protected void doJsTest(@NotNull String fileName) {
|
||||||
doTest(fileName, new K2JSCompiler());
|
doTest(fileName, new K2JSCompiler());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doJsDceTest(@NotNull String fileName) throws Exception {
|
protected void doJsDceTest(@NotNull String fileName) {
|
||||||
doTest(fileName, new K2JSDce());
|
doTest(fileName, new K2JSDce());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -665,6 +665,12 @@ public class CliTestGenerated extends AbstractCliTest {
|
|||||||
doJsTest(fileName);
|
doJsTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sourceMapRelativeRoot.args")
|
||||||
|
public void testSourceMapRelativeRoot() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/js/sourceMapRelativeRoot.args");
|
||||||
|
doJsTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("sourceMapRootAuto.args")
|
@TestMetadata("sourceMapRootAuto.args")
|
||||||
public void testSourceMapRootAuto() throws Exception {
|
public void testSourceMapRootAuto() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/js/sourceMapRootAuto.args");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/js/sourceMapRootAuto.args");
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ object JsLibraryUtils {
|
|||||||
|
|
||||||
private fun File.runIfFileExists(relativePath: String, action: (JsLibrary) -> Unit) {
|
private fun File.runIfFileExists(relativePath: String, action: (JsLibrary) -> Unit) {
|
||||||
if (isFile) {
|
if (isFile) {
|
||||||
action(JsLibrary(readText(), relativePath, correspondingSourceMapFile().contentIfExists()))
|
action(JsLibrary(readText(), relativePath, correspondingSourceMapFile().contentIfExists(), this))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ object JsLibraryUtils {
|
|||||||
|
|
||||||
val stream = zipFile.getInputStream(entry)
|
val stream = zipFile.getInputStream(entry)
|
||||||
val content = FileUtil.loadTextAndClose(stream)
|
val content = FileUtil.loadTextAndClose(stream)
|
||||||
librariesWithoutSourceMaps += JsLibrary(content, relativePath, null)
|
librariesWithoutSourceMaps += JsLibrary(content, relativePath, null, null)
|
||||||
}
|
}
|
||||||
else if (entryName.endsWith(KotlinJavascriptMetadataUtils.JS_MAP_EXT)) {
|
else if (entryName.endsWith(KotlinJavascriptMetadataUtils.JS_MAP_EXT)) {
|
||||||
val correspondingJsPath = entryName.removeSuffix(KotlinJavascriptMetadataUtils.JS_MAP_EXT) +
|
val correspondingJsPath = entryName.removeSuffix(KotlinJavascriptMetadataUtils.JS_MAP_EXT) +
|
||||||
@@ -171,4 +171,4 @@ object JsLibraryUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class JsLibrary(val content: String, val path: String, val sourceMapContent: String?)
|
data class JsLibrary(val content: String, val path: String, val sourceMapContent: String?, val file: File?)
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
|
|||||||
buildAllModules().assertSuccessful()
|
buildAllModules().assertSuccessful()
|
||||||
|
|
||||||
val sourceMapContent = File(getOutputDir(PROJECT_NAME), "$PROJECT_NAME.js.map").readText()
|
val sourceMapContent = File(getOutputDir(PROJECT_NAME), "$PROJECT_NAME.js.map").readText()
|
||||||
val expectedPath = "prefix-dir/pkg/test1.kt"
|
val expectedPath = "prefix-dir/src/pkg/test1.kt"
|
||||||
assertTrue("Source map file should contain relative path ($expectedPath)", sourceMapContent.contains("\"$expectedPath\""))
|
assertTrue("Source map file should contain relative path ($expectedPath)", sourceMapContent.contains("\"$expectedPath\""))
|
||||||
|
|
||||||
val librarySourceMapFile = File(getOutputDir(PROJECT_NAME), "lib/kotlin.js.map")
|
val librarySourceMapFile = File(getOutputDir(PROJECT_NAME), "lib/kotlin.js.map")
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
|||||||
import org.jetbrains.kotlin.utils.*
|
import org.jetbrains.kotlin.utils.*
|
||||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.net.URI
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
||||||
@@ -647,7 +648,10 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
|||||||
val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(representativeModule)
|
val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(representativeModule)
|
||||||
val k2JsArguments = JpsKotlinCompilerSettings.getK2JsCompilerArguments(representativeModule)
|
val k2JsArguments = JpsKotlinCompilerSettings.getK2JsCompilerArguments(representativeModule)
|
||||||
|
|
||||||
val sourceRoots = KotlinSourceFileCollector.getRelevantSourceRoots(representativeTarget).map { it.file }
|
val sourceRoots = representativeModule.contentRootsList.urls
|
||||||
|
.map { URI.create(it) }
|
||||||
|
.filter { it.scheme == "file" }
|
||||||
|
.map { File(it) }
|
||||||
|
|
||||||
val friendPaths = KotlinBuilderModuleScriptGenerator.getProductionModulesWhichInternalsAreVisible(representativeTarget).mapNotNull {
|
val friendPaths = KotlinBuilderModuleScriptGenerator.getProductionModulesWhichInternalsAreVisible(representativeTarget).mapNotNull {
|
||||||
val file = getOutputMetaFile(it, false)
|
val file = getOutputMetaFile(it, false)
|
||||||
|
|||||||
@@ -119,7 +119,8 @@ class DeadCodeElimination(private val logConsumer: (DCELogLevel, String) -> Unit
|
|||||||
val sourceMapFile = File(file.outputPath + ".map")
|
val sourceMapFile = File(file.outputPath + ".map")
|
||||||
val textOutput = TextOutputImpl()
|
val textOutput = TextOutputImpl()
|
||||||
val sourceMapBuilder = SourceMap3Builder(File(file.outputPath), textOutput, "")
|
val sourceMapBuilder = SourceMap3Builder(File(file.outputPath), textOutput, "")
|
||||||
val consumer = SourceMapBuilderConsumer(sourceMapBuilder, SourceFilePathResolver(mutableListOf()), true, true)
|
val sourcePathResolver = SourceFilePathResolver(mutableListOf(), File(file.outputPath).parentFile)
|
||||||
|
val consumer = SourceMapBuilderConsumer(sourceMapBuilder, sourcePathResolver, true, true)
|
||||||
block.accept(JsToStringGenerationVisitor(textOutput, consumer))
|
block.accept(JsToStringGenerationVisitor(textOutput, consumer))
|
||||||
val sourceMapContent = sourceMapBuilder.build()
|
val sourceMapContent = sourceMapBuilder.build()
|
||||||
sourceMapBuilder.addLink()
|
sourceMapBuilder.addLink()
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider;
|
|||||||
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer;
|
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer;
|
||||||
import org.jetbrains.kotlin.serialization.js.ModuleKind;
|
import org.jetbrains.kotlin.serialization.js.ModuleKind;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class JSConfigurationKeys {
|
public class JSConfigurationKeys {
|
||||||
@@ -30,6 +31,9 @@ public class JSConfigurationKeys {
|
|||||||
public static final CompilerConfigurationKey<Boolean> SOURCE_MAP =
|
public static final CompilerConfigurationKey<Boolean> SOURCE_MAP =
|
||||||
CompilerConfigurationKey.create("generate source map");
|
CompilerConfigurationKey.create("generate source map");
|
||||||
|
|
||||||
|
public static final CompilerConfigurationKey<File> OUTPUT_DIR =
|
||||||
|
CompilerConfigurationKey.create("output directory");
|
||||||
|
|
||||||
public static final CompilerConfigurationKey<String> SOURCE_MAP_PREFIX =
|
public static final CompilerConfigurationKey<String> SOURCE_MAP_PREFIX =
|
||||||
CompilerConfigurationKey.create("prefix to add to paths in source map");
|
CompilerConfigurationKey.create("prefix to add to paths in source map");
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,11 @@ public class JsConfig {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<String> getSourceMapRoots() {
|
public List<String> getSourceMapRoots() {
|
||||||
return configuration.get(JSConfigurationKeys.SOURCE_MAP_SOURCE_ROOTS, Collections.singletonList("."));
|
return configuration.get(JSConfigurationKeys.SOURCE_MAP_SOURCE_ROOTS, Collections.emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldGenerateRelativePathsInSourceMap() {
|
||||||
|
return getSourceMapPrefix().isEmpty() && getSourceMapRoots().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.js.backend.ast.metadata.*
|
import org.jetbrains.kotlin.js.backend.ast.metadata.*
|
||||||
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig
|
import org.jetbrains.kotlin.js.config.JsConfig
|
||||||
import org.jetbrains.kotlin.js.inline.util.*
|
import org.jetbrains.kotlin.js.inline.util.*
|
||||||
import org.jetbrains.kotlin.js.parser.OffsetToSourceMapping
|
import org.jetbrains.kotlin.js.parser.OffsetToSourceMapping
|
||||||
@@ -77,7 +78,8 @@ class FunctionReader(
|
|||||||
val kotlinVariable: String,
|
val kotlinVariable: String,
|
||||||
val specialFunctions: Map<String, SpecialFunction>,
|
val specialFunctions: Map<String, SpecialFunction>,
|
||||||
offsetToSourceMappingProvider: () -> OffsetToSourceMapping,
|
offsetToSourceMappingProvider: () -> OffsetToSourceMapping,
|
||||||
val sourceMap: SourceMap?
|
val sourceMap: SourceMap?,
|
||||||
|
val outputDir: File?
|
||||||
) {
|
) {
|
||||||
val offsetToSourceMapping by lazy(offsetToSourceMappingProvider)
|
val offsetToSourceMapping by lazy(offsetToSourceMappingProvider)
|
||||||
|
|
||||||
@@ -89,7 +91,7 @@ class FunctionReader(
|
|||||||
private val moduleNameToInfo by lazy {
|
private val moduleNameToInfo by lazy {
|
||||||
val result = HashMultimap.create<String, ModuleInfo>()
|
val result = HashMultimap.create<String, ModuleInfo>()
|
||||||
|
|
||||||
JsLibraryUtils.traverseJsLibraries(config.libraries.map(::File)) { (content, path, sourceMapContent) ->
|
JsLibraryUtils.traverseJsLibraries(config.libraries.map(::File)) { (content, path, sourceMapContent, file) ->
|
||||||
var current = 0
|
var current = 0
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -131,7 +133,8 @@ class FunctionReader(
|
|||||||
kotlinVariable = kotlinVariable,
|
kotlinVariable = kotlinVariable,
|
||||||
specialFunctions = specialFunctions,
|
specialFunctions = specialFunctions,
|
||||||
offsetToSourceMappingProvider = { OffsetToSourceMapping(content) },
|
offsetToSourceMappingProvider = { OffsetToSourceMapping(content) },
|
||||||
sourceMap = sourceMap
|
sourceMap = sourceMap,
|
||||||
|
outputDir = file?.parentFile
|
||||||
)
|
)
|
||||||
|
|
||||||
result.put(moduleName, moduleInfo)
|
result.put(moduleName, moduleInfo)
|
||||||
@@ -142,6 +145,8 @@ class FunctionReader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val moduleNameMap: Map<String, JsExpression>
|
private val moduleNameMap: Map<String, JsExpression>
|
||||||
|
private val shouldRemapPathToRelativeForm = config.shouldGenerateRelativePathsInSourceMap()
|
||||||
|
private val relativePathCalculator = config.configuration[JSConfigurationKeys.OUTPUT_DIR]?.let { RelativePathCalculator(it) }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
moduleNameMap = buildModuleNameMap(fragments)
|
moduleNameMap = buildModuleNameMap(fragments)
|
||||||
@@ -242,7 +247,9 @@ class FunctionReader(
|
|||||||
|
|
||||||
val sourceMap = info.sourceMap
|
val sourceMap = info.sourceMap
|
||||||
if (sourceMap != null) {
|
if (sourceMap != null) {
|
||||||
val remapper = SourceMapLocationRemapper(sourceMap)
|
val remapper = SourceMapLocationRemapper(sourceMap) {
|
||||||
|
remapPath(removeRedundantPathPrefix(it), info)
|
||||||
|
}
|
||||||
remapper.remap(function)
|
remapper.remap(function)
|
||||||
wrapperStatements?.forEach { remapper.remap(it) }
|
wrapperStatements?.forEach { remapper.remap(it) }
|
||||||
}
|
}
|
||||||
@@ -301,6 +308,25 @@ class FunctionReader(
|
|||||||
param.hasDefaultValue = true
|
param.hasDefaultValue = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun removeRedundantPathPrefix(path: String): String {
|
||||||
|
var index = 0
|
||||||
|
while (index + 2 <= path.length && path.substring(index, index + 2) == "./") {
|
||||||
|
index += 2
|
||||||
|
while (index < path.length && path[index] == '/') {
|
||||||
|
++index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return path.substring(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun remapPath(path: String, info: ModuleInfo): String {
|
||||||
|
if (!shouldRemapPathToRelativeForm) return path
|
||||||
|
val outputDir = info.outputDir ?: return path
|
||||||
|
val calculator = relativePathCalculator ?: return path
|
||||||
|
return calculator.calculateRelativePathTo(File(outputDir, path)) ?: path
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val Char.isWhitespaceOrComma: Boolean
|
private val Char.isWhitespaceOrComma: Boolean
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.js.inline.util
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.js.parser.sourcemaps
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
class SourceMapLocationRemapper(private val sourceMap: SourceMap) {
|
class SourceMapLocationRemapper(private val sourceMap: SourceMap, private val sourceMapPathMapper: (String) -> String = { it }) {
|
||||||
fun remap(node: JsNode) {
|
fun remap(node: JsNode) {
|
||||||
val listCollector = JsNodeFlatListCollector()
|
val listCollector = JsNodeFlatListCollector()
|
||||||
node.accept(listCollector)
|
node.accept(listCollector)
|
||||||
@@ -65,7 +65,7 @@ class SourceMapLocationRemapper(private val sourceMap: SourceMap) {
|
|||||||
val segment = findCorrespondingSegment(node)
|
val segment = findCorrespondingSegment(node)
|
||||||
val sourceFileName = segment?.sourceFileName
|
val sourceFileName = segment?.sourceFileName
|
||||||
node.source = if (sourceFileName != null) {
|
node.source = if (sourceFileName != null) {
|
||||||
val location = JsLocation(segment.sourceFileName, segment.sourceLineNumber, segment.sourceColumnNumber)
|
val location = JsLocation(sourceMapPathMapper(sourceFileName), segment.sourceLineNumber, segment.sourceColumnNumber)
|
||||||
JsLocationWithEmbeddedSource(location, null) { sourceMap.sourceContentResolver(segment.sourceFileName) }
|
JsLocationWithEmbeddedSource(location, null) { sourceMap.sourceContentResolver(segment.sourceFileName) }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ abstract class BasicBoxTest(
|
|||||||
generatedProgram.accept(AmbiguousAstSourcePropagation())
|
generatedProgram.accept(AmbiguousAstSourcePropagation())
|
||||||
|
|
||||||
val output = TextOutputImpl()
|
val output = TextOutputImpl()
|
||||||
val pathResolver = SourceFilePathResolver(mutableListOf(File(".")))
|
val pathResolver = SourceFilePathResolver(mutableListOf(File(".")), null)
|
||||||
val sourceMapBuilder = SourceMap3Builder(outputFile, output, "")
|
val sourceMapBuilder = SourceMap3Builder(outputFile, output, "")
|
||||||
generatedProgram.accept(JsToStringGenerationVisitor(output, SourceMapBuilderConsumer(sourceMapBuilder, pathResolver, false, false)))
|
generatedProgram.accept(JsToStringGenerationVisitor(output, SourceMapBuilderConsumer(sourceMapBuilder, pathResolver, false, false)))
|
||||||
val code = output.toString()
|
val code = output.toString()
|
||||||
|
|||||||
@@ -128,8 +128,7 @@ public final class K2JSTranslator {
|
|||||||
ModuleDescriptor moduleDescriptor = analysisResult.getModuleDescriptor();
|
ModuleDescriptor moduleDescriptor = analysisResult.getModuleDescriptor();
|
||||||
Diagnostics diagnostics = bindingTrace.getBindingContext().getDiagnostics();
|
Diagnostics diagnostics = bindingTrace.getBindingContext().getDiagnostics();
|
||||||
|
|
||||||
List<File> sourceRoots = config.getSourceMapRoots().stream().map(File::new).collect(Collectors.toList());
|
SourceFilePathResolver pathResolver = SourceFilePathResolver.create(config);
|
||||||
SourceFilePathResolver pathResolver = new SourceFilePathResolver(sourceRoots);
|
|
||||||
|
|
||||||
AstGenerationResult translationResult = Translation.generateAst(
|
AstGenerationResult translationResult = Translation.generateAst(
|
||||||
bindingTrace, units, mainCallParameters, moduleDescriptor, config, pathResolver);
|
bindingTrace, units, mainCallParameters, moduleDescriptor, config, pathResolver);
|
||||||
@@ -155,7 +154,6 @@ public final class K2JSTranslator {
|
|||||||
|
|
||||||
ExpandIsCallsKt.expandIsCalls(newFragments);
|
ExpandIsCallsKt.expandIsCalls(newFragments);
|
||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||||
|
|
||||||
JsAstSerializer serializer = new JsAstSerializer(file -> {
|
JsAstSerializer serializer = new JsAstSerializer(file -> {
|
||||||
try {
|
try {
|
||||||
return pathResolver.getPathRelativeToSourceRoots(file);
|
return pathResolver.getPathRelativeToSourceRoots(file);
|
||||||
|
|||||||
@@ -65,9 +65,8 @@ abstract class TranslationResult protected constructor(val diagnostics: Diagnost
|
|||||||
val sourceMapBuilder = SourceMap3Builder(outputFile, output, config.sourceMapPrefix)
|
val sourceMapBuilder = SourceMap3Builder(outputFile, output, config.sourceMapPrefix)
|
||||||
val sourceMapBuilderConsumer =
|
val sourceMapBuilderConsumer =
|
||||||
if (config.configuration.getBoolean(JSConfigurationKeys.SOURCE_MAP)) {
|
if (config.configuration.getBoolean(JSConfigurationKeys.SOURCE_MAP)) {
|
||||||
val sourceRoots = config.sourceMapRoots.map { File(it) }
|
|
||||||
val sourceMapContentEmbedding = config.sourceMapContentEmbedding
|
val sourceMapContentEmbedding = config.sourceMapContentEmbedding
|
||||||
val pathResolver = SourceFilePathResolver(sourceRoots)
|
val pathResolver = SourceFilePathResolver.create(config)
|
||||||
SourceMapBuilderConsumer(
|
SourceMapBuilderConsumer(
|
||||||
sourceMapBuilder,
|
sourceMapBuilder,
|
||||||
pathResolver,
|
pathResolver,
|
||||||
|
|||||||
@@ -18,23 +18,33 @@ package org.jetbrains.kotlin.js.sourceMap;
|
|||||||
|
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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 org.jetbrains.kotlin.js.inline.util.RelativePathCalculator;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class SourceFilePathResolver {
|
public class SourceFilePathResolver {
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Set<File> sourceRoots;
|
private final Set<File> sourceRoots;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final RelativePathCalculator outputDirPathResolver;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Map<File, String> cache = new HashMap<>();
|
private final Map<File, String> cache = new HashMap<>();
|
||||||
|
|
||||||
public SourceFilePathResolver(@NotNull List<File> sourceRoots) {
|
public SourceFilePathResolver(@NotNull List<File> sourceRoots, @Nullable File outputDir) {
|
||||||
this.sourceRoots = new HashSet<>();
|
this.sourceRoots = new HashSet<>();
|
||||||
for (File sourceRoot : sourceRoots) {
|
for (File sourceRoot : sourceRoots) {
|
||||||
this.sourceRoots.add(sourceRoot.getAbsoluteFile());
|
this.sourceRoots.add(sourceRoot.getAbsoluteFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outputDirPathResolver = outputDir != null ? new RelativePathCalculator(outputDir) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -47,7 +57,11 @@ public class SourceFilePathResolver {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private String calculatePathRelativeToSourceRoots(@NotNull File file) throws IOException {
|
private String calculatePathRelativeToSourceRoots(@NotNull File file) throws IOException {
|
||||||
|
String pathRelativeToOutput = calculatePathRelativeToOutput(file);
|
||||||
|
if (pathRelativeToOutput != null) return pathRelativeToOutput;
|
||||||
|
|
||||||
List<String> parts = new ArrayList<>();
|
List<String> parts = new ArrayList<>();
|
||||||
File currentFile = file.getCanonicalFile();
|
File currentFile = file.getCanonicalFile();
|
||||||
|
|
||||||
@@ -64,4 +78,19 @@ public class SourceFilePathResolver {
|
|||||||
}
|
}
|
||||||
return file.getName();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -195,7 +195,7 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() {
|
|||||||
assertFileExists(mapFilePath)
|
assertFileExists(mapFilePath)
|
||||||
val map = fileInWorkingDir(mapFilePath).readText()
|
val map = fileInWorkingDir(mapFilePath).readText()
|
||||||
|
|
||||||
val sourceFilePath = "prefixprefix/example/Dummy.kt"
|
val sourceFilePath = "prefixprefix/src/main/kotlin/example/Dummy.kt"
|
||||||
assertTrue("Source map should contain reference to $sourceFilePath") { map.contains("\"$sourceFilePath\"") }
|
assertTrue("Source map should contain reference to $sourceFilePath") { map.contains("\"$sourceFilePath\"") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,8 +211,8 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() {
|
|||||||
assertFileExists(mapFilePath)
|
assertFileExists(mapFilePath)
|
||||||
val map = fileInWorkingDir(mapFilePath).readText()
|
val map = fileInWorkingDir(mapFilePath).readText()
|
||||||
|
|
||||||
assertTrue("Source map should contain reference to main.kt") { map.contains("\"main.kt\"") }
|
assertTrue("Source map should contain reference to main.kt") { map.contains("\"./src/main/kotlin/main.kt\"") }
|
||||||
assertTrue("Source map should contain reference to foo.kt") { map.contains("\"foo.kt\"") }
|
assertTrue("Source map should contain reference to foo.kt") { map.contains("\"./src/main/kotlin/foo.kt\"") }
|
||||||
assertTrue("Source map should contain source of main.kt") { map.contains("\"fun main(args: Array<String>) {\\n") }
|
assertTrue("Source map should contain source of main.kt") { map.contains("\"fun main(args: Array<String>) {\\n") }
|
||||||
assertTrue("Source map should contain source of foo.kt") { map.contains("\"inline fun foo(): String {\\n") }
|
assertTrue("Source map should contain source of foo.kt") { map.contains("\"inline fun foo(): String {\\n") }
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -24,6 +24,7 @@ allprojects {
|
|||||||
compileKotlin2Js {
|
compileKotlin2Js {
|
||||||
kotlinOptions.freeCompilerArgs = [ "-Xskip-metadata-version-check" ]
|
kotlinOptions.freeCompilerArgs = [ "-Xskip-metadata-version-check" ]
|
||||||
kotlinOptions.sourceMap = true
|
kotlinOptions.sourceMap = true
|
||||||
|
kotlinOptions.sourceMapPrefix = "./"
|
||||||
kotlinOptions.sourceMapEmbedSources = "always"
|
kotlinOptions.sourceMapEmbedSources = "always"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -461,11 +461,9 @@ open class Kotlin2JsCompile() : AbstractKotlinCompile<K2JSCompilerArguments>(),
|
|||||||
|
|
||||||
args.friendModules = friendDependency
|
args.friendModules = friendDependency
|
||||||
|
|
||||||
args.sourceMapBaseDirs = source.orEmpty()
|
if (args.sourceMapBaseDirs == null && !args.sourceMapPrefix.isNullOrEmpty()) {
|
||||||
.asSequence()
|
args.sourceMapBaseDirs = project.projectDir.absolutePath
|
||||||
.filterIsInstance<SourceDirectorySet>()
|
}
|
||||||
.flatMap { it.srcDirs.asSequence() }
|
|
||||||
.joinToString(File.pathSeparator) { it.absolutePath }
|
|
||||||
|
|
||||||
logger.kotlinDebug("compiling with args ${ArgumentUtils.convertArgumentsToStringList(args)}")
|
logger.kotlinDebug("compiling with args ${ArgumentUtils.convertArgumentsToStringList(args)}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user