2016-10-26 7 views
1

JSONを一致するケースクラスに解析するマクロを書きました。マクロとプレイフレームを使用するとコンパイラがクラッシュする

def parse(jsonTree: JsValue): BaseType = macro parserImpl 

def parserImpl(c: blackbox.Context)(jsonTree: c.Tree) = { 
    import c.universe._ 
    val q"$json" = jsonTree 
    val cases = List("X", "Y").map { caseClassName => 
    val caseClass = c.parse(caseClassName) 
    val reader = c.parse(s"JSONHelp.${caseClassName}_reads") 
    val y = cq"""$caseClassName => (($json \ "config").validate[$caseClass]($reader)).get""" 
    println(showCode(y)) 
    y 
    }.toList 

    val r = 
    q""" 
    import play.api.libs.json._ 
    import JSONHelp._ 
    println($json) 
    ($json \ "type").as[String] match { case ..$cases } 
    """ 
    println(showCode(r)) 

    r 
} 

以下は、それが生成するコードである(最後printlnで印刷):

{ 

    import play.api.libs.json._; 

    import JSONHelp._; 

    println(NodeParser.this.json); 

    NodeParser.this.json.\("type").as[String] match { 

    case "X" => NodeParser.this.json.\("config").validate[X](JSONHelp.X_reads).get 

    case "Y" => NodeParser.this.json.\("config").validate[Y](JSONHelp.Y_reads).get 

    } 

} 

マクロ定義を含むサブプロジェクトのコンパイルが正常に動作します。私はマクロを使用して(SBT 0.13.11とScalaの2.11.8を使用して)プロジェクトをコンパイルするときしかし、私は次のエラーを取得する:

java.lang.NullPointerException 

at play.routes.compiler.RoutesCompiler$GeneratedSource$.unapply(RoutesCompiler.scala:37) 

at play.sbt.routes.RoutesCompiler$$anonfun$11$$anonfun$apply$2.isDefinedAt(RoutesCompiler.scala:180) 

at play.sbt.routes.RoutesCompiler$$anonfun$11$$anonfun$apply$2.isDefinedAt(RoutesCompiler.scala:179) 

at scala.Option.collect(Option.scala:250) 

at play.sbt.routes.RoutesCompiler$$anonfun$11.apply(RoutesCompiler.scala:179) 

at play.sbt.routes.RoutesCompiler$$anonfun$11.apply(RoutesCompiler.scala:178) 
+0

これは、マクロ生成コードにコンパイルエラーがある場合にのみ発生します。 – Mohit

答えて

0

私はユーザーではないんだけど、私は木をしたいようだ見ますソースファイルのある位置:

val routesPositionMapper: Position => Option[Position] = position => { 
    position.sourceFile collect { 
     case GeneratedSource(generatedSource) => { 

atPos(pos)(tree)を使用するのが一般的です。あなたは合成木のために入ってくるtree.posを仮定するかもしれません。

+0

あなたのコメントを理解できませんでした。 – Mohit

+0

スニペットはスタックトレースに基づいていました。ツリーは、通常、パーサによって割り当てられる位置を持ちます。ツリーを作成する場合は、手動で位置を割り当てる必要があります。 't.pos = c.macroApplication.pos'などとなります。ポジションはエラー報告のために重要です。ソースコードを検査するためにマクロによって使用されることがあります。 –

+0

https://github.com/sbt/sbt/issues/2766 – Mohit

関連する問題