Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add stub mill.define.Ctx to trick IntelliJ into not erroring #3856

Merged
merged 9 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions main/define/src/mill/define/Cacher.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package mill.define

import scala.collection.mutable
import scala.reflect.macros.blackbox.Context

private[mill] trait Cacher extends mill.moduledefs.Cacher {
private[this] lazy val cacherLazyMap = mutable.Map.empty[sourcecode.Enclosing, Any]

override protected[this] def cachedTarget[T](t: => T)(implicit c: sourcecode.Enclosing): T =
synchronized {
cacherLazyMap.getOrElseUpdate(c, t).asInstanceOf[T]
}
}

private[mill] object Cacher {
def impl0[T: c.WeakTypeTag](c: Context)(t: c.Expr[T]): c.Expr[T] = {
c.Expr[T](wrapCached[T](c)(t.tree))
}
def wrapCached[R: c.WeakTypeTag](c: Context)(t: c.Tree): c.universe.Tree = {

import c.universe._
val owner = c.internal.enclosingOwner
val ownerIsCacherClass =
owner.owner.isClass &&
owner.owner.asClass.baseClasses.exists(_.fullName == "mill.define.Cacher")

if (ownerIsCacherClass && owner.isMethod) q"this.cachedTarget[${weakTypeTag[R]}]($t)"
else c.abort(
c.enclosingPosition,
"Task{} members must be defs defined in a Module class/trait/object body"
)
}
}
14 changes: 12 additions & 2 deletions main/define/src/mill/define/Ctx.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package mill.define

import scala.annotation.implicitNotFound
import scala.annotation.{compileTimeOnly, implicitNotFound}

/**
* The contextual information provided by a [[mill.define.Module]].
Expand Down Expand Up @@ -39,7 +39,7 @@ trait Ctx {
private[mill] def withEnclosingModule(enclosingModule: Any): Ctx = this
}

object Ctx {
object Ctx extends LowPriCtx {
private case class Impl(
enclosing: String,
lineNum: Int,
Expand Down Expand Up @@ -106,3 +106,13 @@ object Ctx {
)
}
}

trait LowPriCtx {
// Dummy `Ctx` available in implicit scope but never actually used.
// as it is provided by the codegen. Defined for IDEs to think that one is available
// and not show errors in build.mill/package.mill even though they can't see the codegen
@compileTimeOnly(
"Modules and Tasks can only be defined within a mill Module"
)
implicit def dummyInfo: Ctx = sys.error("implicit Ctx must be provided")
}
2 changes: 1 addition & 1 deletion main/define/src/mill/define/Module.scala
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ object Module {
* messes up the module discovery process
*/
@internal
class BaseClass(implicit outerCtx0: mill.define.Ctx) extends mill.moduledefs.Cacher {
class BaseClass(implicit outerCtx0: mill.define.Ctx) extends mill.define.Cacher {
def millOuterCtx = outerCtx0
}

Expand Down
24 changes: 12 additions & 12 deletions main/define/src/mill/define/Task.scala
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ object Target extends TaskBase {

val lhs = Applicative.impl0[Task, T, mill.api.Ctx](c)(reify(Result.create(t.splice)).tree)

mill.moduledefs.Cacher.impl0[Target[T]](c)(
mill.define.Cacher.impl0[Target[T]](c)(
reify(
new TargetImpl[T](
lhs.splice,
Expand All @@ -379,7 +379,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[Target[T]](c)(
mill.define.Cacher.impl0[Target[T]](c)(
reify(
new TargetImpl[T](
Applicative.impl0[Task, T, mill.api.Ctx](c)(t.tree).splice,
Expand All @@ -398,7 +398,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[Target[T]](c)(
mill.define.Cacher.impl0[Target[T]](c)(
reify {
val s1 = Applicative.impl0[Task, T, mill.api.Ctx](c)(t.tree).splice
val c1 = ctx.splice
Expand All @@ -421,7 +421,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[Target[T]](c)(
mill.define.Cacher.impl0[Target[T]](c)(
reify(
new TargetImpl[T](
t.splice,
Expand All @@ -444,7 +444,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[SourcesImpl](c)(
mill.define.Cacher.impl0[SourcesImpl](c)(
reify(
new SourcesImpl(
Target.sequence(c.Expr[List[Task[PathRef]]](q"_root_.scala.List(..$wrapped)").splice),
Expand All @@ -461,7 +461,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[SourcesImpl](c)(
mill.define.Cacher.impl0[SourcesImpl](c)(
reify(
new SourcesImpl(
Applicative.impl0[Task, Seq[PathRef], mill.api.Ctx](c)(values.tree).splice,
Expand All @@ -483,7 +483,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[Target[PathRef]](c)(
mill.define.Cacher.impl0[Target[PathRef]](c)(
reify(
new SourceImpl(
wrapped.splice,
Expand All @@ -500,7 +500,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[Target[PathRef]](c)(
mill.define.Cacher.impl0[Target[PathRef]](c)(
reify(
new SourceImpl(
Applicative.impl0[Task, PathRef, mill.api.Ctx](c)(value.tree).splice,
Expand All @@ -519,7 +519,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[InputImpl[T]](c)(
mill.define.Cacher.impl0[InputImpl[T]](c)(
reify(
new InputImpl[T](
Applicative.impl[Task, T, mill.api.Ctx](c)(value).splice,
Expand Down Expand Up @@ -598,7 +598,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[Worker[T]](c)(
mill.define.Cacher.impl0[Worker[T]](c)(
reify(
new Worker[T](t.splice, ctx.splice, taskIsPrivate.splice)
)
Expand All @@ -611,7 +611,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[Worker[T]](c)(
mill.define.Cacher.impl0[Worker[T]](c)(
reify(
new Worker[T](
Applicative.impl[Task, T, mill.api.Ctx](c)(t).splice,
Expand All @@ -630,7 +630,7 @@ object Target extends TaskBase {

val taskIsPrivate = isPrivateTargetOption(c)

mill.moduledefs.Cacher.impl0[PersistentImpl[T]](c)(
mill.define.Cacher.impl0[PersistentImpl[T]](c)(
reify(
new PersistentImpl[T](
Applicative.impl[Task, T, mill.api.Ctx](c)(t).splice,
Expand Down
33 changes: 22 additions & 11 deletions main/define/test/src/mill/define/MacroErrorTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object MacroErrorTests extends TestSuite {

test("errors") {
val expectedMsg =
"Task{} members must be defs defined in a Cacher class/trait/object body"
"Task{} members must be defs defined in a Module class/trait/object body"

val err = compileError("object Foo extends TestBaseModule{ val x = Task {1} }")
assert(err.msg == expectedMsg)
Expand Down Expand Up @@ -84,21 +84,32 @@ object MacroErrorTests extends TestSuite {
// of our `Target#apply()` calls, but we cannot reference any values that
// come from inside the Task{...} block
test("pos") {
val e = compileError("""
val a = Task { 1 }
// This hsould compile
object foo extends TestBaseModule {
def a = Task { 1 }
val arr = Array(a)
val b = {
def b = {
val c = 0
Task{
Task {
arr(c)()
}
}
""")
}
}
test("neg1") {
val e = compileError("""def a = Task { 1 }""")
assert(e.msg.contains(
"Modules and Tasks can only be defined within a mill Module"
"Task{} members must be defs defined in a Module class/trait/object body"
))
}
test("neg") {

test("neg2") {
val e = compileError("object foo extends TestBaseModule{ val a = Task { 1 } }")
assert(e.msg.contains(
"Task{} members must be defs defined in a Module class/trait/object body"
))
}
test("neg3") {

val expectedMsg =
"Target#apply() call cannot use `value n` defined within the Task{...} block"
Expand All @@ -114,7 +125,7 @@ object MacroErrorTests extends TestSuite {
}""")
assert(err.msg == expectedMsg)
}
test("neg2") {
test("neg4") {

val expectedMsg =
"Target#apply() call cannot use `value x` defined within the Task{...} block"
Expand All @@ -129,7 +140,7 @@ object MacroErrorTests extends TestSuite {
}""")
assert(err.msg == expectedMsg)
}
test("neg3") {
test("neg5") {
val borkedCachedDiamond1 = utest.compileError("""
object borkedCachedDiamond1 {
def up = Task { TestUtil.test() }
Expand All @@ -139,7 +150,7 @@ object MacroErrorTests extends TestSuite {
}
""")
assert(borkedCachedDiamond1.msg.contains(
"Modules and Tasks can only be defined within a mill Module"
"Task{} members must be defs defined in a Module class/trait/object body"
))
}
}
Expand Down
Loading