Skip to content

Commit d250020

Browse files
committed
WIP 44 - implement EnclosingClass, pass specific integration tests:
- example.tasks[1-task-graph].local - example.tasks[3-anonymous-tasks].local - example.tasks[4-inputs].local - example.tasks[5-persistent-targets].local - example.tasks[6-workers].local - example.tasks[9-backticked-names].local - integration.feature[hygiene].local - integration.feature[mill-jvm-opts].local - integration.feature[non-identifier-import].local - integration.feature[private-methods].local - integration.feature[repo-config-via-import].local - integration.failure[invalid-meta-module].local - integration.failure[missing-build-file].local - integration.failure[module-init-error].local - integration.failure[multiple-top-level-modules].local - integration.failure[things-outside-top-level-module].local
1 parent 1efbdba commit d250020

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

main/define/src/mill/define/Discover.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ object Discover {
184184
// import mill.main.TokenReaders.*
185185
Discover.apply2(Map(${Varargs(mapping)}*))
186186
}
187-
report.warning(s"generated maindata for ${TypeRepr.of[T].show}:\n${expr.asTerm.show}", TypeRepr.of[T].typeSymbol.pos.getOrElse(Position.ofMacroExpansion))
187+
// TODO: if needed for debugging, we can re-enable this
188+
// report.warning(s"generated maindata for ${TypeRepr.of[T].show}:\n${expr.asTerm.show}", TypeRepr.of[T].typeSymbol.pos.getOrElse(Position.ofMacroExpansion))
188189
expr
189190
}
190191
}
Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,55 @@
11
package mill.define
22

3-
// import sourcecode.Compat.Context
4-
// import language.experimental.macros
3+
import scala.quoted.*
54

65
case class EnclosingClass(value: Class[_])
76
object EnclosingClass {
87
def apply()(implicit c: EnclosingClass) = c.value
9-
implicit def generate: EnclosingClass = ??? // macro impl
10-
// def impl(c: Context): c.Tree = {
11-
// import c.universe._
12-
// // q"new _root_.mill.define.EnclosingClass(classOf[$cls])"
13-
// q"new _root_.mill.define.EnclosingClass(this.getClass)"
14-
// }
8+
inline given generate: EnclosingClass = ${ impl }
9+
10+
// TODO: copied from Task.scala
11+
private def withMacroOwner[T](using Quotes)(op: quotes.reflect.Symbol => T): T = {
12+
import quotes.reflect.*
13+
14+
// In Scala 3, the top level splice of a macro is owned by a symbol called "macro" with the macro flag set,
15+
// but not the method flag.
16+
def isMacroOwner(sym: Symbol)(using Quotes): Boolean =
17+
sym.name == "macro" && sym.flags.is(Flags.Macro | Flags.Synthetic) && !sym.flags.is(
18+
Flags.Method
19+
)
20+
21+
def loop(owner: Symbol): T =
22+
if owner.isPackageDef || owner == Symbol.noSymbol then
23+
report.errorAndAbort(
24+
"Cannot find the owner of the macro expansion",
25+
Position.ofMacroExpansion
26+
)
27+
else if isMacroOwner(owner) then op(owner.owner) // Skip the "macro" owner
28+
else loop(owner.owner)
29+
30+
loop(Symbol.spliceOwner)
31+
}
32+
33+
def impl(using Quotes): Expr[EnclosingClass] = withMacroOwner { owner =>
34+
import quotes.reflect.*
35+
36+
def enclosingClass(sym: Symbol): Symbol =
37+
if sym.isPackageDef || sym == Symbol.noSymbol then
38+
report.errorAndAbort(
39+
"Cannot find the enclosing class of the macro expansion",
40+
Position.ofMacroExpansion
41+
)
42+
else if sym.isClassDef then sym
43+
else enclosingClass(sym.owner)
44+
45+
if owner.flags.is(Flags.Method) then
46+
val cls = enclosingClass(owner)
47+
val ref = This(cls).asExprOf[Any]
48+
'{ new EnclosingClass($ref.getClass) }
49+
else
50+
report.errorAndAbort(
51+
"EnclosingClass.generate can only be used within a method",
52+
Position.ofMacroExpansion
53+
)
54+
}
1555
}

0 commit comments

Comments
 (0)