From c4c6f705605a073f01309532a3505c5ba6387875 Mon Sep 17 00:00:00 2001 From: kasiaMarek Date: Tue, 20 May 2025 14:20:31 +0200 Subject: [PATCH 1/3] tests: add testcase for metals i7460 --- .../src/tests/macros/metals7460.scala | 20 +++++++++++++++++++ .../tools/pc/tests/hover/HoverTermSuite.scala | 16 +++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 presentation-compiler-testcases/src/tests/macros/metals7460.scala diff --git a/presentation-compiler-testcases/src/tests/macros/metals7460.scala b/presentation-compiler-testcases/src/tests/macros/metals7460.scala new file mode 100644 index 000000000000..0b9b1ca494b2 --- /dev/null +++ b/presentation-compiler-testcases/src/tests/macros/metals7460.scala @@ -0,0 +1,20 @@ +package tests.macros + +import scala.quoted.* + +object Macros7460 { + + transparent inline def foo: String = + ${ fooImpl } + + private def fooImpl(using Quotes): Expr[String] = + Expr("foo...") + + transparent inline def bar: String = + ${ barImpl } + + private def barImpl(using Quotes): Expr[String] = + quotes.reflect.Position.ofMacroExpansion.sourceFile.getJPath.get // this line is the culprit + Expr("bar...") + +} diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala index 3f55352804b4..f46a2ba506b9 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala @@ -799,3 +799,19 @@ class HoverTermSuite extends BaseHoverSuite: |""".stripMargin, "def valueOf($name: String): Foo".hover ) + + @Test def `i7460` = + check( + """|package tests.macros + |def m = Macros7460.foo.sub@@string(2, 4) + |""".stripMargin, + "def substring(x$0: Int, x$1: Int): String".hover + ) + + @Test def `i7460-2` = + check( + """|package tests.macros + |def m = Macros7460.bar.sub@@string(2, 4) + |""".stripMargin, + "def substring(x$0: Int, x$1: Int): String".hover + ) From dff5609a1b3efa987d8fe5f28a5eeac54b24a29f Mon Sep 17 00:00:00 2001 From: kasiaMarek Date: Tue, 20 May 2025 15:47:07 +0200 Subject: [PATCH 2/3] add `jpath` to pc virtual file --- .../dotty/tools/dotc/util/SourceFile.scala | 3 +-- compiler/src/dotty/tools/io/VirtualFile.scala | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/util/SourceFile.scala b/compiler/src/dotty/tools/dotc/util/SourceFile.scala index 1c264b395689..eb99fe99d926 100644 --- a/compiler/src/dotty/tools/dotc/util/SourceFile.scala +++ b/compiler/src/dotty/tools/dotc/util/SourceFile.scala @@ -229,8 +229,7 @@ object SourceFile { * It relies on SourceFile#virtual implementation to create the virtual file. */ def virtual(uri: URI, content: String): SourceFile = - val path = Paths.get(uri).toString - SourceFile.virtual(path, content) + SourceFile(new VirtualFile(Paths.get(uri), content.getBytes(StandardCharsets.UTF_8)), content.toCharArray) /** Returns the relative path of `source` within the `reference` path * diff --git a/compiler/src/dotty/tools/io/VirtualFile.scala b/compiler/src/dotty/tools/io/VirtualFile.scala index 6fb9859503f2..404289a6c8cf 100644 --- a/compiler/src/dotty/tools/io/VirtualFile.scala +++ b/compiler/src/dotty/tools/io/VirtualFile.scala @@ -40,15 +40,32 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF this.content = content } + /** + * Initializes this instance with the specified path + * and a name taken from the last path element. + * + * @param path the path of the virtual file to be created + * @param content the initial contents of the virtual file + * @return the created virtual file + */ + def this(path: JPath, content: Array[Byte]) = { + this(path.toString.replace(java.io.File.separatorChar, '/'), content) + this.jpath_ = path + } + private var content = Array.emptyByteArray + private var jpath_ : JPath = null + def absolute: AbstractFile = this /** Returns null. */ - def jpath: JPath = null + def jpath: JPath = jpath_ override def sizeOption: Option[Int] = Some(content.length) + override def exists: Boolean = true + def input : InputStream = new ByteArrayInputStream(content) override def output: OutputStream = { From 62fb6c7674ddec4a5f45dd2cbb8a1b32eb08d384 Mon Sep 17 00:00:00 2001 From: kasiaMarek Date: Thu, 29 May 2025 11:35:49 +0200 Subject: [PATCH 3/3] review fix --- compiler/src/dotty/tools/io/VirtualFile.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/io/VirtualFile.scala b/compiler/src/dotty/tools/io/VirtualFile.scala index 404289a6c8cf..93788990d368 100644 --- a/compiler/src/dotty/tools/io/VirtualFile.scala +++ b/compiler/src/dotty/tools/io/VirtualFile.scala @@ -49,7 +49,8 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF * @return the created virtual file */ def this(path: JPath, content: Array[Byte]) = { - this(path.toString.replace(java.io.File.separatorChar, '/'), content) + this(path.getFileName().toString(), path.toString()) + this.content = content this.jpath_ = path } @@ -59,11 +60,12 @@ class VirtualFile(val name: String, override val path: String) extends AbstractF def absolute: AbstractFile = this - /** Returns null. */ + /** Returns path, which might be a non-existing file or null. */ def jpath: JPath = jpath_ override def sizeOption: Option[Int] = Some(content.length) + /** Always returns true, even if jpath is a non-existing file. */ override def exists: Boolean = true def input : InputStream = new ByteArrayInputStream(content)