From e004fe3874067d743b38d293b5d4d3e4dc2bd658 Mon Sep 17 00:00:00 2001 From: Katarzyna Marek Date: Tue, 24 Oct 2023 11:01:46 +0200 Subject: [PATCH] improvement: recompile focused file if depends on last compiled bt --- .../meta/internal/metals/Compilations.scala | 12 +++- .../internal/metals/MetalsLspService.scala | 7 ++- .../test/scala/tests/DidFocusLspSuite.scala | 59 ++++++++++++++++++- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/metals/src/main/scala/scala/meta/internal/metals/Compilations.scala b/metals/src/main/scala/scala/meta/internal/metals/Compilations.scala index 5889eaad22b..0eabb90d8a5 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/Compilations.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/Compilations.scala @@ -91,10 +91,20 @@ final class Compilations( } yield result } - def compileFiles(paths: Seq[AbsolutePath]): Future[Unit] = { + def compileFiles( + paths: Seq[AbsolutePath], + focusedDocumentBuildTarget: Option[BuildTargetIdentifier], + ): Future[Unit] = { for { targets <- expand(paths) _ <- compileBatch(targets) + _ <- focusedDocumentBuildTarget match { + case Some(bt) + if !targets.contains(bt) && + buildTargets.isInverseDependency(bt, targets.toList) => + compileBatch(bt) + case _ => Future.successful(()) + } _ <- compileWorksheets(paths) } yield () } 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 8ba4ebc850d..86faa1bfe9b 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/MetalsLspService.scala @@ -1330,11 +1330,13 @@ class MetalsLspService( paths.foreach { path => fingerprints.add(path, FileIO.slurp(path, charset)) } + Future .sequence( List( Future(indexer.reindexWorkspaceSources(paths)), - compilations.compileFiles(paths), + compilations + .compileFiles(paths, Option(focusedDocumentBuildTarget.get())), onBuildChanged(paths).ignoreValue, Future.sequence(paths.map(onBuildToolAdded)), ) ++ paths.map(f => Future(interactiveSemanticdbs.textDocument(f))) @@ -1346,7 +1348,8 @@ class MetalsLspService( Future .sequence( List( - compilations.compileFiles(List(path)), + compilations + .compileFiles(List(path), Option(focusedDocumentBuildTarget.get())), Future { diagnostics.didDelete(path) testProvider.onFileDelete(path) diff --git a/tests/unit/src/test/scala/tests/DidFocusLspSuite.scala b/tests/unit/src/test/scala/tests/DidFocusLspSuite.scala index 830e7564334..73767cae753 100644 --- a/tests/unit/src/test/scala/tests/DidFocusLspSuite.scala +++ b/tests/unit/src/test/scala/tests/DidFocusLspSuite.scala @@ -21,7 +21,8 @@ class DidFocusLspSuite extends BaseLspSuite("did-focus") { | "a": {}, | "b": { | "dependsOn": ["a"] - | } + | }, + | "c": {} |} |/a/src/main/scala/a/A.scala |package a @@ -38,6 +39,11 @@ class DidFocusLspSuite extends BaseLspSuite("did-focus") { |object C { | val z: Int = a.A.x |} + |/c/src/main/scala/c/C.scala + |package c + |object E { + | val i: Int = "aaa" + |} """.stripMargin ) _ <- server.didOpen("a/src/main/scala/a/A.scala") @@ -48,6 +54,7 @@ class DidFocusLspSuite extends BaseLspSuite("did-focus") { _ = assert(didCompile == AlreadyCompiled) didCompile <- server.didFocus("b/src/main/scala/b/B.scala") _ = assert(didCompile == AlreadyCompiled) + didCompile <- server.didFocus("c/src/main/scala/c/C.scala") _ <- server.didSave("a/src/main/scala/a/A.scala")( _.replace("val x = 1", "val x = \"string\"") ) @@ -68,6 +75,56 @@ class DidFocusLspSuite extends BaseLspSuite("did-focus") { ) } yield () } + + test("compiled-focused") { + cleanWorkspace() + for { + _ <- initialize( + """ + |/metals.json + |{ + | "a": {}, + | "b": { + | "dependsOn": ["a"] + | } + |} + |/a/src/main/scala/a/A.scala + |package a + |object A { + | val x = 1 + |} + |/a/src/main/scala/a/A2.scala + |package a + |object A2 { + | val y = 1 + |} + |/b/src/main/scala/b/B.scala + |package b + |object C { + | val z: Int = a.A.x + |} + """.stripMargin + ) + _ <- server.didOpen("a/src/main/scala/a/A.scala") + _ <- server.didOpen("b/src/main/scala/b/B.scala") + _ = assertNoDiagnostics() + _ = fakeTime.elapseSeconds(10) + didCompile <- server.didFocus("b/src/main/scala/b/B.scala") + _ <- server.didSave("a/src/main/scala/a/A.scala")( + _.replace("val x = 1", "val x = \"string\"") + ) + _ = fakeTime.elapseSeconds(10) + _ = assertNoDiff( + client.workspaceDiagnostics, + """|b/src/main/scala/b/B.scala:3:16: error: type mismatch; + | found : String + | required: Int + | val z: Int = a.A.x + | ^^^^^ + |""".stripMargin, + ) + } yield () + } } // https://github.com/scalameta/metals/issues/497