Skip to content

Commit 86b8686

Browse files
authored
Merge pull request #551 from raquo/master
Fix source map URLs (as much as possible). Fixes #519
2 parents 3f25107 + 8729503 commit 86b8686

File tree

2 files changed

+60
-3
lines changed

2 files changed

+60
-3
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,5 @@ tzdb/js/src/main/resources/
4141
project/metals.sbt
4242
.direnv/
4343
.bsp/
44+
45+
.DS_Store

build.sbt

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ lazy val commonSettings = Seq(
9494
/**
9595
* Copy source files and translate them to the java.time package
9696
*/
97-
def copyAndReplace(srcDirs: Seq[File], destinationDir: File): Seq[File] = {
97+
def copyAndReplace(
98+
srcDirs: Seq[File],
99+
destinationDir: File,
100+
createNestedDirs: Boolean = false
101+
): Seq[File] = {
98102
// Copy a directory and return the list of files
99103
def copyDirectory(
100104
source: File,
@@ -112,7 +116,12 @@ def copyAndReplace(srcDirs: Seq[File], destinationDir: File): Seq[File] = {
112116
// Copy the source files from the base project, exclude classes on java.util and dirs
113117
val generatedFiles: List[java.io.File] = onlyScalaDirs
114118
.foldLeft(Set.empty[File]) { (files, sourceDir) =>
115-
files ++ copyDirectory(sourceDir, destinationDir, overwrite = true)
119+
val targetDestinationDir = if (createNestedDirs) {
120+
destinationDir / sourceDir.getName
121+
} else {
122+
destinationDir
123+
}
124+
files ++ copyDirectory(sourceDir, targetDestinationDir, overwrite = true)
116125
}
117126
.filterNot(_.isDirectory)
118127
.filter(_.getName.endsWith(".scala"))
@@ -121,6 +130,13 @@ def copyAndReplace(srcDirs: Seq[File], destinationDir: File): Seq[File] = {
121130

122131
// These replacements will in practice rename all the classes from
123132
// org.threeten to java.time
133+
//
134+
// !!! WARNING: AVOID MODIFYING FILE CONTENTS HERE MORE THAN ABSOLUTELY NECESSARY !!!
135+
// - The more significant the change, in terms of changing source code position
136+
// (line number + column), the more broken the Scala.js source maps will be,
137+
// preventing debugging of Scala.js code that uses scala-java-code in the browser.
138+
// - Line-for-line replacements of `package/import x` with `package/import y` are
139+
// mostly ok because they don't affect the remaining code in the file.
124140
def replacements(line: String): String =
125141
line
126142
.replaceAll("package org.threeten$", "package java")
@@ -141,6 +157,7 @@ def copyAndReplace(srcDirs: Seq[File], destinationDir: File): Seq[File] = {
141157
lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform)
142158
.crossType(CrossType.Full)
143159
.in(file("core"))
160+
.disablePlugins(TypelevelScalaJSGitHubPlugin)
144161
.settings(commonSettings)
145162
.settings(
146163
name := "scala-java-time",
@@ -152,10 +169,11 @@ lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform)
152169
if (tlIsScala3.value) Seq("-scalajs-genStaticForwardersForNonTopLevelObjects")
153170
else Seq("-P:scalajs:genStaticForwardersForNonTopLevelObjects")
154171
},
172+
scalaJsGithubSourceMaps("core/shared"),
155173
Compile / sourceGenerators += Def.task {
156174
val srcDirs = (Compile / sourceDirectories).value
157175
val destinationDir = (Compile / sourceManaged).value
158-
copyAndReplace(srcDirs, destinationDir)
176+
copyAndReplace(srcDirs, destinationDir, createNestedDirs = true)
159177
}.taskValue,
160178
libraryDependencies ++= Seq(
161179
"io.github.cquiroz" %%% "scala-java-locales" % scalajavaLocalesVersion
@@ -265,3 +283,40 @@ lazy val demo = crossProject(JSPlatform, JVMPlatform, NativePlatform)
265283
.nativeSettings(
266284
tzdbPlatform := TzdbPlugin.Platform.Native
267285
)
286+
287+
def scalaJsGithubSourceMaps(projectDir: String) =
288+
// - Unfortunately we can only specify one `projectDir`.
289+
// So, if our JS project has sources in both `core/js` and `core/shared`,
290+
// we can only pick one of those, and all sources in the other one will have
291+
// broken URLs in source maps.
292+
// - The root of the problem is that in `copyAndReplace` we copy the contents of
293+
// multiple source directories into a single src_managed directory, and so we
294+
// lose information about where our sources originally came from, and even if we
295+
// could capture or recover this information, the syntax of `mapSourceURI` option
296+
// doesn't allow more than one mapping, so we probably wouldn't be able to use it
297+
// to create multiple mappings.
298+
// - Also, for the same reason, we are unable to map sources that are not copied
299+
// to src_managed (stuff under java.util). Those will have invalid file: URLs.
300+
// - In the future, maybe we can somehow adjust the folder structure inside `src_managed`
301+
// to introduce new top level directories matching project names (`core`).
302+
// - The CI env var is set by Github actions automatically.
303+
// We only want this transformation to run when creating & publishing an artifact to Maven,
304+
// as this lets us use the original local file paths for local dev / publishLocal.
305+
// ---
306+
// - How to test changes to this code locally:
307+
// - Make sure the sys.env.get("CI") filter passes, one way or another
308+
// - publishLocal the core project (press enter to skip passphrase, don't need signing)
309+
// - find the resulting jar – see file path in sbt output. Open it (it's a zip archive).
310+
// - find .sjsir files inside the jar, open some of them with plain text editor
311+
// - in the first bytes of the binary, observe the raw.githubusercontent.com URL in plaintext
312+
// - copy-paste that URL into the browser.
313+
// - It should show the contents of this file on github (subject to caveats above)
314+
// - If it doesn't, make sure the version / commit hash you have locally exists on github (or fake it).
315+
scalacOptions ++= sys.env.get("CI").map { _ =>
316+
val localCopiedSourcesPath = (Compile / sourceManaged).value.toURI
317+
val remoteSourcesPath =
318+
s"https://raw.githubusercontent.com/cquiroz/scala-java-time/${git.gitHeadCommit.value.get}/${projectDir}/src/main/"
319+
val sourcesOptionName =
320+
if (tlIsScala3.value) "-scalajs-mapSourceURI" else "-P:scalajs:mapSourceURI"
321+
s"${sourcesOptionName}:$localCopiedSourcesPath->$remoteSourcesPath"
322+
}

0 commit comments

Comments
 (0)