diff --git a/internal/compiler-bridge/src/main/scala-2.12/xsbt/Compat.scala b/internal/compiler-bridge/src/main/scala-2.12/xsbt/Compat.scala index 13c9d77249..48a691e6f8 100644 --- a/internal/compiler-bridge/src/main/scala-2.12/xsbt/Compat.scala +++ b/internal/compiler-bridge/src/main/scala-2.12/xsbt/Compat.scala @@ -22,10 +22,7 @@ abstract class Compat { /** If given tree contains object tree attachment calls func on tree from attachment. */ protected def processOriginalTreeAttachment(in: Tree)(func: Tree => Unit): Unit = { - import analyzer._ - in.attachments.get[OriginalTreeAttachment].foreach { a => - func(a.original) - } + Compat.OriginalTreeTraverser.Instance.traverseOriginal(in)(func) } } object Compat { @@ -34,6 +31,32 @@ object Compat { // IMain in 2.13 accepts ReplReporter def replReporter(settings: Settings, writer: PrintWriter) = writer + + sealed abstract class OriginalTreeTraverser private { + def traverseOriginal[T <: Global#Tree](t: T)(f: T => Unit): Unit + } + + object OriginalTreeTraverser { + private[this] val cls = try { + Class.forName("scala.tools.nsc.typechecker.StdAttachments$OriginalTreeAttachment") + } catch { case _: Throwable => null } + + private object Reflective extends OriginalTreeTraverser { + private[this] val ct = scala.reflect.ClassTag[AnyRef](cls) + private[this] val meth = cls.getMethod("original") + def traverseOriginal[T <: Global#Tree](t: T)(f: T => Unit): Unit = + t.attachments.get(ct) match { + case Some(attachment) => f(meth.invoke(attachment).asInstanceOf[T]) + case None => + } + } + + private object NoOp extends OriginalTreeTraverser { + def traverseOriginal[T <: Global#Tree](t: T)(f: T => Unit): Unit = () + } + + val Instance = if (cls == null) NoOp else Reflective + } } /** Defines compatibility utils for [[ZincCompiler]]. */