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

ch.epfl.scala.debugadapter.internal.scalasig.ScalaSig.scala Maven / Gradle / Ivy

The newest version!
package ch.epfl.scala.debugadapter.internal.scalasig

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

/**
 * Originally copied from https://github.com/JetBrains/intellij-scala
 * https://github.com/JetBrains/intellij-scala/blob/074e8f98d9789b3e7def3ade8d39e7ae770beccf/scala/decompiler/src/org/jetbrains/plugins/scala/decompiler/scalasig/ScalaSig.scala
 *
 * Nikolay.Tropin
 * 19-Jul-17
 */
class ScalaSig(val entries: Array[Entry]) {
  private var initialized: Boolean = false

  def get(idx: Int): Entry = entries(idx)

  def isInitialized: Boolean = initialized
  def finished(): Unit = initialized = true

  private val classes = ArrayBuffer.empty[ClassSymbol]
  private val objects = ArrayBuffer.empty[ObjectSymbol]
  private val symAnnots = ArrayBuffer.empty[SymAnnot]
  private val parentToChildren = mutable.HashMap.empty[Int, ArrayBuffer[Symbol]]

  def topLevelClasses: Iterable[ClassSymbol] = classes.filter(isTopLevelClass)
  def topLevelObjects: Iterable[ObjectSymbol] = objects.filter(isTopLevel)

  def findCompanionClass(objectSymbol: ObjectSymbol): Option[ClassSymbol] = {
    val owner: Symbol = objectSymbol.symbolInfo.owner.get
    val name = objectSymbol.name
    classes.find(c => c.info.owner.get.eq(owner) && c.name == name)
  }

  def children(symbol: ScalaSigSymbol): Iterable[Symbol] = {
    parentToChildren.keysIterator.find(get(_) eq symbol) match {
      case None => Iterable.empty
      case Some(i) => parentToChildren(i)
    }
  }

  def attributes(symbol: ScalaSigSymbol): Iterable[SymAnnot] = {
    def sameSymbol(ann: SymAnnot) = (ann.symbol.get, symbol) match {
      case (s, t) if s == t => true
      case (m1: MethodSymbol, m2: MethodSymbol) if equiv(m1, m2) => true
      case _ => false
    }
    val forSameSymbol = symAnnots.filter(sameSymbol)
    forSameSymbol.groupBy(_.typeRef).values.map(_.head)
  }

  def addClass(c: ClassSymbol): Unit = classes += c
  def addObject(o: ObjectSymbol): Unit = objects += o
  def addAttribute(a: SymAnnot): Unit = symAnnots += a

  def addChild(parent: Option[Ref[Symbol]], child: Symbol): Unit = {
    parent.foreach { ref =>
      val children =
        parentToChildren.getOrElseUpdate(ref.index, ArrayBuffer.empty)
      children += child
    }
  }

  private def isTopLevel(symbol: Symbol): Boolean = symbol.parent match {
    case Some(_: ExternalSymbol) => true
    case _ => false
  }
  private def isTopLevelClass(symbol: Symbol): Boolean =
    !symbol.isModule && isTopLevel(symbol)

  private def equiv(m1: MethodSymbol, m2: MethodSymbol) = {
    def unwrapType(t: Type) = t match {
      case NullaryMethodType(Ref(tp)) => tp
      case _ => t
    }

    m1.name == m2.name && m1.parent == m2.parent &&
    unwrapType(m1.infoType) == unwrapType(m2.infoType)
  }

  def syntheticSymbols(): Seq[Symbol] =
    parentToChildren.valuesIterator.flatten.filter(_.isSynthetic).toList
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy