diff --git a/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala b/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala index 2dc64a10e9d..b8810ab4e67 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala @@ -2103,10 +2103,17 @@ class MetalsLspService( ): CompletableFuture[WorkspaceEdit] = CancelTokens.future { _ => val moves = params.getFiles.asScala.toSeq.map { rename => - packageProvider.willMovePath( - rename.getOldUri().toAbsolutePath, - rename.getNewUri().toAbsolutePath, - ) + val oldPath = rename.getOldUri().toAbsolutePath + val newPath = rename.getNewUri().toAbsolutePath + /* Changing package for files moved out of the workspace will cause unexpected issues + * This showed up with emacs automated backups. + */ + if (newPath.startWith(workspace)) + packageProvider.willMovePath(oldPath, newPath) + else + Future.successful( + new WorkspaceEdit(Map.empty[String, util.List[TextEdit]].asJava) + ) } Future.sequence(moves).map(_.mergeChanges) } diff --git a/mtags/src/main/scala/scala/meta/internal/mtags/CommonMtagsEnrichments.scala b/mtags/src/main/scala/scala/meta/internal/mtags/CommonMtagsEnrichments.scala index c4216d8c163..6623bc280d1 100644 --- a/mtags/src/main/scala/scala/meta/internal/mtags/CommonMtagsEnrichments.scala +++ b/mtags/src/main/scala/scala/meta/internal/mtags/CommonMtagsEnrichments.scala @@ -579,6 +579,9 @@ trait CommonMtagsEnrichments { None } } + + def startWith(other: AbsolutePath): Boolean = + path.toNIO.startsWith(other.toNIO) } implicit class XtensionJavaPriorityQueue[A](q: util.PriorityQueue[A]) { diff --git a/tests/unit/src/test/scala/tests/RenameFilesLspSuite.scala b/tests/unit/src/test/scala/tests/RenameFilesLspSuite.scala index 49760578474..4ae292eef3b 100644 --- a/tests/unit/src/test/scala/tests/RenameFilesLspSuite.scala +++ b/tests/unit/src/test/scala/tests/RenameFilesLspSuite.scala @@ -1,5 +1,7 @@ package tests +import java.nio.file.Files + class RenameFilesLspSuite extends BaseRenameFilesLspSuite("rename_files") { private val prefix = "a/src/main/scala" @@ -34,6 +36,19 @@ class RenameFilesLspSuite extends BaseRenameFilesLspSuite("rename_files") { expectedRenames = Map("A" -> "A.B"), ) + /* We should not rename if moving outside the workspace */ + renamed( + "outside-workspace", + s"""|/$prefix/A/Sun.scala + |package A + |object Sun + |""".stripMargin, + fileRenames = Map( + s"$prefix/A/Sun.scala" -> Files.createTempFile("Sun", ".scala").toString() + ), + expectedRenames = Map.empty, + ) + renamed( "single-package-non-matching-structure", s"""|/$prefix/A/B/Sun.scala