diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala index 5ea4b8aa21a7..a9f67c8a08aa 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala @@ -1310,6 +1310,9 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util. def Position_sourceCode(self: Position): String = new String(self.source.content(), self.start, self.end - self.start) + def Position_withOffset(self: Position)(start: Int, end: Int): Position = + util.SourcePosition(self.source, util.Spans.Span(start, end)) + // // COMMENTS // diff --git a/library/src/scala/tasty/reflect/Kernel.scala b/library/src/scala/tasty/reflect/Kernel.scala index 1b0144ed9335..cb76760c678e 100644 --- a/library/src/scala/tasty/reflect/Kernel.scala +++ b/library/src/scala/tasty/reflect/Kernel.scala @@ -1067,6 +1067,12 @@ trait Kernel { /** Source code within the position */ def Position_sourceCode(self: Position): String + /** Create a position that ranges from start to end (exclusive) in the given source + * @param start index of the start of the range (0 <= start < end) + * @param end index of the end of the range (start < end <= sizeOf(pos.sourceFile)) + */ + def Position_withOffset(self: Position)(start: Int, end: Int): Position + // // COMMENTS // diff --git a/library/src/scala/tasty/reflect/PositionOps.scala b/library/src/scala/tasty/reflect/PositionOps.scala index f2141925fd28..e90a34f5c61e 100644 --- a/library/src/scala/tasty/reflect/PositionOps.scala +++ b/library/src/scala/tasty/reflect/PositionOps.scala @@ -31,6 +31,13 @@ trait PositionOps extends Core { /** Source code within the position */ def sourceCode: String = kernel.Position_sourceCode(pos) + /** Create a position that ranges from start to end (exclusive) in the given source + * @param start index of the start of the range (0 <= start < end) + * @param end index of the end of the range (start < end <= sizeOf(pos.sourceFile)) + */ + def withOffset(start: Int = pos.start, end: Int = pos.end): Position = + kernel.Position_withOffset(pos)(start, end) + } } diff --git a/tests/neg/tasty-macro-positions.check b/tests/neg/tasty-macro-positions.check new file mode 100644 index 000000000000..04bd51fbdb51 --- /dev/null +++ b/tests/neg/tasty-macro-positions.check @@ -0,0 +1,4 @@ +<122..125> in quoted_2.scala +here (+5) is the the argument is foo +[117..120] in quoted_2.scala +here is the the argument is foo diff --git a/tests/neg/tasty-macro-positions/quoted_1.scala b/tests/neg/tasty-macro-positions/quoted_1.scala new file mode 100644 index 000000000000..4bf59da140b3 --- /dev/null +++ b/tests/neg/tasty-macro-positions/quoted_1.scala @@ -0,0 +1,17 @@ +import scala.quoted._ + +import scala.tasty._ + +object Macros { + + inline def fun(x: Any): Unit = ${ impl('x) } + + def impl(x: Expr[Any])(implicit reflect: Reflection): Expr[Unit] = { + import reflect._ + val pos = x.unseal.underlyingArgument.pos + error("here is the the argument is " + x.unseal.underlyingArgument.showCode, pos) + error("here (+5) is the the argument is " + x.unseal.underlyingArgument.showCode, pos.withOffset(start = pos.start + 5, end = pos.end + 5)) + '{} + } + +} diff --git a/tests/neg/tasty-macro-positions/quoted_2.scala b/tests/neg/tasty-macro-positions/quoted_2.scala new file mode 100644 index 000000000000..632a24446cab --- /dev/null +++ b/tests/neg/tasty-macro-positions/quoted_2.scala @@ -0,0 +1,11 @@ + +import Macros._ + +object Test { + def main(args: Array[String]): Unit = { + def foo: String = "abc" + fun( + foo // error // error + ) + } +}