如何正确匹配Scala 3宏注解中的TypeDef?

z9smfwbn  于 2023-10-18  发布在  Scala
关注(0)|答案(1)|浏览(122)

我创建了一个示例宏注解来测试我是否可以正确匹配case类TypeDef以便稍后修改它,但是它不匹配,尽管一切看起来都很好并且编译好了,下面是它的样子:

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)

我应用它的例子类:

@experimental @table
case class Person(firstName: String, lastName: String)

它总是运行第二条消息,这意味着我无法匹配TypeDef。
我错过了什么?是否需要进一步进口?
还尝试了tree.isInstanceOf[TypeDef]},这正如预期的那样返回true,这使得理解为什么匹配不起作用变得更加复杂。

px9o7tmv

px9o7tmv1#

如果你用Printer.TreeStructure.show(tree)检查树结构,你会看到Person是ClassDef。然后下面的代码将匹配第一个臂

@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)

如果在Person类中添加类型定义,则会找到TypeDef。
例如

@experimental @table
case class Hello(name: String, lastName: String) {
  type Item
}

TreeStructure.show输出

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")))))}

相关问题