Skip to content

Commit 6de8222

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 gaurantee 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 83b1679 commit 6de8222

File tree

4 files changed

+62
-12
lines changed

4 files changed

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

1111
import scala.build.blooprifle.BloopRifleLogger
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}
@@ -85,7 +85,11 @@ class CliLogger(
8585

8686
for (textEdit <- textEditOpt) {
8787
val bTextEdit = TextEdit(range, textEdit.newText)
88-
diag.setData(bTextEdit.toJsonTree())
88+
val workspaceEdit = WorkspaceEdit(changes =
89+
Map(f.path.getOrElse(os.Path("")).toNIO.toUri().toString() -> Array(bTextEdit))
90+
)
91+
val data = DiagnosticData(workspaceEdit)
92+
diag.setData(data.toJsonTree())
8993
}
9094

9195
for (file <- f.path) {

0 commit comments

Comments
 (0)