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

scalafix.internal.util.Pretty.scala Maven / Gradle / Ivy

package scalafix.internal.util

import org.typelevel.paiges.Doc
import scala.meta.Lit
import scalafix.internal.v1.Types
import scalafix.v1._

object Pretty {
  import DocConstants._

  def pretty(constant: Constant): Doc = constant match {
    case UnitConstant => `()`
    case BooleanConstant(value) => Doc.str(value)
    case ByteConstant(value) => Doc.text(Lit.Byte(value).syntax)
    case ShortConstant(value) => Doc.text(Lit.Short(value).syntax)
    case CharConstant(value) => Doc.text(Lit.Char(value).syntax)
    case IntConstant(value) => Doc.str(value)
    case LongConstant(value) => Doc.text(Lit.Long(value).syntax)
    case FloatConstant(value) => Doc.text(Lit.Float(value).syntax)
    case DoubleConstant(value) => Doc.text(Lit.Double(value).syntax)
    case StringConstant(value) => Doc.text(Lit.String(value).syntax)
    case NullConstant => `null`
  }

  def pretty(sym: Symbol): Doc =
    Doc.text(sym.displayName)

  def pretty(tpe: SemanticType): Doc = {
    def prefix(tpe: SemanticType): Doc = {
      tpe match {
        case NoType => Doc.str("")
        case t: TypeRef =>
          val pre: Doc = t.prefix match {
            case _: SingleType | _: ThisType | _: SuperType =>
              prefix(t.prefix) + `.`
            case NoType =>
              Doc.empty
            case _ =>
              prefix(t.prefix) + `#`
          }
          val symbol = pretty(t.symbol)
          val targs =
            if (t.typeArguments.isEmpty) Doc.empty
            else {
              `[` +
                Doc.intercalate(Doc.comma, t.typeArguments.map(normal)) +
                `]`
            }
          pre + symbol + targs
        case t: SingleType =>
          if (t.prefix.isEmpty) pretty(t.symbol)
          else prefix(t.prefix) + `.` + pretty(t.symbol)
        case t: ThisType =>
          if (t.symbol.isNone) pretty(t.symbol)
          else pretty(t.symbol) + `.` + `this`
        case t: SuperType =>
          val pre =
            if (t.prefix.isEmpty) Doc.empty
            else prefix(t.prefix) + `.`
          val sym =
            if (t.symbol.isNone) Doc.empty
            else `[` + pretty(t.symbol) + `]`
          pre + `super` + sym
        case t: ConstantType =>
          pretty(t.constant)
        case t: IntersectionType =>
          Doc.intercalate(
            Doc.space + `&` + Doc.space,
            t.types.map(normal)
          )
        case t: UnionType =>
          Doc.intercalate(
            Doc.space + `|` + Doc.space,
            t.types.map(normal)
          )
        case t: WithType =>
          Doc.intercalate(
            Doc.space + `with` + Doc.space,
            t.types.map(normal)
          )
        case t: StructuralType =>
          val init = normal(t.tpe)
          val declarations =
            if (t.declarations.isEmpty) {
              Doc.space + `{` + `}`
            } else {
              Doc.space +
                Doc
                  .intercalate(Doc.line, t.declarations.map(pretty))
                  .tightBracketBy(`{`, `}`)
            }
          init + declarations
        case t: AnnotatedType =>
          val annotations = t.annotations.filter(_.tpe.nonEmpty)
          val annots =
            if (annotations.isEmpty) {
              Doc.empty
            } else {
              Doc.space + Doc.intercalate(Doc.space, annotations.map(pretty))
            }
          normal(t.tpe) + annots
        case t: ExistentialType =>
          val init = normal(t.tpe)
          val decls = Doc
            .intercalate(Doc.line, t.declarations.map(pretty))
            .tightBracketBy(Doc.space + `forSome` + Doc.space + `{`, `}`)
          init + decls
        case t: UniversalType =>
          val tparams = Doc
            .intercalate(Doc.comma, t.typeParameters.map(pretty))
            .tightBracketBy(`[`, `]` + Doc.space + `=>` + Doc.space)
          normal(t.tpe) + tparams
        case t: ByNameType =>
          `=>` + Doc.space + pretty(t.tpe)
        case t: RepeatedType =>
          `*` + Doc.space + pretty(t.tpe)
      }
    }
    def normal(tpe: SemanticType): Doc = tpe match {
      case _: SingleType | _: ThisType | _: SuperType =>
        prefix(tpe) + `.` + `type`
      case _ =>
        prefix(tpe)
    }
    normal(tpe)
  }

  def pretty(annotation: Annotation): Doc =
    if (annotation.tpe.isEmpty) Doc.empty
    else `@` + pretty(annotation.tpe)

  def pretty(info: SymbolInformation): Doc = {
    Doc.text(info.toString)
  }

  def prettyTermParameter(parameter: SymbolInformation): Doc = {
    Doc.text(parameter.displayName) + `:` + Doc.space +
      pretty(parameter.signature)
  }

  def prettyTypeParameter(parameter: SymbolInformation): Doc = {
    Doc.text(parameter.displayName) + pretty(parameter.signature)
  }

  def prettyTypeParameters(typeParameters: List[SymbolInformation]): Doc = {
    if (typeParameters.isEmpty) Doc.empty
    else {
      `[` +
        Doc.intercalate(Doc.comma, typeParameters.map(prettyTypeParameter)) +
        `]`
    }
  }

  def pretty(signature: Signature): Doc = signature match {
    case NoSignature => Doc.empty
    case t: ClassSignature =>
      val tparams = prettyTypeParameters(t.typeParameters)
      val parents = `extends` + Doc.space +
        Doc.intercalate(Doc.space + `with` + Doc.space, t.parents.map(pretty))
      val body =
        if (t.self.isEmpty && t.declarations.isEmpty) Doc.empty
        else {
          val self =
            if (t.self.isEmpty) Doc.empty
            else Doc.text("self: ") + pretty(t.self) + Doc.text(" =>")
          val declarations =
            if (t.declarations.isEmpty) Doc.empty
            else
              Doc.text(s" +") + Doc.str(t.declarations.length) +
                Doc.text(" decls ")
          Doc.space + `{` + self + declarations + `}`
        }
      tparams + Doc.space + parents + body
    case t: MethodSignature =>
      val tparams = prettyTypeParameters(t.typeParameters)
      val params =
        if (t.parameterLists.isEmpty) Doc.empty
        else {
          val params = t.parameterLists.map { parameterList =>
            Doc.intercalate(Doc.comma, parameterList.map(prettyTermParameter))
          }
          val paramss = Doc.intercalate(`)` + `(`, params)
          `(` + paramss + `)`
        }
      val returnType = pretty(t.returnType)
      tparams + params + `:` + Doc.space + returnType
    case t: TypeSignature =>
      val tparams = prettyTypeParameters(t.typeParameters)
      if (t.lowerBound == t.upperBound) {
        tparams + Doc.text(" = ") + pretty(t.lowerBound)
      } else {
        val lowerBound =
          if (t.lowerBound == Types.scalaNothing) Doc.empty
          else Doc.text(" >: ") + pretty(t.lowerBound)
        val upperBound =
          if (t.upperBound == Types.scalaAny) Doc.empty
          else if (t.upperBound == Types.javaObject) Doc.empty
          else Doc.text(" <: ") + pretty(t.upperBound)
        tparams + lowerBound + upperBound
      }
    case t: ValueSignature =>
      pretty(t.tpe)
  }

  def pretty(tree: SemanticTree): Doc = tree match {
    case NoTree =>
      Doc.empty
    case t: IdTree =>
      pretty(t.symbol)
    case t: SelectTree =>
      pretty(t.qualifier) + `.` + pretty(t.id)
    case t: ApplyTree =>
      Doc
        .intercalate(Doc.comma, t.arguments.map(pretty))
        .tightBracketBy(pretty(t.function) + `(`, `)`)
    case t: TypeApplyTree =>
      val targs = Doc.intercalate(Doc.comma, t.typeArguments.map(pretty))
      pretty(t.function) + `[` + targs + `]`
    case t: FunctionTree =>
      val paramNames =
        t.parameters.map(param => Doc.text(param.info.displayName))
      val params = `(` +
        Doc.intercalate(Doc.comma, paramNames) +
        `)` + Doc.space + `=>`
      pretty(t.body).bracketBy(`{` + Doc.space + params, `}`)
    case t: LiteralTree =>
      pretty(t.constant)
    case t: MacroExpansionTree =>
      `(` + Doc.text("`after-expansion` : ") + pretty(t.tpe) + `)`
    case r: OriginalTree =>
      `*`
    case r: OriginalSubTree =>
      Doc.text("orig") + `(` + Doc.text(r.tree.syntax) + `)`
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy