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 = { 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 + )