2016-10-26 6 views
1

일치하는 사례 클래스로 JSON을 구문 분석하는 매크로를 작성했습니다.매크로 및 재생 프레임 워크를 사용할 때 컴파일러가 작동을 멈 춥니 다

{ 

    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 

    } 

} 

매크로 정의를 포함하는 서브 프로젝트의 컴파일이 잘 작동 :

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 인쇄)가 생성하는 코드이다. 하지만 매크로를 사용하여 (SBT 0.13.11 및 스칼라 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