diff options
author | Haoyi Li <haoyi@haoyi-mbp.corp.dropbox.com> | 2014-11-26 00:45:31 -0800 |
---|---|---|
committer | Haoyi Li <haoyi@haoyi-mbp.corp.dropbox.com> | 2014-11-26 00:45:31 -0800 |
commit | 24f31e120f9537faede7a174bb09ee35f64e1ce4 (patch) | |
tree | 06ffc3ecc7847789008352b7e2b7c040dad48907 /examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/sourcemap/SourceMapper.scala | |
parent | b89ce9cbf79363f8cab09186a5d7ba94bc0af02a (diff) | |
parent | 2c4b142503bd2d871e6818b5cab8c38627d9e4a0 (diff) | |
download | hands-on-scala-js-24f31e120f9537faede7a174bb09ee35f64e1ce4.tar.gz hands-on-scala-js-24f31e120f9537faede7a174bb09ee35f64e1ce4.tar.bz2 hands-on-scala-js-24f31e120f9537faede7a174bb09ee35f64e1ce4.zip |
Merge commit '2c4b142503bd2d871e6818b5cab8c38627d9e4a0' as 'examples/scala-js'
Diffstat (limited to 'examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/sourcemap/SourceMapper.scala')
-rw-r--r-- | examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/sourcemap/SourceMapper.scala | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/sourcemap/SourceMapper.scala b/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/sourcemap/SourceMapper.scala new file mode 100644 index 0000000..6f856a9 --- /dev/null +++ b/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/sourcemap/SourceMapper.scala @@ -0,0 +1,88 @@ +/* __ *\ +** ________ ___ / / ___ __ ____ Scala.js sbt plugin ** +** / __/ __// _ | / / / _ | __ / // __/ (c) 2013, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ |/_// /_\ \ http://scala-js.org/ ** +** /____/\___/_/ |_/____/_/ | |__/ /____/ ** +** |/____/ ** +\* */ + + +package scala.scalajs.tools.sourcemap + +import scala.scalajs.tools.classpath._ + +import com.google.debugging.sourcemap._ + +class SourceMapper(classpath: CompleteClasspath) { + + def map(ste: StackTraceElement, columnNumber: Int): StackTraceElement = { + val mapped = for { + sourceMap <- findSourceMap(ste.getFileName) + } yield map(ste, columnNumber, sourceMap) + + mapped.getOrElse(ste) + } + + def map(ste: StackTraceElement, columnNumber: Int, + sourceMap: String): StackTraceElement = { + + val sourceMapConsumer = + SourceMapConsumerFactory + .parse(sourceMap) + .asInstanceOf[SourceMapConsumerV3] + + /* **Attention** + * - StackTrace positions are 1-based + * - SourceMapConsumer.getMappingForLine() is 1-based + */ + + val lineNumber = ste.getLineNumber + val column = + if (columnNumber == -1) getFirstColumn(sourceMapConsumer, lineNumber) + else columnNumber + + val originalMapping = + sourceMapConsumer.getMappingForLine(lineNumber, column) + + if (originalMapping != null) { + new StackTraceElement( + ste.getClassName, + ste.getMethodName, + originalMapping.getOriginalFile, + originalMapping.getLineNumber) + } else ste + } + + /** both `lineNumber` and the resulting column are 1-based */ + private def getFirstColumn(sourceMapConsumer: SourceMapConsumerV3, + lineNumber1Based: Int) = { + + /* **Attention** + * - SourceMapConsumerV3.EntryVisitor is 0-based!!! + */ + + val lineNumber = lineNumber1Based - 1 + + var column: Option[Int] = None + + sourceMapConsumer.visitMappings( + new SourceMapConsumerV3.EntryVisitor { + def visit(sourceName: String, + symbolName: String, + sourceStartPosition: FilePosition, + startPosition: FilePosition, + endPosition: FilePosition): Unit = + if (!column.isDefined && startPosition.getLine == lineNumber) + column = Some(startPosition.getColumn) + }) + + val column0Based = column.getOrElse(0) + column0Based + 1 + } + + private def findSourceMap(path: String) = { + val candidates = classpath.allCode.filter(_.path == path) + if (candidates.size != 1) None // better no sourcemap than a wrong one + else candidates.head.sourceMap + } +} |