使用方法(字段=方法)为案例 class 生成伴生对象

Generate companion object for case class with methods (field = method)

使用 scala-macros

为案例 class 生成伴随对象

我试过的一些代码示例,它有效我可以获得元组列表(名称 -> 类型)但是如何在同一范围内生成对象?

  import c.universe._
  val tpe = weakTypeOf[T]

  val fields = tpe.decls.collectFirst {
    case m: MethodSymbol if m.isPrimaryConstructor => m
  } .get
    .paramLists
    .head

  val extractParams = fields.map { field =>
    val name = field.asTerm.name
    val fieldName = name.decodedName.toString
    val NullaryMethodType(fieldType) = tpe.decl(name).typeSignature

    c.Expr[List[(String, String)]](
      q"""
       ($fieldName, ${fieldType.toString})
      """
    )

是否可以对某些情况进行注释 class 并且生成的同伴在同一范围内可见?

// test case: defined a class with some fields
@GenerateCompanionWithFields
case class SomeCaseClass(i: Int, b: Byte, c: Char)

目标:

SomeCaseClass.i() // returns Int 
SomeCaseClass.b() // returns Byte
SomeCaseClass.c() // returns Char

您的代码似乎适用于 def macros. But if you want to generate companion you should use macro annotations

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox

object Macros {
  @compileTimeOnly("enable macro paradise")
  class GenerateCompanionWithFields extends StaticAnnotation {
    def macroTransform(annottees: Any*): Any = macro Macro.impl
  }

  object Macro {
    def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
      import c.universe._
      annottees match {
        case (cls @ q"$_ class $tpname[..$_] $_(...$paramss) extends { ..$_ } with ..$_ { $_ => ..$_ }") :: Nil =>

          val newMethods = paramss.flatten.map {
            case q"$_ val $tname: $tpt = $_" =>
              q"def $tname(): String = ${tpt.toString}"
          }

          q"""
             $cls

             object ${tpname.toTermName} {
               ..$newMethods
             }
           """
      }
    }
  }
}

import Macros._

object App {
  @GenerateCompanionWithFields
  case class SomeCaseClass(i: Int, b: Byte, c: Char)
}

//Warning:scalac: {
//  case class SomeCaseClass extends scala.Product with scala.Serializable {
//    <caseaccessor> <paramaccessor> val i: Int = _;
//    <caseaccessor> <paramaccessor> val b: Byte = _;
//    <caseaccessor> <paramaccessor> val c: Char = _;
//    def <init>(i: Int, b: Byte, c: Char) = {
//      super.<init>();
//      ()
//    }
//  };
//  object SomeCaseClass extends scala.AnyRef {
//    def <init>() = {
//      super.<init>();
//      ()
//    };
//    def i(): String = "Int";
//    def b(): String = "Byte";
//    def c(): String = "Char"
//  };
//  ()
//}