Skip to content

Commit 66018c7

Browse files
committed
refactor: change data in bsp.Diagnostic to contain a workspaceEdit
This change is part of the discussion that we had at the Scala Tooling Summit where we decided that using a `WorkspaceEdit` rather than a `TextEdit` provided a more future-proof way of actionable diagnostics since it's richer. This PR makes that changes, but in a limited way. - It only actually changes this when we go from the `Diagnostic` to a BSP Diagnostic. It doesn't for example change the `TextEdit` that the internal representation of Diagnostic has. That's left as is to minimize changes internally. - Right now really only `changes` are supported in the `WorkspaceEdit` mainly because that's all we really need at this time. In the future this could be expanded to use the richer `documentChanges` if the BSP client supports it. - This also changes the structure of `data` slightly to not have the actual edit be at the top level and instead nests it under an `edit` key. There is no gaurauntee that we won't have other keys in `data` in the future, so this sort of allows for that and ensures that we don't get stuck with only being able to have the actual `WorkspaceEdit` at the top level in the `data` object. Fixes #1957
1 parent 6661a22 commit 66018c7

File tree

4 files changed

+65
-14
lines changed

4 files changed

+65
-14
lines changed

modules/build/src/main/scala/scala/build/bsp/BspClient.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import java.nio.file.Paths
88
import java.util.concurrent.{ConcurrentHashMap, ExecutorService}
99

1010
import scala.build.Position.File
11-
import scala.build.bsp.protocol.TextEdit
11+
import scala.build.bsp.protocol.*
1212
import scala.build.errors.{BuildException, CompositeBuildException, Diagnostic, Severity}
1313
import scala.build.postprocessing.LineConversion
1414
import scala.build.{BloopBuildClient, GeneratedSource, Logger}
@@ -223,7 +223,10 @@ class BspClient(
223223

224224
diag.textEdit.foreach { textEdit =>
225225
val bTextEdit = TextEdit(range, textEdit.newText)
226-
bDiag.setData(bTextEdit.toJsonTree())
226+
val workspaceEdit =
227+
WorkspaceEdit(changes = Map(path.toNIO.toUri().toString() -> Array(bTextEdit)))
228+
val data = DiagnosticData(edits = Array(workspaceEdit))
229+
bDiag.setData(data.toJsonTree())
227230
}
228231
bDiag.setSeverity(diag.severity.toBsp4j)
229232
bDiag.setSource("scala-cli")
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package scala.build.bsp.protocol
2+
3+
import ch.epfl.scala.bsp4j as b
4+
import com.google.gson.{Gson, JsonElement}
5+
6+
/** Representation for the data field in a bsp.Diagnostic.
7+
*
8+
* For now this only contains an edit, but there is nothing from keeping it having more field in
9+
* the future.
10+
* @param edit
11+
* The Workspace edit attatched to the Diagnostic.
12+
*/
13+
case class DiagnosticData(edits: Array[WorkspaceEdit]) {
14+
15+
/** Go from the DiagnosticData to Json. This will result in each param being a field in the
16+
* object.
17+
*
18+
* @return
19+
* the JsonElement
20+
*/
21+
def toJsonTree(): JsonElement = new Gson().toJsonTree(this)
22+
}
23+
24+
/** A WorkspaceEdit meant to mimic the LSP WorkspaceEdit.
25+
*
26+
* https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspaceEdit
27+
*
28+
* For now this only utilizes changes, hence the default empty for both documentChanges and
29+
* changeAnnotations. In the future when we support more operations like, CreateFile, RenameFile,
30+
* etc we can expand on this and change the type of documentChanges to actually be an
31+
* Array[TextDocumentEdit] | Array[TextDocumentEditTypes].
32+
*
33+
* @param changes
34+
* A Map of the URI that contains the diagnostic to the TextEdits that it contains.
35+
* @param documentChanges
36+
* NOT CURRENTLY USED
37+
* @param changeAnnotations
38+
* NOT CURRENTLY USED
39+
*/
40+
case class WorkspaceEdit(
41+
changes: Map[String, Array[TextEdit]],
42+
documentChanges: Array[Object] = Array.empty,
43+
changeAnnotations: Map[String, Object] = Map.empty
44+
)
45+
46+
/** A TextEdit meant to mimic the LSP TextEdit.
47+
*
48+
* https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textEdit
49+
*/
50+
case class TextEdit(range: b.Range, newText: String)

modules/build/src/main/scala/scala/build/bsp/protocol/TextEdit.scala

Lines changed: 0 additions & 8 deletions
This file was deleted.

modules/cli/src/main/scala/scala/cli/internal/CliLogger.scala

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import org.scalajs.logging.{Level => ScalaJsLevel, Logger => ScalaJsLogger, Scal
99

1010
import java.io.PrintStream
1111

12-
import scala.build.bsp.protocol.TextEdit
12+
import scala.build.bsp.protocol.*
1313
import scala.build.errors.{BuildException, CompositeBuildException, Diagnostic, Severity}
1414
import scala.build.internal.CustomProgressBarRefreshDisplay
1515
import scala.build.{ConsoleBloopBuildClient, Logger, Position}
@@ -83,9 +83,15 @@ class CliLogger(
8383
diag.setSeverity(severity.toBsp4j)
8484
diag.setSource("scala-cli")
8585

86-
for (textEdit <- textEditOpt) {
87-
val bTextEdit = TextEdit(range, textEdit.newText)
88-
diag.setData(bTextEdit.toJsonTree())
86+
(textEditOpt, f.path) match {
87+
case (Some(textEdit), Right(path)) =>
88+
val bTextEdit = TextEdit(range, textEdit.newText)
89+
val workspaceEdit = WorkspaceEdit(changes =
90+
Map(path.toNIO.toUri().toString() -> Array(bTextEdit))
91+
)
92+
val data = DiagnosticData(edits = Array(workspaceEdit))
93+
diag.setData(data.toJsonTree())
94+
case _ => ()
8995
}
9096

9197
for (file <- f.path) {

0 commit comments

Comments
 (0)