diff --git a/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/bep/BepServer.kt b/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/bep/BepServer.kt index b62e1298d..e73674ced 100644 --- a/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/bep/BepServer.kt +++ b/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/bep/BepServer.kt @@ -100,6 +100,9 @@ class BepServer( private fun processProgressEvent(event: BuildEventStreamProtos.BuildEvent) { if (event.hasProgress()) { + if (target != null) { + processDiagnosticText(event.progress.stderr, target.uri, true) + } // TODO https://youtrack.jetbrains.com/issue/BAZEL-622 // bepLogger.onProgress(event.getProgress()); } @@ -185,7 +188,7 @@ class BepServer( try { val path = Paths.get(URI.create(actionEvent.stderr.uri)) val stdErrText = Files.readString(path) - processDiagnosticText(stdErrText, label) + processDiagnosticText(stdErrText, label, false) } catch (e: FileSystemNotFoundException) { LOGGER.warn(e) } catch (e: IOException) { @@ -193,24 +196,26 @@ class BepServer( } } BuildEventStreamProtos.File.FileCase.CONTENTS -> { - processDiagnosticText(actionEvent.stderr.contents.toStringUtf8(), label) + processDiagnosticText(actionEvent.stderr.contents.toStringUtf8(), label, false) } else -> { - processDiagnosticText("", label) + processDiagnosticText("", label, false) } } } - private fun processDiagnosticText(stdErrText: String, targetLabel: String) { - val events = - diagnosticsService.extractDiagnostics( - stdErrText, targetLabel, startedEvents.first.value - ) - events.forEach(Consumer { publishDiagnosticsParams: PublishDiagnosticsParams? -> - bspClient.onBuildPublishDiagnostics( - publishDiagnosticsParams - ) - }) + private fun processDiagnosticText(stdErrText: String, targetLabel: String, diagnosticsFromProgress: Boolean) { + if (startedEvents.isNotEmpty() && stdErrText.isNotEmpty()) { + val events = + diagnosticsService.extractDiagnostics( + stdErrText, targetLabel, startedEvents.first.value, diagnosticsFromProgress + ) + events.forEach(Consumer { publishDiagnosticsParams: PublishDiagnosticsParams? -> + bspClient.onBuildPublishDiagnostics( + publishDiagnosticsParams + ) + }) + } } private fun consumeCompletedEvent(event: BuildEventStreamProtos.BuildEvent) { diff --git a/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsParser.kt b/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsParser.kt index 4ffec6f07..bee8cafdf 100644 --- a/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsParser.kt +++ b/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsParser.kt @@ -2,9 +2,9 @@ package org.jetbrains.bsp.bazel.server.diagnostics class DiagnosticsParser { - fun parse(bazelOutput: String, target: String): List { + fun parse(bazelOutput: String, target: String, onlyKnownFiles: Boolean): List { val output = prepareOutput(bazelOutput, target) - val diagnostics = collectDiagnostics(output) + val diagnostics = collectDiagnostics(output, onlyKnownFiles) return deduplicate(diagnostics) } @@ -14,7 +14,7 @@ class DiagnosticsParser { return Output(relevantLines, target) } - private fun collectDiagnostics(output: Output): List { + private fun collectDiagnostics(output: Output, onlyKnownFiles: Boolean): List { val diagnostics = mutableListOf() while (output.nonEmpty()) { for (parser in Parsers) { @@ -26,7 +26,7 @@ class DiagnosticsParser { } } - if (diagnostics.isEmpty()) { + if (diagnostics.isEmpty() && !onlyKnownFiles) { diagnostics.add( Diagnostic( position = Position(0, 0), diff --git a/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsService.kt b/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsService.kt index 0bb999263..6e22186d4 100644 --- a/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsService.kt +++ b/server/src/main/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsService.kt @@ -1,11 +1,9 @@ package org.jetbrains.bsp.bazel.server.diagnostics import ch.epfl.scala.bsp4j.BuildTargetIdentifier -import ch.epfl.scala.bsp4j.Diagnostic import ch.epfl.scala.bsp4j.PublishDiagnosticsParams import ch.epfl.scala.bsp4j.TextDocumentIdentifier import java.nio.file.Path -import java.util.concurrent.ConcurrentHashMap import java.util.Collections /** @@ -17,16 +15,20 @@ class DiagnosticsService(workspaceRoot: Path, private val hasAnyProblems: Mutabl private val parser = DiagnosticsParser() private val mapper = DiagnosticBspMapper(workspaceRoot) + /* Warnings are reported before the target completed event, when everything is cleared. so we want to avoid removing them */ + private val updatedInThisRun = mutableSetOf() fun getBspState() = Collections.unmodifiableMap(hasAnyProblems) fun extractDiagnostics( bazelOutput: String, targetLabel: String, - originId: String? + originId: String?, + diagnosticsFromProgress: Boolean ): List { - val parsedDiagnostics = parser.parse(bazelOutput, targetLabel) + val parsedDiagnostics = parser.parse(bazelOutput, targetLabel, diagnosticsFromProgress) val events = mapper.createDiagnostics(parsedDiagnostics, originId) + if (diagnosticsFromProgress) updatedInThisRun.addAll(events) updateProblemState(events) return events } @@ -34,6 +36,10 @@ class DiagnosticsService(workspaceRoot: Path, private val hasAnyProblems: Mutabl fun clearFormerDiagnostics(targetLabel: String): List { val docs = hasAnyProblems[targetLabel] hasAnyProblems.remove(targetLabel) + if (updatedInThisRun.isNotEmpty()) { + hasAnyProblems[targetLabel] = updatedInThisRun.map { it.textDocument }.toSet() + updatedInThisRun.clear() + } return docs ?.map { PublishDiagnosticsParams(it, BuildTargetIdentifier(targetLabel), emptyList(), true)} .orEmpty() diff --git a/server/src/test/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsServiceTest.kt b/server/src/test/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsServiceTest.kt index 9d9c2eec5..04a00a353 100644 --- a/server/src/test/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsServiceTest.kt +++ b/server/src/test/kotlin/org/jetbrains/bsp/bazel/server/diagnostics/DiagnosticsServiceTest.kt @@ -538,7 +538,7 @@ class DiagnosticsServiceTest { diagnosticsBeforeError.shouldBeEmpty() // Extract the diagnostics from BEP, there's an error in `Test.scala` of "//path/to/package:test". - service.extractDiagnostics(output, "//path/to/package:test", null) + service.extractDiagnostics(output, "//path/to/package:test", null, false) // Assert that state is updated service.getBspState().keys.shouldHaveSize(1) @@ -626,8 +626,8 @@ class DiagnosticsServiceTest { ) ) - service.extractDiagnostics(output1, "//path/to/package:test", null) - service.extractDiagnostics(output2, "//path/to/package2:test", null) + service.extractDiagnostics(output1, "//path/to/package:test", null, false) + service.extractDiagnostics(output2, "//path/to/package2:test", null, false) // Assert that state is updated service.getBspState().keys shouldContainExactlyInAnyOrder listOf( @@ -675,6 +675,6 @@ class DiagnosticsServiceTest { } private fun extractDiagnostics(output: String, buildTarget: String): List? { - return DiagnosticsService(workspacePath, ConcurrentHashMap()).extractDiagnostics(output, buildTarget, null) + return DiagnosticsService(workspacePath, ConcurrentHashMap()).extractDiagnostics(output, buildTarget, null, false) } }