diff options
Diffstat (limited to 'examples/scala-js/tools/shared/src/main/scala/scala/scalajs/tools/sourcemap/JSFileBuilder.scala')
-rw-r--r-- | examples/scala-js/tools/shared/src/main/scala/scala/scalajs/tools/sourcemap/JSFileBuilder.scala | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/examples/scala-js/tools/shared/src/main/scala/scala/scalajs/tools/sourcemap/JSFileBuilder.scala b/examples/scala-js/tools/shared/src/main/scala/scala/scalajs/tools/sourcemap/JSFileBuilder.scala new file mode 100644 index 0000000..1bf2254 --- /dev/null +++ b/examples/scala-js/tools/shared/src/main/scala/scala/scalajs/tools/sourcemap/JSFileBuilder.scala @@ -0,0 +1,144 @@ +/* __ *\ +** ________ ___ / / ___ __ ____ Scala.js tools ** +** / __/ __// _ | / / / _ | __ / // __/ (c) 2013-2014, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** +** /____/\___/_/ |_/____/_/ | |__/ /____/ ** +** |/____/ ** +\* */ + + +package scala.scalajs.tools.sourcemap + +import scala.annotation.tailrec + +import scala.collection.mutable + +import java.io._ +import java.util.regex.Pattern +import java.net.{ URI, URISyntaxException } + +import scala.scalajs.ir.Position +import scala.scalajs.tools.{javascript => js} +import scala.scalajs.tools.io._ +import scala.scalajs.tools.optimizer.JSTreeBuilder + +class JSFileBuilder(val name: String, + protected val outputWriter: Writer) extends JSTreeBuilder { + def addLine(line: String): Unit = { + outputWriter.write(line) + outputWriter.write('\n') + } + + def addLines(lines: Seq[String]): Unit = + lines.foreach(addLine) + + def addFile(file: VirtualJSFile): Unit = + addPartsOfFile(file)(!_.startsWith("//# sourceMappingURL=")) + + def addPartsOfFile(file: VirtualJSFile)(selector: String => Boolean): Unit = { + for (line <- file.readLines() if selector(line)) + addLine(line) + } + + /** Add a JavaScript tree representing a statement. + * The tree must be a valid JavaScript tree (typically obtained by + * desugaring a full-fledged IR tree). + */ + def addJSTree(tree: js.Trees.Tree): Unit = { + val printer = new js.Printers.JSTreePrinter(outputWriter) + printer.printTopLevelTree(tree) + // Do not close the printer: we do not have ownership of the writers + } + + /** Closes the underlying writer(s). + */ + def closeWriters(): Unit = { + outputWriter.close() + } +} + +class JSFileBuilderWithSourceMapWriter(n: String, ow: Writer, + protected val sourceMapWriter: SourceMapWriter) + extends JSFileBuilder(n, ow) { + + override def addLine(line: String): Unit = { + super.addLine(line) + sourceMapWriter.nextLine() + } + + private final val NotSelected = -1 + + override def addPartsOfFile(file: VirtualJSFile)( + selector: String => Boolean): Unit = { + val br = new BufferedReader(file.reader) + try { + // Select lines, and remember offsets + val offsets = new mutable.ArrayBuffer[Int] // (maybe NotSelected) + val selectedLineLengths = new mutable.ArrayBuffer[Int] + var line: String = br.readLine() + var selectedCount = 0 + while (line != null) { + if (selector(line)) { + super.addLine(line) // super call not to advance line in source map + offsets += selectedCount + selectedLineLengths += line.length + selectedCount += 1 + } else { + offsets += NotSelected + } + line = br.readLine() + } + + /* We ignore a potential source map. + * This happens typically for corejslib.js and other helper files + * written directly in JS. + * We generate a fake line-by-line source map for these on the fly + */ + val sourceFile = file.toURI + + for (lineNumber <- 0 until offsets.size) { + val offset = offsets(lineNumber) + if (offset != NotSelected) { + val originalPos = Position(sourceFile, lineNumber, 0) + sourceMapWriter.startNode(0, originalPos, None) + sourceMapWriter.endNode(selectedLineLengths(offset)) + sourceMapWriter.nextLine() + } + } + } finally { + br.close() + } + } + + override def addJSTree(tree: js.Trees.Tree): Unit = { + val printer = new js.Printers.JSTreePrinterWithSourceMap( + outputWriter, sourceMapWriter) + printer.printTopLevelTree(tree) + // Do not close the printer: we do not have ownership of the writers + } + + override def complete(): Unit = { + super.complete() + sourceMapWriter.complete() + } + +} + +class JSFileBuilderWithSourceMap(n: String, ow: Writer, + sourceMapOutputWriter: Writer, + relativizeSourceMapBasePath: Option[URI] = None) + extends JSFileBuilderWithSourceMapWriter( + n, ow, + new SourceMapWriter(sourceMapOutputWriter, n, + relativizeSourceMapBasePath)) { + + override def complete(): Unit = { + addLine("//# sourceMappingURL=" + name + ".map") + super.complete() + } + + override def closeWriters(): Unit = { + super.closeWriters() + sourceMapOutputWriter.close() + } +} |