in scio-google-cloud-platform/src/main/scala/com/spotify/scio/bigquery/types/TypeProvider.scala [169:251]
private def getTableDescription(
c: blackbox.Context
)(cd: c.universe.ClassDef): List[c.universe.Tree] =
cd.mods.annotations
.filter(_.children.head.toString.matches("^new description$"))
.map(_.children.tail.head)
@nowarn("msg=match may not be exhaustive")
def toTableImpl(c: blackbox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
import c.universe._
checkMacroEnclosed(c)
val provider: OverrideTypeProvider = OverrideTypeProviderFinder.getProvider
val (r, caseClassTree, name) = annottees.map(_.tree) match {
case (clazzDef @ q"$mods class $cName[..$_] $_(..$fields) extends { ..$_ } with ..$parents { $_ => ..$body }") :: tail
if mods.asInstanceOf[Modifiers].hasFlag(Flag.CASE) =>
if (parents.map(_.toString).toSet != Set("scala.Product", "scala.Serializable")) {
c.abort(c.enclosingPosition, s"Invalid annotation, don't extend the case class $clazzDef")
}
val desc = getTableDescription(c)(clazzDef.asInstanceOf[ClassDef])
val defSchema =
q"override def schema: ${p(c, GModel)}.TableSchema = ${p(c, SType)}.schemaOf[$cName]"
val defAvroSchema =
q"override def avroSchema: org.apache.avro.Schema = ${p(c, SType)}.avroSchemaOf[$cName]"
val defTblDesc =
desc.headOption.map(d => q"override def tableDescription: _root_.java.lang.String = $d")
val defToPrettyString =
q"override def toPrettyString(indent: Int = 0): String = ${p(c, s"$SBQ.types.SchemaUtil")}.toPrettyString(this.schema, ${cName.toString}, indent)"
val defSelectedFields =
q"def selectedFields: _root_.scala.List[_root_.java.lang.String] = ${fields.map { case ValDef(_, fname, _, _) =>
fname.toString
}.toList}"
val fnTrait =
tq"${TypeName(s"Function${fields.size}")}[..${fields.map(_.children.head)}, $cName]"
val traits = (if (fields.size <= 22) Seq(fnTrait) else Seq()) ++ defTblDesc
.map(_ => tq"${p(c, SType)}.HasTableDescription")
val taggedFields = fields.map { case ValDef(m, n, tpt, rhs) =>
provider.initializeToTable(c)(m, n, tpt)
c.universe.ValDef(
c.universe.Modifiers(m.flags, m.privateWithin, m.annotations),
n,
tq"$tpt @${typeOf[BigQueryTag]}",
rhs
)
}
val caseClassTree =
q"""${caseClass(c)(mods, cName, taggedFields, body)}"""
val maybeCompanion = tail.headOption
(
q"""$caseClassTree
${companion(c)(
cName,
traits,
Seq(defSchema, defAvroSchema, defToPrettyString, defSelectedFields) ++ defTblDesc,
taggedFields.asInstanceOf[Seq[Tree]].size,
maybeCompanion
)}
""",
caseClassTree,
cName.toString
)
case t =>
val error =
s"""Invalid annotation:
|
|Refer to https://spotify.github.io/scio/api/com/spotify/scio/bigquery/types/BigQueryType$$$$toTable.html
|for details on how to use `@BigQueryType.toTable`
|
|>> $t
""".stripMargin
c.abort(c.enclosingPosition, error)
}
debug(c)(s"TypeProvider.toTableImpl", r)
if (shouldDumpClassesForPlugin) {
dumpCodeForScalaPlugin(c)(Seq.empty, caseClassTree, name)
}
c.Expr[Any](r)
}