Skip to content

Commit 5c90a84

Browse files
committed
SourcePositionMacro for Scala 3
1 parent d01cdd5 commit 5c90a84

File tree

5 files changed

+95
-47
lines changed

5 files changed

+95
-47
lines changed

.github/workflows/ci.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ jobs:
5151
JVM_OPTS: -Xms800M -Xmx2G -Xss6M -XX:ReservedCodeCacheSize=128M -server -Dsbt.io.virtual=false -Dfile.encoding=UTF-8
5252
SCALA_212: 2.12.15
5353
SCALA_213: 2.13.6
54+
SCALA_3: 3.1.0
5455
UTIL_TESTS: "utilCache/test utilControl/test utilInterface/test utilLogging/test utilPosition/test utilRelation/test utilScripted/test utilTracking/test"
5556
SBT_LOCAL: false
5657
TEST_SBT_VER: 1.5.0
@@ -134,7 +135,7 @@ jobs:
134135
if: ${{ matrix.jobtype == 5 }}
135136
shell: bash
136137
run: |
137-
./sbt -v "++$SCALA_213!; test;"
138+
./sbt -v "++$SCALA_213!; test; ++$SCALA_3!; all utilControl/test utilRelation/test utilPosition/test"
138139
- name: Build and test (6)
139140
if: ${{ matrix.jobtype == 6 }}
140141
shell: bash

.scalafmt.conf

+5
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,8 @@ align.openParenDefnSite = false
2121
danglingParentheses = true
2222

2323
trailingCommas = preserve
24+
25+
# TODO update scalafmt and enable Scala 3
26+
project.excludeFilters = [
27+
"internal/util-position/src/main/scala-3/sbt/internal/util/SourcePositionMacro.scala"
28+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* sbt
3+
* Copyright 2011 - 2018, Lightbend, Inc.
4+
* Copyright 2008 - 2010, Mark Harrah
5+
* Licensed under Apache License 2.0 (see LICENSE)
6+
*/
7+
8+
package sbt.internal.util
9+
10+
import scala.language.experimental.macros
11+
import scala.annotation.tailrec
12+
import scala.reflect.macros.blackbox
13+
import scala.reflect.internal.util.UndefinedPosition
14+
15+
abstract class SourcePositionImpl {
16+
17+
/** Creates a SourcePosition by using the enclosing position of the invocation of this method.
18+
* @return SourcePosition
19+
*/
20+
def fromEnclosing(): SourcePosition = macro SourcePositionMacro.fromEnclosingImpl
21+
}
22+
23+
final class SourcePositionMacro(val c: blackbox.Context) {
24+
import c.universe.{ NoPosition => _, _ }
25+
26+
def fromEnclosingImpl(): Expr[SourcePosition] = {
27+
val pos = c.enclosingPosition
28+
if (!pos.isInstanceOf[UndefinedPosition] && pos.line >= 0 && pos.source != null) {
29+
val f = pos.source.file
30+
val name = constant[String](ownerSource(f.path, f.name))
31+
val line = constant[Int](pos.line)
32+
reify { LinePosition(name.splice, line.splice) }
33+
} else
34+
reify { NoPosition }
35+
}
36+
37+
private[this] def ownerSource(path: String, name: String): String = {
38+
@tailrec def inEmptyPackage(s: Symbol): Boolean =
39+
s != NoSymbol && (
40+
s.owner == c.mirror.EmptyPackage
41+
|| s.owner == c.mirror.EmptyPackageClass
42+
|| inEmptyPackage(s.owner)
43+
)
44+
45+
c.internal.enclosingOwner match {
46+
case ec if !ec.isStatic => name
47+
case ec if inEmptyPackage(ec) => path
48+
case ec => s"(${ec.fullName}) $name"
49+
}
50+
}
51+
52+
private[this] def constant[T: WeakTypeTag](t: T): Expr[T] = c.Expr[T](Literal(Constant(t)))
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* sbt
3+
* Copyright 2011 - 2018, Lightbend, Inc.
4+
* Copyright 2008 - 2010, Mark Harrah
5+
* Licensed under Apache License 2.0 (see LICENSE)
6+
*/
7+
8+
package sbt.internal.util
9+
10+
import scala.quoted.{ Expr, Quotes, quotes }
11+
12+
abstract class SourcePositionImpl {
13+
14+
/** Creates a SourcePosition by using the enclosing position of the invocation of this method.
15+
*
16+
* @return SourcePosition
17+
*/
18+
inline def fromEnclosing(): SourcePosition =
19+
${ SourcePositionImpl.fromEnclosingImpl }
20+
}
21+
22+
object SourcePositionImpl {
23+
24+
def fromEnclosingImpl(using Quotes): Expr[SourcePosition] = {
25+
val x = quotes.reflect.Position.ofMacroExpansion
26+
27+
'{
28+
LinePosition(
29+
path = ${Expr(x.sourceFile.name)},
30+
startLine = ${Expr(x.startLine + 1)}
31+
)
32+
}
33+
}
34+
}

internal/util-position/src/main/scala/sbt/internal/util/Positions.scala

+1-46
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
package sbt.internal.util
99

10-
import scala.language.experimental.macros
11-
1210
sealed trait SourcePosition
1311

1412
sealed trait FilePosition extends SourcePosition {
@@ -28,47 +26,4 @@ final case class RangePosition(path: String, range: LineRange) extends FilePosit
2826
def startLine = range.start
2927
}
3028

31-
object SourcePosition {
32-
33-
/** Creates a SourcePosition by using the enclosing position of the invocation of this method.
34-
* @return SourcePosition
35-
*/
36-
def fromEnclosing(): SourcePosition = macro SourcePositionMacro.fromEnclosingImpl
37-
38-
}
39-
40-
import scala.annotation.tailrec
41-
import scala.reflect.macros.blackbox
42-
import scala.reflect.internal.util.UndefinedPosition
43-
44-
final class SourcePositionMacro(val c: blackbox.Context) {
45-
import c.universe.{ NoPosition => _, _ }
46-
47-
def fromEnclosingImpl(): Expr[SourcePosition] = {
48-
val pos = c.enclosingPosition
49-
if (!pos.isInstanceOf[UndefinedPosition] && pos.line >= 0 && pos.source != null) {
50-
val f = pos.source.file
51-
val name = constant[String](ownerSource(f.path, f.name))
52-
val line = constant[Int](pos.line)
53-
reify { LinePosition(name.splice, line.splice) }
54-
} else
55-
reify { NoPosition }
56-
}
57-
58-
private[this] def ownerSource(path: String, name: String): String = {
59-
@tailrec def inEmptyPackage(s: Symbol): Boolean =
60-
s != NoSymbol && (
61-
s.owner == c.mirror.EmptyPackage
62-
|| s.owner == c.mirror.EmptyPackageClass
63-
|| inEmptyPackage(s.owner)
64-
)
65-
66-
c.internal.enclosingOwner match {
67-
case ec if !ec.isStatic => name
68-
case ec if inEmptyPackage(ec) => path
69-
case ec => s"(${ec.fullName}) $name"
70-
}
71-
}
72-
73-
private[this] def constant[T: WeakTypeTag](t: T): Expr[T] = c.Expr[T](Literal(Constant(t)))
74-
}
29+
object SourcePosition extends SourcePositionImpl

0 commit comments

Comments
 (0)