Ошибка при доступе к классу, который не имеет доступа к информации о типе - PullRequest
0 голосов
/ 31 марта 2020

Есть некоторые классы в библиотеке, которые имеют ИМПОРТ, который не может быть решен. Например, org.scalatest.tools.Framework в ScalaTest.

Если я добавлю scalatest в качестве зависимой библиотеки, она будет добавлена ​​в путь к классам теста, но этот импорт не будет разрешен в обычном пути к классам теста. В тестовом пути к классам нет SBT-модуля.

import sbt.testing.{Event => SbtEvent, Framework => SbtFramework, Runner => SbtRunner, Status => SbtStatus, _}

Мне нужно сканировать классы в соответствии с указанным c макетом пакета и искать классы с указанными c функциями.

def collectXxx(targets: List[c.Symbol]) {
  targets.filter { x =>
    {
      x.isModule || (
        x.isClass &&
          !x.isAbstract &&
          x.asClass.primaryConstructor.isMethod
    } && x.typeSignature.baseClasses.contains(XxxTag.typeSymbol)
  }
}

Это отфильтрует символы, которые являются объектом / классом и наследуются от Xxx. Это будет работать в большинстве случаев, но если в целях есть класс, который не может быть скомпилирован как есть, например, scalatest, то ошибки компилятора не избежать. В момент обращения к baseClasses состояние развертывания макроса устанавливается на глобальную ошибку.

[error] <macro>:1:26: Symbol 'type sbt.testing.Framework' is missing from the classpath.
[error] This symbol is required by 'class org.scalatest.tools.Framework'.
[error] Make sure that type Framework is in your classpath and check for conflicting dependencies with `-Ylog-classpath`.
[error] A full rebuild may help if 'Framework.class' was compiled against an incompatible version of sbt.testing.
[error] type `fresh$macro$612` = org.scalatest.tools.Framework
[error]                          ^

Если вы посмотрите на трассировку стека в режиме отладки, я установил global_error, когда получил доступ к каждому свойству StubClassSymbol.

java.lang.Throwable
    at scala.reflect.internal.Symbols$StubSymbol.fail(Symbols.scala:3552)
    at scala.reflect.internal.Symbols$StubSymbol.info(Symbols.scala:3563)
    at scala.reflect.internal.Symbols$StubSymbol.info$(Symbols.scala:3563)
    at scala.reflect.internal.Symbols$StubClassSymbol.info(Symbols.scala:3567)
  | => cat scala.reflect.internal.Symbols$StubClassSymbol.info(Symbols.scala:3567)
    at scala.reflect.internal.Types$TypeRef.baseClasses(Types.scala:2593)
    at scala.reflect.internal.Types.computeBaseClasses(Types.scala:1703)
    at scala.reflect.internal.Types.computeBaseClasses$(Types.scala:1680)
    at scala.reflect.internal.SymbolTable.computeBaseClasses(SymbolTable.scala:28)
    at scala.reflect.internal.Types.$anonfun$defineBaseClassesOfCompoundType$2(Types.scala:1781)
    at scala.reflect.internal.Types$CompoundType.memo(Types.scala:1651)
    at scala.reflect.internal.Types.defineBaseClassesOfCompoundType(Types.scala:1781)
    at scala.reflect.internal.Types.defineBaseClassesOfCompoundType$(Types.scala:1773)
    at scala.reflect.internal.SymbolTable.defineBaseClassesOfCompoundType(SymbolTable.scala:28)
    at scala.reflect.internal.Types$CompoundType.baseClasses(Types.scala:1634)
    at refuel.internal.AutoDIExtractor.$anonfun$recursivePackageExplore$3(AutoDIExtractor.scala:119)

Я думал о способе обойти это. Возможно, когда не удается разрешить импорт, этот TypeSymbol становится StubClassSymbol. Поэтому я проанализировал структуру Symbol, в которой произошла ошибка, и добавил условие для ее фильтрации, если был найден StubClassSymbol. И этот сработал.

!x.typeSignature.asInstanceOf[ClassInfoTypeApi].parents.exists { pr =>
  pr.typeSymbol.isClass && 
  pr.typeSymbol.asClass.isInstanceOf[scala.reflect.internal.Symbols#StubClassSymbol]
}

Но я думаю, что это действительно настойчиво. Есть ли другой способ обойти это? И мне интересно, действительно ли это охватывает все случаи.

...