0

I would like to use macro to generate a setter for case classes. e.g:

case class Person(name: String, age: Int)

Macro.mkSetter[Person, String]("name") : Person => String => Person

I tried the following implementation but I keep getting the following

error: scala: Error: Unknown source file: embeddedFile--QuasiquoteCompat.scala@6....

(I am using scala 2.10.3 with macro-paradise 2.0.0-SNAPSHOT)

object Macro {

  def mkSetter[A, B](fieldName: String): (A,B) => A = macro mkSetter_impl[A,B]

  def mkSetter_impl[A: c.WeakTypeTag, B: c.WeakTypeTag](c : Context)(fieldName: c.Expr[String]): c.Expr[(A,B) => A] = {
    import c.universe._
    val (aTpe, bTpe) =  (weakTypeOf[A], weakTypeOf[B])

    val constructor = aTpe.declarations.collectFirst {
      case m: MethodSymbol if m.isPrimaryConstructor => m
    }.getOrElse(c.abort(c.enclosingPosition, s"Cannot find constructor in ${weakTypeOf[A]}"))

    val field = constructor.paramss.head.find(
      _.name.decoded == fieldName.toString()
    ).getOrElse(c.abort(c.enclosingPosition, s"Cannot find constructor field named in $fieldName"))

    c.Expr[(A,B) => A](q"{(a: $aTpe, b: $bTpe) => a.copy(${field.name} = b)}")
  }
} 

I do realise that _.name.decoded == fieldName.toString() is not correct way to check method name (even if _.name.decoded == "name" seems to be ok)

Bonus point: generalise macro with varags parameters for parameters with same type, e.g.

 def mkSetter[A, B](fieldNames: String*): A => B => B ... => A = macro mkSetter_impl[A,B]

Thank you!

4
  • 1
    Could you provide more details about your environment, e.g. post a project at github? The issue you're facing seems to be unrelated to the macro that you're trying to write. I've been able to run it successfully with just a couple of minor changes. Commented Jan 21, 2014 at 9:41
  • Thank you @EugeneBurmako. Here is the project I am working on. Commented Jan 21, 2014 at 18:33
  • sbt compile and sbt test are both okay. Do I need to do something special to reproduce the issue? Commented Jan 22, 2014 at 13:35
  • I added some macro tests that passes with sbt. However, I get the same error than before with intellij (Community edition v 13.0.1) when I try to run the same tests. Commented Jan 22, 2014 at 23:31

1 Answer 1

1

Seems to be caused by https://github.com/scalamacros/paradise/issues/11. This week I planned to fix that issue, so it should be fine soon. You could subscribe to updates at scalamacros.org (http://scalamacros.org/news/rss.xml) or follow me on Twitter to get notified when the fix is deployed.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.