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

scala.tasty.reflect.ExtractorsPrinter.scala Maven / Gradle / Ivy

The newest version!
package scala.tasty
package reflect

class ExtractorsPrinter[R <: Reflection & Singleton](val reflect: R) extends Printer[R] {
  import reflect._

  def showTree(tree: Tree): String =
    new Buffer().visitTree(tree).result()

  def showType(tpe: Type): String =
    new Buffer().visitType(tpe).result()

  def showConstant(const: Constant): String =
    new Buffer().visitConstant(const).result()

  def showSymbol(symbol: Symbol): String =
    new Buffer().visitSymbol(symbol).result()

  def showFlags(flags: Flags): String = {
    val flagList = List.newBuilder[String]
    if (flags.is(Flags.Abstract)) flagList += "Flags.Abstract"
    if (flags.is(Flags.Artifact)) flagList += "Flags.Artifact"
    if (flags.is(Flags.Case)) flagList += "Flags.Case"
    if (flags.is(Flags.CaseAccessor)) flagList += "Flags.CaseAccessor"
    if (flags.is(Flags.Contravariant)) flagList += "Flags.Contravariant"
    if (flags.is(Flags.Covariant)) flagList += "Flags.Covariant"
    if (flags.is(Flags.Enum)) flagList += "Flags.Enum"
    if (flags.is(Flags.Erased)) flagList += "Flags.Erased"
    if (flags.is(Flags.ExtensionMethod)) flagList += "Flags.ExtensionMethod"
    if (flags.is(Flags.FieldAccessor)) flagList += "Flags.FieldAccessor"
    if (flags.is(Flags.Final)) flagList += "Flags.Final"
    if (flags.is(Flags.HasDefault)) flagList += "Flags.HasDefault"
    if (flags.is(Flags.Implicit)) flagList += "Flags.Implicit"
    if (flags.is(Flags.Inline)) flagList += "Flags.Inline"
    if (flags.is(Flags.JavaDefined)) flagList += "Flags.JavaDefined"
    if (flags.is(Flags.Lazy)) flagList += "Flags.Lazy"
    if (flags.is(Flags.Local)) flagList += "Flags.Local"
    if (flags.is(Flags.Macro)) flagList += "Flags.Macro"
    if (flags.is(Flags.ModuleClass)) flagList += "Flags.ModuleClass"
    if (flags.is(Flags.Mutable)) flagList += "Flags.Mutable"
    if (flags.is(Flags.Object)) flagList += "Flags.Object"
    if (flags.is(Flags.Override)) flagList += "Flags.Override"
    if (flags.is(Flags.Package)) flagList += "Flags.Package"
    if (flags.is(Flags.Param)) flagList += "Flags.Param"
    if (flags.is(Flags.ParamAccessor)) flagList += "Flags.ParamAccessor"
    if (flags.is(Flags.Private)) flagList += "Flags.Private"
    if (flags.is(Flags.PrivateLocal)) flagList += "Flags.PrivateLocal"
    if (flags.is(Flags.Protected)) flagList += "Flags.Protected"
    if (flags.is(Flags.Scala2x)) flagList += "Flags.Scala2x"
    if (flags.is(Flags.Sealed)) flagList += "Flags.Sealed"
    if (flags.is(Flags.StableRealizable)) flagList += "Flags.StableRealizable"
    if (flags.is(Flags.Static)) flagList += "Flags.javaStatic"
    if (flags.is(Flags.Synthetic)) flagList += "Flags.Synthetic"
    if (flags.is(Flags.Trait)) flagList += "Flags.Trait"
    flagList.result().mkString(" | ")
  }

  private class Buffer { self =>

    private val sb: StringBuilder = new StringBuilder

    def result(): String = sb.result()

    def visitTree(x: Tree): Buffer = x match {
      case Ident(name) =>
        this += "Ident(\"" += name += "\")"
      case Select(qualifier, name) =>
        this += "Select(" += qualifier += ", \"" += name += "\")"
      case This(qual) =>
        this += "This(" += qual += ")"
      case Super(qual, mix) =>
        this += "Super(" += qual += ", " += mix += ")"
      case Apply(fun, args) =>
        this += "Apply(" += fun += ", " ++= args += ")"
      case TypeApply(fun, args) =>
        this += "TypeApply(" += fun += ", " ++= args += ")"
      case Literal(const) =>
        this += "Literal(" += const += ")"
      case New(tpt) =>
        this += "New(" += tpt += ")"
      case Typed(expr, tpt) =>
        this += "Typed(" += expr += ", "  += tpt += ")"
      case NamedArg(name, arg) =>
        this += "NamedArg(\"" += name += "\", " += arg += ")"
      case Assign(lhs, rhs) =>
        this += "Assign(" += lhs += ", " += rhs += ")"
      case Block(stats, expr) =>
        this += "Block(" ++= stats += ", " += expr += ")"
      case If(cond, thenp, elsep) =>
        this += "If(" += cond += ", " += thenp += ", " += elsep += ")"
      case Closure(meth, tpt) =>
        this += "Closure(" += meth += ", " += tpt += ")"
      case Match(selector, cases) =>
        this += "Match(" += selector += ", " ++= cases += ")"
      case GivenMatch(cases) =>
        this += "GivenMatch(" ++= cases += ")"
      case Return(expr) =>
        this += "Return(" += expr += ")"
      case While(cond, body) =>
        this += "While(" += cond += ", " += body += ")"
      case Try(block, handlers, finalizer) =>
        this += "Try(" += block += ", " ++= handlers += ", " += finalizer += ")"
      case Repeated(elems, elemtpt) =>
        this += "Repeated(" ++= elems += ", " += elemtpt += ")"
      case Inlined(call, bindings, expansion) =>
        this += "Inlined("
        visitOption(call, visitTree)
        this += ", " ++= bindings += ", " += expansion += ")"
      case ValDef(name, tpt, rhs) =>
        this += "ValDef(\"" += name += "\", " += tpt += ", " += rhs += ")"
      case DefDef(name, typeParams, paramss, returnTpt, rhs) =>
        this += "DefDef(\"" += name += "\", " ++= typeParams += ", " +++= paramss += ", " += returnTpt += ", " += rhs += ")"
      case TypeDef(name, rhs) =>
        this += "TypeDef(\"" += name += "\", " += rhs += ")"
      case ClassDef(name, constr, parents, derived, self, body) =>
        this += "ClassDef(\"" += name += "\", " += constr += ", "
        visitList[Tree](parents, visitTree)
        this += ", "
        visitList[TypeTree](derived, visitTree)
        this += ", " += self += ", " ++= body += ")"
      case Import(expr, selectors) =>
        this += "Import(" += expr += ", " ++= selectors += ")"
      case PackageClause(pid, stats) =>
        this += "PackageClause(" += pid += ", " ++= stats += ")"
      case Inferred() =>
        this += "Inferred()"
      case TypeIdent(name) =>
        this += "TypeIdent(\"" += name += "\")"
      case TypeSelect(qualifier, name) =>
        this += "TypeSelect(" += qualifier += ", \"" += name += "\")"
      case Projection(qualifier, name) =>
        this += "Projection(" += qualifier += ", \"" += name += "\")"
      case Singleton(ref) =>
        this += "Singleton(" += ref += ")"
      case Refined(tpt, refinements) =>
        this += "Refined(" += tpt += ", " ++= refinements += ")"
      case Applied(tpt, args) =>
        this += "Applied(" += tpt += ", " ++= args += ")"
      case ByName(result) =>
        this += "ByName(" += result += ")"
      case Annotated(arg, annot) =>
        this += "Annotated(" += arg += ", " += annot += ")"
      case LambdaTypeTree(tparams, body) =>
        this += "LambdaTypeTree(" ++= tparams += ", " += body += ")"
      case TypeBind(name, bounds) =>
        this += "TypeBind(" += name += ", " += bounds += ")"
      case TypeBlock(aliases, tpt) =>
        this += "TypeBlock(" ++= aliases += ", " += tpt += ")"
      case TypeBoundsTree(lo, hi) =>
        this += "TypeBoundsTree(" += lo += ", " += hi += ")"
      case WildcardTypeTree() =>
        this += s"WildcardTypeTree()"
      case MatchTypeTree(bound, selector, cases) =>
        this += "MatchTypeTree(" += bound += ", " += selector += ", " ++= cases += ")"
      case CaseDef(pat, guard, body) =>
        this += "CaseDef(" += pat += ", " += guard += ", " += body += ")"
      case TypeCaseDef(pat, body) =>
        this += "TypeCaseDef(" += pat += ", " += body += ")"
      case Bind(name, body) =>
        this += "Bind(\"" += name += "\", " += body += ")"
      case Unapply(fun, implicits, patterns) =>
        this += "Unapply(" += fun += ", " ++= implicits += ", " ++= patterns += ")"
      case Alternatives(patterns) =>
        this += "Alternative(" ++= patterns += ")"
    }

    def visitConstant(x: Constant): Buffer = x match {
      case Constant.Unit() => this += "Constant.Unit()"
      case Constant.Null() => this += "Constant.Null()"
      case Constant.Boolean(value) => this += "Constant.Boolean(" += value += ")"
      case Constant.Byte(value) => this += "Constant.Byte(" += value += ")"
      case Constant.Short(value) => this += "Constant.Short(" += value += ")"
      case Constant.Int(value) => this += "Constant.Int(" += value += ")"
      case Constant.Long(value) => this += "Constant.Long(" += value += "L)"
      case Constant.Float(value) => this += "Constant.Float(" += value += "f)"
      case Constant.Double(value) => this += "Constant.Double(" += value += "d)"
      case Constant.Char(value) => this += "Constant.Char('" += value += "')"
      case Constant.String(value) => this += "Constant.String(\"" += value += "\")"
      case Constant.ClassOf(value) =>
        this += "Constant.ClassOf("
        visitType(value) += ")"
    }

    def visitType(x: Type): Buffer = x match {
      case ConstantType(value) =>
        this += "ConstantType(" += value += ")"
      case TermRef(qual, name) =>
        this += "TermRef(" += qual+= ", \"" += name += "\")"
      case TypeRef(qual, name) =>
        this += "TypeRef(" += qual += ", \"" += name += "\")"
      case Refinement(parent, name, info) =>
        this += "Refinement(" += parent += ", \"" += name += "\", " += info += ")"
      case AppliedType(tycon, args) =>
        this += "AppliedType(" += tycon += ", " ++= args += ")"
      case AnnotatedType(underlying, annot) =>
        this += "AnnotatedType(" += underlying += ", " += annot += ")"
      case AndType(left, right) =>
        this += "AndType(" += left += ", " += right += ")"
      case OrType(left, right) =>
        this += "OrType(" += left += ", " += right += ")"
      case MatchType(bound, scrutinee, cases) =>
        this += "MatchType(" += bound += ", " += scrutinee += ", " ++= cases += ")"
      case ByNameType(underlying) =>
        this += "ByNameType(" += underlying += ")"
      case ParamRef(binder, idx) =>
        this += "ParamRef(" += binder += ", " += idx += ")"
      case ThisType(tp) =>
        this += "ThisType(" += tp += ")"
      case SuperType(thistpe, supertpe) =>
        this += "SuperType(" += thistpe += ", " += supertpe += ")"
      case RecursiveThis(binder) =>
        this += "RecursiveThis(" += binder += ")"
      case RecursiveType(underlying) =>
        this += "RecursiveType(" += underlying += ")"
      case MethodType(argNames, argTypes, resType) =>
        this += "MethodType(" ++= argNames += ", " ++= argTypes += ", " += resType += ")"
      case PolyType(argNames, argBounds, resType) =>
        this += "PolyType(" ++= argNames += ", " ++= argBounds += ", " += resType += ")"
      case TypeLambda(argNames, argBounds, resType) =>
        // resType is not printed to avoid cycles
        this += "TypeLambda(" ++= argNames += ", " ++= argBounds += ", _)"
      case TypeBounds(lo, hi) =>
        this += "TypeBounds(" += lo += ", " += hi += ")"
      case NoPrefix() =>
        this += "NoPrefix()"
    }

    def visitSignature(sig: Signature): Buffer = {
      val Signature(params, res) = sig
      this += "Signature(" ++= params.map(_.toString) += ", " += res += ")"
    }

    def visitImportSelector(sel: ImportSelector): Buffer = sel match {
      case SimpleSelector(id) => this += "SimpleSelector(" += id += ")"
      case RenameSelector(id1, id2) => this += "RenameSelector(" += id1 += ", " += id2 += ")"
      case OmitSelector(id) => this += "OmitSelector(" += id += ")"
    }

    def visitSymbol(x: Symbol): Buffer =
      if x.isPackageDef  then this += "IsPackageDefSymbol(<" += x.fullName += ">)"
      else if x.isClassDef then this += "IsClassDefSymbol(<" += x.fullName += ">)"
      else if x.isDefDef then this += "IsDefDefSymbol(<" += x.fullName += ">)"
      else if x.isValDef then this += "IsValDefSymbol(<" += x.fullName += ">)"
      else if x.isTypeDef then this += "IsTypeDefSymbol(<" += x.fullName += ">)"
      else { assert(x.isNoSymbol); this += "NoSymbol()" }

    def +=(x: Boolean): Buffer = { sb.append(x); this }
    def +=(x: Byte): Buffer = { sb.append(x); this }
    def +=(x: Short): Buffer = { sb.append(x); this }
    def +=(x: Int): Buffer = { sb.append(x); this }
    def +=(x: Long): Buffer = { sb.append(x); this }
    def +=(x: Float): Buffer = { sb.append(x); this }
    def +=(x: Double): Buffer = { sb.append(x); this }
    def +=(x: Char): Buffer = { sb.append(x); this }
    def +=(x: String): Buffer = { sb.append(x); this }

    def ++=(xs: List[String]): Buffer = visitList[String](xs, +=)

    private implicit class StringOps(buff: Buffer) {
      def +=(x: Option[String]): Buffer = { visitOption(x, y => buff += "\"" += y += "\""); buff }
    }

    private implicit class TreeOps(buff: Buffer) {
      def +=(x: Tree): Buffer = { visitTree(x); buff }
      def +=(x: Option[Tree]): Buffer = { visitOption(x, visitTree); buff }
      def ++=(x: List[Tree]): Buffer = { visitList(x, visitTree); buff }
      def +++=(x: List[List[Tree]]): Buffer = { visitList(x, ++=); buff }
    }

    private implicit class ConstantOps(buff: Buffer) {
      def +=(x: Constant): Buffer = { visitConstant(x); buff }
    }

    private implicit class TypeOps(buff: Buffer) {
      def +=(x: Type): Buffer = { visitType(x); buff }
      def +=(x: Option[Type]): Buffer = { visitOption(x, visitType); buff }
      def ++=(x: List[Type]): Buffer = { visitList(x, visitType); buff }
    }

    private implicit class SignatureOps(buff: Buffer) {
      def +=(x: Option[Signature]): Buffer = { visitOption(x, visitSignature); buff }
    }

    private implicit class ImportSelectorOps(buff: Buffer) {
      def ++=(x: List[ImportSelector]): Buffer = { visitList(x, visitImportSelector); buff }
    }

    private implicit class SymbolOps(buff: Buffer) {
      def +=(x: Symbol): Buffer = { visitSymbol(x); buff }
    }

    private def visitOption[U](opt: Option[U], visit: U => Buffer): Buffer = opt match {
      case Some(x) =>
        this += "Some("
        visit(x)
        this += ")"
      case _ =>
        this += "None"
    }

    private def visitList[U](list: List[U], visit: U => Buffer): Buffer = list match {
      case x0 :: xs =>
        this += "List("
        visit(x0)
        def visitNext(xs: List[U]): Unit = xs match {
          case y :: ys =>
            this += ", "
            visit(y)
            visitNext(ys)
          case Nil =>
        }
        visitNext(xs)
        this += ")"
      case Nil =>
        this += "Nil"
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy