diff options
Diffstat (limited to 'contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala')
-rw-r--r-- | contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala b/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala index 8ab17d7e..8e537fb8 100644 --- a/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala +++ b/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala @@ -1,16 +1,19 @@ package mill.contrib.bsp import java.io.File +import java.util.concurrent.{ConcurrentHashMap, ConcurrentMap} -import ch.epfl.scala.bsp4j.{BuildServer, BuildTargetIdentifier, CompileReport, InverseSourcesParams, ScalaBuildServer, StatusCode, TaskFinishParams, TaskId, TextDocumentIdentifier} +import ch.epfl.scala.bsp4j.{BuildServer, BuildTargetIdentifier, CompileReport, Diagnostic, InverseSourcesParams, ScalaBuildServer, StatusCode, TaskFinishParams, TaskId, TextDocumentIdentifier} import ch.epfl.scala.{bsp4j => bsp} import mill.api.BspContext +import org.eclipse.lsp4j.PublishDiagnosticsParams import sbt.internal.inc.ManagedLoggedReporter import sbt.internal.inc.schema.Position import sbt.internal.util.ManagedLogger import xsbti.{Problem, Severity} import scala.collection.JavaConverters._ +import scala.collection.concurrent import scala.compat.java8.OptionConverters._ import scala.io.Source @@ -24,6 +27,8 @@ class BspLoggedReporter(client: bsp.BuildClient, var errors = 0 var warnings = 0 var infos = 0 + var diagnosticMap: concurrent.Map[TextDocumentIdentifier, bsp.PublishDiagnosticsParams] = + new ConcurrentHashMap[TextDocumentIdentifier, bsp.PublishDiagnosticsParams]().asScala override def logError(problem: Problem): Unit = { client.onBuildPublishDiagnostics(getDiagnostics(problem, targetId, compilationOriginId)) @@ -61,31 +66,20 @@ class BspLoggedReporter(client: bsp.BuildClient, // associated to it, then the document field of the diagnostic is set to the uri of the target def getDiagnostics(problem: Problem, targetId: bsp.BuildTargetIdentifier, originId: Option[String]): bsp.PublishDiagnosticsParams = { + val diagnostic = getSingleDiagnostic(problem) val sourceFile = problem.position().sourceFile().asScala - val start = new bsp.Position( - problem.position.startLine.asScala.getOrElse(problem.position.line.asScala.getOrElse(0)), - problem.position.startOffset.asScala.getOrElse(problem.position.offset.asScala.getOrElse(0))) - val end = new bsp.Position( - problem.position.endLine.asScala.getOrElse(problem.position.line.asScala.getOrElse(0)), - problem.position.endOffset.asScala.getOrElse(problem.position.offset.asScala.getOrElse(0))) - val diagnostic = new bsp.Diagnostic(new bsp.Range(start, end), problem.message) - diagnostic.setCode(problem.position.lineContent) - diagnostic.setSource("compiler from mill") - diagnostic.setSeverity( problem.severity match { - case Severity.Info => bsp.DiagnosticSeverity.INFORMATION - case Severity.Error => bsp.DiagnosticSeverity.ERROR - case Severity.Warn => bsp.DiagnosticSeverity.WARNING - } - ) - val textDocument = sourceFile.getOrElse(None) match { + val textDocument = new TextDocumentIdentifier( + sourceFile.getOrElse(None) match { case None => targetId.getUri case f: File => f.toPath.toUri.toString - } - val params = new bsp.PublishDiagnosticsParams( - new bsp.TextDocumentIdentifier(textDocument), - targetId, List(diagnostic).asJava, true) + }) + val params = new bsp.PublishDiagnosticsParams(textDocument, + targetId, + appendDiagnostics(textDocument, diagnostic).asJava + , true) if (originId.nonEmpty) { params.setOriginId(originId.get) } + diagnosticMap.put(textDocument, params) params } @@ -93,6 +87,35 @@ class BspLoggedReporter(client: bsp.BuildClient, if (errors > 0) StatusCode.ERROR else StatusCode.OK } + private[this] def appendDiagnostics(textDocument: TextDocumentIdentifier, + currentDiagnostic: Diagnostic): List[Diagnostic] = { + diagnosticMap.getOrElse(textDocument, new bsp.PublishDiagnosticsParams( + textDocument, + targetId, + List.empty[Diagnostic].asJava, true)).getDiagnostics.asScala.toList ++ + List(currentDiagnostic) + } + + private[this] def getSingleDiagnostic(problem: Problem): Diagnostic ={ + + val start = new bsp.Position( + problem.position.startLine.asScala.getOrElse(problem.position.line.asScala.getOrElse(0)), + problem.position.startOffset.asScala.getOrElse(problem.position.offset.asScala.getOrElse(0))) + val end = new bsp.Position( + problem.position.endLine.asScala.getOrElse(problem.position.line.asScala.getOrElse(0)), + problem.position.endOffset.asScala.getOrElse(problem.position.offset.asScala.getOrElse(0))) + val diagnostic = new bsp.Diagnostic(new bsp.Range(start, end), problem.message) + diagnostic.setCode(problem.position.lineContent) + diagnostic.setSource("compiler from mill") + diagnostic.setSeverity( problem.severity match { + case Severity.Info => bsp.DiagnosticSeverity.INFORMATION + case Severity.Error => bsp.DiagnosticSeverity.ERROR + case Severity.Warn => bsp.DiagnosticSeverity.WARNING + } + ) + diagnostic + } + private[this] def getErrorCode(file: Option[File], start: bsp.Position, end: bsp.Position, position: xsbti.Position): String = { file match { case None => position.lineContent |