All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalafix.util.TreeOps.scala Maven / Gradle / Ivy

package scalafix.util

import scala.meta._
import scalafix.v1.Symbol
import scala.meta.internal.semanticdb.Scala.Symbols
import scala.meta.internal.semanticdb.Scala.Descriptor

object TreeExtractors {
  object :&&: {
    def unapply[A](arg: A): Option[(A, A)] =
      Some(arg -> arg)
  }

  object Select {
    def unapply(tree: Tree): Option[(Term, Name)] = tree match {
      case Term.Select(qual, name) => Some(qual -> name)
      case Type.Select(qual, name) => Some(qual -> name)
      case _ => None
    }
  }

  object Mods {
    def unapply(tree: Tree): Option[List[Mod]] = tree match {
      case Ctor.Primary(mods, _, _) => Some(mods)
      case Ctor.Secondary(mods, _, _, _, _) => Some(mods)
      case Decl.Def(mods, _, _, _, _) => Some(mods)
      case Decl.Type(mods, _, _, _) => Some(mods)
      case Decl.Val(mods, _, _) => Some(mods)
      case Decl.Var(mods, _, _) => Some(mods)
      case Defn.Class(mods, _, _, _, _) => Some(mods)
      case Defn.Def(mods, _, _, _, _, _) => Some(mods)
      case Defn.Macro(mods, _, _, _, _, _) => Some(mods)
      case Defn.Object(mods, _, _) => Some(mods)
      case Defn.Trait(mods, _, _, _, _) => Some(mods)
      case Defn.Type(mods, _, _, _) => Some(mods)
      case Defn.Val(mods, _, _, _) => Some(mods)
      case Defn.Var(mods, _, _, _) => Some(mods)
      case Pkg.Object(mods, _, _) => Some(mods)
      case Term.Param(mods, _, _, _) => Some(mods)
      case Type.Param(mods, _, _, _, _, _) => Some(mods)
      case _ => None
    }
  }
}
object TreeOps {
  def chain(ref: Term.Ref): List[Name] = ref match {
    case n: Name => List(n)
    case Term.Select(qual: Term.Ref, name) => name :: chain(qual)
    case _ => Nil
  }
  def inferGlobalSymbol(tree: Tree): Option[Symbol] = {
    def loop(t: Tree): Option[String] = {
      t match {
        case _: Defn.Val | _: Defn.Var | _: Template =>
          t.parent.flatMap(loop)
        case p: Pkg =>
          for {
            parent <- t.parent
            owner <- loop(parent)
            next = chain(p.ref).foldRight(owner) {
              case (n, o) => Symbols.Global(o, Descriptor.Package(n.value))
            }
          } yield next
        case d: Member =>
          for {
            parent <- t.parent
            owner <- loop(parent)
            desc <- d match {
              case _: Defn.Object => Some(Descriptor.Term(d.name.value))
              case _: Defn.Class => Some(Descriptor.Type(d.name.value))
              case _: Defn.Trait => Some(Descriptor.Type(d.name.value))
              case _: Pat.Var => Some(Descriptor.Term(d.name.value))
              case _: Defn.Def =>
                for {
                  stats <- parent match {
                    case t: Template => Some(t.stats)
                    case _ => None
                  }
                  conflicts = stats.collect {
                    case m: Defn.Def if m.name.value == d.name.value => m
                  }
                  indexOf = conflicts.indexOf(d)
                  disambiguator = {
                    if (indexOf > 0) "(+" + indexOf + ")"
                    else "()"
                  }
                } yield Descriptor.Method(d.name.value, disambiguator)
              case _ => None
            }
          } yield Symbols.Global(owner, desc)
        case _: Source =>
          Some(Symbols.RootPackage)
        case _ =>
          None
      }
    }
    val result = tree match {
      case n: Name =>
        tree.parent.flatMap(loop)
      case _ => loop(tree)
    }
    result.map(Symbol(_))
  }
  def parents(tree: Tree): Stream[Tree] =
    tree #:: (tree.parent match {
      case Some(x) => parents(x)
      case _ => Stream.empty
    })
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy