<commit_before>package splain

import tools.nsc._
import collection.mutable.{Buffer, Map}

trait Formatting
{ self: Analyzer =>
  import global._
  import Console._

  def featureInfix: Boolean

  object DealiasedType
  extends TypeMap
  {
    def apply(tp: Type): Type = tp match {
      case TypeRef(pre, sym, args)
      if sym.isAliasType && !sym.isInDefaultNamespace =>
        mapOver(tp.dealias)
      case _ =>
        mapOver(tp)
    }
  }

  def dealias(tpe: Type) = formatInfix(DealiasedType(tpe), true)

  def isSymbolic(tpe: Type) =
    tpe.typeSymbol.name.encodedName.toString !=
      tpe.typeSymbol.name.decodedName.toString

  def formatRefinement(sym: Symbol) = {
    if (sym.hasRawInfo) {
      val rhs = formatInfix(sym.rawInfo, true)
      s"$sym = $rhs"
    }
    else sym.toString
  }

  def formatSimpleType(tpe: Type) = tpe match {
    case a: RefinedType =>
      val simple = a.parents.map(formatInfix(_, true)).mkString(" with ")
      val refine = a.decls.map(formatRefinement).mkString("; ")
      s"$simple {$refine}"
    case a =>
      a.typeSymbol.name.decodedName.toString
  }

  def formatTypeApply(simple: String, args: List[String]) =
    args.mkString(s"$simple[", ",", "]")

  def formatTuple(args: List[String]) =
    args match {
      case head :: Nil => head
      case _ => args.mkString("(", ",", ")")
    }

  def formatFunction(args: List[String]) = {
    val (params, returnt) = args.splitAt(args.length - 1)
    s"${formatTuple(params)} => ${formatTuple(returnt)}"
  }

  def formatType[A](tpe: Type, args: List[A], top: Boolean,
    rec: A => Boolean => String): String = {
    val simple = formatSimpleType(tpe)
    def formattedArgs = args.map(rec(_)(true))
    if (simple.startsWith("Function")) formatFunction(formattedArgs)
    else if (simple.startsWith("Tuple")) formatTuple(formattedArgs)
    else args match {
      case left :: right :: Nil if isSymbolic(tpe) =>
        val l = rec(left)(false)
        val r = rec(right)(false)
        val t = s"$l $simple $r"
        if (top) t else s"($t)"
      case head :: tail =>
        formatTypeApply(simple, formattedArgs)
      case _ =>
        simple
    }
  }

  def formatInfix(tpe: Type, top: Boolean): String = {
    val rec = (tp: Type) => (t: Boolean) => formatInfix(tp, t)
    if (featureInfix) formatType(tpe, tpe.typeArgs, top, rec)
    else tpe.toLongString
  }

  def formatDiff(found: Type, req: Type, top: Boolean): String = {
    import Console._
    if (found.typeSymbol == req.typeSymbol) {
      val rec = (l: Type, r: Type) => (t: Boolean) => formatDiff(l, r, t)
      val recT = rec.tupled
      val args = found.typeArgs zip req.typeArgs
      formatType(found, args, top, recT)
    }
    else {
      val l = formatInfix(found, true)
      val r = formatInfix(req, true)<commit_msg>add parens around function<commit_after>package splain

import tools.nsc._
import collection.mutable.{Buffer, Map}

trait Formatting
{ self: Analyzer =>
  import global._
  import Console._

  def featureInfix: Boolean

  object DealiasedType
  extends TypeMap
  {
    def apply(tp: Type): Type = tp match {
      case TypeRef(pre, sym, args)
      if sym.isAliasType && !sym.isInDefaultNamespace =>
        mapOver(tp.dealias)
      case _ =>
        mapOver(tp)
    }
  }

  def dealias(tpe: Type) = formatInfix(DealiasedType(tpe), true)

  def isSymbolic(tpe: Type) =
    tpe.typeSymbol.name.encodedName.toString !=
      tpe.typeSymbol.name.decodedName.toString

  def formatRefinement(sym: Symbol) = {
    if (sym.hasRawInfo) {
      val rhs = formatInfix(sym.rawInfo, true)
      s"$sym = $rhs"
    }
    else sym.toString
  }

  def formatSimpleType(tpe: Type) = tpe match {
    case a: RefinedType =>
      val simple = a.parents.map(formatInfix(_, true)).mkString(" with ")
      val refine = a.decls.map(formatRefinement).mkString("; ")
      s"$simple {$refine}"
    case a =>
      a.typeSymbol.name.decodedName.toString
  }

  def formatTypeApply(simple: String, args: List[String]) =
    args.mkString(s"$simple[", ",", "]")

  def formatTuple(args: List[String]) =
    args match {
      case head :: Nil => head
      case _ => args.mkString("(", ",", ")")
    }

  def formatFunction(args: List[String]) = {
    val (params, returnt) = args.splitAt(args.length - 1)
    s"${formatTuple(params)} => ${formatTuple(returnt)}"
  }

  def parens(expr: String, top: Boolean) =
    if (top) expr else s"($expr)"

  def formatType[A](tpe: Type, args: List[A], top: Boolean,
    rec: A => Boolean => String): String = {
    val simple = formatSimpleType(tpe)
    def formattedArgs = args.map(rec(_)(true))
    if (simple.startsWith("Function"))
      parens(formatFunction(formattedArgs), top)
    else if (simple.startsWith("Tuple")) formatTuple(formattedArgs)
    else args match {
      case left :: right :: Nil if isSymbolic(tpe) =>
        val l = rec(left)(false)
        val r = rec(right)(false)
        val t = s"$l $simple $r"
        parens(t, top)
      case head :: tail =>
        formatTypeApply(simple, formattedArgs)
      case _ =>
        simple
    }
  }

  def formatInfix(tpe: Type, top: Boolean): String = {
    val rec = (tp: Type) => (t: Boolean) => formatInfix(tp, t)
    if (featureInfix) formatType(tpe, tpe.typeArgs, top, rec)
    else tpe.toLongString
  }

  def formatDiff(found: Type, req: Type, top: Boolean): String = {
    import Console._
    if (found.typeSymbol == req.typeSymbol) {
      val rec = (l: Type, r: Type) => (t: Boolean) => formatDiff(l, r, t)
      val recT = rec.tupled
      val args = found.typeArgs zip req.typeArgs
      formatType(found, args, top, recT)
    }
    else {
      val l = formatInfix(found, true)
      val r = formatInfix(req, true)
{'fraction_non_alphanumeric': 0.14003841452767593, 'fraction_numerical': 0.00034922297887200976, 'mean_word_length': 2.907230559345157, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6402601', 'n_tokens_mistral': 1963, 'n_tokens_neox': 1938, 'n_words': 476}