3

我正在尝试创建一个 scalameta 注释,它将在现有对象中定义一个新的案例类。

我的目标是改造:

object MyObj {
  case class A()
}

进入:

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

为此,我创建了以下注释:

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
  }
}

和这个主要的类来测试它:

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()
}

当我编译并运行主类时,代码的行为符合预期。
在编译期间它打印:

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

并在运行代码后:

Hello
B(2,22)

我的问题是当我尝试使用 intellij 使用此代码时。
代码从 intellij 编译和运行,但新类B无法识别,因此代码完成和提示都不起作用

在此处输入图像描述

我正在使用最新的 intellij 和 scala 插件


我已将完整项目上传到 git: https ://github.com/lev112/scalameta_intellij/tree/master

这是我第一次尝试使用 scalameta,我试图了解它是否是 intellij 中的错误,或者我做错了什么

4

1 回答 1

1

就像旧式宏一样,scalameta 代码需要在单独的编译单元中定义,以便首先编译它们,然后在编译其他源代码时可以调用它们。

感谢https://www.michaelpollmeier.com/2016/12/01/scalameta-code-generation-tutorial

于 2018-08-12T16:35:35.097 回答