@@ -47,6 +47,96 @@ import Annotations.Annotation
4747 * }
4848 */
4949object 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+
50140 private type DefaultValueSymbols = Map [Int , Symbol ]
51141 private type ParameterAnnotationss = Seq [Seq [Annotation ]]
52142
@@ -95,7 +185,6 @@ object MainProxies {
95185 mainMethods(EmptyTree , stats).flatMap(mainProxy)
96186 }
97187
98- import untpd ._
99188 def mainProxy (mainFun : Symbol , paramAnnotations : ParameterAnnotationss , defaultValueSymbols : DefaultValueSymbols , docComment : Option [Comment ])(using Context ): List [TypeDef ] = {
100189 val mainAnnot = mainFun.getAnnotation(defn.MainAnnot ).get
101190 def pos = mainFun.sourcePos
0 commit comments