@@ -467,9 +467,33 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
467467 * otherwise the can be `Term` containing the `New` applied to the parameters of the extended class.
468468 * @param body List of members of the class. The members must align with the members of `cls`.
469469 */
470+ // TODO add selfOpt: Option[ValDef]?
470471 @ experimental def apply (cls : Symbol , parents : List [Tree /* Term | TypeTree */ ], body : List [Statement ]): ClassDef
471472 def copy (original : Tree )(name : String , constr : DefDef , parents : List [Tree /* Term | TypeTree */ ], selfOpt : Option [ValDef ], body : List [Statement ]): ClassDef
472473 def unapply (cdef : ClassDef ): (String , DefDef , List [Tree /* Term | TypeTree */ ], Option [ValDef ], List [Statement ])
474+
475+
476+ /** Create the ValDef and ClassDef of a module (equivalent to an `object` declaration in source code).
477+ *
478+ * Equivalent to
479+ * ```
480+ * def module(module: Symbol, parents: List[Tree], body: List[Statement]): (ValDef, ClassDef) =
481+ * val modCls = module.moduleClass
482+ * val modClassDef = ClassDef(modCls, parents, body)
483+ * val modValDef = ValDef(module, Some(Apply(Select(New(TypeIdent(modCls)), cls.primaryConstructor), Nil)))
484+ * List(modValDef, modClassDef)
485+ * ```
486+ *
487+ * @param module the module symbol (created using `Symbol.newModule`)
488+ * @param parents parents of the module class
489+ * @param body body of the module class
490+ * @return The module lazy val definition and module class definition.
491+ * These should be added one after the other (in that order) in the body of a class or statements of a block.
492+ *
493+ * @syntax markdown
494+ */
495+ // TODO add selfOpt: Option[ValDef]?
496+ @ experimental def module (module : Symbol , parents : List [Tree /* Term | TypeTree */ ], body : List [Statement ]): (ValDef , ClassDef )
473497 }
474498
475499 /** Makes extension methods on `ClassDef` available without any imports */
@@ -3638,8 +3662,67 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
36383662 * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be
36393663 * direct or indirect children of the reflection context's owner.
36403664 */
3665+ // TODO: add flags and privateWithin
36413666 @ experimental def newClass (parent : Symbol , name : String , parents : List [TypeRepr ], decls : Symbol => List [Symbol ], selfType : Option [TypeRepr ]): Symbol
36423667
3668+ /** Generates a new module symbol with an associated module class symbol,
3669+ * this is equivalent to an `object` declaration in source code.
3670+ * This method returns the module symbol. The module class can be accessed calling `moduleClass` on this symbol.
3671+ *
3672+ * Example usage:
3673+ * ```scala
3674+ * //{
3675+ * given Quotes = ???
3676+ * import quotes.reflect._
3677+ * //}
3678+ * val moduleName: String = Symbol.freshName("MyModule")
3679+ * val parents = List(TypeTree.of[Object])
3680+ * def decls(cls: Symbol): List[Symbol] =
3681+ * List(Symbol.newMethod(cls, "run", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Unit]), Flags.EmptyFlags, Symbol.noSymbol))
3682+ *
3683+ * val mod = Symbol.newModule(Symbol.spliceOwner, moduleName, Flags.EmptyFlags, Flags.EmptyFlags, parents.map(_.tpe), decls, Symbol.noSymbol)
3684+ * val cls = mod.moduleClass
3685+ * val runSym = cls.declaredMethod("run").head
3686+ *
3687+ * val runDef = DefDef(runSym, _ => Some('{ println("run") }.asTerm))
3688+ * val modDef = ClassDef.module(mod, parents, body = List(runDef))
3689+ *
3690+ * val callRun = Apply(Select(Ref(mod), runSym), Nil)
3691+ *
3692+ * Block(modDef.toList, callRun)
3693+ * ```
3694+ * constructs the equivalent to
3695+ * ```scala
3696+ * //{
3697+ * given Quotes = ???
3698+ * import quotes.reflect._
3699+ * //}
3700+ * '{
3701+ * object MyModule$macro$1 extends Object:
3702+ * def run(): Unit = println("run")
3703+ * MyModule$macro$1.run()
3704+ * }
3705+ * ```
3706+ *
3707+ * @param parent The owner of the class
3708+ * @param name The name of the class
3709+ * @param modFlags extra flags with which the module symbol should be constructed
3710+ * @param clsFlags extra flags with which the module class symbol should be constructed
3711+ * @param parents The parent classes of the class. The first parent must not be a trait.
3712+ * @param decls A function that takes the symbol of the module class as input and return the symbols of its declared members
3713+ * @param privateWithin the symbol within which this new method symbol should be private. May be noSymbol.
3714+ *
3715+ * This symbol starts without an accompanying definition.
3716+ * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing
3717+ * this symbol to `ClassDef.module`.
3718+ *
3719+ * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be
3720+ * direct or indirect children of the reflection context's owner.
3721+ *
3722+ * @syntax markdown
3723+ */
3724+ @ experimental def newModule (owner : Symbol , name : String , modFlags : Flags , clsFlags : Flags , parents : List [TypeRepr ], decls : Symbol => List [Symbol ], privateWithin : Symbol ): Symbol
3725+
36433726 /** Generates a new method symbol with the given parent, name and type.
36443727 *
36453728 * To define a member method of a class, use the `newMethod` within the `decls` function of `newClass`.
@@ -4217,7 +4300,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
42174300 // FLAGS //
42184301 // /////////////
42194302
4220- /** FlagSet of a Symbol */
4303+ /** Flags of a Symbol */
42214304 type Flags
42224305
42234306 /** Module object of `type Flags` */
0 commit comments