mirror of https://github.com/sbt/sbt.git
Merge pull request #146 from dwijnand/SourcePosition
Give SourcePosition a macro instance creator
This commit is contained in:
commit
b0baf7de6d
14
build.sbt
14
build.sbt
|
|
@ -94,11 +94,15 @@ lazy val utilControl = (project in internalPath / "util-control").settings(
|
||||||
mimaSettings,
|
mimaSettings,
|
||||||
)
|
)
|
||||||
|
|
||||||
val utilPosition = (project in file("internal") / "util-position").settings(
|
val utilPosition = (project in file("internal") / "util-position")
|
||||||
commonSettings,
|
.dependsOn(utilTesting % Test)
|
||||||
name := "Util Position",
|
.settings(
|
||||||
mimaSettings,
|
commonSettings,
|
||||||
)
|
name := "Util Position",
|
||||||
|
scalacOptions += "-language:experimental.macros",
|
||||||
|
libraryDependencies += scalaReflect.value,
|
||||||
|
mimaSettings,
|
||||||
|
)
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
lazy val utilLogging = (project in internalPath / "util-logging")
|
lazy val utilLogging = (project in internalPath / "util-logging")
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,49 @@ final case class LineRange(start: Int, end: Int) {
|
||||||
final case class RangePosition(path: String, range: LineRange) extends FilePosition {
|
final case class RangePosition(path: String, range: LineRange) extends FilePosition {
|
||||||
def startLine = range.start
|
def startLine = range.start
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object SourcePosition {
|
||||||
|
|
||||||
|
/** Creates a SourcePosition by using the enclosing position of the invocation of this method.
|
||||||
|
* @see [[scala.reflect.macros.Enclosures#enclosingPosition]]
|
||||||
|
* @return SourcePosition
|
||||||
|
*/
|
||||||
|
def fromEnclosing(): SourcePosition = macro SourcePositionMacro.fromEnclosingImpl
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
import scala.annotation.tailrec
|
||||||
|
import scala.reflect.macros.blackbox
|
||||||
|
import scala.reflect.internal.util.UndefinedPosition
|
||||||
|
|
||||||
|
final class SourcePositionMacro(val c: blackbox.Context) {
|
||||||
|
import c.universe.{ NoPosition => _, _ }
|
||||||
|
|
||||||
|
def fromEnclosingImpl(): Expr[SourcePosition] = {
|
||||||
|
val pos = c.enclosingPosition
|
||||||
|
if (!pos.isInstanceOf[UndefinedPosition] && pos.line >= 0 && pos.source != null) {
|
||||||
|
val f = pos.source.file
|
||||||
|
val name = constant[String](ownerSource(f.path, f.name))
|
||||||
|
val line = constant[Int](pos.line)
|
||||||
|
reify { LinePosition(name.splice, line.splice) }
|
||||||
|
} else
|
||||||
|
reify { NoPosition }
|
||||||
|
}
|
||||||
|
|
||||||
|
private[this] def ownerSource(path: String, name: String): String = {
|
||||||
|
@tailrec def inEmptyPackage(s: Symbol): Boolean =
|
||||||
|
s != NoSymbol && (
|
||||||
|
s.owner == c.mirror.EmptyPackage
|
||||||
|
|| s.owner == c.mirror.EmptyPackageClass
|
||||||
|
|| inEmptyPackage(s.owner)
|
||||||
|
)
|
||||||
|
|
||||||
|
c.internal.enclosingOwner match {
|
||||||
|
case ec if !ec.isStatic => name
|
||||||
|
case ec if inEmptyPackage(ec) => path
|
||||||
|
case ec => s"(${ec.fullName}) $name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private[this] def constant[T: WeakTypeTag](t: T): Expr[T] = c.Expr[T](Literal(Constant(t)))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package sbt.internal.util
|
||||||
|
|
||||||
|
import org.scalatest._
|
||||||
|
|
||||||
|
class SourcePositionSpec extends FlatSpec {
|
||||||
|
"SourcePosition()" should "return a sane SourcePosition" in {
|
||||||
|
val filename = "SourcePositionSpec.scala"
|
||||||
|
val lineNumber = 9
|
||||||
|
SourcePosition.fromEnclosing() match {
|
||||||
|
case LinePosition(path, startLine) => assert(path === filename && startLine === lineNumber)
|
||||||
|
case RangePosition(path, range) => assert(path === filename && inRange(range, lineNumber))
|
||||||
|
case NoPosition => fail("No source position found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def inRange(range: LineRange, lineNo: Int) =
|
||||||
|
range.start until range.end contains lineNo
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue