Skip to content

Commit

Permalink
Remove new main
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasstucki committed Feb 24, 2022
1 parent f6e8146 commit 2a9d894
Show file tree
Hide file tree
Showing 82 changed files with 62 additions and 1,936 deletions.
36 changes: 21 additions & 15 deletions compiler/src/dotty/tools/dotc/ast/MainProxies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ import NameKinds.DefaultGetterName
import Annotations.Annotation

object MainProxies {

/** Generate proxy classes for @main functions and @myMain functions where myMain <:< MainAnnotation */
def proxies(stats: List[tpd.Tree])(using Context): List[untpd.Tree] = {
mainAnnotationProxies(stats) ++ mainProxies(stats)
}

/** Generate proxy classes for @main functions.
* A function like
*
Expand All @@ -29,7 +35,7 @@ object MainProxies {
* catch case err: ParseError => showError(err)
* }
*/
def mainProxiesOld(stats: List[tpd.Tree])(using Context): List[untpd.Tree] = {
private def mainProxies(stats: List[tpd.Tree])(using Context): List[untpd.Tree] = {
import tpd._
def mainMethods(stats: List[Tree]): List[Symbol] = stats.flatMap {
case stat: DefDef if stat.symbol.hasAnnotation(defn.MainAnnot) =>
Expand All @@ -39,11 +45,11 @@ object MainProxies {
case _ =>
Nil
}
mainMethods(stats).flatMap(mainProxyOld)
mainMethods(stats).flatMap(mainProxy)
}

import untpd._
def mainProxyOld(mainFun: Symbol)(using Context): List[TypeDef] = {
private def mainProxy(mainFun: Symbol)(using Context): List[TypeDef] = {
val mainAnnotSpan = mainFun.getAnnotation(defn.MainAnnot).get.tree.span
def pos = mainFun.sourcePos
val argsRef = Ident(nme.args)
Expand Down Expand Up @@ -160,7 +166,7 @@ object MainProxies {
* }
* }
*/
def mainProxies(stats: List[tpd.Tree])(using Context): List[untpd.Tree] = {
private def mainAnnotationProxies(stats: List[tpd.Tree])(using Context): List[untpd.Tree] = {
import tpd._

/**
Expand All @@ -183,12 +189,12 @@ object MainProxies {
def mainMethods(scope: Tree, stats: List[Tree]): List[(Symbol, ParameterAnnotationss, DefaultValueSymbols, Option[Comment])] = stats.flatMap {
case stat: DefDef =>
val sym = stat.symbol
sym.annotations.filter(_.matches(defn.MainAnnot)) match {
sym.annotations.filter(_.matches(defn.MainAnnotationClass)) match {
case Nil =>
Nil
case _ :: Nil =>
val paramAnnotations = stat.paramss.flatMap(_.map(
valdef => valdef.symbol.annotations.filter(_.matches(defn.MainAnnotParameterAnnotation))
valdef => valdef.symbol.annotations.filter(_.matches(defn.MainAnnotationParameterAnnotation))
))
(sym, paramAnnotations.toVector, defaultValueSymbols(scope, sym), stat.rawComment) :: Nil
case mainAnnot :: others =>
Expand All @@ -202,11 +208,11 @@ object MainProxies {
}

// Assuming that the top-level object was already generated, all main methods will have a scope
mainMethods(EmptyTree, stats).flatMap(mainProxy)
mainMethods(EmptyTree, stats).flatMap(mainAnnotationProxy)
}

def mainProxy(mainFun: Symbol, paramAnnotations: ParameterAnnotationss, defaultValueSymbols: DefaultValueSymbols, docComment: Option[Comment])(using Context): List[TypeDef] = {
val mainAnnot = mainFun.getAnnotation(defn.MainAnnot).get
private def mainAnnotationProxy(mainFun: Symbol, paramAnnotations: ParameterAnnotationss, defaultValueSymbols: DefaultValueSymbols, docComment: Option[Comment])(using Context): List[TypeDef] = {
val mainAnnot = mainFun.getAnnotation(defn.MainAnnotationClass).get
def pos = mainFun.sourcePos
val cmdName: TermName = Names.termName("cmd")

Expand Down Expand Up @@ -244,15 +250,15 @@ object MainProxies {
val (argRef, formalType, getterSym) = {
val argRef0 = Apply(Ident(argName), Nil)
if formal.isRepeatedParam then
(repeated(argRef0), formal.argTypes.head, defn.MainAnnotCommand_varargGetter)
else (argRef0, formal, defn.MainAnnotCommand_argGetter)
(repeated(argRef0), formal.argTypes.head, defn.MainAnnotationCommand_varargGetter)
else (argRef0, formal, defn.MainAnnotationCommand_argGetter)
}

// The ParameterInfos
val parameterInfos = {
val param = paramName.toString
val paramInfosTree = New(
TypeTree(defn.MainAnnotParameterInfos.typeRef),
TypeTree(defn.MainAnnotationParameterInfos.typeRef),
// Arguments to be passed to ParameterInfos' constructor
List(List(lit(param), lit(formalType.show)))
)
Expand Down Expand Up @@ -352,11 +358,11 @@ object MainProxies {
cmdName,
TypeTree(),
Apply(
Select(instanciateAnnotation(mainAnnot), defn.MainAnnot_command.name),
Select(instanciateAnnotation(mainAnnot), defn.MainAnnotation_command.name),
Ident(nme.args) :: lit(mainFun.showName) :: lit(documentation.mainDoc) :: parameterInfoss
)
)
val run = Apply(Select(Ident(cmdName), defn.MainAnnotCommand_run.name), mainCall)
val run = Apply(Select(Ident(cmdName), defn.MainAnnotationCommand_run.name), mainCall)
val body = Block(cmd :: args, run)
val mainArg = ValDef(nme.args, TypeTree(defn.ArrayType.appliedTo(defn.StringType)), EmptyTree)
.withFlags(Param)
Expand All @@ -369,7 +375,7 @@ object MainProxies {
case tree => super.transform(tree)
}
val annots = mainFun.annotations
.filterNot(_.matches(defn.MainAnnot))
.filterNot(_.matches(defn.MainAnnotationClass))
.map(annot => insertTypeSplices.transform(annot.tree))
val mainMeth = DefDef(nme.main, (mainArg :: Nil) :: Nil, TypeTree(defn.UnitType), body)
.withFlags(JavaStatic)
Expand Down
21 changes: 11 additions & 10 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -849,16 +849,16 @@ class Definitions {

@tu lazy val XMLTopScopeModule: Symbol = requiredModule("scala.xml.TopScope")

@tu lazy val MainAnnot: ClassSymbol = requiredClass("scala.annotation.MainAnnotation")
@tu lazy val MainAnnot_command: Symbol = MainAnnot.requiredMethod("command")
@tu lazy val MainAnnotParameterInfos: ClassSymbol = requiredClass("scala.annotation.MainAnnotation.ParameterInfos")
@tu lazy val MainAnnotationParameterInfos_withDocumentation: Symbol = MainAnnotParameterInfos.requiredMethod("withDocumentation")
@tu lazy val MainAnnotationParameterInfos_withAnnotations: Symbol = MainAnnotParameterInfos.requiredMethod("withAnnotations")
@tu lazy val MainAnnotParameterAnnotation: ClassSymbol = requiredClass("scala.annotation.MainAnnotation.ParameterAnnotation")
@tu lazy val MainAnnotCommand: ClassSymbol = requiredClass("scala.annotation.MainAnnotation.Command")
@tu lazy val MainAnnotCommand_argGetter: Symbol = MainAnnotCommand.requiredMethod("argGetter")
@tu lazy val MainAnnotCommand_varargGetter: Symbol = MainAnnotCommand.requiredMethod("varargGetter")
@tu lazy val MainAnnotCommand_run: Symbol = MainAnnotCommand.requiredMethod("run")
@tu lazy val MainAnnotationClass: ClassSymbol = requiredClass("scala.annotation.MainAnnotation")
@tu lazy val MainAnnotation_command: Symbol = MainAnnotationClass.requiredMethod("command")
@tu lazy val MainAnnotationParameterInfos: ClassSymbol = requiredClass("scala.annotation.MainAnnotation.ParameterInfos")
@tu lazy val MainAnnotationParameterInfos_withDocumentation: Symbol = MainAnnotationParameterInfos.requiredMethod("withDocumentation")
@tu lazy val MainAnnotationParameterInfos_withAnnotations: Symbol = MainAnnotationParameterInfos.requiredMethod("withAnnotations")
@tu lazy val MainAnnotationParameterAnnotation: ClassSymbol = requiredClass("scala.annotation.MainAnnotation.ParameterAnnotation")
@tu lazy val MainAnnotationCommand: ClassSymbol = requiredClass("scala.annotation.MainAnnotation.Command")
@tu lazy val MainAnnotationCommand_argGetter: Symbol = MainAnnotationCommand.requiredMethod("argGetter")
@tu lazy val MainAnnotationCommand_varargGetter: Symbol = MainAnnotationCommand.requiredMethod("varargGetter")
@tu lazy val MainAnnotationCommand_run: Symbol = MainAnnotationCommand.requiredMethod("run")

@tu lazy val CommandLineParserModule: Symbol = requiredModule("scala.util.CommandLineParser")
@tu lazy val CLP_ParseError: ClassSymbol = CommandLineParserModule.requiredClass("ParseError").typeRef.symbol.asClass
Expand Down Expand Up @@ -915,6 +915,7 @@ class Definitions {
@tu lazy val InlineParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InlineParam")
@tu lazy val ErasedParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ErasedParam")
@tu lazy val InvariantBetweenAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InvariantBetween")
@tu lazy val MainAnnot: ClassSymbol = requiredClass("scala.main")
@tu lazy val MigrationAnnot: ClassSymbol = requiredClass("scala.annotation.migration")
@tu lazy val NowarnAnnot: ClassSymbol = requiredClass("scala.annotation.nowarn")
@tu lazy val TransparentTraitAnnot: ClassSymbol = requiredClass("scala.annotation.transparentTrait")
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1348,9 +1348,10 @@ trait Checking {
/** check that annotation `annot` is applicable to symbol `sym` */
def checkAnnotApplicable(annot: Tree, sym: Symbol)(using Context): Boolean =
!ctx.reporter.reportsErrorsFor {
val annotCls = Annotations.annotClass(annot)
val concreteAnnot = Annotations.ConcreteAnnotation(annot)
val pos = annot.srcPos
if (concreteAnnot.matches(defn.MainAnnot)) {
if (annotCls == defn.MainAnnot || concreteAnnot.matches(defn.MainAnnotationClass)) {
if (!sym.isRealMethod)
report.error(em"main annotation cannot be applied to $sym", pos)
if (!sym.owner.is(Module) || !sym.owner.isStatic)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1227,7 +1227,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
if pos < mtpe.paramInfos.length then
mtpe.paramInfos(pos)
// This works only if vararg annotations match up.
// See neg/i14367.scala for an example where the inferred type is mispredicted.
// See neg/i14367.scala for an example where the inferred type is mispredicted.
// Nevertheless, the alternative would be to give up completely, so this is
// defensible.
else NoType
Expand Down Expand Up @@ -2581,7 +2581,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
pkg.moduleClass.info.decls.lookup(topLevelClassName).ensureCompleted()
var stats1 = typedStats(tree.stats, pkg.moduleClass)._1
if (!ctx.isAfterTyper)
stats1 = stats1 ++ typedBlockStats(MainProxies.mainProxies(stats1))._1
stats1 = stats1 ++ typedBlockStats(MainProxies.proxies(stats1))._1
cpy.PackageDef(tree)(pid1, stats1).withType(pkg.termRef)
}
case _ =>
Expand Down
10 changes: 7 additions & 3 deletions library/src/scala/annotation/MainAnnotation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package scala.annotation
* or `command.argsGetter` if is a final varargs parameter,
* - a call to `command.run` with the closure of user-main applied to all arguments.
*/
@experimental
trait MainAnnotation extends StaticAnnotation:

/** The class used for argument string parsing. E.g. `scala.util.CommandLineParser.FromString`,
Expand All @@ -24,8 +25,9 @@ trait MainAnnotation extends StaticAnnotation:
def command(args: Array[String], commandName: String, documentation: String, parameterInfoss: MainAnnotation.ParameterInfos*): MainAnnotation.Command[ArgumentParser, MainResultType]
end MainAnnotation

@experimental
object MainAnnotation:
// Inspired by https://github.com/scala-js/scala-js/blob/0708917912938714d52be1426364f78a3d1fd269/linker-interface/shared/src/main/scala/org/scalajs/linker/interface/StandardConfig.scala#L23-L218

final class ParameterInfos private (
/** The name of the parameter */
val name: String,
Expand All @@ -36,13 +38,15 @@ object MainAnnotation:
/** The ParameterAnnotations associated with the parameter. Defaults to Seq.empty. */
val annotations: Seq[ParameterAnnotation],
) {
// Main public constructor
/** ParameterInfos with a name and the type of the parameter */
def this(name: String, typeName: String) =
this(name, typeName, None, Seq.empty)

/** Copy this ParameterInfos and sets the documentation */
def withDocumentation(doc: String): ParameterInfos =
new ParameterInfos(name, typeName, Some(doc), annotations)

/** Copy this ParameterInfos and sets the annotations */
def withAnnotations(annots: ParameterAnnotation*): ParameterInfos =
new ParameterInfos(name, typeName, documentation, annots)

Expand All @@ -64,6 +68,6 @@ object MainAnnotation:
def run(program: => MainResultType): Unit
end Command

/** An annotation for the parameters of a MainAnnotated method. */
/** Marker trait for annotations that will be included in the ParameterInfos annotations. */
trait ParameterAnnotation extends StaticAnnotation
end MainAnnotation
Loading

0 comments on commit 2a9d894

Please sign in to comment.