@@ -17,6 +17,7 @@ import mill.given
1717
1818import java .io .PrintStream
1919import java .util .concurrent .CompletableFuture
20+ import scala .collection .mutable
2021import scala .concurrent .Promise
2122import scala .jdk .CollectionConverters .*
2223import scala .reflect .ClassTag
@@ -29,7 +30,8 @@ private class MillBuildServer(
2930 serverVersion : String ,
3031 serverName : String ,
3132 logStream : PrintStream ,
32- canReload : Boolean
33+ canReload : Boolean ,
34+ debugMessages : Boolean
3335) extends ExternalModule
3436 with BuildServer {
3537
@@ -55,12 +57,16 @@ private class MillBuildServer(
5557 if (statePromise.isCompleted) statePromise = Promise [State ]() // replace the promise
5658 evaluatorsOpt.foreach { evaluators =>
5759 statePromise.success(
58- new State (topLevelProjectRoot, evaluators, debug)
60+ new State (topLevelProjectRoot, evaluators, s => debug(s()) )
5961 )
6062 }
6163 }
6264
63- def debug (msg : String ): Unit = logStream.println(msg)
65+ def print (msg : String ): Unit =
66+ logStream.println(msg)
67+ def debug (msg : => String ): Unit =
68+ if (debugMessages)
69+ logStream.println(" [debug] " + msg)
6470
6571 def onConnectWithClient (buildClient : BuildClient ): Unit = client = buildClient
6672
@@ -109,7 +115,7 @@ private class MillBuildServer(
109115 case d : JsonObject =>
110116 debug(s " extra data: ${d} of type ${d.getClass}" )
111117 readVersion(d, " semanticdbVersion" ).foreach { version =>
112- debug (
118+ print (
113119 s " Got client semanticdbVersion: ${version}. Enabling SemanticDB support. "
114120 )
115121 clientWantsSemanticDb = true
@@ -126,27 +132,27 @@ private class MillBuildServer(
126132 }
127133
128134 override def onBuildInitialized (): Unit = {
129- debug (" Build initialized" )
135+ print (" Build initialized" )
130136 }
131137
132138 override def buildShutdown (): CompletableFuture [Object ] = {
133- debug( s " Entered buildShutdown " )
139+ print( " Entered buildShutdown" )
134140 shutdownRequested = true
135141 onSessionEnd match {
136142 case None =>
137143 case Some (onEnd) =>
138- debug (" Shutdown build..." )
144+ print (" Shutdown build..." )
139145 onEnd(BspServerResult .Shutdown )
140146 }
141147 SemanticDbJavaModule .resetContext()
142148 CompletableFuture .completedFuture(null .asInstanceOf [Object ])
143149 }
144150 override def onBuildExit (): Unit = {
145- debug (" Entered onBuildExit" )
151+ print (" Entered onBuildExit" )
146152 onSessionEnd match {
147153 case None =>
148154 case Some (onEnd) =>
149- debug (" Exiting build..." )
155+ print (" Exiting build..." )
150156 onEnd(BspServerResult .Shutdown )
151157 }
152158 SemanticDbJavaModule .resetContext()
@@ -204,7 +210,7 @@ private class MillBuildServer(
204210 onSessionEnd match {
205211 case None => " unsupportedWorkspaceReload" .asInstanceOf [Object ]
206212 case Some (onEnd) =>
207- debug (" Reloading workspace..." )
213+ print (" Reloading workspace..." )
208214 onEnd(BspServerResult .ReloadWorkspace ).asInstanceOf [Object ]
209215 }
210216 }
@@ -405,7 +411,7 @@ private class MillBuildServer(
405411 (Task .Anon { () }, ev)
406412 val task = Task .Anon {
407413 Task .log.debug(
408- " Ignoring invalid compile request for test module ${m.bspBuildTarget.displayName}"
414+ s " Ignoring invalid compile request for test module ${m.bspBuildTarget.displayName}"
409415 )
410416 }
411417 (task, ev)
@@ -669,38 +675,50 @@ private class MillBuildServer(
669675 }
670676
671677 // group by evaluator (different root module)
672- val evaluated = groupList(tasksSeq.toSeq)(_._2)(_._1)
673- .map { case ((ev, id), ts) =>
674- val results = evaluate(ev, ts)
675- val failures = results.transitiveResults.collect {
676- case (_, res : ExecResult .Failing [_]) => res
678+ val groups0 = groupList(tasksSeq.toSeq)(_._2._1) {
679+ case (tasks, (_, id)) => (id, tasks)
680+ }
681+
682+ val evaluated = groups0.flatMap {
683+ case (ev, targetIdTasks) =>
684+ val results = evaluate(ev, targetIdTasks.map(_._2))
685+ val idByTasks = targetIdTasks.map { case (id, task) => (task : Task [_], id) }.toMap
686+ val failures = results.transitiveResults.toSeq.collect {
687+ case (task, res : ExecResult .Failing [_]) if idByTasks.contains(task) =>
688+ (idByTasks(task), res)
677689 }
678690
679- def logError (errorMsg : String ): Unit = {
691+ def logError (id : BuildTargetIdentifier , errorMsg : String ): Unit = {
680692 val msg = s " Request ' $prefix' failed for ${id.getUri}: ${errorMsg}"
681693 debug(msg)
682694 client.onBuildLogMessage(new LogMessageParams (MessageType .ERROR , msg))
683695 }
684696
685- if (failures.nonEmpty) {
686- logError(failures.mkString(" , " ))
697+ if (failures.nonEmpty)
698+ for ((id, failure) <- failures)
699+ logError(id, failure.toString)
700+
701+ val resultsById = targetIdTasks.flatMap {
702+ case (id, task) =>
703+ results.transitiveResults(task)
704+ .asSuccess
705+ .map(_.value.value.asInstanceOf [W ])
706+ .map((id, _))
687707 }
688708
689- // only the successful results
690- val successes = results.values.map(_.value).asInstanceOf [Seq [W ]]
691- successes
692- .flatMap { v =>
709+ resultsById.flatMap {
710+ case (id, values) =>
693711 try {
694- Seq (f(ev, state, id, state.bspModulesById(id)._1, v ))
712+ Seq (f(ev, state, id, state.bspModulesById(id)._1, values ))
695713 } catch {
696714 case NonFatal (e) =>
697- logError(e.toString)
715+ logError(id, e.toString)
698716 Seq ()
699717 }
700- }
701- }
718+ }
719+ }
702720
703- agg(evaluated.flatten. asJava, state)
721+ agg(evaluated.asJava, state)
704722 }
705723 }
706724
@@ -717,12 +735,12 @@ private class MillBuildServer(
717735 hint : String ,
718736 checkInitialized : Boolean = true
719737 )(f : State => V ): CompletableFuture [V ] = {
720- debug (s " Entered ${hint}" )
738+ print (s " Entered ${hint}" )
721739
722740 val start = System .currentTimeMillis()
723741 val prefix = hint.split(" " ).head
724742 def took =
725- debug (s " ${prefix} took ${System .currentTimeMillis() - start} msec " )
743+ print (s " ${prefix} took ${System .currentTimeMillis() - start} msec " )
726744
727745 val future = new CompletableFuture [V ]()
728746 if (checkInitialized && ! initialized) {
@@ -762,11 +780,11 @@ private class MillBuildServer(
762780 hint : String ,
763781 checkInitialized : Boolean = true
764782 )(f : => V ): CompletableFuture [V ] = {
765- debug (s " Entered ${hint}" )
783+ print (s " Entered ${hint}" )
766784 val start = System .currentTimeMillis()
767785 val prefix = hint.split(" " ).head
768786 def took =
769- debug (s " ${prefix} took ${System .currentTimeMillis() - start} msec " )
787+ print (s " ${prefix} took ${System .currentTimeMillis() - start} msec " )
770788
771789 val future = new CompletableFuture [V ]()
772790
@@ -834,10 +852,27 @@ private object MillBuildServer {
834852 * the order of appearance of the keys from the input sequence
835853 */
836854 private def groupList [A , K , B ](seq : Seq [A ])(key : A => K )(f : A => B ): Seq [(K , Seq [B ])] = {
837- val keyIndices = seq.map(key).distinct.zipWithIndex.toMap
838- seq.groupMap(key)(f)
839- .toSeq
840- .sortBy { case (k, _) => keyIndices(k) }
855+ val map = new mutable.HashMap [K , mutable.ListBuffer [B ]]
856+ val list = new mutable.ListBuffer [(K , mutable.ListBuffer [B ])]
857+ for (a <- seq) {
858+ val k = key(a)
859+ val b = f(a)
860+ val l = map.getOrElseUpdate(
861+ k, {
862+ val buf = mutable.ListBuffer [B ]()
863+ list.append((k, buf))
864+ buf
865+ }
866+ )
867+ l.append(b)
868+ }
869+ list
870+ .iterator
871+ .map {
872+ case (k, l) =>
873+ (k, l.result())
874+ }
875+ .toList
841876 }
842877
843878 def jvmBuildTarget (d : JvmBuildTarget ): bsp4j.JvmBuildTarget =
0 commit comments