@@ -14,10 +14,21 @@ import scala.collection.mutable
1414 * the `Task.Command` methods we find. This mapping from `Class[_]` to `MainData`
1515 * can then be used later to look up the `MainData` for any module.
1616 */
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+ }
1829
1930object Discover {
20- class Node (
31+ class ClassInfo (
2132 val entryPoints : Seq [mainargs.MainData [_, _]],
2233 val declaredNames : Seq [String ]
2334 )
@@ -37,14 +48,19 @@ object Discover {
3748 def rec (tpe : TypeRepr ): Unit = {
3849 if (seen.add(tpe)) {
3950 val typeSym = tpe.typeSymbol
40- for {
51+ val memberTypes : Seq [ TypeRepr ] = for {
4152 m <- typeSym.fieldMembers ++ typeSym.methodMembers
4253 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)
4561 } {
46- rec(memberTpe )
47- memberTpe .asType match {
62+ rec(tpe )
63+ tpe .asType match {
4864 case ' [mill.define.Cross [m]] => rec(TypeRepr .of[m])
4965 case _ => () // no cross argument to extract
5066 }
@@ -100,83 +116,63 @@ object Discover {
100116 // otherwise the compiler likes to give us stuff in random orders, which
101117 // causes the code to be generated in random order resulting in code hashes
102118 // 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)
109124 assertParamListCounts(
110125 curCls,
111- methods ,
126+ declMethods ,
112127 (TypeRepr .of[mill.define.Command [? ]], 1 , " `Task.Command`" ),
113128 (TypeRepr .of[mill.define.Target [? ]], 0 , " Target" )
114129 )
115- }
116130
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))
161161 }
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+ }
165173 }
166174
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) }* )) }
180176 }
181177 }
182178}
0 commit comments