Code generated with scalameta is not recognized by intellij

348 Views Asked by At

I'm trying to create a scalameta annotation, that will define a new case class inside of an existing object.

my goal is to transform:

object MyObj {
  case class A()
}

into:

object MyObj {
  case class A()
  case class B(b: Int, bb: Int)
}

for that I created the following annotation:

import scala.annotation.StaticAnnotation
import scala.meta._

class schema extends StaticAnnotation {
  inline def apply(defn: Any): Any = meta {
    val q"..$mods object $ename extends $template" = defn

    val generatedClass: Defn.Class =
      q"""
         case class B(b: Int, bb: Int)
       """

    //the stats that were defined in the annotated object
    val existingStats: scala.collection.immutable.Seq[Stat] = template.stats.get

    //new stats
    val stats = Some(existingStats :+ generatedClass)

    //the new template
    val newT = template.copy(stats=stats)

    val res =
      q"""
         ..$mods object $ename extends $newT
       """

    println("============== result ==============")
    println("res: " +res)
    println("====================================")
    res
  }
}

and this main class to test it:

object Main {

  def main(args: Array[String]): Unit = {
    println("Hello")

    val b = new MyObj.B(2,22)
    val q = MyObj.A()
    println(b)

  }
}


@schema
object MyObj {
  case class A()
}

When I compile and and run the main class, the code behaves as expected.
during compile it prints:

============== result ==============
res: object MyObj {
  case class A()
  case class B(b: Int, bb: Int)
}
====================================

and after running the code:

Hello
B(2,22)

My problem is when I try to work with this code with intellij.
The code compiles and run from intellij, but the new class B can't be recognized, and therefore non of the code completion and hints don't work

enter image description here

I'm using the latest intellij and scala plugin


I've uploaded the full project to git: https://github.com/lev112/scalameta_intellij/tree/master

This is the first time I'm trying to use scalameta, and I'm trying to understand if it's a bug in intellij, or am I doing something wrong

1

There are 1 best solutions below

0
On

Just like with old-style macros, the scalameta code needs to be defined in a separate compilation unit so that they get compiled first and can then be invoked while compiling the other sources.

Thanks to https://www.michaelpollmeier.com/2016/12/01/scalameta-code-generation-tutorial