@@ -14,10 +14,21 @@ import scala.collection.mutable
14
14
* the `Task.Command` methods we find. This mapping from `Class[_]` to `MainData`
15
15
* can then be used later to look up the `MainData` for any module.
16
16
*/
17
- class Discover (val classInfo : Map [Class [_], Discover .Node ], val allNames : Seq [String ])
17
+ class Discover (val classInfo : Map [Class [_], Discover .ClassInfo ]) {
18
+ def resolveEntrypoint (cls : Class [_], name : String ) = {
19
+ val res = for {
20
+ (cls2, node) <- classInfo
21
+ if cls2.isAssignableFrom(cls)
22
+ ep <- node.entryPoints
23
+ if ep.name == name
24
+ } yield ep
25
+
26
+ res.headOption
27
+ }
28
+ }
18
29
19
30
object Discover {
20
- class Node (
31
+ class ClassInfo (
21
32
val entryPoints : Seq [mainargs.MainData [_, _]],
22
33
val declaredNames : Seq [String ]
23
34
)
@@ -37,14 +48,19 @@ object Discover {
37
48
def rec (tpe : TypeRepr ): Unit = {
38
49
if (seen.add(tpe)) {
39
50
val typeSym = tpe.typeSymbol
40
- for {
51
+ val memberTypes : Seq [ TypeRepr ] = for {
41
52
m <- typeSym.fieldMembers ++ typeSym.methodMembers
42
53
if m != Symbol .noSymbol
43
- memberTpe = m.termRef
44
- if memberTpe.baseClasses.contains(moduleSym)
54
+ } yield m.termRef
55
+
56
+ val parentTypes : Seq [TypeRepr ] = tpe.baseClasses.map(_.typeRef)
57
+
58
+ for {
59
+ tpe <- memberTypes ++ parentTypes
60
+ if tpe.baseClasses.contains(moduleSym)
45
61
} {
46
- rec(memberTpe )
47
- memberTpe .asType match {
62
+ rec(tpe )
63
+ tpe .asType match {
48
64
case ' [mill.define.Cross [m]] => rec(TypeRepr .of[m])
49
65
case _ => () // no cross argument to extract
50
66
}
@@ -100,83 +116,63 @@ object Discover {
100
116
// otherwise the compiler likes to give us stuff in random orders, which
101
117
// causes the code to be generated in random order resulting in code hashes
102
118
// changing unnecessarily
103
- val mapping : Seq [(Expr [(Class [_], Node )], Seq [String ])] = for {
104
- discoveredModuleType <- seen.toSeq.sortBy(_.typeSymbol.fullName)
105
- curCls = discoveredModuleType
106
- methods = filterDefs(curCls.typeSymbol.methodMembers)
107
- declMethods = filterDefs(curCls.typeSymbol.declaredMethods)
108
- _ = {
119
+ val mapping : Seq [(TypeRepr , (Seq [scala.quoted.Expr [mainargs.MainData [? , ? ]]], Seq [String ]))] =
120
+ for {
121
+ curCls <- seen.toSeq.sortBy(_.typeSymbol.fullName)
122
+ } yield {
123
+ val declMethods = filterDefs(curCls.typeSymbol.declaredMethods)
109
124
assertParamListCounts(
110
125
curCls,
111
- methods ,
126
+ declMethods ,
112
127
(TypeRepr .of[mill.define.Command [? ]], 1 , " `Task.Command`" ),
113
128
(TypeRepr .of[mill.define.Target [? ]], 0 , " Target" )
114
129
)
115
- }
116
130
117
- names =
118
- sortedMethods(curCls, sub = TypeRepr .of[mill.define.NamedTask [? ]], methods).map(_.name)
119
- entryPoints = for {
120
- m <- sortedMethods(curCls, sub = TypeRepr .of[mill.define.Command [? ]], methods)
121
- } yield curCls.asType match {
122
- case ' [t] =>
123
- val expr =
124
- try
125
- createMainData[Any , t](
126
- m,
127
- m.annotations.find(_.tpe =:= TypeRepr .of[mainargs.main]).getOrElse(' {
128
- new mainargs.main()
129
- }.asTerm),
130
- m.paramSymss
131
- ).asExprOf[mainargs.MainData [? , ? ]]
132
- catch {
133
- case NonFatal (e) =>
134
- val (before, Array (after, _* )) = e.getStackTrace().span(e =>
135
- ! (e.getClassName() == " mill.define.Discover$Router$" && e.getMethodName() == " applyImpl" )
136
- ): @ unchecked
137
- val trace =
138
- (before :+ after).map(_.toString).mkString(" trace:\n " , " \n " , " \n ..." )
139
- report.errorAndAbort(
140
- s " Error generating maindata for ${m.fullName}: ${e}\n $trace" ,
141
- m.pos.getOrElse(Position .ofMacroExpansion)
142
- )
143
- }
144
- expr
145
- }
146
- declaredNames =
147
- sortedMethods(
148
- curCls,
149
- sub = TypeRepr .of[mill.define.NamedTask [? ]],
150
- declMethods
151
- ).map(_.name)
152
- if names.nonEmpty || entryPoints.nonEmpty
153
- } yield {
154
- // by wrapping the `overridesRoutes` in a lambda function we kind of work around
155
- // the problem of generating a *huge* macro method body that finally exceeds the
156
- // JVM's maximum allowed method size
157
- val overridesLambda = ' {
158
- def triple () =
159
- new Node ($ { Expr .ofList(entryPoints) }, $ { Expr (declaredNames) })
160
- triple()
131
+ val names =
132
+ sortedMethods(
133
+ curCls,
134
+ sub = TypeRepr .of[mill.define.NamedTask [? ]],
135
+ declMethods
136
+ ).map(_.name)
137
+ val entryPoints = for {
138
+ m <- sortedMethods(curCls, sub = TypeRepr .of[mill.define.Command [? ]], declMethods)
139
+ } yield curCls.asType match {
140
+ case ' [t] =>
141
+ val expr =
142
+ try
143
+ createMainData[Any , t](
144
+ m,
145
+ m.annotations
146
+ .find(_.tpe =:= TypeRepr .of[mainargs.main])
147
+ .getOrElse(' { new mainargs.main() }.asTerm),
148
+ m.paramSymss
149
+ ).asExprOf[mainargs.MainData [? , ? ]]
150
+ catch {
151
+ case NonFatal (e) =>
152
+ report.errorAndAbort(
153
+ s " Error generating maindata for ${m.fullName}: ${e}\n ${e.getStackTrace().mkString(" \n " )}" ,
154
+ m.pos.getOrElse(Position .ofMacroExpansion)
155
+ )
156
+ }
157
+ expr
158
+ }
159
+
160
+ (curCls.widen, (entryPoints, names))
161
161
}
162
- val lhs =
163
- Ref (defn.Predef_classOf ).appliedToType(discoveredModuleType.widen).asExprOf[Class [? ]]
164
- (' { $lhs -> $overridesLambda }, names)
162
+
163
+ val mappingExpr = mapping.collect {
164
+ case (cls, (entryPoints, names)) if entryPoints.nonEmpty || names.nonEmpty =>
165
+ // by wrapping the `overridesRoutes` in a lambda function we kind of work around
166
+ // the problem of generating a *huge* macro method body that finally exceeds the
167
+ // JVM's maximum allowed method size
168
+ ' {
169
+ def func () = new ClassInfo ($ { Expr .ofList(entryPoints.toList) }, $ { Expr (names) })
170
+
171
+ ($ { Ref (defn.Predef_classOf ).appliedToType(cls).asExprOf[Class [? ]] }, func())
172
+ }
165
173
}
166
174
167
- val expr : Expr [Discover ] =
168
- ' {
169
- // TODO: we can not import this here, so we have to import at the use site now, or redesign?
170
- // import mill.main.TokenReaders.*
171
- // import mill.api.JsonFormatters.*
172
- new Discover (
173
- Map [Class [_], Node ]($ { Varargs (mapping.map(_._1)) }* ),
174
- $ { Expr (mapping.iterator.flatMap(_._2).distinct.toList.sorted) }
175
- )
176
- }
177
- // TODO: if needed for debugging, we can re-enable this
178
- // report.warning(s"generated discovery for ${TypeRepr.of[T].show}:\n${expr.asTerm.show}", TypeRepr.of[T].typeSymbol.pos.getOrElse(Position.ofMacroExpansion))
179
- expr
175
+ ' { new Discover (Map [Class [_], ClassInfo ]($ { Varargs (mappingExpr) }* )) }
180
176
}
181
177
}
182
178
}
0 commit comments