SourcePositionMacro for Scala 3

This commit is contained in:
xuwei-k 2021-11-16 10:36:27 +09:00
parent d01cdd53e1
commit 5c90a84c72
5 changed files with 95 additions and 47 deletions

View File

@ -51,6 +51,7 @@ jobs:
JVM_OPTS: -Xms800M -Xmx2G -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8 JVM_OPTS: -Xms800M -Xmx2G -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8
SCALA_212: 2.12.15 SCALA_212: 2.12.15
SCALA_213: 2.13.6 SCALA_213: 2.13.6
SCALA_3: 3.1.0
UTIL_TESTS: "utilCache/test utilControl/test utilInterface/test utilLogging/test utilPosition/test utilRelation/test utilScripted/test utilTracking/test" UTIL_TESTS: "utilCache/test utilControl/test utilInterface/test utilLogging/test utilPosition/test utilRelation/test utilScripted/test utilTracking/test"
SBT_LOCAL: false SBT_LOCAL: false
TEST_SBT_VER: 1.5.0 TEST_SBT_VER: 1.5.0
@ -134,7 +135,7 @@ jobs:
if: ${{ matrix.jobtype == 5 }} if: ${{ matrix.jobtype == 5 }}
shell: bash shell: bash
run: | run: |
./sbt -v "++$SCALA_213!; test;" ./sbt -v "++$SCALA_213!; test; ++$SCALA_3!; all utilControl/test utilRelation/test utilPosition/test"
- name: Build and test (6) - name: Build and test (6)
if: ${{ matrix.jobtype == 6 }} if: ${{ matrix.jobtype == 6 }}
shell: bash shell: bash

View File

@ -21,3 +21,8 @@ align.openParenDefnSite = false
danglingParentheses = true danglingParentheses = true
trailingCommas = preserve trailingCommas = preserve
# TODO update scalafmt and enable Scala 3
project.excludeFilters = [
"internal/util-position/src/main/scala-3/sbt/internal/util/SourcePositionMacro.scala"
]

View File

@ -0,0 +1,53 @@
/*
* sbt
* Copyright 2011 - 2018, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt.internal.util
import scala.language.experimental.macros
import scala.annotation.tailrec
import scala.reflect.macros.blackbox
import scala.reflect.internal.util.UndefinedPosition
abstract class SourcePositionImpl {
/** Creates a SourcePosition by using the enclosing position of the invocation of this method.
* @return SourcePosition
*/
def fromEnclosing(): SourcePosition = macro SourcePositionMacro.fromEnclosingImpl
}
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)))
}

View File

@ -0,0 +1,34 @@
/*
* sbt
* Copyright 2011 - 2018, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt.internal.util
import scala.quoted.{ Expr, Quotes, quotes }
abstract class SourcePositionImpl {
/** Creates a SourcePosition by using the enclosing position of the invocation of this method.
*
* @return SourcePosition
*/
inline def fromEnclosing(): SourcePosition =
${ SourcePositionImpl.fromEnclosingImpl }
}
object SourcePositionImpl {
def fromEnclosingImpl(using Quotes): Expr[SourcePosition] = {
val x = quotes.reflect.Position.ofMacroExpansion
'{
LinePosition(
path = ${Expr(x.sourceFile.name)},
startLine = ${Expr(x.startLine + 1)}
)
}
}
}

View File

@ -7,8 +7,6 @@
package sbt.internal.util package sbt.internal.util
import scala.language.experimental.macros
sealed trait SourcePosition sealed trait SourcePosition
sealed trait FilePosition extends SourcePosition { sealed trait FilePosition extends SourcePosition {
@ -28,47 +26,4 @@ final case class RangePosition(path: String, range: LineRange) extends FilePosit
def startLine = range.start def startLine = range.start
} }
object SourcePosition { object SourcePosition extends SourcePositionImpl
/** Creates a SourcePosition by using the enclosing position of the invocation of this method.
* @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)))
}