I created an example macro annotation to test if I can properly match a case class TypeDef to later modify it, but it does not match, though all seems fine and compiles, heres how it looks:
import scala.annotation.{MacroAnnotation, experimental}
import scala.quoted.*
object Macros:
@experimental
class table extends MacroAnnotation:
def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] =
import quotes.reflect.*
tree match
case td @ TypeDef(_, _) =>
report.error(s"from macro annotation1 ${td.symbol}")
List(tree)
case _ =>
report.error(s"from macro annotation2 $tree")
List(tree)
Example case class where I applied it:
@experimental @table
case class Person(firstName: String, lastName: String)
It always runs the second message meaning I wasn't able to match the TypeDef.
What am I missing? Any further imports needed?
Also tried tree.isInstanceOf[TypeDef]}
and this returns true as expected, making it even more complicated to understand why the match did not work.
If you check tree structure with Printer.TreeStructure.show(tree)
you will see that Person is ClassDef. Then following code will match on first arm
@experimental class table extends MacroAnnotation:
override def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] =
import quotes.reflect.*
tree match
case td @ ClassDef(className, _, _, _, _)=>
report.error(s"from macro annotation1 ${className}")
List(tree)
case _ =>
report.error(s"from macro annotation2 $tree")
List(tree)
A TypeDef will be found if you add a type definition inside yours Person
class.
Example
@experimental @table
case class Hello(name: String, lastName: String) {
type Item
}
TreeStructure.show output
ClassDef("Hello", DefDef("<init>", List(TermParamClause(List(ValDef("name", TypeIdent("String"), None), ValDef("lastName", TypeIdent("String"), None)))), Inferred(), None), List(Apply(Select(New(Inferred()), "<init>"), Nil), TypeSelect(Select(Ident("_root_"), "scala"), "Product"), TypeSelect(Select(Ident("_root_"), "scala"), "Serializable")), None, List(DefDef("hashCode", List(TermParamClause(Nil)), Inferred(), Some(Apply(Ident("_hashCode"), List(This(Some("Hello")))))), DefDef("equals", List(TermParamClause(List(ValDef("x$0", Inferred(), None)))), Inferred(), Some(Apply(Select(Apply(Select(This(Some("Hello")), "eq"), List(TypeApply(Select(Ident("x$0"), "$asInstanceOf$"), List(Inferred())))), "||"), List(Match(Ident("x$0"), List(CaseDef(Bind("x$0", Typed(Wildcard(), Inferred())), None, Apply(Select(Apply(Select(Apply(Select(Select(This(Some("Hello")), "name"), "=="), List(Select(Ident("x$0"), "name"))), "&&"), List(Apply(Select(Select(This(Some("Hello")), "lastName"), "=="), List(Select(Ident("x$0"), "lastName"))))), "&&"), List(Apply(Select(Ident("x$0"), "canEqual"), List(This(Some("Hello"))))))), CaseDef(Wildcard(), None, Literal(BooleanConstant(false))))))))), DefDef("toString", List(TermParamClause(Nil)), Inferred(), Some(Apply(Ident("_toString"), List(This(Some("Hello")))))), DefDef("canEqual", List(TermParamClause(List(ValDef("that", Inferred(), None)))), Inferred(), Some(TypeApply(Select(Ident("that"), "isInstanceOf"), List(Inferred())))), DefDef("productArity", Nil, Inferred(), Some(Literal(IntConstant(2)))), DefDef("productPrefix", Nil, Inferred(), Some(Literal(StringConstant("Hello")))), DefDef("productElement", List(TermParamClause(List(ValDef("n", Inferred(), None)))), Inferred(), Some(Match(Ident("n"), List(CaseDef(Literal(IntConstant(0)), None, Select(This(Some("Hello")), "_1")), CaseDef(Literal(IntConstant(1)), None, Select(This(Some("Hello")), "_2")), CaseDef(Wildcard(), None, Apply(Ident("throw"), List(Apply(Select(New(Inferred()), "<init>"), List(Apply(Select(Ident("n"), "toString"), Nil)))))))))), DefDef("productElementName", List(TermParamClause(List(ValDef("n", Inferred(), None)))), Inferred(), Some(Match(Ident("n"), List(CaseDef(Literal(IntConstant(0)), None, Literal(StringConstant("name"))), CaseDef(Literal(IntConstant(1)), None, Literal(StringConstant("lastName"))), CaseDef(Wildcard(), None, Apply(Ident("throw"), List(Apply(Select(New(Inferred()), "<init>"), List(Apply(Select(Ident("n"), "toString"), Nil)))))))))), ValDef("name", Inferred(), None), ValDef("lastName", Inferred(), None), TypeDef("Item", TypeBoundsTree(Inferred(), Inferred())), DefDef("copy", List(TermParamClause(List(ValDef("name", Inferred(), None), ValDef("lastName", Inferred(), None)))), Inferred(), Some(Apply(Select(New(Inferred()), "<init>"), List(Ident("name"), Ident("lastName"))))), DefDef("copy$default$1", Nil, Inferred(), Some(Ident("name"))), DefDef("copy$default$2", Nil, Inferred(), Some(Ident("lastName"))), DefDef("_1", Nil, Inferred(), Some(Select(This(None), "name"))), DefDef("_2", Nil, Inferred(), Some(Select(This(None), "lastName")))))}