summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandra Dima <alexandra.dima@jetbrains.com>2019-07-10 17:12:12 +0200
committerSamvel Abrahamyan <samvel1024@gmail.com>2019-10-12 14:32:58 +0200
commit0d53a6e057ae24ecf0bfd5bf0929310723c31282 (patch)
tree1503d4f04ff8c4bfb54f3ae841293ae20076eb8b
parentb71748b1b58da3b70ceb9290257ed688b71fbe21 (diff)
downloadmill-0d53a6e057ae24ecf0bfd5bf0929310723c31282.tar.gz
mill-0d53a6e057ae24ecf0bfd5bf0929310723c31282.tar.bz2
mill-0d53a6e057ae24ecf0bfd5bf0929310723c31282.zip
Implemented support for publishing compilation diagnostics through the custom BspLoggedReporter reporter. Patched the mill.api.Ctx data structure as well as the evaluate() method on mill's Evaluator in order to accept a potential reporter from the outside, or use a default value if none is given.
-rw-r--r--contrib/bsp/src/mill/contrib/MainMillBuildServer.scala30
-rw-r--r--contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala82
-rw-r--r--contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala152
-rw-r--r--contrib/bsp/src/mill/contrib/bsp/ModuleUtils.scala3
-rw-r--r--main/api/src/mill/api/Ctx.scala5
-rw-r--r--main/core/src/eval/Evaluator.scala27
-rw-r--r--scalalib/api/src/ZincWorkerApi.scala8
-rw-r--r--scalalib/src/JavaModule.scala9
-rw-r--r--scalalib/src/ScalaModule.scala7
-rw-r--r--scalalib/worker/src/ZincWorkerImpl.scala43
-rw-r--r--scratch/build.sc4
11 files changed, 323 insertions, 47 deletions
diff --git a/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala b/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala
index a8508ab6..7caaf5d3 100644
--- a/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala
+++ b/contrib/bsp/src/mill/contrib/MainMillBuildServer.scala
@@ -7,10 +7,10 @@ import java.nio.file.FileAlreadyExistsException
import java.util.concurrent.{CancellationException, CompletableFuture, ExecutorService, Executors, Future}
import upickle.default._
-import ch.epfl.scala.bsp4j.{BspConnectionDetails, BuildClient, ScalaTestClassesParams}
+import ch.epfl.scala.bsp4j.{BspConnectionDetails, BuildClient, DidChangeBuildTarget, LogMessageParams, PublishDiagnosticsParams, ScalaTestClassesParams, ShowMessageParams, TaskFinishParams, TaskProgressParams, TaskStartParams, WorkspaceBuildTargetsResult}
import mill._
import mill.api.Strict
-import mill.contrib.bsp.{MillBuildServer, ModuleUtils}
+import mill.contrib.bsp.{BspLoggedReporter, MillBuildServer, ModuleUtils}
import mill.define.{Command, Discover, ExternalModule, Target, Task}
import mill.eval.Evaluator
import mill.scalalib._
@@ -20,6 +20,7 @@ import requests.Compress.None
import upickle.default
import scala.collection.JavaConverters._
+import scala.io.Source
object MainMillBuildServer extends ExternalModule {
@@ -152,11 +153,28 @@ object MainMillBuildServer extends ExternalModule {
def experiment(ev: Evaluator): Command[Unit] = T.command {
val millServer = new mill.contrib.bsp.MillBuildServer(ev, bspVersion, version, languages)
- val mods: Seq[JavaModule] = modules(ev)()
- for (module <- mods) {
- println(module.millModuleSegments.parts.mkString("."))
+ val client = new BuildClient {
+ var diagnostics = List.empty[PublishDiagnosticsParams]
+ override def onBuildShowMessage(params: ShowMessageParams): Unit = ???
+ override def onBuildLogMessage(params: LogMessageParams): Unit = ???
+ override def onBuildTaskStart(params: TaskStartParams): Unit = ???
+ override def onBuildTaskProgress(params: TaskProgressParams): Unit = ???
+ override def onBuildTaskFinish(params: TaskFinishParams): Unit = ???
+ override def onBuildPublishDiagnostics(
+ params: PublishDiagnosticsParams
+ ): Unit = {
+ diagnostics ++= List(params)
}
-
+ override def onBuildTargetDidChange(params: DidChangeBuildTarget): Unit =
+ ???
+ }
+ for (module <- millServer.millModules) {
+ ev.evaluate(Strict.Agg(module.compile), Option(new BspLoggedReporter(client,
+ millServer.moduleToTargetId(module),
+ Option.empty[String],
+ 10, millServer.getCompilationLogger)))
+ //println("Diagnostics: " + client.diagnostics)
+ }
}
/**
diff --git a/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala b/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala
new file mode 100644
index 00000000..31900211
--- /dev/null
+++ b/contrib/bsp/src/mill/contrib/bsp/BspLoggedReporter.scala
@@ -0,0 +1,82 @@
+package mill.contrib.bsp
+
+import java.io.File
+
+import ch.epfl.scala.{bsp4j => bsp}
+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.compat.java8.OptionConverters._
+import scala.io.Source
+
+class BspLoggedReporter(client: bsp.BuildClient,
+ targetId: bsp.BuildTargetIdentifier,
+ compilationOriginId: Option[String],
+ maxErrors: Int,
+ logger: ManagedLogger) extends ManagedLoggedReporter(maxErrors, logger) {
+
+ override def logError(problem: Problem): Unit = {
+ client.onBuildPublishDiagnostics(getDiagnostics(problem, targetId, compilationOriginId))
+ println("Sent diagnostics to the client")
+ super.logError(problem)
+ println("Logged the error")
+ }
+
+ override def logInfo(problem: Problem): Unit = {
+ client.onBuildPublishDiagnostics(getDiagnostics(problem, targetId, compilationOriginId))
+ super.logInfo(problem)
+ }
+
+ override def logWarning(problem: Problem): Unit = {
+ client.onBuildPublishDiagnostics(getDiagnostics(problem, targetId, compilationOriginId))
+ super.logWarning(problem)
+ }
+
+ def getDiagnostics(problem: Problem, targetId: bsp.BuildTargetIdentifier, originId: Option[String]):
+ bsp.PublishDiagnosticsParams = {
+ println("Problem: " + problem)
+ val sourceFile = problem.position().sourceFile().asScala
+ val start = new bsp.Position(
+ problem.position.startLine.asScala.getOrElse(0),
+ problem.position.startOffset.asScala.getOrElse(0))
+ val end = new bsp.Position(
+ problem.position.endLine.asScala.getOrElse(0),
+ problem.position.endOffset.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 params = new bsp.PublishDiagnosticsParams(
+ new bsp.TextDocumentIdentifier(sourceFile.getOrElse(new File(targetId.getUri)).toPath.toAbsolutePath.toUri.toString),
+ targetId, List(diagnostic).asJava, true)
+
+ if (originId.nonEmpty) { params.setOriginId(originId.get) }
+ println("Diagnostics: " + params)
+ params
+ }
+
+ private[this] def getErrorCode(file: Option[File], start: bsp.Position, end: bsp.Position, position: xsbti.Position): String = {
+ file match {
+ case None => position.lineContent
+ case f: Option[File] =>
+ val source = Source.fromFile(f.get)
+ source.close()
+ val lines = source.getLines.toSeq
+ val code = lines(start.getLine).substring(start.getCharacter) +
+ lines.take(start.getLine - 1).takeRight(lines.length - end.getLine - 1).mkString("\n") +
+ lines(end.getLine).substring(0, end.getCharacter + 1)
+ code
+ }
+
+ }
+
+}
diff --git a/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala b/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala
index 91d9c4fd..5d79ee76 100644
--- a/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala
+++ b/contrib/bsp/src/mill/contrib/bsp/MillBuildServer.scala
@@ -1,25 +1,34 @@
package mill.contrib.bsp
+import java.io.File
+
import sbt.testing._
import java.util.{Calendar, Collections}
import java.util.concurrent.CompletableFuture
+import scala.compat.java8.OptionConverters._
import mill.scalalib.Lib.discoverTests
import ch.epfl.scala.bsp4j._
+import ch.epfl.scala.{bsp4j => bsp}
import mill.{scalalib, _}
import mill.api.{Loose, Result, Strict}
import mill.contrib.bsp.ModuleUtils._
import mill.eval.Evaluator
import mill.scalalib._
-import mill.scalalib.api.CompilationResult
-import mill.scalalib.api.ZincWorkerApi
+import mill.scalalib.api.{CompilationResult, ZincWorkerApi}
+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, Success}
+import mill.api.Result.{Failing, Failure, Success}
import scala.collection.JavaConverters._
import mill.modules.Jvm
import mill.util.{Ctx, PrintLogger}
import mill.define.{Discover, ExternalModule, Target, Task}
+import sbt.internal.util.{ConsoleOut, MainAppender, ManagedLogger}
+import sbt.util.LogExchange
import scala.io.Source
@@ -31,7 +40,6 @@ class MillBuildServer(evaluator: Evaluator,
implicit def millScoptEvaluatorReads[T] = new mill.main.EvaluatorScopt[T]()
lazy val millDiscover: Discover[MillBuildServer.this.type] = Discover[this.type]
-
val bspVersion: String = _bspVersion
val supportedLanguages: List[String] = languages
val millServerVersion: String = serverVersion
@@ -44,7 +52,6 @@ class MillBuildServer(evaluator: Evaluator,
var moduleToTarget: Predef.Map[JavaModule, BuildTarget] =
ModuleUtils.millModulesToBspTargets(millModules, evaluator, List("scala", "java"))
-
var clientInitialized = false
val ctx: Ctx.Log with Ctx.Home = new Ctx.Log with Ctx.Home {
@@ -217,6 +224,131 @@ class MillBuildServer(evaluator: Evaluator,
future
}
+ private[this] def getErrorCode(file: File, start: bsp.Position, end: bsp.Position): String = {
+
+ val source = Source.fromFile(file)
+ source.close()
+ val lines = source.getLines.toSeq
+ val code = lines(start.getLine).substring(start.getCharacter) +
+ lines.take(start.getLine - 1).takeRight(lines.length - end.getLine - 1).mkString("\n") +
+ lines(end.getLine).substring(0, end.getCharacter + 1)
+ code
+ }
+
+ def getDiagnosticsFromFile(analysisFile: os.Path, targetId: BuildTargetIdentifier, originId: Option[String]):
+ Seq[PublishDiagnosticsParams] = {
+ val analysisStore: AnalysisStore = FileAnalysisStore.getDefault(analysisFile.toIO)
+ analysisStore.get.asScala match {
+ case contents: AnalysisContents =>
+ val sourceInfoMap: Map[File, SourceInfo] = contents.getAnalysis.readSourceInfos.getAllSourceInfos.asScala
+ var diagnosticsParams = Seq.empty[PublishDiagnosticsParams]
+ for ( (file, sourceInfo) <- sourceInfoMap) {
+ var diagnostics = List.empty[Diagnostic]
+ for (problem <- sourceInfo.getReportedProblems) {
+ val start = new bsp.Position(
+ problem.position.startLine.asScala.getOrElse(0),
+ problem.position.startOffset.asScala.getOrElse(0))
+ val end = new bsp.Position(
+ problem.position.endLine.asScala.getOrElse(0),
+ problem.position.endOffset.asScala.getOrElse(0))
+ val diagnostic = new Diagnostic(new Range(start, end), problem.message)
+ diagnostic.setCode(getErrorCode(file, start, end))
+ diagnostic.setSource("compiler from mill")
+
+ diagnostic.setSeverity( problem.severity match {
+ case Severity.Info => DiagnosticSeverity.INFORMATION
+ case Severity.Error => DiagnosticSeverity.ERROR
+ case Severity.Warn => DiagnosticSeverity.WARNING
+ }
+ )
+ diagnostics ++= List(diagnostic)
+ }
+ val params = new PublishDiagnosticsParams(new TextDocumentIdentifier(file.toURI.toString),
+ targetId, diagnostics.asJava, true)
+ if (originId.nonEmpty) { params.setOriginId(originId.get) }
+ diagnosticsParams ++= Seq(params)
+ }
+ diagnosticsParams
+ case None => Seq.empty[PublishDiagnosticsParams]
+ }
+ }
+
+ def getSourceFileCompileErrors(problems: Seq[Problem]): Map[File, Array[Problem]] = {
+ val problemsMap = Map.empty[File, Array[Problem]]
+
+ for (problem <- problems) {
+ try {
+ val sourceFile = problem.position.sourceFile.get
+ if (problemsMap.contains(sourceFile)) {
+ problemsMap(sourceFile) = problemsMap(sourceFile) ++ Array(problem)
+ } else {
+ problemsMap(sourceFile) = Array(problem)
+ }
+
+ } catch {
+ case e: Exception =>
+ }
+ }
+ problemsMap
+ }
+
+ def getDiagnostics(problems: Array[Problem], targetId: BuildTargetIdentifier, originId: Option[String]):
+ Seq[PublishDiagnosticsParams] = {
+ var diagnosticsParams = Seq.empty[PublishDiagnosticsParams]
+ for (( sourceFile, problems ) <- getSourceFileCompileErrors(problems)) {
+ var diagnostics = Seq.empty[Diagnostic]
+ for (problem <- problems) {
+ val start = new bsp.Position(
+ problem.position.startLine.asScala.getOrElse(0),
+ problem.position.startOffset.asScala.getOrElse(0))
+ val end = new bsp.Position(
+ problem.position.endLine.asScala.getOrElse(0),
+ problem.position.endOffset.asScala.getOrElse(0))
+ val diagnostic = new Diagnostic(new Range(start, end), problem.message)
+ diagnostic.setCode(getErrorCode(sourceFile, start, end))
+ diagnostic.setSource("compiler from mill")
+ diagnostic.setSeverity( problem.severity match {
+ case Severity.Info => DiagnosticSeverity.INFORMATION
+ case Severity.Error => DiagnosticSeverity.ERROR
+ case Severity.Warn => DiagnosticSeverity.WARNING
+ }
+ )
+ diagnostics ++= List(diagnostic)
+ }
+ val params = new PublishDiagnosticsParams(new TextDocumentIdentifier(sourceFile.toPath.toAbsolutePath.toUri.toString),
+ targetId, diagnostics.asJava, true)
+
+ if (originId.nonEmpty) { params.setOriginId(originId.get) }
+ diagnosticsParams ++= Seq(params)
+ }
+ diagnosticsParams
+ }
+
+ def getOriginId(params: CompileParams): Option[String] = {
+ try {
+ Option(params.getOriginId)
+ } catch {
+ case e: Exception => Option.empty[String]
+ }
+ }
+
+ def sendCompilationDiagnostics(problems: Array[Problem], targetId: BuildTargetIdentifier, compileParams: CompileParams) = {
+ for (publishDiagnosticsParams <-
+ getDiagnostics(problems, targetId, getOriginId(compileParams))) {
+ client.onBuildPublishDiagnostics(publishDiagnosticsParams)
+ }
+ }
+
+ def getCompilationLogger: ManagedLogger = {
+ val consoleAppender = MainAppender.defaultScreen(ConsoleOut.printStreamOut(
+ mill.util.DummyLogger.outputStream
+ ))
+ val l = LogExchange.logger("Hello")
+ LogExchange.unbindLoggerAppenders("Hello")
+ LogExchange.bindLoggerAppenders("Hello", (consoleAppender -> sbt.util.Level.Info) :: Nil)
+ l
+ }
+
//TODO: send task notifications - start, progress and finish
//TODO: if the client wants to give compilation arguments and the module
// already has some from the build file, what to do?
@@ -229,9 +361,10 @@ class MillBuildServer(evaluator: Evaluator,
var compileTime = 0
for (targetId <- compileParams.getTargets.asScala) {
if (moduleToTarget(targetIdToModule(targetId)).getCapabilities.getCanCompile) {
- var millModule = targetIdToModule(targetId)
+ val millModule = targetIdToModule(targetId)
//millModule.javacOptions = compileParams.getArguments.asScala
val compileTask = millModule.compile
+
// send notification to client that compilation of this target started
val taskStartParams = new TaskStartParams(new TaskId(compileTask.hashCode().toString))
taskStartParams.setEventTime(System.currentTimeMillis())
@@ -240,8 +373,13 @@ class MillBuildServer(evaluator: Evaluator,
taskStartParams.setData(new CompileTask(targetId))
client.onBuildTaskStart(taskStartParams)
- val result = millEvaluator.evaluate(Strict.Agg(compileTask))
+ val result = millEvaluator.evaluate(Strict.Agg(compileTask),
+ Option(new BspLoggedReporter(client,
+ targetId,
+ getOriginId(compileParams),
+ 10, getCompilationLogger)))
val endTime = System.currentTimeMillis()
+
compileTime += result.timings.map(timingTuple => timingTuple._2).sum
var statusCode = StatusCode.OK
diff --git a/contrib/bsp/src/mill/contrib/bsp/ModuleUtils.scala b/contrib/bsp/src/mill/contrib/bsp/ModuleUtils.scala
index 266d832a..a3202aab 100644
--- a/contrib/bsp/src/mill/contrib/bsp/ModuleUtils.scala
+++ b/contrib/bsp/src/mill/contrib/bsp/ModuleUtils.scala
@@ -51,6 +51,9 @@ object ModuleUtils {
supportedLanguages.asJava,
dependencies,
capabilities)
+ if (module.isInstanceOf[ScalaModule]) {
+ buildTarget.setDataKind("scala")
+ }
buildTarget.setData(dataBuildTarget)
buildTarget.setDisplayName(module.millModuleSegments.last.value.toList.head.pathSegments.head)
buildTarget.setBaseDirectory(module.millSourcePath.toNIO.toAbsolutePath.toUri.toString)
diff --git a/main/api/src/mill/api/Ctx.scala b/main/api/src/mill/api/Ctx.scala
index 69d01f7e..7d081d6a 100644
--- a/main/api/src/mill/api/Ctx.scala
+++ b/main/api/src/mill/api/Ctx.scala
@@ -2,8 +2,8 @@ package mill.api
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.implicitConversions
-
import os.Path
+import sbt.internal.inc.ManagedLoggedReporter
/**
* Provides access to various resources in the context of a currently execution Target.
@@ -60,7 +60,8 @@ class Ctx(
dest0: () => os.Path,
val log: Logger,
val home: os.Path,
- val env: Map[String, String]
+ val env: Map[String, String],
+ val reporter: Option[ManagedLoggedReporter]
)
extends Ctx.Dest
with Ctx.Log
diff --git a/main/core/src/eval/Evaluator.scala b/main/core/src/eval/Evaluator.scala
index f4ec8ff9..22132a8f 100644
--- a/main/core/src/eval/Evaluator.scala
+++ b/main/core/src/eval/Evaluator.scala
@@ -5,7 +5,6 @@ import java.net.URLClassLoader
import scala.collection.JavaConverters._
import scala.collection.mutable
import scala.util.control.NonFatal
-
import ammonite.runtime.SpecialClassLoader
import mill.util.Router.EntryPoint
import mill.define.{Ctx => _, _}
@@ -13,11 +12,15 @@ import mill.api.Result.{Aborted, OuterStack, Success}
import mill.util
import mill.util._
import mill.api.Strict.Agg
+import sbt.internal.inc.ManagedLoggedReporter
+import sbt.internal.util.{ConsoleOut, MainAppender}
+import sbt.util.LogExchange
case class Labelled[T](task: NamedTask[T],
segments: Segments){
def format = task match{
case t: Target[T] => Some(t.readWrite.asInstanceOf[upickle.default.ReadWriter[T]])
+ case t: PersistentArgs[T] => Some(t.readWrite.asInstanceOf[upickle.default.ReadWriter[T]])
case _ => None
}
def writer = task match{
@@ -40,7 +43,7 @@ case class Evaluator(home: os.Path,
val classLoaderSignHash = classLoaderSig.hashCode()
- def evaluate(goals: Agg[Task[_]]): Evaluator.Results = {
+ def evaluate(goals: Agg[Task[_]], reporter: Option[ManagedLoggedReporter] = Option.empty[ManagedLoggedReporter]): Evaluator.Results = {
os.makeDir.all(outPath)
val (sortedGroups, transitive) = Evaluator.plan(rootModule, goals)
@@ -66,7 +69,8 @@ case class Evaluator(home: os.Path,
terminal,
group,
results,
- counterMsg
+ counterMsg,
+ reporter
)
someTaskFailed = someTaskFailed || newResults.exists(task => !task._2.isInstanceOf[Success[_]])
@@ -111,7 +115,8 @@ case class Evaluator(home: os.Path,
def evaluateGroupCached(terminal: Either[Task[_], Labelled[_]],
group: Agg[Task[_]],
results: collection.Map[Task[_], Result[(Any, Int)]],
- counterMsg: String
+ counterMsg: String,
+ reporter: Option[ManagedLoggedReporter]
): (collection.Map[Task[_], Result[(Any, Int)]], Seq[Task[_]], Boolean) = {
val externalInputsHash = scala.util.hashing.MurmurHash3.orderedHash(
@@ -133,7 +138,8 @@ case class Evaluator(home: os.Path,
inputsHash,
paths = None,
maybeTargetLabel = None,
- counterMsg = counterMsg
+ counterMsg = counterMsg,
+ reporter
)
(newResults, newEvaluated, false)
case Right(labelledNamedTask) =>
@@ -185,7 +191,8 @@ case class Evaluator(home: os.Path,
inputsHash,
paths = Some(paths),
maybeTargetLabel = Some(msgParts.mkString),
- counterMsg = counterMsg
+ counterMsg = counterMsg,
+ reporter
)
newResults(labelledNamedTask.task) match{
@@ -259,7 +266,8 @@ case class Evaluator(home: os.Path,
inputsHash: Int,
paths: Option[Evaluator.Paths],
maybeTargetLabel: Option[String],
- counterMsg: String): (mutable.LinkedHashMap[Task[_], Result[(Any, Int)]], mutable.Buffer[Task[_]]) = {
+ counterMsg: String,
+ reporter: Option[ManagedLoggedReporter]): (mutable.LinkedHashMap[Task[_], Result[(Any, Int)]], mutable.Buffer[Task[_]]) = {
val newEvaluated = mutable.Buffer.empty[Task[_]]
@@ -319,9 +327,10 @@ case class Evaluator(home: os.Path,
},
multiLogger,
home,
- env
+ env,
+ reporter //new ManagedLoggedReporter(10, logger)
)
-
+ println("Reporter: " + reporter)
val out = System.out
val in = System.in
val err = System.err
diff --git a/scalalib/api/src/ZincWorkerApi.scala b/scalalib/api/src/ZincWorkerApi.scala
index 53a98c24..e80895d6 100644
--- a/scalalib/api/src/ZincWorkerApi.scala
+++ b/scalalib/api/src/ZincWorkerApi.scala
@@ -3,6 +3,8 @@ package mill.scalalib.api
import mill.api.Loose.Agg
import mill.api.PathRef
import mill.api.JsonFormatters._
+import sbt.internal.inc._
+
object ZincWorkerApi{
type Ctx = mill.api.Ctx.Dest with mill.api.Ctx.Log with mill.api.Ctx.Home
}
@@ -11,7 +13,8 @@ trait ZincWorkerApi {
def compileJava(upstreamCompileOutput: Seq[CompilationResult],
sources: Agg[os.Path],
compileClasspath: Agg[os.Path],
- javacOptions: Seq[String])
+ javacOptions: Seq[String],
+ reporter: Option[ManagedLoggedReporter])
(implicit ctx: ZincWorkerApi.Ctx): mill.api.Result[CompilationResult]
/** Compile a mixed Scala/Java or Scala-only project */
@@ -23,7 +26,8 @@ trait ZincWorkerApi {
scalaOrganization: String,
scalacOptions: Seq[String],
compilerClasspath: Agg[os.Path],
- scalacPluginClasspath: Agg[os.Path])
+ scalacPluginClasspath: Agg[os.Path],
+ reporter: Option[ManagedLoggedReporter])
(implicit ctx: ZincWorkerApi.Ctx): mill.api.Result[CompilationResult]
def discoverMainClasses(compilationResult: CompilationResult)
diff --git a/scalalib/src/JavaModule.scala b/scalalib/src/JavaModule.scala
index b9987ca1..e6c47324 100644
--- a/scalalib/src/JavaModule.scala
+++ b/scalalib/src/JavaModule.scala
@@ -13,6 +13,9 @@ import mill.modules.Jvm.{createAssembly, createJar}
import Lib._
import mill.scalalib.publish.{Artifact, Scope}
import mill.api.Loose.Agg
+import sbt.internal.inc.ManagedLoggedReporter
+import sbt.internal.util.{ConsoleOut, MainAppender}
+import sbt.util.LogExchange
/**
* Core configuration required to compile a single Scala compilation target
@@ -209,15 +212,17 @@ trait JavaModule extends mill.Module with TaskModule with GenIdeaModule { outer
} yield PathRef(path)
}
+
/**
* Compiles the current module to generate compiled classfiles/bytecode
*/
- def compile: T[mill.scalalib.api.CompilationResult] = T.persistent{
+ def compile: T[mill.scalalib.api.CompilationResult] = T.persistent {
zincWorker.worker().compileJava(
upstreamCompileOutput(),
allSourceFiles().map(_.path),
compileClasspath().map(_.path),
- javacOptions()
+ javacOptions(),
+ T.ctx().reporter
)
}
diff --git a/scalalib/src/ScalaModule.scala b/scalalib/src/ScalaModule.scala
index 0ebd5700..5c7a4c97 100644
--- a/scalalib/src/ScalaModule.scala
+++ b/scalalib/src/ScalaModule.scala
@@ -10,6 +10,9 @@ import mill.scalalib.api.Util.isDotty
import Lib._
import mill.api.Loose.Agg
import mill.api.DummyInputStream
+import sbt.internal.inc.ManagedLoggedReporter
+import sbt.internal.util.{ConsoleOut, MainAppender}
+import sbt.util.LogExchange
/**
* Core configuration required to compile a single Scala compilation target
@@ -128,7 +131,8 @@ trait ScalaModule extends JavaModule { outer =>
resolveDeps(T.task{runIvyDeps() ++ scalaLibraryIvyDeps() ++ transitiveIvyDeps()})()
}
- override def compile: T[mill.scalalib.api.CompilationResult] = T.persistent{
+ override def compile: T[mill.scalalib.api.CompilationResult] = T.persistent {
+
zincWorker.worker().compileMixed(
upstreamCompileOutput(),
allSourceFiles().map(_.path),
@@ -139,6 +143,7 @@ trait ScalaModule extends JavaModule { outer =>
scalacOptions(),
scalaCompilerClasspath().map(_.path),
scalacPluginClasspath().map(_.path),
+ T.ctx().reporter
)
}
diff --git a/scalalib/worker/src/ZincWorkerImpl.scala b/scalalib/worker/src/ZincWorkerImpl.scala
index cf37812c..bd61b440 100644
--- a/scalalib/worker/src/ZincWorkerImpl.scala
+++ b/scalalib/worker/src/ZincWorkerImpl.scala
@@ -4,15 +4,15 @@ import java.io.File
import java.util.Optional
import scala.ref.WeakReference
-
import mill.api.Loose.Agg
-import mill.api.{KeyedLockedCache, PathRef}
+import mill.api.{CompilationAnalysis, KeyedLockedCache, PathRef}
import xsbti.compile.{CompilerCache => _, FileAnalysisStore => _, ScalaInstance => _, _}
import mill.scalalib.api.Util.{grepJar, isDotty, scalaBinaryVersion}
import sbt.internal.inc._
import sbt.internal.util.{ConsoleOut, MainAppender}
import sbt.util.LogExchange
import mill.scalalib.api.{CompilationResult, ZincWorkerApi}
+import upickle.core.Visitor
case class MockedLookup(am: File => Optional[CompileAnalysis]) extends PerClasspathEntryLookup {
override def analysis(classpathEntry: File): Optional[CompileAnalysis] =
am(classpathEntry)
@@ -61,7 +61,7 @@ class ZincWorkerImpl(compilerBridge: Either[
scalaVersion,
scalaOrganization,
compilerClasspath,
- scalacPluginClasspath,
+ scalacPluginClasspath
) { compilers: Compilers =>
val scaladocClass = compilers.scalac().scalaInstance().loader().loadClass("scala.tools.nsc.ScalaDoc")
val scaladocMethod = scaladocClass.getMethod("process", classOf[Array[String]])
@@ -155,20 +155,23 @@ class ZincWorkerImpl(compilerBridge: Either[
def compileJava(upstreamCompileOutput: Seq[CompilationResult],
sources: Agg[os.Path],
compileClasspath: Agg[os.Path],
- javacOptions: Seq[String])
+ javacOptions: Seq[String],
+ reporter: Option[ManagedLoggedReporter])
(implicit ctx: ZincWorkerApi.Ctx): mill.api.Result[CompilationResult] = {
for(res <- compileJava0(
upstreamCompileOutput.map(c => (c.analysisFile, c.classes.path)),
sources,
compileClasspath,
- javacOptions
+ javacOptions,
+ reporter
)) yield CompilationResult(res._1, PathRef(res._2))
}
def compileJava0(upstreamCompileOutput: Seq[(os.Path, os.Path)],
sources: Agg[os.Path],
compileClasspath: Agg[os.Path],
- javacOptions: Seq[String])
+ javacOptions: Seq[String],
+ reporter: Option[ManagedLoggedReporter])
(implicit ctx: ZincWorkerApi.Ctx): mill.api.Result[(os.Path, os.Path)] = {
compileInternal(
upstreamCompileOutput,
@@ -176,7 +179,8 @@ class ZincWorkerImpl(compilerBridge: Either[
compileClasspath,
javacOptions,
scalacOptions = Nil,
- javaOnlyCompilers
+ javaOnlyCompilers,
+ reporter
)
}
@@ -188,7 +192,8 @@ class ZincWorkerImpl(compilerBridge: Either[
scalaOrganization: String,
scalacOptions: Seq[String],
compilerClasspath: Agg[os.Path],
- scalacPluginClasspath: Agg[os.Path])
+ scalacPluginClasspath: Agg[os.Path],
+ reporter: Option[ManagedLoggedReporter])
(implicit ctx: ZincWorkerApi.Ctx): mill.api.Result[CompilationResult] = {
for (res <- compileMixed0(
@@ -200,7 +205,8 @@ class ZincWorkerImpl(compilerBridge: Either[
scalaOrganization,
scalacOptions,
compilerClasspath,
- scalacPluginClasspath
+ scalacPluginClasspath,
+ reporter
)) yield CompilationResult(res._1, PathRef(res._2))
}
@@ -212,13 +218,14 @@ class ZincWorkerImpl(compilerBridge: Either[
scalaOrganization: String,
scalacOptions: Seq[String],
compilerClasspath: Agg[os.Path],
- scalacPluginClasspath: Agg[os.Path])
+ scalacPluginClasspath: Agg[os.Path],
+ reporter: Option[ManagedLoggedReporter])
(implicit ctx: ZincWorkerApi.Ctx): mill.api.Result[(os.Path, os.Path)] = {
withCompilers(
scalaVersion,
scalaOrganization,
compilerClasspath,
- scalacPluginClasspath,
+ scalacPluginClasspath
) {compilers: Compilers =>
compileInternal(
upstreamCompileOutput,
@@ -226,7 +233,8 @@ class ZincWorkerImpl(compilerBridge: Either[
compileClasspath,
javacOptions,
scalacOptions = scalacPluginClasspath.map(jar => s"-Xplugin:$jar").toSeq ++ scalacOptions,
- compilers
+ compilers,
+ reporter
)
}
}
@@ -298,7 +306,8 @@ class ZincWorkerImpl(compilerBridge: Either[
compileClasspath: Agg[os.Path],
javacOptions: Seq[String],
scalacOptions: Seq[String],
- compilers: Compilers)
+ compilers: Compilers,
+ reporter: Option[ManagedLoggedReporter])
(implicit ctx: ZincWorkerApi.Ctx): mill.api.Result[(os.Path, os.Path)] = {
os.makeDir.all(ctx.dest)
@@ -312,7 +321,10 @@ class ZincWorkerImpl(compilerBridge: Either[
LogExchange.bindLoggerAppenders(id, (consoleAppender -> sbt.util.Level.Info) :: Nil)
l
}
-
+ val newReporter = reporter match {
+ case None => new ManagedLoggedReporter(10, logger)
+ case r: Option[ManagedLoggedReporter] => r.get
+ }
val analysisMap0 = upstreamCompileOutput.map(_.swap).toMap
def analysisMap(f: File): Optional[CompileAnalysis] = {
@@ -350,7 +362,7 @@ class ZincWorkerImpl(compilerBridge: Either[
zincIOFile,
new FreshCompilerCache,
IncOptions.of(),
- new ManagedLoggedReporter(10, logger),
+ newReporter,//new ManagedLoggedReporter(10, logger),
None,
Array()
),
@@ -372,7 +384,6 @@ class ZincWorkerImpl(compilerBridge: Either[
newResult.setup()
)
)
-
mill.api.Result.Success((zincFile, classesDir))
}catch{case e: CompileFailed => mill.api.Result.Failure(e.toString)}
}
diff --git a/scratch/build.sc b/scratch/build.sc
index 817f68e4..c36b554f 100644
--- a/scratch/build.sc
+++ b/scratch/build.sc
@@ -1,9 +1,9 @@
import mill._, scalalib._
-import $ivy.`com.lihaoyi::mill-contrib-bsp:0.4.1-7-be21ae-DIRTY1fe41d7a`
+//import $ivy.`com.lihaoyi::mill-contrib-bsp:0.4.1-7-be21ae-DIRTY1fe41d7a`
object mill_exercise extends ScalaModule {
def scalaVersion = "2.12.8"
-
+ def mainClass = Some("mill_exercise.Compiler")
def ivyDeps = Agg(
ivy"org.scalameta::metals:0.5.2",
ivy"org.scalameta::scalameta:4.1.9",