diff options
author | Alexandra Dima <alexandra.dima@jetbrains.com> | 2019-07-22 10:44:50 +0200 |
---|---|---|
committer | Samvel Abrahamyan <samvel1024@gmail.com> | 2019-10-12 14:33:07 +0200 |
commit | b5347266ee73d62659d01bdfe2d3444680a98747 (patch) | |
tree | 0e7452f50e574c50c953c7c93fcc359748cb742b /contrib | |
parent | 2e37532d915d54f61bc645faa6b0c73f29c5d9ea (diff) | |
download | mill-b5347266ee73d62659d01bdfe2d3444680a98747.tar.gz mill-b5347266ee73d62659d01bdfe2d3444680a98747.tar.bz2 mill-b5347266ee73d62659d01bdfe2d3444680a98747.zip |
Modified the compilation diagnostics reporter to send not only the currently generated diagnostic, but also all of the past diagnostics discovered for a certain source file. This will be compatible with the idea that each set of diagnostics for a certain file invalidates all other diagnostics received in the past.
Diffstat (limited to 'contrib')
4 files changed, 94 insertions, 71 deletions
diff --git a/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala b/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala index 24adaf1d..ba1dbcec 100644 --- a/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala +++ b/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala @@ -7,10 +7,11 @@ import java.nio.file.FileAlreadyExistsException import java.util.concurrent.{CancellationException, CompletableFuture, ExecutorService, Executors, Future} import upickle.default._ -import ch.epfl.scala.bsp4j.{BspConnectionDetails, BuildClient, CleanCacheParams, CompileParams, DidChangeBuildTarget, LogMessageParams, PublishDiagnosticsParams, ScalaTestClassesParams, ShowMessageParams, TaskFinishParams, TaskProgressParams, TaskStartParams, TestParams, WorkspaceBuildTargetsResult} +import ch.epfl.scala.bsp4j.{BspConnectionDetails, BuildClient, BuildTargetIdentifier, CleanCacheParams, CompileParams, CompileTask, DidChangeBuildTarget, LogMessageParams, PublishDiagnosticsParams, ScalaTestClassesParams, ScalacOptionsParams, ShowMessageParams, SourcesParams, TaskFinishParams, TaskProgressParams, TaskStartParams, TestParams, WorkspaceBuildTargetsResult} import mill._ -import mill.api.Strict -import mill.contrib.bsp.{BspLoggedReporter, MillBuildServer, ModuleUtils} +import mill.api.Result.{Aborted, Skipped} +import mill.api.{BspContext, Result, Strict} +import mill.contrib.bsp.{BspLoggedReporter, MillBspLogger, MillBuildServer, ModuleUtils, TaskParameters} import mill.define.{Command, Discover, ExternalModule, Target, Task} import mill.eval.Evaluator import mill.scalalib._ @@ -172,23 +173,24 @@ object MainMillBuildServer extends ExternalModule { } override def onBuildTaskFinish(params: TaskFinishParams): Unit = { - println("Task Finish: " + params) + //println("Task Finish: " + params) } override def onBuildPublishDiagnostics( params: PublishDiagnosticsParams ): Unit = { - diagnostics ++= List(params) + println("Diagnostics: " + params) } override def onBuildTargetDidChange(params: DidChangeBuildTarget): Unit = ??? } millServer.client = client millServer.initialized = true - println(millServer.buildTargetCleanCache( - new CleanCacheParams(millServer.millModules.map(m => millServer.moduleToTargetId(m)).asJava)).get) - println(millServer.buildTargetCompile( - new CompileParams(millServer.millModules.map(m => millServer.moduleToTargetId(m)).asJava)).get) - println("Diagnostics: " + client.diagnostics) + val compileParams = new CompileParams(millServer.moduleCodeToTargetId.values. + filter(t => millServer.targetIdToModule(t) != millServer.rootModule).toList.asJava) + val pool = millServer.getBspLoggedReporterPool(TaskParameters.fromCompileParams(compileParams), (t) => s"Started compiling target: $t", + "compile-task", (targetId: BuildTargetIdentifier) => new CompileTask(targetId)) + println(millServer.buildTargetCleanCache(new CleanCacheParams(millServer.moduleCodeToTargetId.values.toList.asJava)).get) + println(millServer.buildTargetCompile(compileParams).get) } /** 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 diff --git a/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala b/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala index 2c25a9fc..1666ed60 100644 --- a/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala +++ b/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala @@ -18,8 +18,6 @@ import sbt.internal.inc._ import xsbti.{Position, Problem, Severity} import xsbti.compile.{AnalysisContents, AnalysisStore, FileAnalysisStore} import xsbti.compile.analysis.SourceInfo - -import scala.collection.mutable.Map import mill.api.Result.{Failing, Failure, Success} import scala.collection.JavaConverters._ @@ -46,6 +44,7 @@ class MillBuildServer(evaluator: Evaluator, val millServerVersion: String = serverVersion var cancelator: () => Unit = () => () var millEvaluator: Evaluator = evaluator + var rootModule: JavaModule = ModuleUtils.getRootJavaModule(evaluator.rootModule) var millModules: Seq[JavaModule] = getMillModules(millEvaluator) var client: BuildClient = _ var moduleToTargetId: Predef.Map[JavaModule, BuildTargetIdentifier] = ModuleUtils.getModuleTargetIdMap( @@ -54,7 +53,7 @@ class MillBuildServer(evaluator: Evaluator, ) var targetIdToModule: Predef.Map[BuildTargetIdentifier, JavaModule] = targetToModule(moduleToTargetId) var moduleToTarget: Predef.Map[JavaModule, BuildTarget] = - ModuleUtils.millModulesToBspTargets(millModules, evaluator, List("scala", "java")) + ModuleUtils.millModulesToBspTargets(millModules, rootModule, evaluator, List("scala", "java")) var moduleCodeToTargetId: Predef.Map[Int, BuildTargetIdentifier] = for ( (targetId, module) <- targetIdToModule ) yield (targetId, module.hashCode()).swap @@ -247,14 +246,13 @@ class MillBuildServer(evaluator: Evaluator, l } - private[this] def getBspLoggedReporterPool(params: Parameters, taskStartMessage: String => String, + def getBspLoggedReporterPool(params: Parameters, taskStartMessage: String => String, taskStartDataKind: String, taskStartData: BuildTargetIdentifier => Object): Int => Option[ManagedLoggedReporter] = { (int: Int) => - val targetId = moduleCodeToTargetId(int) - val taskId = new TaskId(targetIdToModule(targetId).compile.hashCode.toString) if (moduleCodeToTargetId.contains(int)) { - println("Module: " + int) + val targetId = moduleCodeToTargetId(int) + val taskId = new TaskId(targetIdToModule(targetId).compile.hashCode.toString) val taskStartParams = new TaskStartParams(taskId) taskStartParams.setEventTime(System.currentTimeMillis()) taskStartParams.setData(taskStartData(targetId)) @@ -526,14 +524,15 @@ class MillBuildServer(evaluator: Evaluator, ev.rootModule.millInternal.segmentsToModules.values. collect { case m: scalalib.JavaModule => m - }.toSeq + }.toSeq ++ Seq(rootModule) } private[this] def recomputeTargets(): Unit = { + rootModule = ModuleUtils.getRootJavaModule(millEvaluator.rootModule) millModules = getMillModules(millEvaluator) moduleToTargetId = ModuleUtils.getModuleTargetIdMap(millModules, millEvaluator) targetIdToModule = targetToModule(moduleToTargetId) - moduleToTarget = ModuleUtils.millModulesToBspTargets(millModules, evaluator, List("scala", "java")) + moduleToTarget = ModuleUtils.millModulesToBspTargets(millModules, rootModule, evaluator, List("scala", "java")) } private[this] def handleExceptions[T, V](serverMethod: T => V, input: T): CompletableFuture[V] = { diff --git a/contrib/bsp/src/mill/contrib/bsp/ModuleUtils.scala b/contrib/bsp/src/mill/contrib/bsp/ModuleUtils.scala index d0db5fd0..36415c5f 100644 --- a/contrib/bsp/src/mill/contrib/bsp/ModuleUtils.scala +++ b/contrib/bsp/src/mill/contrib/bsp/ModuleUtils.scala @@ -31,40 +31,42 @@ object ModuleUtils { dummyModule, DummyLogger) def millModulesToBspTargets(modules: Seq[JavaModule], + rootModule: JavaModule, evaluator: Evaluator, supportedLanguages: List[String]): Predef.Map[JavaModule, BuildTarget] = { val moduleIdMap = getModuleTargetIdMap(modules, evaluator) - val rootModule = getRootJavaModule(evaluator.rootModule) - var moduleToTarget = Predef.Map[JavaModule, BuildTarget]( - rootModule -> getRootTarget(rootModule, evaluator) - ) + var moduleToTarget = Predef.Map[JavaModule, BuildTarget]() for ( module <- modules ) { - val dataBuildTarget = computeScalaBuildTarget(module, evaluator) - val capabilities = getModuleCapabilities(module, evaluator) - val buildTargetTag: List[String] = module match { - case m: TestModule => List(BuildTargetTag.TEST) - case m: JavaModule => List(BuildTargetTag.LIBRARY, BuildTargetTag.APPLICATION) + if (module == rootModule) { + moduleToTarget ++= Map(module -> getRootTarget(module, evaluator)) + } else { + val dataBuildTarget = computeScalaBuildTarget(module, evaluator) + val capabilities = getModuleCapabilities(module, evaluator) + val buildTargetTag: List[String] = module match { + case m: TestModule => List(BuildTargetTag.TEST) + case m: JavaModule => List(BuildTargetTag.LIBRARY, BuildTargetTag.APPLICATION) + } + + val dependencies = module match { + case m: JavaModule => m.moduleDeps.map(dep => moduleIdMap(dep)).toList.asJava + } + + val buildTarget = new BuildTarget(moduleIdMap(module), + buildTargetTag.asJava, + supportedLanguages.asJava, + dependencies, + capabilities) + if (module.isInstanceOf[ScalaModule]) { + buildTarget.setDataKind("scala") + } + buildTarget.setData(dataBuildTarget) + buildTarget.setDisplayName(moduleName(module.millModuleSegments)) + buildTarget.setBaseDirectory(module.intellijModulePath.toNIO.toAbsolutePath.toUri.toString) + + if (!moduleToTarget.contains(module)) moduleToTarget ++= Map(module -> buildTarget) } - - val dependencies = module match { - case m: JavaModule => m.moduleDeps.map(dep => moduleIdMap(dep)).toList.asJava - } - - val buildTarget = new BuildTarget(moduleIdMap(module), - buildTargetTag.asJava, - supportedLanguages.asJava, - dependencies, - capabilities) - if (module.isInstanceOf[ScalaModule]) { - buildTarget.setDataKind("scala") - } - buildTarget.setData(dataBuildTarget) - buildTarget.setDisplayName(moduleName(module.millModuleSegments)) - buildTarget.setBaseDirectory(module.intellijModulePath.toNIO.toAbsolutePath.toUri.toString) - - if (!moduleToTarget.contains(module)) moduleToTarget ++= Map(module -> buildTarget) } moduleToTarget @@ -168,10 +170,7 @@ object ModuleUtils { } def getModuleTargetIdMap(modules: Seq[JavaModule], evaluator:Evaluator): Predef.Map[JavaModule, BuildTargetIdentifier] = { - var moduleToTarget = Map[JavaModule, BuildTargetIdentifier]( - getRootJavaModule(evaluator.rootModule) -> new BuildTargetIdentifier(evaluator.rootModule.millSourcePath. - toNIO.toAbsolutePath.toUri.toString) - ) + var moduleToTarget = Map[JavaModule, BuildTargetIdentifier]() for ( module <- modules ) { moduleToTarget ++= Map(module -> new BuildTargetIdentifier( |