aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/backend/sjs/JSPositions.scala
blob: 10570da00129fa5ebe686bfc6805584734ca2d91 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package dotty.tools.backend.sjs

import dotty.tools.dotc.core._
import Contexts._
import dotty.tools.dotc.util.Positions
import Positions.Position

import org.scalajs.core.ir

/** Conversion utilities from dotty Positions to IR Positions. */
class JSPositions()(implicit ctx: Context) {

  /** Implicit conversion from dotty Position to ir.Position. */
  implicit def pos2irPos(pos: Positions.Position): ir.Position = {
    if (!pos.exists) ir.Position.NoPosition
    else {
      val source = pos2irPosCache.toIRSource(ctx.compilationUnit.source)
      val sourcePos = ctx.compilationUnit.source.atPos(pos)
      // dotty positions are 1-based but IR positions are 0-based
      ir.Position(source, sourcePos.line-1, sourcePos.column-1)
    }
  }

  /** Implicitly materializes an ir.Position from an implicit dotty Position. */
  implicit def implicitPos2irPos(
      implicit pos: Positions.Position): ir.Position = {
    pos2irPos(pos)
  }

  private[this] object pos2irPosCache { // scalastyle:ignore
    import dotty.tools.dotc.util._

    private[this] var lastDotcSource: SourceFile = null
    private[this] var lastIRSource: ir.Position.SourceFile = null

    def toIRSource(dotcSource: SourceFile): ir.Position.SourceFile = {
      if (dotcSource != lastDotcSource) {
        lastIRSource = convert(dotcSource)
        lastDotcSource = dotcSource
      }
      lastIRSource
    }

    private[this] def convert(dotcSource: SourceFile): ir.Position.SourceFile = {
      dotcSource.file.file match {
        case null =>
          new java.net.URI(
              "virtualfile",        // Pseudo-Scheme
              dotcSource.file.path, // Scheme specific part
              null                  // Fragment
          )
        case file =>
          val srcURI = file.toURI
          def matches(pat: java.net.URI) = pat.relativize(srcURI) != srcURI

          // TODO
          /*scalaJSOpts.sourceURIMaps.collectFirst {
            case ScalaJSOptions.URIMap(from, to) if matches(from) =>
              val relURI = from.relativize(srcURI)
              to.fold(relURI)(_.resolve(relURI))
          } getOrElse*/ srcURI
      }
    }
  }
}