Skip to content

Commit b9eb88f

Browse files
committed
Add TASTy reflect error with custom positions
Having custom positions is necessary to emit errors inside string interpolators such as ```scala xml"<a><<b></a>" ^^ Some parsing error here ```
1 parent 8ecc927 commit b9eb88f

File tree

12 files changed

+94
-9
lines changed

12 files changed

+94
-9
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,15 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
3636
def error(msg: => String, pos: Position)(implicit ctx: Context): Unit =
3737
ctx.error(msg, pos)
3838

39+
def error(msg: => String, sourceFile: SourceFile, start: Int, end: Int)(implicit ctx: Context): Unit =
40+
ctx.error(msg, util.SourcePosition(sourceFile, util.Spans.Span(start, end)))
41+
3942
def warning(msg: => String, pos: Position)(implicit ctx: Context): Unit =
4043
ctx.warning(msg, pos)
4144

45+
def warning(msg: => String, sourceFile: SourceFile, start: Int, end: Int)(implicit ctx: Context): Unit =
46+
ctx.error(msg, util.SourcePosition(sourceFile, util.Spans.Span(start, end)))
47+
4248
//
4349
// Settings
4450
//
@@ -1297,7 +1303,7 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
12971303

12981304
def Position_exists(self: Position): Boolean = self.exists
12991305

1300-
def Position_sourceFile(self: Position): java.nio.file.Path = self.source.file.jpath
1306+
def Position_sourceFile(self: Position): SourceFile = self.source
13011307

13021308
def Position_startLine(self: Position): Int = self.startLine
13031309

@@ -1310,6 +1316,16 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
13101316
def Position_sourceCode(self: Position): String =
13111317
new String(self.source.content(), self.start, self.end - self.start)
13121318

1319+
//
1320+
// SOURCE FILES
1321+
//
1322+
1323+
type SourceFile = util.SourceFile
1324+
1325+
def SourceFile_jpath(self: SourceFile): java.nio.file.Path = self.file.jpath
1326+
1327+
def SourceFile_content(self: SourceFile): String = new String(self.content())
1328+
13131329
//
13141330
// COMMENTS
13151331
//

library/src/scala/tasty/reflect/Core.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,12 @@ trait Core {
407407
/** JVM signature of a method */
408408
type Signature = kernel.Signature
409409

410-
/** Source position */
410+
/** Position in a source file */
411411
type Position = kernel.Position
412412

413+
/** Scala source file */
414+
type SourceFile = kernel.SourceFile
415+
413416
/** Comment */
414417
type Comment = kernel.Comment
415418

library/src/scala/tasty/reflect/Kernel.scala

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,15 @@ trait Kernel {
145145
/** Report a compilation error with the given message at the given position */
146146
def error(msg: => String, pos: Position)(implicit ctx: Context): Unit
147147

148+
/** Report a compilation error with the given message at the given position range */
149+
def error(msg: => String, source: SourceFile, start: Int, end: Int)(implicit ctx: Context): Unit
150+
148151
/** Report a compilation warning with the given message at the given position */
149152
def warning(msg: => String, pos: Position)(implicit ctx: Context): Unit
150153

154+
/** Report a compilation warning with the given message at the given position range */
155+
def warning(msg: => String, source: SourceFile, start: Int, end: Int)(implicit ctx: Context): Unit
156+
151157
//
152158
// Settings
153159
//
@@ -1037,7 +1043,7 @@ trait Kernel {
10371043
// POSITIONS
10381044
//
10391045

1040-
/** Source position */
1046+
/** Position in a source file */
10411047
type Position <: AnyRef
10421048

10431049
/** The start offset in the source file */
@@ -1050,7 +1056,7 @@ trait Kernel {
10501056
def Position_exists(self: Position): Boolean
10511057

10521058
/** Source file in which this position is located */
1053-
def Position_sourceFile(self: Position): java.nio.file.Path
1059+
def Position_sourceFile(self: Position): SourceFile
10541060

10551061
/** The start line in the source file */
10561062
def Position_startLine(self: Position): Int
@@ -1067,6 +1073,19 @@ trait Kernel {
10671073
/** Source code within the position */
10681074
def Position_sourceCode(self: Position): String
10691075

1076+
//
1077+
// SOURCE FILE
1078+
//
1079+
1080+
/** Scala source file */
1081+
type SourceFile <: AnyRef
1082+
1083+
/** Path to a source file */
1084+
def SourceFile_jpath(self: SourceFile): java.nio.file.Path
1085+
1086+
/** Content of a source file */
1087+
def SourceFile_content(self: SourceFile): String
1088+
10701089
//
10711090
// COMMENTS
10721091
//

library/src/scala/tasty/reflect/PositionOps.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trait PositionOps extends Core {
1414
def exists: Boolean = kernel.Position_exists(pos)
1515

1616
/** Source file in which this position is located */
17-
def sourceFile: java.nio.file.Path = kernel.Position_sourceFile(pos)
17+
def sourceFile: SourceFile = kernel.Position_sourceFile(pos)
1818

1919
/** The start line in the source file */
2020
def startLine: Int = kernel.Position_startLine(pos)
@@ -33,4 +33,14 @@ trait PositionOps extends Core {
3333

3434
}
3535

36+
implicit class SourceFileAPI(sourceFile: SourceFile) {
37+
38+
/** Path to this source file */
39+
def jpath: java.nio.file.Path = kernel.SourceFile_jpath(sourceFile)
40+
41+
/** Content of this source file */
42+
def content: String = kernel.SourceFile_content(sourceFile)
43+
44+
}
45+
3646
}

library/src/scala/tasty/reflect/ReportingOps.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ trait ReportingOps extends Core {
55
def error(msg: => String, pos: Position)(implicit ctx: Context): Unit =
66
kernel.error(msg, pos)
77

8+
def error(msg: => String, source: SourceFile, start: Int, end: Int)(implicit ctx: Context): Unit =
9+
kernel.error(msg, source, start, end)
10+
811
def warning(msg: => String, pos: Position)(implicit ctx: Context): Unit =
912
kernel.warning(msg, pos)
1013

14+
def warning(msg: => String, source: SourceFile, start: Int, end: Int)(implicit ctx: Context): Unit =
15+
kernel.warning(msg, source, start, end)
1116
}

tests/neg/tasty-macro-positions.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<122..125> in quoted_2.scala
2+
here (+5) is the the argument is foo
3+
[117..120] in quoted_2.scala
4+
here is the the argument is foo
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import scala.quoted._
2+
3+
import scala.tasty._
4+
5+
object Macros {
6+
7+
inline def fun(x: Any): Unit = ${ impl('x) }
8+
9+
def impl(x: Expr[Any])(implicit reflect: Reflection): Expr[Unit] = {
10+
import reflect._
11+
val pos = x.unseal.underlyingArgument.pos
12+
error("here is the the argument is " + x.unseal.underlyingArgument.showCode, pos)
13+
error("here (+5) is the the argument is " + x.unseal.underlyingArgument.showCode, pos.sourceFile, pos.start + 5, pos.end + 5)
14+
'{}
15+
}
16+
17+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
import Macros._
3+
4+
object Test {
5+
def main(args: Array[String]): Unit = {
6+
def foo: String = "abc"
7+
fun(
8+
foo // error // error
9+
)
10+
}
11+
}

tests/run/tasty-macro-positions/quoted_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ object Macros {
3232

3333
def posStr(relfection: Reflection)(pos: relfection.Position): Expr[String] = {
3434
import relfection._
35-
s"${pos.sourceFile.getFileName.toString}:[${pos.start}..${pos.end}]".toExpr
35+
s"${pos.sourceFile.jpath.getFileName.toString}:[${pos.start}..${pos.end}]".toExpr
3636
}
3737
}

tests/run/tasty-positioned/quoted_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ object Positioned {
1515
import reflect.{Position => _, _}
1616
val pos = rootPosition
1717

18-
val path = pos.sourceFile.toString.toExpr
18+
val path = pos.sourceFile.jpath.toString.toExpr
1919
val start = pos.start.toExpr
2020
val end = pos.end.toExpr
2121
val startLine = pos.startLine.toExpr

0 commit comments

Comments
 (0)