tiran
tiran

Reputation: 2431

scala macro Unknown type error with java bean class creation

I created the following code snippet for use as an encode generator for scala type to java type.

object Macros {
  def encode[A <: Product, B](value:A):B = macro MacrosImpl.encode_impl[A, B]
}

class MacrosImpl(val c:Context) {
  import c.universe._
  def encode_impl[ScalaType: c.WeakTypeTag, JavaType: c.WeakTypeTag](value:c.Expr[ScalaType]) = {

    val scalaType: WeakTypeTag[ScalaType] = implicitly[WeakTypeTag[ScalaType]]

    val fields = scalaType.tpe.typeSymbol.companion.typeSignature.members.collectFirst {
      case method if method.name.toString == "apply" => method
    }.toList.flatMap(_.asMethod.paramLists.flatten).
      map{
      case s if s.name.toString == "id" => q"underlying.setId($value.$s.orNull)"
      case s => q"underlying.${c.universe.newTermName("set" + s.name.toString.capitalize) }($value.$s)"
    }

    val javaType: WeakTypeTag[JavaType] = implicitly[WeakTypeTag[JavaType]]

    q"""
       val underlying = new ${javaType.tpe}()
       ..$fields
       underlying
       """
  }
}

This compiles in macro project compile time just fine, when i try to use it. It throws an exception in using library project compilation.

private val x: IpDataEntry = IpDataEntry(None, "a", "a")
println(Macros.encode[IpDataEntry, Underlying](x)) //not comp


[error] Unknown type: <error>, <error> [class scala.reflect.internal.Types$ErrorType$, class scala.reflect.internal.Types$ErrorType$] TypeRef? false
[trace] Stack trace suppressed: run 'last web/compile:compile' for the full output.
[error] (web/compile:compile) scala.reflect.internal.FatalError: Unknown type: <error>, <error> [class scala.reflect.internal.Types$ErrorType$, class scala.reflect.internal.Types$ErrorType$] TypeRef? false
[error] Total time: 12 s, completed Jun 19, 2014 11:53:42 AM

I'm stuck here and I cannot find anything wrong in my code.

Scala version is 2.11.1.

Upvotes: 4

Views: 448

Answers (1)

tiran
tiran

Reputation: 2431

I found the solution by myself. in code block

q"underlying.setId($value.$s.orNull)"

$s is not a TermName. so I modified it as

q"underlying.setId($value.${c.universe.newTermName(s.name.toString)}.orNull)"

Anyway it is really useful if that error directs to the correct problem in the syntax tree. I waste about 2 days to find out the problem.

Upvotes: 1

Related Questions