Есть некоторые классы в библиотеке, которые имеют ИМПОРТ, который не может быть решен. Например, 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]
}
Но я думаю, что это действительно настойчиво. Есть ли другой способ обойти это? И мне интересно, действительно ли это охватывает все случаи.