Skip to content

Commit 92db848

Browse files
Keep old version of MainProxies for #14156
1 parent 5519509 commit 92db848

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

compiler/src/dotty/tools/dotc/ast/MainProxies.scala

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,96 @@ import Annotations.Annotation
4747
* }
4848
*/
4949
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+
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

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,12 @@ class Definitions {
871871
@tu lazy val MainAnnotCommand_varargGetter: Symbol = MainAnnotCommand.requiredMethod("varargGetter")
872872
@tu lazy val MainAnnotCommand_run: Symbol = MainAnnotCommand.requiredMethod("run")
873873

874+
@tu lazy val CommandLineParserModule: Symbol = requiredModule("scala.util.CommandLineParser")
875+
@tu lazy val CLP_ParseError: ClassSymbol = CommandLineParserModule.requiredClass("ParseError").typeRef.symbol.asClass
876+
@tu lazy val CLP_parseArgument: Symbol = CommandLineParserModule.requiredMethod("parseArgument")
877+
@tu lazy val CLP_parseRemainingArguments: Symbol = CommandLineParserModule.requiredMethod("parseRemainingArguments")
878+
@tu lazy val CLP_showError: Symbol = CommandLineParserModule.requiredMethod("showError")
879+
874880
@tu lazy val TupleTypeRef: TypeRef = requiredClassRef("scala.Tuple")
875881
def TupleClass(using Context): ClassSymbol = TupleTypeRef.symbol.asClass
876882
@tu lazy val Tuple_cons: Symbol = TupleClass.requiredMethod("*:")

0 commit comments

Comments
 (0)