1

Suppose i have some class with some methods


class Clz ... {

  def someMethod: Map[String, Long] = ... 

  def id: Long = 0L
}

i'm need to reuse someMethod and overwrite id i don't know why but it's throw Stackoverflow and also i'm need to do something with params/methods of Clz without returning the result

what i've tried:

object Macros {


    def impl(c: whitebox.Context)(annottees: c.Tree*): c.Tree = {
      import c.universe._

      annottees match {

        case (cls @ q"$_ class $tpname[..$_] $_(...$paramss) extends { ..$_ } with ..$_ { $_ => ..$stats }") :: Nil =>

          val someMethodM = stats
            .filter(case q"$_ def $methodName: $_ = $_" => methodName.toString == "someMethod")
            .map {
              case q"$_ def $_: $_ = $res" => res
            }

          q"""
             $cls

             object ClzCompanion {

               val someMethodsRef: Map[String, Int] = Map.apply(..$someMethodM)

               ..${
                  paramss
                    .flatten
                    .foreach {
                      case q"$_ val $nname: $tpt = $valuee" => 
                        // simply do something with valuee and nothing else
                        // "fire and forget"
                     }
                  }

               ..${
                  paramss
                    .flatten
                    .map {
                      case q"$_ val $nname: $tpt = $valuee" => 
                        // here logic, if this nname in someMethodsRef then
                        // someMethodsRef.find({ case (key, _) => key == nname) match {
                        //    case Some(_) => "def $nname: ($tpt, Int) = ... // new method with body
                        //    case None => do nothing...  
                     }
                  }

               }
           """
      }
    }
  }

how i can overwrite the id method at Clz?

and why it throws StackOverflow??

  • Can't reproduce Stackoverflow. Now your macro annotation generates object `ClzCompanion` near to annotated class (e.g. `Clz`). If you switch on `scalacOptions += "-Ymacro-debug-lite"` in `build.sbt` you'll see what code is generated. For example if you have `def someMethod: Map[String, Long] = Map("a" -> 1L, "b" -> 2L)` inside `@your_annotation class Clz` then inside `ClzCompanion` there will be `val someMethodsRef: Map[String, Int] = Map.apply(Map("a" -> 1L, "b" -> 2L))`. Obviously this can't compile. – Dmytro Mitin Nov 28 '19 at 19:58
  • What do you mean by overwriting method `id`? It's not clear what you're doing here `..${paramss.flatten.foreach ...` Hardly it should be `foreach`. Maybe `map`? Write your code before macro expansion and desired generated code after macro expansion. – Dmytro Mitin Nov 28 '19 at 20:02
  • @DmytroMitin the problem was "key == nname" - it's a function call, thats why my code threw a Stackoverflow . ${nname.toString} - is solution. – pureFPevangelist Nov 29 '19 at 18:44

0 Answers0