Merge pull request #7795 from Friendseeker/bsp-forward-port

[2.x] Fix stale bsp diagnostics
This commit is contained in:
eugene yokota 2024-10-21 18:04:29 -04:00 committed by GitHub
commit acf8ec77c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 81 additions and 3 deletions

View File

@ -25,6 +25,7 @@ import xsbti.{
import scala.jdk.CollectionConverters.*
import scala.collection.mutable
import java.nio.file.Path
/**
* Provides methods for sending success and failure reports and publishing diagnostics.
@ -88,7 +89,7 @@ final class BuildServerReporterImpl(
import sbt.internal.inc.JavaInterfaceUtil._
private lazy val exchange = StandardMain.exchange
private val problemsByFile = mutable.Map[VirtualFileRef, Vector[Problem]]()
private val problemsByFile = mutable.Map[Path, Vector[Problem]]()
// sometimes the compiler returns a fake position such as <macro>
// on Windows, this causes InvalidPathException (see #5994 and #6720)
@ -112,9 +113,10 @@ final class BuildServerReporterImpl(
override def sendFailureReport(sources: Array[VirtualFile]): Unit = {
for (source <- sources) {
val problems = problemsByFile.getOrElse(source, Vector.empty)
val problems = problemsByFile.getOrElse(converter.toPath(source), Vector.empty)
sendReport(source, problems)
}
notifyFirstReport()
}
private def sendReport(source: VirtualFileRef, problems: Vector[Problem]): Unit = {
@ -150,7 +152,11 @@ final class BuildServerReporterImpl(
id <- problem.position.sourcePath.toOption
(document, diagnostic) <- mapProblemToDiagnostic(problem)
} {
val fileRef = VirtualFileRef.of(id)
// Note: We're putting the real path in `fileRef` because the `id` String can take
// two forms, either a ${something}/relativePath, or the absolute path of the source.
// But where we query this, we always have _only_ a ${something}/relativePath available.
// So here we "normalize" to the real path.
val fileRef = converter.toPath(VirtualFileRef.of(id))
problemsByFile(fileRef) = problemsByFile.getOrElse(fileRef, Vector.empty) :+ problem
val params = PublishDiagnosticsParams(

View File

@ -252,6 +252,78 @@ class BuildServerTest extends AbstractServerTest {
)
}
test("buildTarget/compile [Java diagnostics] clear stale warnings") {
val buildTarget = buildTargetUri("javaProj", "Compile")
val testFile = new File(svr.baseDirectory, s"java-proj/src/main/java/example/Hello.java")
val otherBuildFile = new File(svr.baseDirectory, "force-java-out-of-process-compiler.sbt")
// Setting `javaHome` will force SBT to shell out to an external Java compiler instead
// of using the local compilation service offered by the JVM running this SBT instance.
IO.write(
otherBuildFile,
"""
|lazy val javaProj = project
| .in(file("java-proj"))
| .settings(
| javacOptions += "-Xlint:all",
| javaHome := Some(file(System.getProperty("java.home")))
| )
|""".stripMargin
)
reloadWorkspace()
compile(buildTarget)
assertMessage(
"build/publishDiagnostics",
"Hello.java",
""""severity":2""",
"""found raw type: List"""
)(message = "should send publishDiagnostics with severity 2 for Hello.java")
assertMessage(
"build/publishDiagnostics",
"Hello.java",
""""severity":1""",
"""incompatible types: int cannot be converted to String"""
)(
message = "should send publishDiagnostics with severity 1 for Hello.java"
)
// Note the messages changed slightly in both cases. That's interesting
IO.write(
testFile,
"""|package example;
|
|import java.util.List;
|import java.util.ArrayList;
|
|class Hello {
| public static void main(String[] args) {
| List<String> list = new ArrayList<>();
| String msg = "42";
| System.out.println(msg);
| }
|}
|""".stripMargin
)
compile(buildTarget)
assertMessage(
"build/publishDiagnostics",
"Hello.java",
"\"diagnostics\":[]",
"\"reset\":true"
)(
message = "should send publishDiagnostics with empty diagnostics"
)
IO.delete(otherBuildFile)
reloadWorkspace()
()
}
test("buildTarget/scalacOptions, buildTarget/javacOptions") {
val buildTargets = Seq(
buildTargetUri("util", "Compile"),