Временное решение для ошибки аннотации макросов Scala - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть аннотация макроса, которую я использую для добавления класса неявного типа в метод-компаньон.

@MyMacro case class MyClass[T](a: String, b: Int, t: T)

Большую часть времени он работает, как ожидалось, но он ломается, когда я использую обозначение ограничения типа:

@MyMacro case class MyClass[T: TypeClass](a: String, b: Int, t: T)
// private[this] not allowed for case class parameters

Эта ошибка была описана на SO , а - как ошибка .

Дело в том, что макросы (v1) больше не поддерживаются, поэтому я не могу ожидать, что это будет исправлено.

Итак, что я хотел знать: могу ли я исправить это самостоятельно в макросе? Это изменение сделано в AST таким образом, чтобы я мог как-то отменить его? Я хотел бы попробовать восстановить его внутри макроса, вместо того, чтобы заставлять всех пользователей переписывать свой код в ...(implicit tc: TypeClass[T]).

1 Ответ

0 голосов
/ 07 ноября 2018
class AnnotationType() extends scala.annotation.StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro AnnotationTypeImpl.impl
}

class AnnotationTypeImpl(val c: blackbox.Context) {

  import c.universe._

  def impl(annottees: Tree*): Tree = {

    val tree = annottees.head.asInstanceOf[ClassDef]

    val newTree = tree match {
      case ClassDef(mods, name, tparams, impl@Template(parents, self, body)) =>
        val newBody = body.map {
          case ValDef(mods, name, tpt, rhs) =>
            // look here
            // the flag of `private[this]` is Flag.PRIVATE | Flag.LOCAL
            // the flag of `private` is Flag.PRIVATE
            // drop Flag.LOCAL in Modifiers.flags ,  it will change `private[this]` to `private`
            val newMods =
              if(mods.hasFlag(Flag.IMPLICIT))
                mods.asInstanceOf[scala.reflect.internal.Trees#Modifiers].&~(Flag.LOCAL.asInstanceOf[Long]).&~(Flag.CASEACCESSOR.asInstanceOf[Long]).asInstanceOf[Modifiers]
              else
                mods
            ValDef(newMods, name, tpt, rhs)

          case e => e
        }
        ClassDef(mods, name, tparams, Template(parents, self, newBody))
    }
    println(show(tree))
    println(show(newTree))

    q"..${newTree +: annottees.tail}"
  }
}

// тест

@AnnotationType()
case class AnnotationTypeTest[T: Option](a: T){
  def option = implicitly[Option[T]]
}

object AnnotationTypeTest {
  def main(args: Array[String]): Unit = {
    implicit val x = Option(1)

    println(AnnotationTypeTest(100))
    println(AnnotationTypeTest(100).option)
    println(AnnotationTypeTest(100).copy(a =2222))
    println(AnnotationTypeTest(100).copy(a =2222)(Some(999)).option)
  }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...