2017-12-26 2 views
0

Ich möchte eine Methode 'toCSV' injizieren, um eine Klasse in CSV-String zu analysieren. Meine Funktion zwei paramters nehmen:Lifting String mit Scalameta

  • Seq [String]: header
  • Seq [Seq [Alle]]: Felder

Mein Makro:

class model extends scala.annotation.StaticAnnotation { 

    inline def apply(defn: Any): Any = meta { 
    defn match { 
     case cls @ Defn.Class(_, _, _, Ctor.Primary(_, _, paramss), template) => 

     def createToCSV(paramss: Seq[Seq[Term.Param]]): Defn.Def = { 

      val names = paramss.flatten.map(param => param.name.syntax) 
      val fields = paramss.map(_.map(param => Term.Name(param.name.value))) 

      q"""def toCSV = 
      CSVTools.toCSV(Seq(...$names), Seq(Seq(...$fields)))""" 
     } 

     val toCSVImpl = createToCSV(paramss) 

     val templateStats: Seq[Stat] = toCSVImpl +: template.stats.getOrElse(Nil) 
     cls.copy(templ = template.copy(stats = Some(templateStats))) 
     case _ => 
     println(defn.structure) 
     abort("@model must annotate a class.") 
    } 
    } 
} 

Die Variable Begriff ist a Seq [String] und die Quasiquotes-Syntax akzeptieren nur einen Term. daher unterhalb der Fehler aufgetreten ist:

[error] /home/xxxxx/intellij/workspace/heroes-scala-meta/macros/src/main/scala/examples/model.scala:18: type mismatch when unquoting; 
[error] found : scala.collection.immutable.Seq[String] 
[error] required: scala.collection.immutable.Seq[scala.collection.immutable.Seq[scala.meta.Term.Arg]] 
[error]    CSVTools.toCSV(Seq(...$names), Seq(Seq(...$fields)))""" 
[error]         ^
[error] one error found 
[error] (macros/compile:compileIncremental) Compilation failed 

Haben Sie eine Lösung?

Vielen Dank im Voraus,

Antwort

1

Dies ist wahrscheinlich ein bisschen hacky aber es scheint zu funktionieren: explizit Ihre names zu Stringliterale Karte

class model extends scala.annotation.StaticAnnotation { 

    inline def apply(defn: Any): Any = meta { 
    defn match { 
     case [email protected](_, _, _, Ctor.Primary(_, _, paramss), template) => 

     def createToCSV(paramss: Seq[Seq[Term.Param]]): Defn.Def = { 

      val names: Seq[String] = paramss.flatten.map(param => param.name.syntax) 
      val fields = paramss.map(_.map(param => Term.Name(param.name.value))) 

      val nameLiterals: Seq[Lit.String] = names.map(n => q"$n".asInstanceOf[Lit.String]) 

      q"""def toCSV = 
       CSVTools.toCSV(scala.collection.immutable.Seq(..$nameLiterals), 
          scala.collection.immutable.Seq(scala.collection.immutable.Seq(...$fields)))""" 
     } 

     val toCSVImpl = createToCSV(paramss) 

     val templateStats: Seq[Stat] = toCSVImpl +: template.stats.getOrElse(Nil) 
     cls.copy(templ = template.copy(stats = Some(templateStats))) 
     case _ => 
     println(defn.structure) 
     abort("@model must annotate a class.") 
    } 
    } 
} 
+0

das funktioniert, danke! – user2931656

Verwandte Themen