Ошибка компиляции подтверждается в момент обращения к typeSignature определенного символа при раскрытии макроса - PullRequest
0 голосов
/ 04 июля 2019

Мне пришлось посмотреть на конкретные объявления в макросе и изучить их индивидуально. Многие такие ошибки возникали при попытке проверить объявление потока akka.

def getType(symbol: Symbol): Type = {
  symbol.typeSignature
}
[error] error while loading SmallSortedMap$Entry, class file '/Users/xxx/.ivy2/cache/com.typesafe.akka/akka-protobuf_2.13/jars/akka-protobuf_2.13-2.5.23.jar(akka/protobuf/SmallSortedMap$Entry.class)' is broken
[error] (class java.util.NoSuchElementException/key not found: K)

Таким образом, кажется, что возникает ошибка при доступе к типу Sygnature для конкретного символа.

Я хочу проигнорировать это, спрятать и успешно скомпилировать

def getType(symbol: Symbol): Option[Type] = {
  Try {
    symbol.typeSignature
  }.getOrElse(None) // Can not capture
}

Однако, похоже, что "класс сломан" не может быть пойман "Попробовать". Например, пакеты с этим символом исключаются как черные списки. В результате при каждом добавлении зависимости может происходить сложное обслуживание.

  if (symbol.isNotBroken) {
    symbol.typeSignature
  }

Есть ли способ решить этот путь?






Попробуйте

Я пробовал typeCheck.

implicit class RichVectorSymbol(value: Vector[Symbol]) {
    def accessible: Vector[Symbol] = {
      value.flatMap { x =>
        scala.util.Try {
          print(s"typecheck ${x.fullName} ")
          c.typecheck(q"${c.parse(x.fullName)}", silent = true)
        } match {
          case Success(r) if r.nonEmpty =>
            println("Success")
            Some(r.symbol)
          case Failure(e) =>
            println("Fail")
            c.warning(c.enclosingPosition, e.getMessage)
            None
          case _ =>
            println("Empty")
            None
        }
      }
    }
  }

в результате.

// Success case
typecheck akka.event.jul.Logger Success
typecheck akka.io.dns.CachePolicy Success
typecheck akka.io.dns.DnsSettings Success

// Fail case
typecheck com.fasterxml.jackson.databind.ObjectMapper$2 [error] error while loading ObjectMapper$2, class file '/Users/xxxxx/.ivy2/cache/com.fasterxml.jackson.core/jackson-databind/bundles/jackson-databind-2.9.8.jar(com/fasterxml/jackson/databind/ObjectMapper$2.class)' is broken
[error] (class java.util.NoSuchElementException/key not found: T)
Empty
typecheck akka.protobuf.SmallSortedMap$Entry [error] error while loading SmallSortedMap$Entry, class file '/Users/xxxxx/.ivy2/cache/com.typesafe.akka/akka-protobuf_2.13/jars/akka-protobuf_2.13-2.5.23.jar(akka/protobuf/SmallSortedMap$Entry.class)' is broken
[error] (class java.util.NoSuchElementException/key not found: K)
Empty

Вот так я был вынужден скомпилировать ошибку. Образец здесь. https://github.com/giiita/scaladia/blob/master/scaladia-macro/src/main/scala/com/phylage/scaladia/internal/AutoDIExtractor.scala






Debugging

После прочтения исходного кода scala я выкинул изнутри понятное IOException, но не смог его уловить, поэтому на всякий случай сообщил о проблеме https://github.com/scala/bug/issues/11611

1 Ответ

1 голос
/ 04 июля 2019

В макросе вы можете попробовать

c.typecheck(q"${... some tree ...}", silent = true)

Если дерево не проверяет тип, это возвращает пустое дерево.


Вроде бы знак доллара в akka.protobuf.SmallSortedMap$Entry.Если мы заменим $ на # или ., то ошибка class file is broken изменится на class SmallSortedMap in package protobuf cannot be accessed in package akka.protobuf, это потому, что SmallSortedMap имеет доступ к частному пакету (по умолчанию Java).

Мне удалось отловить ошибку, когда я передаю тип в качестве строкового параметра в макрос и использую # или . вместо $.

  def foo[T]: Unit = macro fooImpl[T]

  def fooImpl[T: c.WeakTypeTag](c: blackbox.Context): c.Tree = {
    import c.universe._
    try {
      println(weakTypeOf[T].typeSymbol.typeSignature)
    } catch {
      case ex: Throwable => println(ex)
    }
    q"()"
  }

  def foo1(tpe: String): Unit = macro foo1Impl

  def foo1Impl(c: blackbox.Context)(tpe: c.Tree): c.Tree = {
    import c.universe._
    val q"${tpeStr: String}" = tpe
    try {
      println(c.typecheck(c.parse(s"val ${c.freshName()}: $tpeStr = ???")))
//      println(c.typecheck(c.parse(tpeStr), mode = c.TYPEmode))
//      println(c.typecheck(c.parse(tpeStr), mode = c.TYPEmode).symbol.companion.typeSignature)
//      println(c.typecheck(c.parse(tpeStr), mode = c.TYPEmode).tpe.typeSymbol.typeSignature)
//      println(c.typecheck(c.parse(tpeStr), mode = c.TYPEmode).tpe)
    } catch {
      case ex: Throwable => println(ex)
    }
    q"()"
  }

  foo[Int]
//  foo[akka.protobuf.SmallSortedMap$Entry]//Error:scalac: error while loading SmallSortedMap$Entry, class file '.ivy2/cache/com.typesafe.akka/akka-protobuf_2.13/jars/akka-protobuf_2.13-2.5.23.jar(akka/protobuf/SmallSortedMap$Entry.class)' is broken(class java.util.NoSuchElementException/key not found: K)
//  foo[akka.protobuf.SmallSortedMap#Entry]//Error: class SmallSortedMap in package protobuf cannot be accessed in package akka.protobuf
//  foo[akka.protobuf.SmallSortedMap.Entry]//Error:class SmallSortedMap in package protobuf cannot be accessed in package akka.protobuf

//  foo1("Int")
//  foo1("akka.protobuf.SmallSortedMap$Entry")//Error:scalac: error while loading SmallSortedMap$Entry, class file '.ivy2/cache/com.typesafe.akka/akka-protobuf_2.13/jars/akka-protobuf_2.13-2.5.23.jar(akka/protobuf/SmallSortedMap$Entry.class)' is broken (class java.util.NoSuchElementException/key not found: K)
  foo1("akka.protobuf.SmallSortedMap#Entry")//Warning:scalac: scala.reflect.macros.TypecheckException: class SmallSortedMap in package protobuf cannot be accessed in package akka.protobuf
  foo1("akka.protobuf.SmallSortedMap.Entry")//Warning:scalac: scala.reflect.macros.TypecheckException: class SmallSortedMap in package protobuf cannot be accessed in package akka.protobuf

В противном случае при вызове foo[... SomeType ...], SomeType проверяется перед проверкой макроса foo.

https://stackoverflow.com/a/56754290/5249621

http://www.scala -archive.org / Expand-macros-before-typechecking-its-аргументы деревьев-td4641188.html

...