Создать сопутствующий объект для класса дела с помощью методов (field = method)

Создать сопутствующий объект для case-класса с помощью макросов scala

некоторый пример кода, который я пробовал, он работает, я могу получить список кортежей (имя -> тип), но как создать объект в той же области видимости?

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

Можно ли аннотировать некоторый класс дел и созданный компаньон сделать видимым в той же области видимости?

// 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

1 ответ

Ваш код, похоже, предназначен для макросов def. Но если вы хотите создать компаньон, вы должны использовать макро-аннотации

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"
//  };
//  ()
//}

автоматически генерировать объект case для класса case

Другие вопросы по тегам