@@ -47,6 +47,96 @@ import Annotations.Annotation
47
47
* }
48
48
*/
49
49
object MainProxies {
50
+ def mainProxiesOld (stats : List [tpd.Tree ])(using Context ): List [untpd.Tree ] = {
51
+ import tpd ._
52
+ def mainMethods (stats : List [Tree ]): List [Symbol ] = stats.flatMap {
53
+ case stat : DefDef if stat.symbol.hasAnnotation(defn.MainAnnot ) =>
54
+ stat.symbol :: Nil
55
+ case stat @ TypeDef (name, impl : Template ) if stat.symbol.is(Module ) =>
56
+ mainMethods(impl.body)
57
+ case _ =>
58
+ Nil
59
+ }
60
+ mainMethods(stats).flatMap(mainProxyOld)
61
+ }
62
+
63
+ import untpd ._
64
+ def mainProxyOld (mainFun : Symbol )(using Context ): List [TypeDef ] = {
65
+ val mainAnnotSpan = mainFun.getAnnotation(defn.MainAnnot ).get.tree.span
66
+ def pos = mainFun.sourcePos
67
+ val argsRef = Ident (nme.args)
68
+
69
+ def addArgs (call : untpd.Tree , mt : MethodType , idx : Int ): untpd.Tree =
70
+ if (mt.isImplicitMethod) {
71
+ report.error(s " @main method cannot have implicit parameters " , pos)
72
+ call
73
+ }
74
+ else {
75
+ val args = mt.paramInfos.zipWithIndex map {
76
+ (formal, n) =>
77
+ val (parserSym, formalElem) =
78
+ if (formal.isRepeatedParam) (defn.CLP_parseRemainingArguments , formal.argTypes.head)
79
+ else (defn.CLP_parseArgument , formal)
80
+ val arg = Apply (
81
+ TypeApply (ref(parserSym.termRef), TypeTree (formalElem) :: Nil ),
82
+ argsRef :: Literal (Constant (idx + n)) :: Nil )
83
+ if (formal.isRepeatedParam) repeated(arg) else arg
84
+ }
85
+ val call1 = Apply (call, args)
86
+ mt.resType match {
87
+ case restpe : MethodType =>
88
+ if (mt.paramInfos.lastOption.getOrElse(NoType ).isRepeatedParam)
89
+ report.error(s " varargs parameter of @main method must come last " , pos)
90
+ addArgs(call1, restpe, idx + args.length)
91
+ case _ =>
92
+ call1
93
+ }
94
+ }
95
+
96
+ var result : List [TypeDef ] = Nil
97
+ if (! mainFun.owner.isStaticOwner)
98
+ report.error(s " @main method is not statically accessible " , pos)
99
+ else {
100
+ var call = ref(mainFun.termRef)
101
+ mainFun.info match {
102
+ case _ : ExprType =>
103
+ case mt : MethodType =>
104
+ call = addArgs(call, mt, 0 )
105
+ case _ : PolyType =>
106
+ report.error(s " @main method cannot have type parameters " , pos)
107
+ case _ =>
108
+ report.error(s " @main can only annotate a method " , pos)
109
+ }
110
+ val errVar = Ident (nme.error)
111
+ val handler = CaseDef (
112
+ Typed (errVar, TypeTree (defn.CLP_ParseError .typeRef)),
113
+ EmptyTree ,
114
+ Apply (ref(defn.CLP_showError .termRef), errVar :: Nil ))
115
+ val body = Try (call, handler :: Nil , EmptyTree )
116
+ val mainArg = ValDef (nme.args, TypeTree (defn.ArrayType .appliedTo(defn.StringType )), EmptyTree )
117
+ .withFlags(Param )
118
+ /** Replace typed `Ident`s that have been typed with a TypeSplice with the reference to the symbol.
119
+ * The annotations will be retype-checked in another scope that may not have the same imports.
120
+ */
121
+ def insertTypeSplices = new TreeMap {
122
+ override def transform (tree : Tree )(using Context ): Tree = tree match
123
+ case tree : tpd.Ident @ unchecked => TypedSplice (tree)
124
+ case tree => super .transform(tree)
125
+ }
126
+ val annots = mainFun.annotations
127
+ .filterNot(_.matches(defn.MainAnnot ))
128
+ .map(annot => insertTypeSplices.transform(annot.tree))
129
+ val mainMeth = DefDef (nme.main, (mainArg :: Nil ) :: Nil , TypeTree (defn.UnitType ), body)
130
+ .withFlags(JavaStatic )
131
+ .withAnnotations(annots)
132
+ val mainTempl = Template (emptyConstructor, Nil , Nil , EmptyValDef , mainMeth :: Nil )
133
+ val mainCls = TypeDef (mainFun.name.toTypeName, mainTempl)
134
+ .withFlags(Final | Invisible )
135
+ if (! ctx.reporter.hasErrors) result = mainCls.withSpan(mainAnnotSpan.toSynthetic) :: Nil
136
+ }
137
+ result
138
+ }
139
+
50
140
private type DefaultValueSymbols = Map [Int , Symbol ]
51
141
private type ParameterAnnotationss = Seq [Seq [Annotation ]]
52
142
@@ -95,7 +185,6 @@ object MainProxies {
95
185
mainMethods(EmptyTree , stats).flatMap(mainProxy)
96
186
}
97
187
98
- import untpd ._
99
188
def mainProxy (mainFun : Symbol , paramAnnotations : ParameterAnnotationss , defaultValueSymbols : DefaultValueSymbols , docComment : Option [Comment ])(using Context ): List [TypeDef ] = {
100
189
val mainAnnot = mainFun.getAnnotation(defn.MainAnnot ).get
101
190
def pos = mainFun.sourcePos
0 commit comments