Skip to content
6 changes: 5 additions & 1 deletion contrib/playlib/src/mill/playlib/RouteCompilerWorker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ private[playlib] class RouteCompilerWorker {
dest.toIO
) match {
case null =>
Result.Success(CompilationResult(Task.dest / "zinc", PathRef(Task.dest)))
Result.Success(CompilationResult(
Task.dest / "zinc",
PathRef(Task.dest),
semanticDbFiles = None
))
case err => Result.Failure(err)
}
}
Expand Down
6 changes: 5 additions & 1 deletion contrib/twirllib/src/mill/twirllib/TwirlWorker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,11 @@ object TwirlWorker {
val zincFile = ctx.dest / "zinc"
val classesDir = ctx.dest

mill.api.Result.Success(CompilationResult(zincFile, PathRef(classesDir)))
mill.api.Result.Success(CompilationResult(
zincFile,
PathRef(classesDir),
semanticDbFiles = None
))
}

private def twirlExtensionClass(name: String, formats: Map[String, String]) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ trait SemanticDbJavaModuleApi {
private[mill] def bspCompiledClassesAndSemanticDbFiles: TaskApi[UnresolvedPathApi[?]]
}
object SemanticDbJavaModuleApi {
val buildTimeJavaSemanticDbVersion = BuildInfo.semanticDbJavaVersion
val buildTimeSemanticDbVersion = BuildInfo.semanticDBVersion
val buildTimeJavaSemanticDbVersion: String = BuildInfo.semanticDbJavaVersion
val buildTimeSemanticDbVersion: String = BuildInfo.semanticDBVersion

private[mill] val contextSemanticDbVersion: InheritableThreadLocal[Option[String]] =
new InheritableThreadLocal[Option[String]] {
protected override def initialValue(): Option[String] = None.asInstanceOf[Option[String]]
protected override def initialValue(): Option[String] = None
}

private[mill] val contextJavaSemanticDbVersion: InheritableThreadLocal[Option[String]] =
new InheritableThreadLocal[Option[String]] {
protected override def initialValue(): Option[String] = None.asInstanceOf[Option[String]]
protected override def initialValue(): Option[String] = None
}

private[mill] def resetContext(): Unit = {
Expand Down
8 changes: 7 additions & 1 deletion core/api/src/mill/api/BuildCtx.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package mill.api
import collection.mutable
import mill.api.Watchable
import mill.constants.EnvVars
import mill.constants.{EnvVars, OutFiles, OutFolderMode}

import scala.util.DynamicVariable

/**
Expand Down Expand Up @@ -50,6 +51,7 @@ object BuildCtx {
}
}

/** As [[watchValue]] but watches a file path. */
def watch(p: os.Path): os.Path = {
val watchable = Watchable.Path(p.toNIO, false, PathRef(p).sig)
watchedValues.append(watchable)
Expand All @@ -59,4 +61,8 @@ object BuildCtx {
def watch0(w: Watchable): Unit = watchedValues.append(w)

def evalWatch0(w: Watchable): Unit = evalWatchedValues.append(w)

// TODO review: doc me
private[mill] def bspSemanticDbSesssionsFolder =
workspaceRoot / os.SubPath(OutFiles.outFor(OutFolderMode.BSP)) / "semanticdb-sessions"
}
36 changes: 36 additions & 0 deletions core/api/src/mill/api/Task.scala
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,11 @@ object Task {
def withFilter(f: T => Boolean): Task[T] = this
def zip[V](other: Task[V]): Task[(T, V)] = new Task.Zipped(this, other)

// /** Runs `before` function before the task and then `after` funciton after the task. */
// def wrap[IntermediateData, TaskResult](
// before: => IntermediateData
// )(after: (IntermediateData, T) => TaskResult): Task[TaskResult] =
// Task.Wrapped(this, () => before, after)
}

private[api] class Sequence[+T](inputs0: Seq[Task[T]]) extends Task[Seq[T]] {
Expand All @@ -310,6 +315,37 @@ object Task {
val inputs: Seq[Task[?]] = List(source)
}

// private[api] class Wrapped[Input, IntermediateData, TaskResult](
// source: Task[Input],
// before: () => IntermediateData,
// after: (IntermediateData, Input) => TaskResult
// ) extends Task[TaskResult] {
// val inputs: Seq[Task[?]] = source.inputs
//
// def evaluate(ctx: mill.api.TaskCtx): Result[TaskResult] = {
// println("before()")
// val intermediateData = before()
// println(s"intermediateData=$intermediateData")
//// val input = ctx.arg(0).asInstanceOf[Input]
// val input = source.evaluate(ctx)
// println(s"input=$input")
// println("after()")
// val result = after(intermediateData, input)
// println(s"result=$result")
// result
// }
//
// override def sideHash: Int = source.sideHash
// override def persistent: Boolean = source.persistent
// override private[mill] def isExclusiveCommand = source.isExclusiveCommand
//
// override private[mill] def asSimple = source.asSimple.map { simple => ??? }
//
// override private[mill] def asCommand = source.asCommand.map { command => ??? }
//
// override private[mill] def asWorker = source.asWorker.map { worker => ??? }
// }

private[api] class Zipped[+T, +V](source1: Task[T], source2: Task[V]) extends Task[(T, V)] {
def evaluate(ctx: mill.api.TaskCtx): Result[(T, V)] = (ctx.arg(0), ctx.arg(1))
val inputs: Seq[Task[?]] = List(source1, source2)
Expand Down
6 changes: 6 additions & 0 deletions core/constants/src/mill/constants/EnvVars.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ public class EnvVars {
*/
public static final String MILL_OUTPUT_DIR = "MILL_OUTPUT_DIR";

/**
* Output directory where Mill workers' state and Mill tasks output should be
* written to for the Mill instances running in BSP mode.
*/
public static final String MILL_BSP_OUTPUT_DIR = "MILL_BSP_OUTPUT_DIR";

/**
* If set to "1", Mill will re-use the regular @{Link OutFiles#out} folder instead of
* using a separate one for BSP output.
Expand Down
20 changes: 16 additions & 4 deletions core/constants/src/mill/constants/OutFiles.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ public class OutFiles {
*/
private static final String envOutOrNull = System.getenv(EnvVars.MILL_OUTPUT_DIR);

/**
* Allows us to override the `out/mill-bsp-out` folder from the environment via the
* {@link EnvVars#MILL_BSP_OUTPUT_DIR} variable.
*/
private static final String envBspOutOrNull = System.getenv(EnvVars.MILL_BSP_OUTPUT_DIR);

/** @see EnvVars#MILL_NO_SEPARATE_BSP_OUTPUT_DIR */
public static final boolean mergeBspOut =
"1".equals(System.getenv(EnvVars.MILL_NO_SEPARATE_BSP_OUTPUT_DIR));
Expand All @@ -28,24 +34,30 @@ public class OutFiles {
*/
public static final String out = envOutOrNull == null ? defaultOut : envOutOrNull;

/**
* Default hard-coded value for the Mill `out/` folder path when Mill is running in BSP mode. Unless you know
* what you are doing, you should favor using {@link #outFor} instead.
*/
public static final String defaultBspOut = "out/mill-bsp-out";

/**
* Path of the Mill `out/` folder when Mill is running in BSP mode. Unless you know
* what you are doing, you should favor using {@link #outFor} instead.
*/
public static final String bspOut = "out/mill-bsp-out";
public static final String bspOut = envBspOutOrNull == null ? defaultBspOut : envBspOutOrNull;

/**
* Path of the Mill {@link #out} folder.
*
* @param outMode If {@link #envOutOrNull} is set, this parameter is ignored.
*/
public static String outFor(OutFolderMode outMode) {
if (envOutOrNull != null) return envOutOrNull;
switch (outMode) {
case REGULAR:
return out;
return envOutOrNull != null ? envOutOrNull : out;
case BSP:
return mergeBspOut ? out : bspOut;
if (envBspOutOrNull != null) return envBspOutOrNull;
return mergeBspOut ? outFor(OutFolderMode.REGULAR) : bspOut;
default:
throw new IllegalArgumentException("Unknown out folder mode: " + outMode);
}
Expand Down
2 changes: 1 addition & 1 deletion core/exec/src/mill/exec/GroupExecution.scala
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ object GroupExecution {
if (path.startsWith(workspace) && !validReadDests.exists(path.startsWith(_))) {
sys.error(
s"Reading from ${path.relativeTo(workspace)} not allowed during execution of `$terminal`.\n" +
"You can only read files referenced by `Task.Source` or `Task.Sources`, or within a `Task.Input"
"You can only read files referenced by `Task.Source` or `Task.Sources`, or within a `Task.Input`"
)
}
}
Expand Down
3 changes: 2 additions & 1 deletion integration/bsp-util/src/BspServerTestUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.eclipse.lsp4j.jsonrpc.services.JsonRequest
import java.io.ByteArrayOutputStream
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.{CompletableFuture, ExecutorService, Executors, ThreadFactory}
import scala.annotation.unused
import scala.jdk.CollectionConverters.*
import scala.reflect.ClassTag

Expand Down Expand Up @@ -226,7 +227,7 @@ object BspServerTestUtil {
workspacePath: os.Path,
coursierCache: os.Path = os.Path(CacheDefaults.location),
javaHome: os.Path = os.Path(sys.props("java.home")),
javaVersion: String = sys.props("java.version")
@unused javaVersion: String = sys.props("java.version")
): Seq[(String, String)] =
Seq(
workspacePath.toURI.toASCIIString.stripSuffix("/") -> "file:///workspace",
Expand Down
2 changes: 2 additions & 0 deletions libs/androidlib/src/mill/androidlib/AndroidModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ trait AndroidModule extends JavaModule { outer =>
.internalWorker()
.compileJava(
ZincCompileJava(
compileTo = Task.dest,
upstreamCompileOutput = upstreamCompileOutput(),
sources = androidLibsRClasses().map(_.path),
compileClasspath = Seq.empty,
Expand Down Expand Up @@ -648,6 +649,7 @@ trait AndroidModule extends JavaModule { outer =>
.internalWorker()
.compileJava(
ZincCompileJava(
compileTo = Task.dest,
upstreamCompileOutput = upstreamCompileOutput(),
sources = sources.map(_.path),
compileClasspath = androidTransitiveLibRClasspath().map(_.path),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ trait AndroidHiltSupport extends KspModule, AndroidKotlinModule {
val analysisFile = Task.dest / "kotlin.analysis.dummy"
os.write(target = analysisFile, data = "", createFolders = true)

CompilationResult(analysisFile, transformClasses)
CompilationResult(analysisFile, transformClasses, semanticDbFiles = None)
}

def hiltProcessorClasspath: T[Seq[PathRef]] = Task {
Expand Down
Loading