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

dotty.tools.dotc.interactive.SourceTree.scala Maven / Gradle / Ivy

package dotty.tools
package dotc
package interactive

import scala.io.Codec

import ast.tpd
import core._, core.Decorators.{sourcePos => _, _}
import Contexts._, NameOps._, Symbols._, StdNames._
import util._, util.Positions._

/** A typechecked named `tree` coming from `source` */
case class SourceTree(tree: tpd.NameTree, source: SourceFile) {
  /** The position of `tree` */
  def pos(implicit ctx: Context): SourcePosition = source.atPos(tree.pos)

  /** The position of the name in `tree` */
  def namePos(implicit ctx: Context): SourcePosition = {
    // FIXME: Merge with NameTree#namePos ?
    val treePos = tree.pos
    if (treePos.isZeroExtent || tree.name.toTermName == nme.ERROR)
      NoSourcePosition
    else {
      val nameLength = tree.name.stripModuleClassSuffix.show.toString.length
      val position = {
        // FIXME: This is incorrect in some cases, like with backquoted identifiers,
        //        see https://github.com/lampepfl/dotty/pull/1634#issuecomment-257079436
        val (start, end) =
          if (!treePos.isSynthetic)
            (treePos.point, treePos.point + nameLength)
          else
            // If we don't have a point, we need to find it
            (treePos.end - nameLength, treePos.end)
        Position(start, end, start)
      }
      source.atPos(position)
    }
  }
}

object SourceTree {
  def fromSymbol(sym: ClassSymbol, id: String = "")(implicit ctx: Context): Option[SourceTree] = {
    if (sym == defn.SourceFileAnnot || // FIXME: No SourceFile annotation on SourceFile itself
        sym.sourceFile == null) // FIXME: We cannot deal with external projects yet
      None
    else {
      import ast.Trees._
      def sourceTreeOfClass(tree: tpd.Tree): Option[SourceTree] = tree match {
        case PackageDef(_, stats) =>
          stats.flatMap(sourceTreeOfClass).headOption
        case tree: tpd.TypeDef if tree.symbol == sym =>
          val sourceFile = new SourceFile(sym.sourceFile, Codec.UTF8)
          Some(SourceTree(tree, sourceFile))
        case _ => None
      }
      sourceTreeOfClass(sym.treeContaining(id))
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy