aboutsummaryrefslogblamecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/NameExtractors.scala
blob: 2ffbf51e1d11a28a0503b129f9d6c171a610e069 (plain) (tree)



















































































































































                                                                                                                             
package dotty.tools.dotc
package core

import Names._
import NameOps._
import StdNames._
import util.DotClass

object NameExtractors {

  abstract class NameInfo extends DotClass {
    def tag: Int
    def mkString(underlying: TermName): String
    def map(f: SimpleTermName => SimpleTermName): NameInfo = this
  }

  val simpleTermNameInfo = new NameInfo {
    def tag = 0
    def mkString(underlying: TermName): String = unsupported("mkString")
  }

  abstract class NameExtractor(val tag: Int) extends DotClass { self =>
    def mkString(underlying: TermName, info: ThisInfo): String
    def infoString: String
    type ThisInfo <: Info
    class Info extends NameInfo { this: ThisInfo =>
      def tag = self.tag
      def mkString(underlying: TermName) = self.mkString(underlying, this)
      override def toString = infoString
    }
  }

  abstract class ClassifiedNameExtractor(tag: Int, val infoString: String) extends NameExtractor(tag) {
    type ThisInfo = Info
    val info = new Info
    def apply(qual: TermName) =
      qual.derived(info)
    def unapply(name: DerivedTermName): Option[TermName] =  name match {
      case DerivedTermName(underlying, `info`) => Some(underlying)
      case _ => None
    }
  }

  class PrefixNameExtractor(tag: Int, prefix: String, infoString: String) extends ClassifiedNameExtractor(tag, infoString) {
    def mkString(underlying: TermName, info: ThisInfo) = prefix ++ underlying
  }

  class SuffixNameExtractor(tag: Int, suffix: String, infoString: String) extends ClassifiedNameExtractor(tag, infoString) {
    def mkString(underlying: TermName, info: ThisInfo) = underlying.toString ++ suffix
  }

  trait QualifiedInfo extends NameInfo {
    val name: SimpleTermName
  }

  abstract class QualifiedNameExtractor(tag: Int, val separator: String, val infoString: String) extends NameExtractor(tag) {
    type ThisInfo = QualInfo
    case class QualInfo(val name: SimpleTermName) extends Info with QualifiedInfo {
      override def map(f: SimpleTermName => SimpleTermName): NameInfo = new QualInfo(f(name))
      override def toString = s"$infoString $name"
    }
    def apply(qual: TermName, name: SimpleTermName) =
      qual.derived(new QualInfo(name))
    def unapply(name: DerivedTermName): Option[(TermName, SimpleTermName)] = name match {
      case DerivedTermName(qual, info: this.QualInfo) => Some((qual, info.name))
      case _ => None
    }
    def mkString(underlying: TermName, info: ThisInfo) =
      s"$underlying$separator${info.name}"
  }

  object AnyQualifiedName {
    def unapply(name: DerivedTermName): Option[(TermName, QualifiedNameExtractor # QualInfo)] = name match {
      case DerivedTermName(qual, info: QualifiedNameExtractor # QualInfo) =>
        Some((name.underlying, info))
      case _ => None
    }
  }

  trait NumberedInfo {
    def num: Int
  }

  abstract class NumberedNameExtractor(tag: Int, val infoString: String) extends NameExtractor(tag) {
    type ThisInfo = NumberedInfo
    case class NumberedInfo(val num: Int) extends Info with NameExtractors.NumberedInfo {
      override def toString = s"$infoString $num"
    }
    def apply(qual: TermName, num: Int) =
      qual.derived(new NumberedInfo(num))
    def unapply(name: DerivedTermName): Option[(TermName, Int)] = name match {
      case DerivedTermName(underlying, info: this.NumberedInfo) => Some((underlying, info.num))
      case _ => None
    }
  }

  object QualifiedName   extends QualifiedNameExtractor(1, ".", "Qualified")
  object FlattenedName   extends QualifiedNameExtractor(2, "$", "Flattened")
  object XpandedName    extends QualifiedNameExtractor(3, str.EXPAND_SEPARATOR, "Expanded")
  object TraitSetterName extends QualifiedNameExtractor(4, str.TRAIT_SETTER_SEPARATOR, "TraitSetter")

  object DefaultGetterName extends NumberedNameExtractor(5, "DefaultGetter") {
    def mkString(underlying: TermName, info: ThisInfo) = {
      val prefix = if (underlying.isConstructorName) nme.DEFAULT_GETTER_INIT else underlying
      prefix.toString + nme.DEFAULT_GETTER + (info.num + 1)
    }
  }

  object VariantName extends NumberedNameExtractor(6, "Variant") {
    val varianceToPrefix = Map(-1 -> '-', 0 -> '=', 1 -> '+')
    val prefixToVariance = Map('-' -> -1, '=' -> 0, '+' -> 1)
    def mkString(underlying: TermName, info: ThisInfo) = {
      varianceToPrefix(info.num).toString + underlying
    }
  }

  val SuperAccessorName = new PrefixNameExtractor(7, str.SUPER_PREFIX, "SuperAccessor")
  val InitializerName = new PrefixNameExtractor(8, str.INITIALIZER_PREFIX, "Initializer")
  val ShadowedName = new PrefixNameExtractor(9, str.SHADOWED_PREFIX, "Shadowed")
  val ModuleClassName = new SuffixNameExtractor(10, "$", "ModuleClass")

  object SignedName extends NameExtractor(63) {

    /** @param parts  resultSig followed by paramsSig */
    case class SignedInfo(sig: Signature) extends Info {
      override def toString = s"$infoString $sig"
    }
    type ThisInfo = SignedInfo

    def apply(qual: TermName, sig: Signature) =
      qual.derived(new SignedInfo(sig))
    def unapply(name: DerivedTermName): Option[(TermName, Signature)] = name match {
      case DerivedTermName(underlying, info: SignedInfo) => Some((underlying, info.sig))
      case _ => None
    }

    def mkString(underlying: TermName, info: ThisInfo): String = unsupported("mkString")
    def infoString: String = "Signed"
  }

  def definesNewName(tag: Int) = tag <= TraitSetterName.tag

  val separatorToQualified: Map[String, QualifiedNameExtractor] =
    Map("." -> QualifiedName,
      "$" -> FlattenedName,
      str.EXPAND_SEPARATOR -> XpandedName,
      str.TRAIT_SETTER_SEPARATOR -> TraitSetterName)
}