From 2cbc56ff7d413bc06f6cc0531d08e4d6835ee067 Mon Sep 17 00:00:00 2001 From: Hamza REMMAL Date: Sun, 14 Apr 2024 18:17:39 +0200 Subject: [PATCH] Add support for companion in MacroAnnotations --- .../dotty/tools/dotc/CompilationUnit.scala | 4 +- .../dotc/ast/TreeMapWithTrackedStats.scala | 80 ++++++++ .../dotty/tools/dotc/transform/Inlining.scala | 89 ++++++--- .../dotc/transform/MacroAnnotations.scala | 176 ++++++++++-------- .../tools/dotc/transform/PostTyper.scala | 3 +- .../scala/annotation/MacroAnnotation.scala | 35 ++-- .../annot-accessIndirect/Macro_1.scala | 4 +- .../annot-accessIndirect/Macro_2.scala | 6 +- tests/neg-macros/annot-crash/Macro_1.scala | 2 +- .../annot-empty-result/Macro_1.scala | 2 +- .../annot-error-annot/Macro_1.scala | 6 +- .../neg-macros/annot-ill-abort/Macro_1.scala | 2 +- .../Macro_1.scala | 8 +- .../annot-mod-class-add-top-val/Macro_1.scala | 8 +- .../Macro_1.scala | 4 +- .../Macro_1.scala | 4 +- tests/neg-macros/annot-on-type/Macro_1.scala | 4 +- .../annot-result-owner/Macro_1.scala | 6 +- tests/neg-macros/annot-suspend-cycle.check | 12 +- .../annot-suspend-cycle/Macro.scala | 10 +- tests/neg-macros/i18677-a/Macro_1.scala | 24 ++- tests/neg-macros/i18677-b/Macro_1.scala | 24 ++- tests/neg-macros/i18825/Macro_1.scala | 10 +- tests/neg-macros/i19676.check | 13 ++ tests/neg-macros/i19676/Macro_1.scala | 19 ++ tests/neg-macros/i19676/Test_2.scala | 4 + tests/neg-macros/wrong-owner.check | 2 +- tests/neg-macros/wrong-owner/Macro_1.scala | 10 +- .../Macro_1.scala | 11 ++ .../Test_2.scala | 3 + .../pos-macros/annot-in-object/Macro_1.scala | 6 +- tests/pos-macros/annot-suspend/Macro_1.scala | 4 +- .../annot-then-inline/Macro_1.scala | 8 +- tests/pos-macros/i19537/Macro_1.scala | 3 +- tests/pos-macros/i19539/Macro_1.scala | 3 +- .../macro-annot-with-companion/Macro_1.scala | 12 ++ .../macro-annot-with-companion/Test_2.scala | 15 ++ .../annot-add-global-class/Macro_1.scala | 8 +- .../annot-add-global-object/Macro_1.scala | 8 +- .../annot-add-local-class/Macro_1.scala | 8 +- .../annot-add-local-object/Macro_1.scala | 8 +- .../annot-add-nested-class/Macro_1.scala | 8 +- .../annot-add-nested-object/Macro_1.scala | 8 +- .../annot-annot-order/Macro_1.scala | 10 +- tests/run-macros/annot-bind/Macro_1.scala | 8 +- .../run-macros/annot-changeVal/Macro_1.scala | 6 +- .../annot-concrete-class/Macro_1.scala | 2 +- tests/run-macros/annot-export/Macro_1.scala | 6 +- tests/run-macros/annot-gen2/Macro_1.scala | 8 +- tests/run-macros/annot-gen2/Macro_2.scala | 8 +- tests/run-macros/annot-generate/Macro_1.scala | 4 +- tests/run-macros/annot-generate/Macro_2.scala | 8 +- .../run-macros/annot-macro-main/Macro_1.scala | 10 +- tests/run-macros/annot-memo/Macro_1.scala | 10 +- .../annot-mod-class-add-def/Macro_1.scala | 10 +- .../Macro_1.scala | 10 +- .../Macro_1.scala | 10 +- .../Macro_1.scala | 10 +- .../annot-mod-class-add-val/Macro_1.scala | 10 +- .../annot-mod-class-add-var/Macro_1.scala | 10 +- .../annot-mod-class-data/Macro_1.scala | 10 +- .../annot-mod-class-equals/Macro_1.scala | 10 +- .../annot-mod-class-mod-def/Macro_1.scala | 10 +- .../annot-mod-class-mod-val/Macro_1.scala | 10 +- .../Macro_1.scala | 10 +- .../Macro_1.scala | 10 +- .../Macro_1.scala | 10 +- .../annot-result-order/Macro_1.scala | 4 +- .../run-macros/annot-simple-fib/Macro_1.scala | 8 +- .../run-macros/annot-unrollLast/Macro_1.scala | 2 +- tests/run-macros/i18806/Macro_1.scala | 10 +- tests/run-macros/i19676/Macro_1.scala | 28 +++ tests/run-macros/i19676/Test_2.scala | 36 ++++ tests/run/quotes-add-erased/Macro_1.scala | 2 +- 74 files changed, 637 insertions(+), 347 deletions(-) create mode 100644 compiler/src/dotty/tools/dotc/ast/TreeMapWithTrackedStats.scala create mode 100644 tests/neg-macros/i19676.check create mode 100644 tests/neg-macros/i19676/Macro_1.scala create mode 100644 tests/neg-macros/i19676/Test_2.scala create mode 100644 tests/pos-macros/annot-dependency-between-modules/Macro_1.scala create mode 100644 tests/pos-macros/annot-dependency-between-modules/Test_2.scala create mode 100644 tests/pos-macros/macro-annot-with-companion/Macro_1.scala create mode 100644 tests/pos-macros/macro-annot-with-companion/Test_2.scala create mode 100644 tests/run-macros/i19676/Macro_1.scala create mode 100644 tests/run-macros/i19676/Test_2.scala diff --git a/compiler/src/dotty/tools/dotc/CompilationUnit.scala b/compiler/src/dotty/tools/dotc/CompilationUnit.scala index adced57d5801..326107a410a9 100644 --- a/compiler/src/dotty/tools/dotc/CompilationUnit.scala +++ b/compiler/src/dotty/tools/dotc/CompilationUnit.scala @@ -17,7 +17,7 @@ import config.{SourceVersion, Feature} import StdNames.nme import scala.annotation.internal.sharable import scala.util.control.NoStackTrace -import transform.MacroAnnotations +import transform.MacroAnnotations.isMacroAnnotation class CompilationUnit protected (val source: SourceFile, val info: CompilationUnitInfo | Null) { @@ -193,7 +193,7 @@ object CompilationUnit { case _ => case _ => for annot <- tree.symbol.annotations do - if MacroAnnotations.isMacroAnnotation(annot) then + if annot.isMacroAnnotation then ctx.compilationUnit.hasMacroAnnotations = true traverseChildren(tree) } diff --git a/compiler/src/dotty/tools/dotc/ast/TreeMapWithTrackedStats.scala b/compiler/src/dotty/tools/dotc/ast/TreeMapWithTrackedStats.scala new file mode 100644 index 000000000000..9fef3c0e9be1 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/ast/TreeMapWithTrackedStats.scala @@ -0,0 +1,80 @@ +package dotty.tools.dotc +package ast + +import tpd.* +import core.Contexts.* +import core.Symbols.* +import util.Property + +import scala.collection.mutable + +abstract class TreeMapWithTrackedStats extends TreeMapWithImplicits: + + import TreeMapWithTrackedStats.* + + // It is safe to assume that the companion of a tree is in the same scope + // Therefore, when expanding MacroAnnotations, we will only keep track of + // the trees in the same scope as the current transformed tree + + protected final def getTracked(sym: Symbol)(using Context): Option[MemberDef] = + for trees <- ctx.property(TrackedTrees) + tree <- trees.get(sym) + yield tree + + protected final def updateTracked(tree: Tree)(using Context): Tree = + tree match + case tree: MemberDef => + trackedTrees.update(tree.symbol, tree) + tree + case _ => tree + end updateTracked + + private final def withUpdatedTree(stats: List[Tree])(using Context) = + val trackedTrees = TreeMapWithTrackedStats.trackedTrees + stats.mapConserve: + case tree: MemberDef if trackedTrees.contains(tree.symbol) => + trackedTrees(tree.symbol) + case stat => stat + + override def transform(tree: Tree)(using Context): Tree = + tree match + case PackageDef(_, stats) => + // Step I: Collect and memoize all the stats + inContext(trackedTreesCtx(stats)): + // Step II: Transform the tree + val result = super.transform(tree) + // Step III: Reconcile between the symbols in syms and the tree + (result: @unchecked) match + case pkg@PackageDef(pid, stats) => + cpy.PackageDef(pkg)(pid = pid, stats = withUpdatedTree(stats)) + case block: Block => + // Step I: Collect all the member definitions in the block + inContext(trackedTreesCtx(block.stats)): + // Step II: Transform the tree + val result = super.transform(tree) + // Step III: Reconcile between the symbols in syms and the tree + (result: @unchecked) match + case b@Block(stats, expr) => + cpy.Block(b)(expr = expr, stats = withUpdatedTree(stats)) + case TypeDef(_, impl: Template) => + // Step I: Collect and memoize all the stats + inContext(trackedTreesCtx(impl.body)): + // Step II: Transform the tree + val result = super.transform(tree) + // Step III: Reconcile between the symbols in syms and the tree + (result : @unchecked) match + case tree@TypeDef(name, impl: Template) => + cpy.TypeDef(tree)(rhs = cpy.Template(impl)(body = withUpdatedTree(impl.body))) + case _ => super.transform(tree) + +end TreeMapWithTrackedStats + +object TreeMapWithTrackedStats: + private val TrackedTrees = new Property.Key[mutable.Map[Symbol, tpd.MemberDef]] + + private def trackedTrees(using Context): mutable.Map[Symbol, MemberDef] = + ctx.property(TrackedTrees).get + + private def trackedTreesCtx(stats: List[Tree])(using Context): Context = + val treesToTrack = stats.collect { case m: MemberDef => (m.symbol, m) } + ctx.fresh.setProperty(TrackedTrees, mutable.Map(treesToTrack*)) diff --git a/compiler/src/dotty/tools/dotc/transform/Inlining.scala b/compiler/src/dotty/tools/dotc/transform/Inlining.scala index 94df114290e4..caebd81d833f 100644 --- a/compiler/src/dotty/tools/dotc/transform/Inlining.scala +++ b/compiler/src/dotty/tools/dotc/transform/Inlining.scala @@ -1,20 +1,24 @@ package dotty.tools.dotc package transform +import ast.tpd +import ast.Trees.* +import ast.TreeMapWithTrackedStats import core.* import Flags.* +import Decorators.* import Contexts.* import Symbols.* +import Decorators.* +import config.Printers.inlining +import DenotTransformers.IdentityDenotTransformer +import MacroAnnotations.hasMacroAnnotation +import inlines.Inlines +import quoted.* +import staging.StagingLevel +import util.Property -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.ast.Trees.* -import dotty.tools.dotc.quoted.* -import dotty.tools.dotc.inlines.Inlines -import dotty.tools.dotc.ast.TreeMapWithImplicits -import dotty.tools.dotc.core.DenotTransformers.IdentityDenotTransformer -import dotty.tools.dotc.staging.StagingLevel - -import scala.collection.mutable.ListBuffer +import scala.collection.mutable /** Inlines all calls to inline methods that are not in an inline method or a quote */ class Inlining extends MacroTransform, IdentityDenotTransformer { @@ -56,38 +60,21 @@ class Inlining extends MacroTransform, IdentityDenotTransformer { def newTransformer(using Context): Transformer = new Transformer { override def transform(tree: tpd.Tree)(using Context): tpd.Tree = - new InliningTreeMap().transform(tree) + InliningTreeMap().transform(tree) } - private class InliningTreeMap extends TreeMapWithImplicits { + private class InliningTreeMap extends TreeMapWithTrackedStats { /** List of top level classes added by macro annotation in a package object. * These are added to the PackageDef that owns this particular package object. */ - private val newTopClasses = MutableSymbolMap[ListBuffer[Tree]]() + private val newTopClasses = MutableSymbolMap[mutable.ListBuffer[Tree]]() override def transform(tree: Tree)(using Context): Tree = { tree match case tree: MemberDef => - if tree.symbol.is(Inline) then tree - else if tree.symbol.is(Param) then super.transform(tree) - else if - !tree.symbol.isPrimaryConstructor - && StagingLevel.level == 0 - && MacroAnnotations.hasMacroAnnotation(tree.symbol) - then - val trees = (new MacroAnnotations(self)).expandAnnotations(tree) - val trees1 = trees.map(super.transform) - - // Find classes added to the top level from a package object - val (topClasses, trees2) = - if ctx.owner.isPackageObject then trees1.partition(_.symbol.owner == ctx.owner.owner) - else (Nil, trees1) - if topClasses.nonEmpty then - newTopClasses.getOrElseUpdate(ctx.owner.owner, new ListBuffer) ++= topClasses - - flatTree(trees2) - else super.transform(tree) + // Fetch the latest tracked tree (It might have already been processed by its companion) + transformMemberDef(getTracked(tree.symbol).getOrElse(tree)) case _: Typed | _: Block => super.transform(tree) case _: PackageDef => @@ -113,7 +100,47 @@ class Inlining extends MacroTransform, IdentityDenotTransformer { else Inlines.inlineCall(tree1) else super.transform(tree) } + + private def transformMemberDef(tree: MemberDef)(using Context) : Tree = + if tree.symbol.is(Inline) then tree + else if tree.symbol.is(Param) then + super.transform(tree) + else if + !tree.symbol.isPrimaryConstructor + && StagingLevel.level == 0 + && tree.symbol.hasMacroAnnotation + then + // Fetch the companion's tree + val companionSym = + if tree.symbol.is(ModuleClass) then tree.symbol.companionClass + else if tree.symbol.is(ModuleVal) then NoSymbol + else tree.symbol.companionModule.moduleClass + + // Expand and process MacroAnnotations + val (trees, companion) = MacroAnnotations.expandAnnotations(tree, getTracked(companionSym)) + + // Enter the new symbols & Update the tracked trees + (companion.toList ::: trees).foreach: tree => + MacroAnnotations.enterMissingSymbols(tree, self) + updateTracked(tree) + + // Perform inlining on the expansion of the annotations + val trees1 = trees.map(super.transform) + trees1.foreach(updateTracked) + + // Find classes added to the top level from a package object + val (topClasses, trees2) = + if ctx.owner.isPackageObject then trees1.partition(_.symbol.owner == ctx.owner.owner) + else (Nil, trees1) + if topClasses.nonEmpty then + newTopClasses.getOrElseUpdate(ctx.owner.owner, new mutable.ListBuffer) ++= topClasses + flatTree(trees2) + else + updateTracked(super.transform(tree)) + end transformMemberDef + } + } object Inlining: diff --git a/compiler/src/dotty/tools/dotc/transform/MacroAnnotations.scala b/compiler/src/dotty/tools/dotc/transform/MacroAnnotations.scala index c83e4d7b7819..629d47eab286 100644 --- a/compiler/src/dotty/tools/dotc/transform/MacroAnnotations.scala +++ b/compiler/src/dotty/tools/dotc/transform/MacroAnnotations.scala @@ -3,19 +3,19 @@ package transform import scala.language.unsafeNulls -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.ast.Trees.* -import dotty.tools.dotc.config.Printers.{macroAnnot => debug} -import dotty.tools.dotc.core.Annotations.* -import dotty.tools.dotc.core.Contexts.* -import dotty.tools.dotc.core.Decorators.* -import dotty.tools.dotc.core.DenotTransformers.IdentityDenotTransformer -import dotty.tools.dotc.core.Flags.* -import dotty.tools.dotc.core.MacroClassLoader -import dotty.tools.dotc.core.Symbols.* -import dotty.tools.dotc.core.Types.* -import dotty.tools.dotc.quoted.* -import dotty.tools.dotc.util.SrcPos +import ast.tpd +import ast.Trees.* +import config.Printers.macroAnnot as debug +import core.Annotations.* +import core.Contexts.* +import core.Decorators.* +import core.DenotTransformers.DenotTransformer +import core.Flags.* +import core.MacroClassLoader +import core.Symbols.* +import core.Types.* +import quoted.* +import util.SrcPos import scala.quoted.runtime.impl.{QuotesImpl, SpliceScope} import scala.quoted.Quotes @@ -23,94 +23,118 @@ import scala.util.control.NonFatal import java.lang.reflect.InvocationTargetException -class MacroAnnotations(phase: IdentityDenotTransformer): +object MacroAnnotations: import tpd.* - import MacroAnnotations.* + + extension (annot: Annotation) + /** Is this an annotation that implements `scala.annation.MacroAnnotation` */ + def isMacroAnnotation(using Context): Boolean = + annot.tree.symbol.maybeOwner.derivesFrom(defn.MacroAnnotationClass) + end extension + + extension (sym: Symbol) + /** Is this symbol annotated with an annotation that implements `scala.annation.MacroAnnotation` */ + def hasMacroAnnotation(using Context): Boolean = + sym.getAnnotation(defn.MacroAnnotationClass).isDefined + end extension /** Expands every macro annotation that is on this tree. * Returns a list with transformed definition and any added definitions. */ - def expandAnnotations(tree: MemberDef)(using Context): List[DefTree] = - if !hasMacroAnnotation(tree.symbol) then - List(tree) - else if tree.symbol.is(Module) && !tree.symbol.isClass then - // only class is transformed - List(tree) + def expandAnnotations(tree: MemberDef, companion: Option[MemberDef])(using Context): (List[MemberDef], Option[MemberDef]) = + if !tree.symbol.hasMacroAnnotation then + (List(tree), companion) + else if tree.symbol.is(ModuleVal) then + // only module classes are transformed + (List(tree), companion) else if tree.symbol.isType && !tree.symbol.isClass then report.error("macro annotations are not supported on type", tree) - List(tree) + (List(tree), companion) else debug.println(i"Expanding macro annotations of:\n$tree") - val macroInterpreter = new Interpreter(tree.srcPos, MacroClassLoader.fromContext) - val allTrees = List.newBuilder[DefTree] - var insertedAfter: List[List[DefTree]] = Nil + val prefixedTrees = List.newBuilder[MemberDef] // Apply all macro annotation to `tree` and collect new definitions in order - val transformedTree: DefTree = tree.symbol.annotations.foldLeft(tree) { (tree, annot) => - if isMacroAnnotation(annot) then - debug.println(i"Expanding macro annotation: ${annot}") - - // Interpret call to `new myAnnot(..).transform(using )()` - val transformedTrees = callMacro(macroInterpreter, tree, annot) - transformedTrees.span(_.symbol != tree.symbol) match - case (prefixed, newTree :: suffixed) => - allTrees ++= prefixed - insertedAfter = suffixed :: insertedAfter - for prefixedTree <- prefixed do - checkMacroDef(prefixedTree, tree, annot) - for suffixedTree <- suffixed do - checkMacroDef(suffixedTree, tree, annot) - TreeChecker.checkMacroGeneratedTree(tree, newTree) - newTree - case (Nil, Nil) => - report.error(i"Unexpected `Nil` returned by `(${annot.tree}).transform(..)` during macro expansion", annot.tree.srcPos) - tree - case (_, Nil) => - report.error(i"Transformed tree for ${tree} was not return by `(${annot.tree}).transform(..)` during macro expansion", annot.tree.srcPos) - tree - else - tree - } - - allTrees += transformedTree - insertedAfter.foreach(allTrees.++=) - - val result = allTrees.result() - for tree <- result do enterMissingSymbols(tree) + val unprocessed = (tree, companion, List.empty[MemberDef]) + val (transformedTree, transformedCompanion, suffixed) = + tree.symbol.annotations.foldLeft(unprocessed): (lastResult, annot) => + if annot.isMacroAnnotation then + val (tree, companion, suffixed) = lastResult + debug.println(i"Expanding macro annotation: ${annot}") + // Interpret call to `new myAnnot(..).transform(using )(, )` + val (transformedTrees, transformedCompanion) = callMacro(macroInterpreter, tree, companion, annot) + // Establish the trees order and check the integrity of the trees + transformedTrees.span(_.symbol != tree.symbol) match + case (newPrefixed, newTree :: newSuffixed) => + // Check the integrity of the generated trees + for prefixedTree <- newPrefixed do checkMacroDef(prefixedTree, tree, annot) + for suffixedTree <- newSuffixed do checkMacroDef(suffixedTree, tree, annot) + for tcompanion <- transformedCompanion do TreeChecker.checkMacroGeneratedTree(companion.get, tcompanion) + TreeChecker.checkMacroGeneratedTree(tree, newTree) + prefixedTrees ++= newPrefixed + (newTree, transformedCompanion, newSuffixed ::: suffixed) + case (_, Nil) => + report.error(i"Transformed tree for ${tree} was not return by `(${annot.tree}).transform(..)` during macro expansion", annot.tree.srcPos) + lastResult + else + lastResult + end val + + // Complete the list of transformed/generated definitions + val result = prefixedTrees.result() ::: transformedTree :: suffixed debug.println(result.map(_.show).mkString("expanded to:\n", "\n", "")) - result + (result, transformedCompanion) + end expandAnnotations - /** Interpret the code `new annot(..).transform(using )()` */ - private def callMacro(interpreter: Interpreter, tree: MemberDef, annot: Annotation)(using Context): List[MemberDef] = - // TODO: Remove when scala.annaotaion.MacroAnnotation is no longer experimental + /** Interpret the code `new annot(..).transform(using )(, )` */ + private def callMacro(interpreter: Interpreter, tree: MemberDef, companion: Option[MemberDef], annot: Annotation) + (using Context): (List[MemberDef], Option[MemberDef]) = + // TODO: Remove when scala.annotation.MacroAnnotation is no longer experimental import scala.reflect.Selectable.reflectiveSelectable type MacroAnnotation = { - def transform(using Quotes)(tree: Object/*Erased type of quotes.refelct.Definition*/): List[MemberDef /*quotes.refelct.Definition known to be MemberDef in QuotesImpl*/] + def transform(using Quotes)( + tree: Object/*Erased type of quotes.reflect.Definition*/, + companion: Option[Object/*Erased type of quotes.reflect.Definition*/] + ): List[MemberDef /*quotes.refelct.Definition known to be MemberDef in QuotesImpl*/] } // Interpret macro annotation instantiation `new myAnnot(..)` + // TODO: Make this error handling stronger (no error handling at the moment) val annotInstance = interpreter.interpret[MacroAnnotation](annot.tree).get + // TODO: Remove when scala.annaotaion.MacroAnnotation is no longer experimental assert(annotInstance.getClass.getClassLoader.loadClass("scala.annotation.MacroAnnotation").isInstance(annotInstance)) val quotes = QuotesImpl()(using SpliceScope.contextWithNewSpliceScope(tree.symbol.sourcePos)(using MacroExpansion.context(tree)).withOwner(tree.symbol.owner)) - try annotInstance.transform(using quotes)(tree.asInstanceOf[quotes.reflect.Definition]) + try + val result = annotInstance.transform(using quotes)(tree, companion) + // Process the result based on if the companion was present or not + // The idea is that we try to find a transformation of the companion if we do provide one + companion.map(_.symbol) match + case None => (result, companion) + case Some(companionSym) => result.partition(_.symbol == companionSym) match + case (Nil, result) => (result, companion) // companion didn't change + case (newCompanion :: Nil, result) => (result, Some(newCompanion)) + case (_, result) => + report.error(i"Transformed companion for ${tree} was returned more than once by `(${annot.tree}).transform(..)` during macro expansion", annot.tree) + (result, companion) + catch - // TODO: Replace this case when scala.annaotaion.MacroAnnotation is no longer experimental and reflectiveSelectable is not used + // TODO: Replace this case when scala.annotation.MacroAnnotation is no longer experimental and reflectiveSelectable is not used // Replace this case with the nested cases. case ex0: InvocationTargetException => ex0.getCause match case ex: scala.quoted.runtime.StopMacroExpansion => if !ctx.reporter.hasErrors then report.error("Macro expansion was aborted by the macro without any errors reported. Macros should issue errors to end-users when aborting a macro expansion with StopMacroExpansion.", annot.tree) - List(tree) + (List(tree), companion) case Interpreter.MissingClassValidInCurrentRun(sym, origin) => Interpreter.suspendOnMissing(sym, origin, annot.tree) case NonFatal(ex) => - val stack0 = ex.getStackTrace.takeWhile(_.getClassName != "dotty.tools.dotc.transform.MacroAnnotations") + val stack0 = ex.getStackTrace.takeWhile(_.getClassName != this.getClass().getName()) val stack = stack0.take(1 + stack0.lastIndexWhere(_.getMethodName == "transform")) val msg = em"""Failed to evaluate macro. @@ -118,9 +142,10 @@ class MacroAnnotations(phase: IdentityDenotTransformer): | ${stack.mkString("\n ")} |""" report.error(msg, annot.tree) - List(tree) + (List(tree), companion) case _ => throw ex0 + end callMacro /** Check that this tree can be added by the macro annotation */ private def checkMacroDef(newTree: DefTree, annotatedTree: Tree, annot: Annotation)(using Context) = @@ -133,14 +158,13 @@ class MacroAnnotations(phase: IdentityDenotTransformer): report.error(i"macro annotation $annot added $sym with an inconsistent owner. Expected it to be owned by ${annotated.owner} but was owned by ${sym.owner}.", annot.tree) else if annotated.isClass && annotated.owner.is(Package) /*&& !sym.isClass*/ then report.error(i"macro annotation can not add top-level ${sym.showKind}. $annot tried to add $sym.", annot.tree) + end checkMacroDef - /** - * Enter the symbols generated by MacroAnnotations - */ - private def enterMissingSymbols(tree: DefTree)(using Context) = new TreeTraverser { + /** Enter the symbols generated by MacroAnnotations */ + def enterMissingSymbols(tree: MemberDef, phase: DenotTransformer)(using Context) = new TreeTraverser { def traverse(tree: tpd.Tree)(using Context): Unit = tree match case tdef @ TypeDef(_, template: Template) => - val isSymbolInDecls = tdef.symbol.asClass.info.decls.toList.toSet + val isSymbolInDecls = atNextPhase(tdef.symbol.asClass.info.decls.toList.toSet) for tree <- template.body if tree.isDef do if tree.symbol.owner != tdef.symbol then report.error(em"Macro added a definition with the wrong owner - ${tree.symbol.owner} - ${tdef.symbol} in ${tree.source}", tree.srcPos) @@ -150,12 +174,4 @@ class MacroAnnotations(phase: IdentityDenotTransformer): case _ => traverseChildren(tree) }.traverse(tree) -object MacroAnnotations: - - /** Is this an annotation that implements `scala.annation.MacroAnnotation` */ - def isMacroAnnotation(annot: Annotation)(using Context): Boolean = - annot.tree.symbol.maybeOwner.derivesFrom(defn.MacroAnnotationClass) - - /** Is this symbol annotated with an annotation that implements `scala.annation.MacroAnnotation` */ - def hasMacroAnnotation(sym: Symbol)(using Context): Boolean = - sym.getAnnotation(defn.MacroAnnotationClass).isDefined +end MacroAnnotations diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index 30c994a1777c..e809c0fad463 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -20,6 +20,7 @@ import util.SrcPos import reporting.* import NameKinds.WildcardParamName import cc.* +import dotty.tools.dotc.transform.MacroAnnotations.hasMacroAnnotation object PostTyper { val name: String = "posttyper" @@ -560,7 +561,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase => /** Check if the definition has macro annotation and sets `compilationUnit.hasMacroAnnotations` if needed. */ private def registerIfHasMacroAnnotations(tree: DefTree)(using Context) = - if !Inlines.inInlineMethod && MacroAnnotations.hasMacroAnnotation(tree.symbol) then + if !Inlines.inInlineMethod && tree.symbol.hasMacroAnnotation then ctx.compilationUnit.hasMacroAnnotations = true /** Check macro annotations implementations */ diff --git a/library/src/scala/annotation/MacroAnnotation.scala b/library/src/scala/annotation/MacroAnnotation.scala index 02e9470f06fd..ffaa0cf88464 100644 --- a/library/src/scala/annotation/MacroAnnotation.scala +++ b/library/src/scala/annotation/MacroAnnotation.scala @@ -45,9 +45,12 @@ trait MacroAnnotation extends StaticAnnotation: * import scala.collection.concurrent * * class memoize extends MacroAnnotation: - * def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + * def transform(using Quotes)( + * definition: quotes.reflect.Definition, + * companion: Option[quotes.reflect.Definition] + * ): List[quotes.reflect.Definition] = * import quotes.reflect.* - * tree match + * definition match * case DefDef(name, TermParamClause(param :: Nil) :: Nil, tpt, Some(rhsTree)) => * (param.tpt.tpe.asType, tpt.tpe.asType) match * case ('[t], '[u]) => @@ -58,16 +61,17 @@ trait MacroAnnotation extends StaticAnnotation: * '{ concurrent.TrieMap.empty[t, u] }.asTerm * val cacheVal = ValDef(cacheSymbol, Some(cacheRhs)) * val newRhs = - * given Quotes = tree.symbol.asQuotes + * given Quotes = definition.symbol.asQuotes * val cacheRefExpr = Ref(cacheSymbol).asExprOf[concurrent.Map[t, u]] * val paramRefExpr = Ref(param.symbol).asExprOf[t] * val rhsExpr = rhsTree.asExprOf[u] * '{ $cacheRefExpr.getOrElseUpdate($paramRefExpr, $rhsExpr) }.asTerm - * val newTree = DefDef.copy(tree)(name, TermParamClause(param :: Nil) :: Nil, tpt, Some(newRhs)) + * val newTree = DefDef.copy(definition)(name, TermParamClause(param :: Nil) :: Nil, tpt, Some(newRhs)) * List(cacheVal, newTree) * case _ => * report.error("Annotation only supported on `def` with a single argument are supported") - * List(tree) + * List(definition) + * end transform * ``` * with this macro annotation a user can write * ```scala @@ -102,11 +106,14 @@ trait MacroAnnotation extends StaticAnnotation: * * @experimental * class equals extends MacroAnnotation: - * def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + * def transform(using Quotes)( + * definition: quotes.reflect.Definition, + * companion: Option[quotes.reflect.Definition] + * ): List[quotes.reflect.Definition] = * import quotes.reflect.* - * tree match + * definition match * case ClassDef(className, ctr, parents, self, body) => - * val cls = tree.symbol + * val cls = definition.symbol * * val constructorParameters = ctr.paramss.collect { case clause: TermParamClause => clause } * if constructorParameters.size != 1 || constructorParameters.head.params.isEmpty then @@ -139,10 +146,11 @@ trait MacroAnnotation extends StaticAnnotation: * val hashCodeOverrideDef = DefDef(hashCodeOverrideSym, _ => Some(Ref(hashSym))) * * val newBody = equalsOverrideDef :: hashVal :: hashCodeOverrideDef :: body - * List(ClassDef.copy(tree)(className, ctr, parents, self, newBody)) + * List(ClassDef.copy(definition)(className, ctr, parents, self, newBody)) * case _ => * report.error("Annotation only supports `class`") - * List(tree) + * List(definition) + * end transform * * private def equalsExpr[T: Type](that: Expr[Any], thisFields: List[Expr[Any]])(using Quotes): Expr[Boolean] = * '{ @@ -204,9 +212,10 @@ trait MacroAnnotation extends StaticAnnotation: * override def hashCode(): Int = hash$macro$1 * ``` * - * @param Quotes Implicit instance of Quotes used for tree reflection - * @param tree Tree that will be transformed + * @param Quotes Implicit instance of Quotes used for tree reflection + * @param definition Tree that will be transformed + * @param companion Tree for the companion class or module if the definition is respectively a module or a class * * @syntax markdown */ - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] diff --git a/tests/neg-macros/annot-accessIndirect/Macro_1.scala b/tests/neg-macros/annot-accessIndirect/Macro_1.scala index 8679edcfc0c3..7f4136e10652 100644 --- a/tests/neg-macros/annot-accessIndirect/Macro_1.scala +++ b/tests/neg-macros/annot-accessIndirect/Macro_1.scala @@ -3,9 +3,9 @@ import scala.quoted._ @experimental class hello extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ val helloSymbol = Symbol.newVal(Symbol.spliceOwner, Symbol.freshName("hello"), TypeRepr.of[String], Flags.EmptyFlags, Symbol.noSymbol) val helloVal = ValDef(helloSymbol, Some(Literal(StringConstant("Hello, World!")))) - List(helloVal, tree) + List(helloVal, definition) } diff --git a/tests/neg-macros/annot-accessIndirect/Macro_2.scala b/tests/neg-macros/annot-accessIndirect/Macro_2.scala index d069175ce166..5fa2ba1aa2bf 100644 --- a/tests/neg-macros/annot-accessIndirect/Macro_2.scala +++ b/tests/neg-macros/annot-accessIndirect/Macro_2.scala @@ -3,16 +3,16 @@ import scala.quoted._ @experimental class foo extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ val s = '{@hello def foo1(x: Int): Int = x + 1;()}.asTerm val fooDef = s.asInstanceOf[Inlined].body.asInstanceOf[Block].statements.head.asInstanceOf[DefDef] val hello = Ref(Symbol.spliceOwner.declaredFields("hello").head).asExprOf[String] // error - tree match + definition match case DefDef(name, params, tpt, Some(t)) => val rhs = '{ ${t.asExprOf[String]} + $hello }.asTerm - val newDef = DefDef.copy(tree)(name, params, tpt, Some(rhs)) + val newDef = DefDef.copy(definition)(name, params, tpt, Some(rhs)) List(fooDef, newDef) } diff --git a/tests/neg-macros/annot-crash/Macro_1.scala b/tests/neg-macros/annot-crash/Macro_1.scala index f3d5b3f602f8..06fb08062181 100644 --- a/tests/neg-macros/annot-crash/Macro_1.scala +++ b/tests/neg-macros/annot-crash/Macro_1.scala @@ -3,6 +3,6 @@ import scala.quoted._ @experimental class crash extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = ??? } diff --git a/tests/neg-macros/annot-empty-result/Macro_1.scala b/tests/neg-macros/annot-empty-result/Macro_1.scala index ff3be61c05d2..9b22027ce929 100644 --- a/tests/neg-macros/annot-empty-result/Macro_1.scala +++ b/tests/neg-macros/annot-empty-result/Macro_1.scala @@ -3,6 +3,6 @@ import scala.quoted._ @experimental class nilAnnot extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = Nil } diff --git a/tests/neg-macros/annot-error-annot/Macro_1.scala b/tests/neg-macros/annot-error-annot/Macro_1.scala index d54b69903e02..6597a11be7d2 100644 --- a/tests/neg-macros/annot-error-annot/Macro_1.scala +++ b/tests/neg-macros/annot-error-annot/Macro_1.scala @@ -3,7 +3,7 @@ import scala.quoted._ @experimental class error extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = - quotes.reflect.report.error("MACRO ERROR", tree.pos) - List(tree) + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = + quotes.reflect.report.error("MACRO ERROR", definition.pos) + List(definition) } diff --git a/tests/neg-macros/annot-ill-abort/Macro_1.scala b/tests/neg-macros/annot-ill-abort/Macro_1.scala index 446ce0a5331b..4689ffbe2f2c 100644 --- a/tests/neg-macros/annot-ill-abort/Macro_1.scala +++ b/tests/neg-macros/annot-ill-abort/Macro_1.scala @@ -3,6 +3,6 @@ import scala.quoted._ @experimental class crash extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = throw new scala.quoted.runtime.StopMacroExpansion } diff --git a/tests/neg-macros/annot-mod-class-add-top-method/Macro_1.scala b/tests/neg-macros/annot-mod-class-add-top-method/Macro_1.scala index b5c49695ad2a..7dc8cb2c4479 100644 --- a/tests/neg-macros/annot-mod-class-add-top-method/Macro_1.scala +++ b/tests/neg-macros/annot-mod-class-add-top-method/Macro_1.scala @@ -4,14 +4,14 @@ import scala.collection.mutable @experimental class addTopLevelMethod extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => val methType = MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Int]) val methSym = Symbol.newMethod(Symbol.spliceOwner, Symbol.freshName("toLevelMethod"), methType, Flags.EmptyFlags, Symbol.noSymbol) val methDef = DefDef(methSym, _ => Some(Literal(IntConstant(1)))) - List(methDef, tree) + List(methDef, definition) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/neg-macros/annot-mod-class-add-top-val/Macro_1.scala b/tests/neg-macros/annot-mod-class-add-top-val/Macro_1.scala index c6f21e181879..12443d329108 100644 --- a/tests/neg-macros/annot-mod-class-add-top-val/Macro_1.scala +++ b/tests/neg-macros/annot-mod-class-add-top-val/Macro_1.scala @@ -4,13 +4,13 @@ import scala.collection.mutable @experimental class addTopLevelVal extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => val valSym = Symbol.newVal(Symbol.spliceOwner, Symbol.freshName("toLevelVal"), TypeRepr.of[Int], Flags.EmptyFlags, Symbol.noSymbol) val valDef = ValDef(valSym, Some(Literal(IntConstant(1)))) - List(valDef, tree) + List(valDef, definition) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/neg-macros/annot-mod-top-method-add-top-method/Macro_1.scala b/tests/neg-macros/annot-mod-top-method-add-top-method/Macro_1.scala index 45679b65c03b..8609af376ad7 100644 --- a/tests/neg-macros/annot-mod-top-method-add-top-method/Macro_1.scala +++ b/tests/neg-macros/annot-mod-top-method-add-top-method/Macro_1.scala @@ -5,9 +5,9 @@ import scala.collection.mutable @experimental // Assumes annotation is on top level def or val class addTopLevelMethodOutsidePackageObject extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ val methType = MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Int]) val methSym = Symbol.newMethod(Symbol.spliceOwner.owner, Symbol.freshName("toLevelMethod"), methType, Flags.EmptyFlags, Symbol.noSymbol) val methDef = DefDef(methSym, _ => Some(Literal(IntConstant(1)))) - List(methDef, tree) + List(methDef, definition) diff --git a/tests/neg-macros/annot-mod-top-method-add-top-val/Macro_1.scala b/tests/neg-macros/annot-mod-top-method-add-top-val/Macro_1.scala index c6c4c32afcb8..a9ae0efd76b4 100644 --- a/tests/neg-macros/annot-mod-top-method-add-top-val/Macro_1.scala +++ b/tests/neg-macros/annot-mod-top-method-add-top-val/Macro_1.scala @@ -5,8 +5,8 @@ import scala.collection.mutable @experimental // Assumes annotation is on top level def or val class addTopLevelValOutsidePackageObject extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ val valSym = Symbol.newVal(Symbol.spliceOwner.owner, Symbol.freshName("toLevelVal"), TypeRepr.of[Int], Flags.EmptyFlags, Symbol.noSymbol) val valDef = ValDef(valSym, Some(Literal(IntConstant(1)))) - List(valDef, tree) + List(valDef, definition) diff --git a/tests/neg-macros/annot-on-type/Macro_1.scala b/tests/neg-macros/annot-on-type/Macro_1.scala index 7468c5a200a6..631a5bcc201d 100644 --- a/tests/neg-macros/annot-on-type/Macro_1.scala +++ b/tests/neg-macros/annot-on-type/Macro_1.scala @@ -3,6 +3,6 @@ import scala.quoted._ @experimental class voidAnnot extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = - List(tree) + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = + List(definition) } diff --git a/tests/neg-macros/annot-result-owner/Macro_1.scala b/tests/neg-macros/annot-result-owner/Macro_1.scala index 34f7541f726b..af3d8dbb6656 100644 --- a/tests/neg-macros/annot-result-owner/Macro_1.scala +++ b/tests/neg-macros/annot-result-owner/Macro_1.scala @@ -3,9 +3,9 @@ import scala.quoted._ @experimental class insertVal extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ // Use of wrong owner - val valSym = Symbol.newVal(tree.symbol, Symbol.freshName("definitionWithWrongOwner"), TypeRepr.of[Unit], Flags.Private, Symbol.noSymbol) + val valSym = Symbol.newVal(definition.symbol, Symbol.freshName("definitionWithWrongOwner"), TypeRepr.of[Unit], Flags.Private, Symbol.noSymbol) val valDef = ValDef(valSym, Some('{}.asTerm)) - List(valDef, tree) + List(valDef, definition) diff --git a/tests/neg-macros/annot-suspend-cycle.check b/tests/neg-macros/annot-suspend-cycle.check index 437398f1d668..7b87943be2af 100644 --- a/tests/neg-macros/annot-suspend-cycle.check +++ b/tests/neg-macros/annot-suspend-cycle.check @@ -1,9 +1,9 @@ --- [E129] Potential Issue Warning: tests/neg-macros/annot-suspend-cycle/Macro.scala:7:4 -------------------------------- -7 | new Foo - | ^^^^^^^ - | A pure expression does nothing in statement position - | - | longer explanation available when compiling with `-explain` +-- [E129] Potential Issue Warning: tests/neg-macros/annot-suspend-cycle/Macro.scala:10:6 ------------------------------- +10 | new Foo + | ^^^^^^^ + | A pure expression does nothing in statement position + | + | longer explanation available when compiling with `-explain` Cyclic macro dependencies in tests/neg-macros/annot-suspend-cycle/Test.scala. Compilation stopped since no further progress can be made. diff --git a/tests/neg-macros/annot-suspend-cycle/Macro.scala b/tests/neg-macros/annot-suspend-cycle/Macro.scala index 4143e2c32062..9106c3e2a37e 100644 --- a/tests/neg-macros/annot-suspend-cycle/Macro.scala +++ b/tests/neg-macros/annot-suspend-cycle/Macro.scala @@ -3,7 +3,11 @@ import scala.quoted._ @experimental class cycle extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = - new Foo - List(tree) + def transform(using Quotes)( + definition: quotes.reflect.Definition, + companion: Option[quotes.reflect.Definition] + ): List[quotes.reflect.Definition] = + new Foo + List(definition) + end transform } diff --git a/tests/neg-macros/i18677-a/Macro_1.scala b/tests/neg-macros/i18677-a/Macro_1.scala index c3df616ed4e6..c89e259679c5 100644 --- a/tests/neg-macros/i18677-a/Macro_1.scala +++ b/tests/neg-macros/i18677-a/Macro_1.scala @@ -6,13 +6,17 @@ import quoted.* trait Foo class extendFoo extends MacroAnnotation : - override def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = - import quotes.reflect.* - tree match - case ClassDef(name, ctr, p, self, body) => - val parents = List(TypeTree.of[Foo]) - val newTree = ClassDef.copy(tree)(name, ctr, parents, self, body) - newTree :: Nil - case _ => - report.error("@extendFoo can only annotate class definitions") - tree :: Nil \ No newline at end of file + def transform(using Quotes)( + definition: quotes.reflect.Definition, + companion: Option[quotes.reflect.Definition] + ): List[quotes.reflect.Definition] = + import quotes.reflect.* + definition match + case ClassDef(name, ctr, p, self, body) => + val parents = List(TypeTree.of[Foo]) + val newTree = ClassDef.copy(definition)(name, ctr, parents, self, body) + newTree :: Nil + case _ => + report.error("@extendFoo can only annotate class definitions") + definition :: Nil + end transform diff --git a/tests/neg-macros/i18677-b/Macro_1.scala b/tests/neg-macros/i18677-b/Macro_1.scala index 9e1b9be5e696..cc953896f5e3 100644 --- a/tests/neg-macros/i18677-b/Macro_1.scala +++ b/tests/neg-macros/i18677-b/Macro_1.scala @@ -6,13 +6,17 @@ import quoted.* class Foo class extendFoo extends MacroAnnotation : - override def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = - import quotes.reflect.* - tree match - case ClassDef(name, ctr, p, self, body) => - val parents = List(TypeTree.of[Foo]) - val newTree = ClassDef.copy(tree)(name, ctr, parents, self, body) - newTree :: Nil - case _ => - report.error("@extendFoo can only annotate class definitions") - tree :: Nil \ No newline at end of file + def transform(using Quotes)( + definition: quotes.reflect.Definition, + companion: Option[quotes.reflect.Definition] + ): List[quotes.reflect.Definition] = + import quotes.reflect.* + definition match + case ClassDef(name, ctr, p, self, body) => + val parents = List(TypeTree.of[Foo]) + val newTree = ClassDef.copy(definition)(name, ctr, parents, self, body) + newTree :: Nil + case _ => + report.error("@extendFoo can only annotate class definitions") + definition :: Nil + end transform diff --git a/tests/neg-macros/i18825/Macro_1.scala b/tests/neg-macros/i18825/Macro_1.scala index c099954f3858..adeb320c1403 100644 --- a/tests/neg-macros/i18825/Macro_1.scala +++ b/tests/neg-macros/i18825/Macro_1.scala @@ -4,16 +4,16 @@ import scala.quoted.* @experimental class toString extends MacroAnnotation : - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect.* - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val toStringSym = Symbol.requiredMethod("java.lang.Object.toString") val toStringOverrideSym = Symbol.newMethod(cls, "toString", toStringSym.info, Flags.Override, Symbol.noSymbol) val toStringDef = DefDef(toStringOverrideSym, _ => Some(Literal(StringConstant("Hello from macro")))) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, toStringDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, toStringDef :: body) List(newClassDef) case _ => report.error("@toString can only be annotated on class definitions") - tree :: Nil + definition :: Nil diff --git a/tests/neg-macros/i19676.check b/tests/neg-macros/i19676.check new file mode 100644 index 000000000000..2c8da2582f9e --- /dev/null +++ b/tests/neg-macros/i19676.check @@ -0,0 +1,13 @@ + +-- Error: tests/neg-macros/i19676/Test_2.scala:3:0 --------------------------------------------------------------------- +3 |@buggy // error + |^^^^^^ + |Transformed companion for @SourceFile("tests/neg-macros/i19676/Test_2.scala") @experimental("Added by -experimental") final module class Foo() + | extends AnyRef(), scala.deriving.Mirror.Product { this: Foo.type => + | private def writeReplace(): AnyRef = new scala.runtime.ModuleSerializationProxy(classOf[Foo.type]) + | def apply(): Foo = new Foo() + | def unapply(x$1: Foo): true.type = true + | override def toString: String = "Foo" + | type MirroredMonoType = Foo + | def fromProduct(x$0: Product): Foo.MirroredMonoType = new Foo() + |} was returned more than once by `(new buggy()).transform(..)` during macro expansion diff --git a/tests/neg-macros/i19676/Macro_1.scala b/tests/neg-macros/i19676/Macro_1.scala new file mode 100644 index 000000000000..a5598c448a1c --- /dev/null +++ b/tests/neg-macros/i19676/Macro_1.scala @@ -0,0 +1,19 @@ +//> using options -experimental -Yno-experimental + +import scala.annotation.MacroAnnotation +import scala.quoted.* + +class buggy extends MacroAnnotation: + + def transform(using Quotes) + (definition: quotes.reflect.Definition, + companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = + + import quotes.reflect.* + companion match + case Some(companion) => + List(definition, companion, companion) + case None => + report.error("The goal of this test is to return the companion more than once to trigger a compilation error") + List(definition) + end transform \ No newline at end of file diff --git a/tests/neg-macros/i19676/Test_2.scala b/tests/neg-macros/i19676/Test_2.scala new file mode 100644 index 000000000000..0142d263f103 --- /dev/null +++ b/tests/neg-macros/i19676/Test_2.scala @@ -0,0 +1,4 @@ +//> using options -experimental -Yno-experimental + +@buggy // error +case class Foo() \ No newline at end of file diff --git a/tests/neg-macros/wrong-owner.check b/tests/neg-macros/wrong-owner.check index ca8751d0fe1c..26316d3fc687 100644 --- a/tests/neg-macros/wrong-owner.check +++ b/tests/neg-macros/wrong-owner.check @@ -17,6 +17,6 @@ | |Error: |assertion failed: bad owner; method toString has owner class String, expected was class Foo - |owner chain = method toString, class String, package java.lang, package java, package , ctxOwners = class Foo, class Foo, package , package , package , package , package , package , package , package , package , , , , , + |owner chain = method toString, class String, package java.lang, package java, package , ctxOwners = class Foo, class Foo, package , package , package , package , package , package , package , package , package , package , , , , , | |stacktrace available when compiling with `-Ydebug` diff --git a/tests/neg-macros/wrong-owner/Macro_1.scala b/tests/neg-macros/wrong-owner/Macro_1.scala index 85127b701f81..2e101f849802 100644 --- a/tests/neg-macros/wrong-owner/Macro_1.scala +++ b/tests/neg-macros/wrong-owner/Macro_1.scala @@ -4,16 +4,16 @@ import scala.quoted.* @experimental class wrongOwner extends MacroAnnotation : - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect.* - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val toStringSym = Symbol.requiredMethod("java.lang.Object.toString") val toStringOverrideSym = Symbol.newMethod(Symbol.classSymbol("java.lang.String"), "toString", toStringSym.info, Flags.Override, Symbol.noSymbol) val toStringDef = DefDef(toStringOverrideSym, _ => Some(Literal(StringConstant("Hello from macro")))) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, toStringDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, toStringDef :: body) List(newClassDef) case _ => report.error("@toString can only be annotated on class definitions") - tree :: Nil + definition :: Nil diff --git a/tests/pos-macros/annot-dependency-between-modules/Macro_1.scala b/tests/pos-macros/annot-dependency-between-modules/Macro_1.scala new file mode 100644 index 000000000000..e196e0984dfe --- /dev/null +++ b/tests/pos-macros/annot-dependency-between-modules/Macro_1.scala @@ -0,0 +1,11 @@ +import scala.annotation.* +import scala.quoted.* + +@experimental +class void extends MacroAnnotation: + def transform(using Quotes)( + definition: quotes.reflect.Definition, + companion: Option[quotes.reflect.Definition] + ) : List[quotes.reflect.Definition] = + definition +: companion.toList + end transform diff --git a/tests/pos-macros/annot-dependency-between-modules/Test_2.scala b/tests/pos-macros/annot-dependency-between-modules/Test_2.scala new file mode 100644 index 000000000000..f809330af52d --- /dev/null +++ b/tests/pos-macros/annot-dependency-between-modules/Test_2.scala @@ -0,0 +1,3 @@ + +@void @void +class Foo \ No newline at end of file diff --git a/tests/pos-macros/annot-in-object/Macro_1.scala b/tests/pos-macros/annot-in-object/Macro_1.scala index 143bd46b8ecc..2086f9ec4cb1 100644 --- a/tests/pos-macros/annot-in-object/Macro_1.scala +++ b/tests/pos-macros/annot-in-object/Macro_1.scala @@ -6,9 +6,11 @@ import scala.quoted._ object Foo: @experimental class void extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = List(tree) + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = + List(definition) object Bar: @experimental class void extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = List(tree) + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = + List(definition) diff --git a/tests/pos-macros/annot-suspend/Macro_1.scala b/tests/pos-macros/annot-suspend/Macro_1.scala index 3c391a1a041f..4ae96186b777 100644 --- a/tests/pos-macros/annot-suspend/Macro_1.scala +++ b/tests/pos-macros/annot-suspend/Macro_1.scala @@ -5,5 +5,5 @@ import scala.quoted._ @experimental class void extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = - List(tree) + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = + List(definition) diff --git a/tests/pos-macros/annot-then-inline/Macro_1.scala b/tests/pos-macros/annot-then-inline/Macro_1.scala index 99fece18299a..f3226e24d4da 100644 --- a/tests/pos-macros/annot-then-inline/Macro_1.scala +++ b/tests/pos-macros/annot-then-inline/Macro_1.scala @@ -5,14 +5,14 @@ import scala.quoted._ @experimental class useInlinedIdentity extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect.* - tree match + definition match case DefDef(name, params, tpt, Some(rhs)) => val newRhs = - given Quotes = tree.symbol.asQuotes + given Quotes = definition.symbol.asQuotes '{ inlinedIdentity(${rhs.asExpr}) }.asTerm - List(DefDef.copy(tree)(name, params, tpt, Some(newRhs))) + List(DefDef.copy(definition)(name, params, tpt, Some(newRhs))) } inline def inlinedIdentity(x: Any): x.type = x diff --git a/tests/pos-macros/i19537/Macro_1.scala b/tests/pos-macros/i19537/Macro_1.scala index 932994657d24..a44c212599d3 100644 --- a/tests/pos-macros/i19537/Macro_1.scala +++ b/tests/pos-macros/i19537/Macro_1.scala @@ -3,4 +3,5 @@ import scala.quoted.* @experimental class annotation extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition) = List(tree) + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = + List(definition) diff --git a/tests/pos-macros/i19539/Macro_1.scala b/tests/pos-macros/i19539/Macro_1.scala index 932994657d24..a44c212599d3 100644 --- a/tests/pos-macros/i19539/Macro_1.scala +++ b/tests/pos-macros/i19539/Macro_1.scala @@ -3,4 +3,5 @@ import scala.quoted.* @experimental class annotation extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition) = List(tree) + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = + List(definition) diff --git a/tests/pos-macros/macro-annot-with-companion/Macro_1.scala b/tests/pos-macros/macro-annot-with-companion/Macro_1.scala new file mode 100644 index 000000000000..8fc11f98a7c2 --- /dev/null +++ b/tests/pos-macros/macro-annot-with-companion/Macro_1.scala @@ -0,0 +1,12 @@ +import scala.annotation.MacroAnnotation + +import scala.quoted.* + +class transform extends MacroAnnotation: + override def transform(using Quotes)( + tree: quotes.reflect.Definition, + companion: Option[quotes.reflect.Definition] + ) : List[quotes.reflect.Definition] = { + import quotes.reflect.* + List(tree) + } diff --git a/tests/pos-macros/macro-annot-with-companion/Test_2.scala b/tests/pos-macros/macro-annot-with-companion/Test_2.scala new file mode 100644 index 000000000000..ddf73334389b --- /dev/null +++ b/tests/pos-macros/macro-annot-with-companion/Test_2.scala @@ -0,0 +1,15 @@ + +@transform +class Foo + +@transform +class Bar + +@transform +object Foo + +@transform +class A + +@transform +object B \ No newline at end of file diff --git a/tests/run-macros/annot-add-global-class/Macro_1.scala b/tests/run-macros/annot-add-global-class/Macro_1.scala index 6ac77913e3ab..a6ebf1c64d9d 100644 --- a/tests/run-macros/annot-add-global-class/Macro_1.scala +++ b/tests/run-macros/annot-add-global-class/Macro_1.scala @@ -8,9 +8,9 @@ import scala.collection.mutable @experimental class addClass extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, List(TermParamClause(Nil)), tpt, Some(rhs)) => val parents = List(TypeTree.of[Object]) def decls(cls: Symbol): List[Symbol] = @@ -25,8 +25,8 @@ class addClass extends MacroAnnotation: val newCls = Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), Nil) - val newDef = DefDef.copy(tree)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(newCls, runSym), Nil))) + val newDef = DefDef.copy(definition)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(newCls, runSym), Nil))) List(clsDef, newDef) case _ => report.error("Annotation only supports `def` with one argument") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-add-global-object/Macro_1.scala b/tests/run-macros/annot-add-global-object/Macro_1.scala index f7c901a49aa5..c2fe5bbfe9e5 100644 --- a/tests/run-macros/annot-add-global-object/Macro_1.scala +++ b/tests/run-macros/annot-add-global-object/Macro_1.scala @@ -6,9 +6,9 @@ import scala.collection.mutable @experimental class addClass extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, List(TermParamClause(Nil)), tpt, Some(rhs)) => val parents = List(TypeTree.of[Object]) def decls(cls: Symbol): List[Symbol] = @@ -23,8 +23,8 @@ class addClass extends MacroAnnotation: val modDef = ClassDef.module(mod, parents, body = List(runDef)) - val newDef = DefDef.copy(tree)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(Ref(mod), runSym), Nil))) + val newDef = DefDef.copy(definition)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(Ref(mod), runSym), Nil))) modDef.toList ::: newDef :: Nil case _ => report.error("Annotation only supports `def` with one argument") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-add-local-class/Macro_1.scala b/tests/run-macros/annot-add-local-class/Macro_1.scala index 57a2d543ffbc..07f6d98e7c99 100644 --- a/tests/run-macros/annot-add-local-class/Macro_1.scala +++ b/tests/run-macros/annot-add-local-class/Macro_1.scala @@ -6,9 +6,9 @@ import scala.collection.mutable @experimental class addClass extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, List(TermParamClause(Nil)), tpt, Some(rhs)) => val parents = List(TypeTree.of[Object]) def decls(cls: Symbol): List[Symbol] = @@ -22,8 +22,8 @@ class addClass extends MacroAnnotation: val newCls = Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), Nil) - val newDef = DefDef.copy(tree)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(newCls, runSym), Nil))) + val newDef = DefDef.copy(definition)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(newCls, runSym), Nil))) List(clsDef, newDef) case _ => report.error("Annotation only supports `def` with one argument") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-add-local-object/Macro_1.scala b/tests/run-macros/annot-add-local-object/Macro_1.scala index 6f6e11e7361c..18534730e16b 100644 --- a/tests/run-macros/annot-add-local-object/Macro_1.scala +++ b/tests/run-macros/annot-add-local-object/Macro_1.scala @@ -6,9 +6,9 @@ import scala.collection.mutable @experimental class addClass extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, List(TermParamClause(Nil)), tpt, Some(rhs)) => val parents = List(TypeTree.of[Object]) def decls(cls: Symbol): List[Symbol] = @@ -23,8 +23,8 @@ class addClass extends MacroAnnotation: val (modVal, clsDef) = ClassDef.module(mod, parents, body = List(runDef)) - val newDef = DefDef.copy(tree)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(Ref(mod), runSym), Nil))) + val newDef = DefDef.copy(definition)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(Ref(mod), runSym), Nil))) List(modVal, clsDef, newDef) case _ => report.error("Annotation only supports `def` with one argument") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-add-nested-class/Macro_1.scala b/tests/run-macros/annot-add-nested-class/Macro_1.scala index e13e3841501a..631e3044a39c 100644 --- a/tests/run-macros/annot-add-nested-class/Macro_1.scala +++ b/tests/run-macros/annot-add-nested-class/Macro_1.scala @@ -6,9 +6,9 @@ import scala.collection.mutable @experimental class addClass extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, List(TermParamClause(Nil)), tpt, Some(rhs)) => val parents = List(TypeTree.of[Object]) def decls(cls: Symbol): List[Symbol] = @@ -23,8 +23,8 @@ class addClass extends MacroAnnotation: val newCls = Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), Nil) - val newDef = DefDef.copy(tree)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(newCls, runSym), Nil))) + val newDef = DefDef.copy(definition)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(newCls, runSym), Nil))) List(clsDef, newDef) case _ => report.error("Annotation only supports `def` with one argument") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-add-nested-object/Macro_1.scala b/tests/run-macros/annot-add-nested-object/Macro_1.scala index f8cde8de5bf0..0069a1010a78 100644 --- a/tests/run-macros/annot-add-nested-object/Macro_1.scala +++ b/tests/run-macros/annot-add-nested-object/Macro_1.scala @@ -6,9 +6,9 @@ import scala.collection.mutable @experimental class addClass extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, List(TermParamClause(Nil)), tpt, Some(rhs)) => val parents = List(TypeTree.of[Object]) def decls(cls: Symbol): List[Symbol] = @@ -23,8 +23,8 @@ class addClass extends MacroAnnotation: val (modVal, clsDef) = ClassDef.module(mod, parents, body = List(runDef)) - val newDef = DefDef.copy(tree)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(Ref(mod), runSym), Nil))) + val newDef = DefDef.copy(definition)(name, List(TermParamClause(Nil)), tpt, Some(Apply(Select(Ref(mod), runSym), Nil))) List(modVal, clsDef, newDef) case _ => report.error("Annotation only supports `def` with one argument") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-annot-order/Macro_1.scala b/tests/run-macros/annot-annot-order/Macro_1.scala index 9d3e8e40c01a..a177225d635f 100644 --- a/tests/run-macros/annot-annot-order/Macro_1.scala +++ b/tests/run-macros/annot-annot-order/Macro_1.scala @@ -5,15 +5,15 @@ import scala.quoted._ @experimental class print(msg: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, params, tpt, Some(rhsTree)) => - given Quotes = tree.symbol.asQuotes + given Quotes = definition.symbol.asQuotes rhsTree.asExpr match case '{ $rhsExpr: t } => val newRhs = '{ println(${Expr(msg)}); $rhsExpr }.asTerm - List(DefDef.copy(tree)(name, params, tpt, Some(newRhs))) + List(DefDef.copy(definition)(name, params, tpt, Some(newRhs))) case _ => report.error("Annotation only supported on `def`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-bind/Macro_1.scala b/tests/run-macros/annot-bind/Macro_1.scala index 0997f35ccf4a..fd0aaf1343a0 100644 --- a/tests/run-macros/annot-bind/Macro_1.scala +++ b/tests/run-macros/annot-bind/Macro_1.scala @@ -5,15 +5,15 @@ import scala.quoted._ @experimental class bind(str: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ValDef(name, tpt, Some(rhsTree)) => val valSym = Symbol.newVal(Symbol.spliceOwner, Symbol.freshName(str), tpt.tpe, Flags.Private, Symbol.noSymbol) val valDef = ValDef(valSym, Some(rhsTree)) val newRhs = Ref(valSym) - val newTree = ValDef.copy(tree)(name, tpt, Some(newRhs)) + val newTree = ValDef.copy(definition)(name, tpt, Some(newRhs)) List(valDef, newTree) case _ => report.error("Annotation only supported on `val` with a single argument are supported") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-changeVal/Macro_1.scala b/tests/run-macros/annot-changeVal/Macro_1.scala index d55282f8c390..d32cbe85ef35 100644 --- a/tests/run-macros/annot-changeVal/Macro_1.scala +++ b/tests/run-macros/annot-changeVal/Macro_1.scala @@ -7,8 +7,8 @@ import scala.annotation.MacroAnnotation object ChangeVal: @experimental class change(i: Int) extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect.* - tree match - case ValDef(n, t, _) => List(ValDef.copy(tree)(n, t, Some(Literal(IntConstant(i))))) + definition match + case ValDef(n, t, _) => List(ValDef.copy(definition)(n, t, Some(Literal(IntConstant(i))))) } diff --git a/tests/run-macros/annot-concrete-class/Macro_1.scala b/tests/run-macros/annot-concrete-class/Macro_1.scala index e91f9c1ccafe..326b450088e6 100644 --- a/tests/run-macros/annot-concrete-class/Macro_1.scala +++ b/tests/run-macros/annot-concrete-class/Macro_1.scala @@ -5,7 +5,7 @@ import scala.quoted.* class implementAFoo extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(tree: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect.* tree match case ClassDef(name, cstr, parents, self, body) => diff --git a/tests/run-macros/annot-export/Macro_1.scala b/tests/run-macros/annot-export/Macro_1.scala index fbe97684079b..b135245790ba 100644 --- a/tests/run-macros/annot-export/Macro_1.scala +++ b/tests/run-macros/annot-export/Macro_1.scala @@ -6,10 +6,10 @@ import scala.collection.mutable.Map @experimental class returnClassName extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, params, tpt, _) => val rhs = Literal(StringConstant(Symbol.spliceOwner.name.stripSuffix("$"))) - List(DefDef.copy(tree)(name, params, tpt, Some(rhs))) + List(DefDef.copy(definition)(name, params, tpt, Some(rhs))) } diff --git a/tests/run-macros/annot-gen2/Macro_1.scala b/tests/run-macros/annot-gen2/Macro_1.scala index 05428aac7375..503d6e192cdd 100644 --- a/tests/run-macros/annot-gen2/Macro_1.scala +++ b/tests/run-macros/annot-gen2/Macro_1.scala @@ -5,14 +5,14 @@ import scala.quoted._ @experimental class hello extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, params, tpt, Some(t)) => - given Quotes = tree.symbol.asQuotes + given Quotes = definition.symbol.asQuotes val rhs = '{ ${t.asExprOf[String]} + "hello" }.asTerm - val newDef = DefDef.copy(tree)(name, params, tpt, Some(rhs)) + val newDef = DefDef.copy(definition)(name, params, tpt, Some(rhs)) List(newDef) } diff --git a/tests/run-macros/annot-gen2/Macro_2.scala b/tests/run-macros/annot-gen2/Macro_2.scala index 3e2e228abb3e..9cb734dfdb00 100644 --- a/tests/run-macros/annot-gen2/Macro_2.scala +++ b/tests/run-macros/annot-gen2/Macro_2.scala @@ -5,11 +5,11 @@ import scala.quoted._ @experimental class foo extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, params, tpt, Some(t)) => - given Quotes = tree.symbol.asQuotes + given Quotes = definition.symbol.asQuotes val s = Ref(params.head.params.head.symbol).asExprOf[String] val rhs = '{ @hello def foo1(s: String): String = ${ @@ -18,6 +18,6 @@ class foo extends MacroAnnotation { } foo1($s) }.asTerm - val newDef = DefDef.copy(tree)(name, params, tpt, Some(rhs)) + val newDef = DefDef.copy(definition)(name, params, tpt, Some(rhs)) List(newDef) } diff --git a/tests/run-macros/annot-generate/Macro_1.scala b/tests/run-macros/annot-generate/Macro_1.scala index b88cc62afb06..b64d888aab80 100644 --- a/tests/run-macros/annot-generate/Macro_1.scala +++ b/tests/run-macros/annot-generate/Macro_1.scala @@ -5,9 +5,9 @@ import scala.quoted._ @experimental class hello extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ val helloSymbol = Symbol.newVal(Symbol.spliceOwner, Symbol.freshName("hello"), TypeRepr.of[String], Flags.EmptyFlags, Symbol.noSymbol) val helloVal = ValDef(helloSymbol, Some(Literal(StringConstant("Hello, World!")))) - List(helloVal, tree) + List(helloVal, definition) } diff --git a/tests/run-macros/annot-generate/Macro_2.scala b/tests/run-macros/annot-generate/Macro_2.scala index 911625eac645..37c88459e3e1 100644 --- a/tests/run-macros/annot-generate/Macro_2.scala +++ b/tests/run-macros/annot-generate/Macro_2.scala @@ -5,15 +5,15 @@ import scala.quoted._ @experimental class foo extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, params, tpt, Some(t)) => - given Quotes = tree.symbol.asQuotes + given Quotes = definition.symbol.asQuotes val rhs = '{ @hello def foo(x: Int): Int = x + 1 ${t.asExprOf[Int]} }.asTerm - val newDef = DefDef.copy(tree)(name, params, tpt, Some(rhs)) + val newDef = DefDef.copy(definition)(name, params, tpt, Some(rhs)) List(newDef) } diff --git a/tests/run-macros/annot-macro-main/Macro_1.scala b/tests/run-macros/annot-macro-main/Macro_1.scala index 2a585bee2bc1..4470febe1244 100644 --- a/tests/run-macros/annot-macro-main/Macro_1.scala +++ b/tests/run-macros/annot-macro-main/Macro_1.scala @@ -6,9 +6,9 @@ import scala.collection.mutable @experimental class mainMacro extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, List(TermParamClause(Nil)), _, _) => val parents = List(TypeTree.of[Object]) def decls(cls: Symbol): List[Symbol] = @@ -17,10 +17,10 @@ class mainMacro extends MacroAnnotation: val cls = Symbol.newClass(Symbol.spliceOwner.owner, name, parents = parents.map(_.tpe), decls, selfType = None) val mainSym = cls.declaredMethod("main").head - val mainDef = DefDef(mainSym, _ => Some(Apply(Ref(tree.symbol), Nil))) + val mainDef = DefDef(mainSym, _ => Some(Apply(Ref(definition.symbol), Nil))) val clsDef = ClassDef(cls, parents, body = List(mainDef)) - List(clsDef, tree) + List(clsDef, definition) case _ => report.error("Annotation only supports `def` without arguments") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-memo/Macro_1.scala b/tests/run-macros/annot-memo/Macro_1.scala index cd990e1d6cce..492f1e337dfb 100644 --- a/tests/run-macros/annot-memo/Macro_1.scala +++ b/tests/run-macros/annot-memo/Macro_1.scala @@ -6,9 +6,9 @@ import scala.collection.concurrent @experimental class memoize extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, TermParamClause(param :: Nil) :: Nil, tpt, Some(rhsTree)) => (param.tpt.tpe.asType, tpt.tpe.asType) match case ('[t], '[u]) => @@ -19,13 +19,13 @@ class memoize extends MacroAnnotation: '{ concurrent.TrieMap.empty[t, u] }.asTerm val cacheVal = ValDef(cacheSymbol, Some(cacheRhs)) val newRhs = - given Quotes = tree.symbol.asQuotes + given Quotes = definition.symbol.asQuotes val cacheRefExpr = Ref(cacheSymbol).asExprOf[concurrent.Map[t, u]] val paramRefExpr = Ref(param.symbol).asExprOf[t] val rhsExpr = rhsTree.asExprOf[u] '{ $cacheRefExpr.getOrElseUpdate($paramRefExpr, $rhsExpr) }.asTerm - val newTree = DefDef.copy(tree)(name, TermParamClause(param :: Nil) :: Nil, tpt, Some(newRhs)) + val newTree = DefDef.copy(definition)(name, TermParamClause(param :: Nil) :: Nil, tpt, Some(newRhs)) List(cacheVal, newTree) case _ => report.error("Annotation only supported on `def` with a single argument are supported") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-add-def/Macro_1.scala b/tests/run-macros/annot-mod-class-add-def/Macro_1.scala index 855dce06f279..acd878f7d556 100644 --- a/tests/run-macros/annot-mod-class-add-def/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-def/Macro_1.scala @@ -6,11 +6,11 @@ import scala.collection.mutable @experimental class addIndirectToString(msg: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val stringMethType = ByNameType.apply(TypeRepr.of[String]) val stringSym = Symbol.newMethod(cls, Symbol.freshName("string"), stringMethType, Flags.Private, Symbol.noSymbol) val stringDef = DefDef(stringSym, _ => Some(Literal(StringConstant(msg)))) @@ -20,9 +20,9 @@ class addIndirectToString(msg: String) extends MacroAnnotation: val toStringDef = DefDef(toStringOverrideSym, _ => Some(Ref(stringSym))) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, stringDef :: toStringDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, stringDef :: toStringDef :: body) List(newClassDef) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-add-inner-class/Macro_1.scala b/tests/run-macros/annot-mod-class-add-inner-class/Macro_1.scala index 395bfd7a28db..4294e44dd45b 100644 --- a/tests/run-macros/annot-mod-class-add-inner-class/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-inner-class/Macro_1.scala @@ -6,11 +6,11 @@ import scala.collection.mutable @experimental class addInnerClass extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol def showClassDecls(showCls: Symbol): List[Symbol] = List(Symbol.newMethod(showCls, "showMe", MethodType(List("x"))(_ => List(cls.typeRef), _ => TypeRepr.of[String]))) @@ -27,9 +27,9 @@ class addInnerClass extends MacroAnnotation: val toStringOverrideSym = Symbol.newMethod(cls, "toString", toStringMethType, Flags.Override, Symbol.noSymbol) val toStringDef = DefDef(toStringOverrideSym, _ => Some(newShowCallShowMe)) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, showClass :: toStringDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, showClass :: toStringDef :: body) List(newClassDef) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-add-lazy-val/Macro_1.scala b/tests/run-macros/annot-mod-class-add-lazy-val/Macro_1.scala index f72f28b610d6..c772f6cf43a6 100644 --- a/tests/run-macros/annot-mod-class-add-lazy-val/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-lazy-val/Macro_1.scala @@ -6,11 +6,11 @@ import scala.collection.mutable @experimental class addMemoToString(msg: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val stringLazyValSym = Symbol.newVal(cls, Symbol.freshName("string"), TypeRepr.of[String], Flags.Lazy | Flags.Private, Symbol.noSymbol) val toStringMethType = Symbol.requiredMethod("java.lang.Object.toString").info @@ -19,9 +19,9 @@ class addMemoToString(msg: String) extends MacroAnnotation: val stringLazyValDef = ValDef(stringLazyValSym, Some(Literal(StringConstant(msg)))) val toStringDef = DefDef(toStringOverrideSym, _ => Some(Ref(stringLazyValSym))) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, stringLazyValDef :: toStringDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, stringLazyValDef :: toStringDef :: body) List(newClassDef) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-add-local-class/Macro_1.scala b/tests/run-macros/annot-mod-class-add-local-class/Macro_1.scala index 0156812adeb1..50df9e86446d 100644 --- a/tests/run-macros/annot-mod-class-add-local-class/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-local-class/Macro_1.scala @@ -6,11 +6,11 @@ import scala.collection.mutable @experimental class addInnerClass extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val toStringMethType = Symbol.requiredMethod("java.lang.Object.toString").info val toStringOverrideSym = Symbol.newMethod(cls, "toString", toStringMethType, Flags.Override, Symbol.noSymbol) @@ -28,9 +28,9 @@ class addInnerClass extends MacroAnnotation: val showClass = ClassDef(showClassSym, parents, body = List(showMeDef)) val toStringDef = DefDef(toStringOverrideSym, _ => Some(Block(List(showClass), newShowCallShowMe))) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, toStringDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, toStringDef :: body) List(newClassDef) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-add-val/Macro_1.scala b/tests/run-macros/annot-mod-class-add-val/Macro_1.scala index fc0294dcb051..cf69949dd8ad 100644 --- a/tests/run-macros/annot-mod-class-add-val/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-val/Macro_1.scala @@ -6,11 +6,11 @@ import scala.collection.mutable @experimental class addMemoToString(msg: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val stringValSym = Symbol.newVal(cls, Symbol.freshName("string"), TypeRepr.of[String], Flags.Private, Symbol.noSymbol) val toStringMethType = Symbol.requiredMethod("java.lang.Object.toString").info @@ -19,9 +19,9 @@ class addMemoToString(msg: String) extends MacroAnnotation: val stringValDef = ValDef(stringValSym, Some(Literal(StringConstant(msg)))) val toStringDef = DefDef(toStringOverrideSym, _ => Some(Ref(stringValSym))) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, stringValDef :: toStringDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, stringValDef :: toStringDef :: body) List(newClassDef) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-add-var/Macro_1.scala b/tests/run-macros/annot-mod-class-add-var/Macro_1.scala index be38689613e7..0eb8592accbf 100644 --- a/tests/run-macros/annot-mod-class-add-var/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-add-var/Macro_1.scala @@ -6,11 +6,11 @@ import scala.collection.mutable @experimental class addCountToString(msg: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val countVarSym = Symbol.newVal(cls, Symbol.freshName("count"), TypeRepr.of[Int], Flags.Mutable | Flags.Private, Symbol.noSymbol) val toStringMethType = Symbol.requiredMethod("java.lang.Object.toString").info @@ -26,9 +26,9 @@ class addCountToString(msg: String) extends MacroAnnotation: ) )) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, countVarDef :: toStringDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, countVarDef :: toStringDef :: body) List(newClassDef) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-data/Macro_1.scala b/tests/run-macros/annot-mod-class-data/Macro_1.scala index a175eb274268..938b4d7d4bd6 100644 --- a/tests/run-macros/annot-mod-class-data/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-data/Macro_1.scala @@ -5,11 +5,11 @@ import scala.quoted.* @experimental class data extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect.* - tree match + definition match case ClassDef(className, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val constructorParameters = ctr.paramss.collect { case clause: TermParamClause => clause } if constructorParameters.size != 1 || constructorParameters.head.params.isEmpty then @@ -51,10 +51,10 @@ class data extends MacroAnnotation: val equalsOverrideDef = DefDef(equalsOverrideSym, equalsOverrideDefBody) val newBody = toStringDef :: hashCodeOverrideDef :: equalsOverrideDef :: body - List(ClassDef.copy(tree)(className, ctr, parents, self, newBody)) + List(ClassDef.copy(definition)(className, ctr, parents, self, newBody)) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) private def toStringExpr(className: String, thisFields: List[Expr[Any]])(using Quotes): Expr[String] = val fieldsSeq = Expr.ofSeq(thisFields) diff --git a/tests/run-macros/annot-mod-class-equals/Macro_1.scala b/tests/run-macros/annot-mod-class-equals/Macro_1.scala index 10184eada1e2..625598d3911e 100644 --- a/tests/run-macros/annot-mod-class-equals/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-equals/Macro_1.scala @@ -5,11 +5,11 @@ import scala.quoted.* @experimental class equals extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect.* - tree match + definition match case ClassDef(className, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val constructorParameters = ctr.paramss.collect { case clause: TermParamClause => clause } if constructorParameters.size != 1 || constructorParameters.head.params.isEmpty then @@ -42,10 +42,10 @@ class equals extends MacroAnnotation: val hashCodeOverrideDef = DefDef(hashCodeOverrideSym, _ => Some(Ref(hashSym))) val newBody = equalsOverrideDef :: hashVal :: hashCodeOverrideDef :: body - List(ClassDef.copy(tree)(className, ctr, parents, self, newBody)) + List(ClassDef.copy(definition)(className, ctr, parents, self, newBody)) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) private def equalsExpr[T: Type](that: Expr[Any], thisFields: List[Expr[Any]])(using Quotes): Expr[Boolean] = '{ diff --git a/tests/run-macros/annot-mod-class-mod-def/Macro_1.scala b/tests/run-macros/annot-mod-class-mod-def/Macro_1.scala index 7a73b0a773e9..9c28d7427f9c 100644 --- a/tests/run-macros/annot-mod-class-mod-def/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-mod-def/Macro_1.scala @@ -6,11 +6,11 @@ import scala.collection.mutable @experimental class modToString(msg: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val toStringSym = cls.methodMember("toString").head val newBody = body.span(_.symbol != toStringSym) match @@ -21,7 +21,7 @@ class modToString(msg: String) extends MacroAnnotation: report.error("toString was not defined") body - List(ClassDef.copy(tree)(name, ctr, parents, self, newBody)) + List(ClassDef.copy(definition)(name, ctr, parents, self, newBody)) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-mod-val/Macro_1.scala b/tests/run-macros/annot-mod-class-mod-val/Macro_1.scala index fda7b5f037d8..0d07a6bd2006 100644 --- a/tests/run-macros/annot-mod-class-mod-val/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-mod-val/Macro_1.scala @@ -6,11 +6,11 @@ import scala.collection.mutable @experimental class setValue(field: String, value: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val valSym = cls.fieldMember(field) val newBody = body.span(_.symbol != valSym) match @@ -21,7 +21,7 @@ class setValue(field: String, value: String) extends MacroAnnotation: report.error(s"`val $field` was not defined") body - List(ClassDef.copy(tree)(name, ctr, parents, self, newBody)) + List(ClassDef.copy(definition)(name, ctr, parents, self, newBody)) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-override-def/Macro_1.scala b/tests/run-macros/annot-mod-class-override-def/Macro_1.scala index e6d7bba79d54..2e9b9356d845 100644 --- a/tests/run-macros/annot-mod-class-override-def/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-override-def/Macro_1.scala @@ -6,19 +6,19 @@ import scala.collection.mutable @experimental class genToString(msg: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val toStringSym = Symbol.requiredMethod("java.lang.Object.toString") val toStringOverrideSym = Symbol.newMethod(cls, "toString", toStringSym.info, Flags.Override, Symbol.noSymbol) val toStringDef = DefDef(toStringOverrideSym, _ => Some(Literal(StringConstant(msg)))) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, toStringDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, toStringDef :: body) List(newClassDef) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-override-val/Macro_1.scala b/tests/run-macros/annot-mod-class-override-val/Macro_1.scala index d7409a649427..6ec02e349051 100644 --- a/tests/run-macros/annot-mod-class-override-val/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-override-val/Macro_1.scala @@ -6,18 +6,18 @@ import scala.collection.mutable @experimental class overrideField(field: String, value: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val overrideSym = Symbol.newVal(cls, field, TypeRepr.of[String], Flags.Override, Symbol.noSymbol) val valDef = ValDef(overrideSym, Some(Literal(StringConstant(value)))) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, valDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, valDef :: body) List(newClassDef) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-mod-class-unused-new-sym/Macro_1.scala b/tests/run-macros/annot-mod-class-unused-new-sym/Macro_1.scala index fbcb9049d947..6760714aaa5e 100644 --- a/tests/run-macros/annot-mod-class-unused-new-sym/Macro_1.scala +++ b/tests/run-macros/annot-mod-class-unused-new-sym/Macro_1.scala @@ -6,15 +6,15 @@ import scala.collection.mutable @experimental class newUnusedSymbol extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol val toStringMethType = Symbol.requiredMethod("java.lang.Object.toString").info val toStringOverrideSym = Symbol.newMethod(cls, "toString", toStringMethType, Flags.Override, Symbol.noSymbol) // Test that toStringOverrideSym is not accidentally entered in the class - List(tree) + List(definition) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/annot-result-order/Macro_1.scala b/tests/run-macros/annot-result-order/Macro_1.scala index c81641037b67..cb9121eb8d01 100644 --- a/tests/run-macros/annot-result-order/Macro_1.scala +++ b/tests/run-macros/annot-result-order/Macro_1.scala @@ -5,7 +5,7 @@ import scala.quoted._ @experimental class print(msg: String) extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ def printMsg(msg: String) = val valSym = Symbol.newVal(Symbol.spliceOwner, Symbol.freshName("print"), TypeRepr.of[Unit], Flags.Private, Symbol.noSymbol) @@ -13,4 +13,4 @@ class print(msg: String) extends MacroAnnotation: given Quotes = valSym.asQuotes '{ println(${Expr(msg)}) }.asTerm ValDef(valSym, Some(valRhs)) - List(printMsg(s"before: $msg"), tree, printMsg(s"after: $msg")) + List(printMsg(s"before: $msg"), definition, printMsg(s"after: $msg")) diff --git a/tests/run-macros/annot-simple-fib/Macro_1.scala b/tests/run-macros/annot-simple-fib/Macro_1.scala index e5852d5ce73c..f8a74663f775 100644 --- a/tests/run-macros/annot-simple-fib/Macro_1.scala +++ b/tests/run-macros/annot-simple-fib/Macro_1.scala @@ -6,9 +6,9 @@ import scala.collection.mutable.Map @experimental class memoize extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case DefDef(name, params, tpt, Some(fibTree)) => val cacheName = Symbol.freshName(name + "Cache") val cacheSymbol = Symbol.newVal(Symbol.spliceOwner, cacheName, TypeRepr.of[Map[Int, Int]], Flags.EmptyFlags, Symbol.noSymbol) @@ -17,7 +17,7 @@ class memoize extends MacroAnnotation { '{Map.empty[Int, Int]}.asTerm val cacheVal = ValDef(cacheSymbol, Some(cacheRhs)) val rhs = - given Quotes = tree.symbol.asQuotes + given Quotes = definition.symbol.asQuotes val fibCache = Ref(cacheSymbol).asExprOf[Map[Int, Int]] val n = Ref(params.head.params.head.symbol).asExprOf[Int] '{ @@ -28,6 +28,6 @@ class memoize extends MacroAnnotation { $fibCache($n) = res res }.asTerm - val newFib = DefDef.copy(tree)(name, params, tpt, Some(rhs)) + val newFib = DefDef.copy(definition)(name, params, tpt, Some(rhs)) List(cacheVal, newFib) } diff --git a/tests/run-macros/annot-unrollLast/Macro_1.scala b/tests/run-macros/annot-unrollLast/Macro_1.scala index e220811433e3..bcb2a94d5ac3 100644 --- a/tests/run-macros/annot-unrollLast/Macro_1.scala +++ b/tests/run-macros/annot-unrollLast/Macro_1.scala @@ -12,7 +12,7 @@ class unrollLast extends StaticAnnotation @experimental class unrollHelper extends MacroAnnotation { - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(tree: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ tree match case tree: DefDef => transformDefDef(tree) diff --git a/tests/run-macros/i18806/Macro_1.scala b/tests/run-macros/i18806/Macro_1.scala index 461080b67b95..06ab612ce416 100644 --- a/tests/run-macros/i18806/Macro_1.scala +++ b/tests/run-macros/i18806/Macro_1.scala @@ -3,11 +3,11 @@ import scala.quoted._ @experimental class gen1 extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(definition: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ - tree match + definition match case ClassDef(name, ctr, parents, self, body) => - val cls = tree.symbol + val cls = definition.symbol // val meth = cls.methodMember("foo").head // val fooTpe = cls.typeRef.memberType(meth) @@ -17,8 +17,8 @@ class gen1 extends MacroAnnotation: val fooDef = DefDef(fooOverrideSym, _ => Some(Literal(StringConstant("hi")))) - val newClassDef = ClassDef.copy(tree)(name, ctr, parents, self, fooDef :: body) + val newClassDef = ClassDef.copy(definition)(name, ctr, parents, self, fooDef :: body) List(newClassDef) case _ => report.error("Annotation only supports `class`") - List(tree) + List(definition) diff --git a/tests/run-macros/i19676/Macro_1.scala b/tests/run-macros/i19676/Macro_1.scala new file mode 100644 index 000000000000..d0f77255cbb9 --- /dev/null +++ b/tests/run-macros/i19676/Macro_1.scala @@ -0,0 +1,28 @@ +//> using options -experimental -Yno-experimental + +import scala.annotation.MacroAnnotation +import scala.quoted.* + +class companionToString(str: String) extends MacroAnnotation: + + def transform(using Quotes)( + definition: quotes.reflect.Definition, + companion: Option[quotes.reflect.Definition] + ): List[quotes.reflect.Definition] = + + import quotes.reflect.* + companion match + case Some(cls@ClassDef(name, ctr, parents, self, body)) => + val symbol = cls.symbol + val toStringSym = Symbol.requiredMethod("java.lang.Object.toString") + val toStringOverrideSym = Symbol.newMethod(symbol, "toString", toStringSym.info, Flags.Override, Symbol.noSymbol) + val toStringDef = DefDef(toStringOverrideSym, _ => Some(Literal(StringConstant(s"$name: $str")))) + val newCompanion = ClassDef.copy(cls)(name, ctr, parents, self, toStringDef :: body) + List(definition, newCompanion) + case Some(unexpected) => + report.error(s"Unexpected companion: ${unexpected.show}") + List(definition) + case None => + report.error("Companion is not available to transform") + List(definition) + end transform \ No newline at end of file diff --git a/tests/run-macros/i19676/Test_2.scala b/tests/run-macros/i19676/Test_2.scala new file mode 100644 index 000000000000..4110d3c7f482 --- /dev/null +++ b/tests/run-macros/i19676/Test_2.scala @@ -0,0 +1,36 @@ +//> using options -experimental -Yno-experimental + +@companionToString("transformed by class") +class InPackage + +@companionToString("transformed by object") +object InPackage + +val (cls: Any, obj: Any) = { + + @companionToString("transformed by class") + class InBlock + + @companionToString("transformed by object") + object InBlock + + (new InBlock, InBlock) +} + +object Wrapper { + + @companionToString("transformed by class") + class InInnerClass + + @companionToString("transformed by object") + object InInnerClass + +} + +@main def Test = + assert((new InPackage).toString() == "InPackage: transformed by object") + assert(InPackage.toString() == "InPackage$: transformed by class") + assert(cls.toString() == "InBlock: transformed by object") + assert(obj.toString() == "InBlock$: transformed by class") + assert((new Wrapper.InInnerClass).toString() == "InInnerClass: transformed by object") + assert(Wrapper.InInnerClass.toString() == "InInnerClass$: transformed by class") diff --git a/tests/run/quotes-add-erased/Macro_1.scala b/tests/run/quotes-add-erased/Macro_1.scala index 5b95051a3744..66ec1c3642d8 100644 --- a/tests/run/quotes-add-erased/Macro_1.scala +++ b/tests/run/quotes-add-erased/Macro_1.scala @@ -7,7 +7,7 @@ import scala.quoted._ class NewAnnotation extends scala.annotation.Annotation class erasedParamsMethod extends MacroAnnotation: - def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = + def transform(using Quotes)(tree: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = import quotes.reflect._ tree match case ClassDef(name, ctr, parents, self, body) =>