@@ -14,30 +14,13 @@ 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
- case class Discover private (
18
- value : Map [
19
- Class [_],
20
- (Seq [String ], Seq [mainargs.MainData [_, _]], Seq [String ])
21
- ],
22
- dummy : Int = 0 /* avoid conflict with Discover.apply(value: Map) below*/
23
- ) {
24
- @ deprecated(" Binary compatibility shim" , " Mill 0.11.4" )
25
- private [define] def this (value : Map [Class [_], Seq [mainargs.MainData [_, _]]]) =
26
- this (value.view.mapValues((Nil , _, Nil )).toMap)
27
- @ deprecated(" Binary compatibility shim" , " Mill 0.11.4" )
28
- private [define] def copy (value : Map [Class [_], Seq [mainargs.MainData [_, _]]]): Discover = {
29
- new Discover (value.view.mapValues((Nil , _, Nil )).toMap, dummy)
30
- }
31
- }
17
+ class Discover (val classInfo : Map [Class [_], Discover .Node ], val allNames : Seq [String ])
32
18
33
19
object Discover {
34
- def apply2 [T ](value : Map [Class [_], (Seq [String ], Seq [mainargs.MainData [_, _]], Seq [String ])])
35
- : Discover =
36
- new Discover (value)
37
-
38
- @ deprecated(" Binary compatibility shim" , " Mill 0.11.4" )
39
- def apply [T ](value : Map [Class [_], Seq [mainargs.MainData [_, _]]]): Discover =
40
- new Discover (value.view.mapValues((Nil , _, Nil )).toMap)
20
+ class Node (
21
+ val entryPoints : Seq [mainargs.MainData [_, _]],
22
+ val declaredNames : Seq [String ]
23
+ )
41
24
42
25
inline def apply [T ]: Discover = $ { Router .applyImpl[T ] }
43
26
@@ -46,7 +29,7 @@ object Discover {
46
29
import mainargs .Macros .*
47
30
import scala .util .control .NonFatal
48
31
49
- def applyImpl [T : Type ](using Quotes ): Expr [Discover ] = {
32
+ def applyImpl [T : Type ](using quotes : Quotes ): Expr [Discover ] = {
50
33
import quotes .reflect .*
51
34
val seen = mutable.Set .empty[TypeRepr ]
52
35
val moduleSym = Symbol .requiredClass(" mill.define.Module" )
@@ -62,10 +45,8 @@ object Discover {
62
45
} {
63
46
rec(memberTpe)
64
47
memberTpe.asType match {
65
- case ' [mill.define.Cross [m]] =>
66
- rec(TypeRepr .of[m])
67
- case _ =>
68
- () // no cross argument to extract
48
+ case ' [mill.define.Cross [m]] => rec(TypeRepr .of[m])
49
+ case _ => () // no cross argument to extract
69
50
}
70
51
}
71
52
}
@@ -107,89 +88,91 @@ object Discover {
107
88
)
108
89
)
109
90
91
+ def sortedMethods (curCls : TypeRepr , sub : TypeRepr , methods : Seq [Symbol ]): Seq [Symbol ] =
92
+ for {
93
+ m <- methods.toList.sortBy(_.fullName)
94
+ mType = curCls.memberType(m)
95
+ returnType = methodReturn(mType)
96
+ if returnType <:< sub
97
+ } yield m
98
+
110
99
// Make sure we sort the types and methods to keep the output deterministic;
111
100
// otherwise the compiler likes to give us stuff in random orders, which
112
101
// causes the code to be generated in random order resulting in code hashes
113
102
// changing unnecessarily
114
- val mapping = for {
103
+ val mapping : Seq [( Expr [( Class [_], Node )], Seq [ String ])] = for {
115
104
discoveredModuleType <- seen.toSeq.sortBy(_.typeSymbol.fullName)
116
105
curCls = discoveredModuleType
117
106
methods = filterDefs(curCls.typeSymbol.methodMembers)
118
107
declMethods = filterDefs(curCls.typeSymbol.declaredMethods)
119
- overridesRoutes = {
108
+ _ = {
120
109
assertParamListCounts(
121
110
curCls,
122
111
methods,
123
112
(TypeRepr .of[mill.define.Command [? ]], 1 , " `Task.Command`" ),
124
113
(TypeRepr .of[mill.define.Target [? ]], 0 , " Target" )
125
114
)
115
+ }
126
116
127
- def sortedMethods (sub : TypeRepr , methods : Seq [Symbol ] = methods): Seq [Symbol ] =
128
- for {
129
- m <- methods.toList.sortBy(_.fullName)
130
- mType = curCls.memberType(m)
131
- returnType = methodReturn(mType)
132
- if returnType <:< sub
133
- } yield m
134
-
135
- Tuple3 (
136
- for {
137
- m <- sortedMethods(sub = TypeRepr .of[mill.define.NamedTask [? ]])
138
- } yield m.name, // .decoded // we don't need to decode the name in Scala 3
139
- for {
140
- m <- sortedMethods(sub = TypeRepr .of[mill.define.Command [? ]])
141
- } yield curCls.asType match {
142
- case ' [t] =>
143
- val expr =
144
- try
145
- createMainData[Any , t](
146
- m,
147
- m.annotations.find(_.tpe =:= TypeRepr .of[mainargs.main]).getOrElse(' {
148
- new mainargs.main()
149
- }.asTerm),
150
- m.paramSymss
151
- ).asExprOf[mainargs.MainData [? , ? ]]
152
- catch {
153
- case NonFatal (e) =>
154
- val (before, Array (after, _* )) = e.getStackTrace().span(e =>
155
- ! (e.getClassName() == " mill.define.Discover$Router$" && e.getMethodName() == " applyImpl" )
156
- ): @ unchecked
157
- val trace =
158
- (before :+ after).map(_.toString).mkString(" trace:\n " , " \n " , " \n ..." )
159
- report.errorAndAbort(
160
- s " Error generating maindata for ${m.fullName}: ${e}\n $trace" ,
161
- m.pos.getOrElse(Position .ofMacroExpansion)
162
- )
163
- }
164
- // report.warning(s"generated maindata for ${m.fullName}:\n${expr.asTerm.show}", m.pos.getOrElse(Position.ofMacroExpansion))
165
- expr
166
- },
167
- for
168
- m <- sortedMethods(sub = TypeRepr .of[mill.define.Task [? ]], methods = declMethods)
169
- yield m.name.toString
170
- )
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
171
145
}
172
- if overridesRoutes._1.nonEmpty || overridesRoutes._2.nonEmpty || overridesRoutes._3.nonEmpty
146
+ declaredNames =
147
+ sortedMethods(
148
+ curCls,
149
+ sub = TypeRepr .of[mill.define.NamedTask [? ]],
150
+ declMethods
151
+ ).map(_.name)
152
+ if names.nonEmpty || entryPoints.nonEmpty
173
153
} yield {
174
- val (names, mainDataExprs, taskNames) = overridesRoutes
175
154
// by wrapping the `overridesRoutes` in a lambda function we kind of work around
176
155
// the problem of generating a *huge* macro method body that finally exceeds the
177
156
// JVM's maximum allowed method size
178
157
val overridesLambda = ' {
179
- def triple () = ($ { Expr (names) }, $ { Expr .ofList(mainDataExprs) }, $ { Expr (taskNames) })
158
+ def triple () =
159
+ new Node ($ { Expr .ofList(entryPoints) }, $ { Expr (declaredNames) })
180
160
triple()
181
161
}
182
162
val lhs =
183
163
Ref (defn.Predef_classOf ).appliedToType(discoveredModuleType.widen).asExprOf[Class [? ]]
184
- ' { $lhs -> $overridesLambda }
164
+ ( ' { $lhs -> $overridesLambda }, names)
185
165
}
186
166
187
167
val expr : Expr [Discover ] =
188
168
' {
189
169
// TODO: we can not import this here, so we have to import at the use site now, or redesign?
190
170
// import mill.main.TokenReaders.*
191
171
// import mill.api.JsonFormatters.*
192
- Discover .apply2(Map ($ { Varargs (mapping) }* ))
172
+ new Discover (
173
+ Map [Class [_], Node ]($ { Varargs (mapping.map(_._1)) }* ),
174
+ $ { Expr (mapping.iterator.flatMap(_._2).distinct.toList.sorted) }
175
+ )
193
176
}
194
177
// TODO: if needed for debugging, we can re-enable this
195
178
// report.warning(s"generated discovery for ${TypeRepr.of[T].show}:\n${expr.asTerm.show}", TypeRepr.of[T].typeSymbol.pos.getOrElse(Position.ofMacroExpansion))
0 commit comments