Scala - how to print case classes like (pretty printed) tree

前端 未结 10 1873
情歌与酒
情歌与酒 2020-12-07 22:35

I\'m making a parser with Scala Combinators. It is awesome. What I end up with is a long list of entagled case classes, like: ClassDecl(Complex,List(VarDecl(Real,float

10条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-07 23:06

    import java.lang.reflect.Field
    ...
    
    /**
      * Pretty prints case classes with field names.
      * Handles sequences and arrays of such values.
      * Ideally, one could take the output and paste it into source code and have it compile.
      */
    def prettyPrint(a: Any): String = {
      // Recursively get all the fields; this will grab vals declared in parents of case classes.
      def getFields(cls: Class[_]): List[Field] =
        Option(cls.getSuperclass).map(getFields).getOrElse(Nil) ++
            cls.getDeclaredFields.toList.filterNot(f =>
              f.isSynthetic || java.lang.reflect.Modifier.isStatic(f.getModifiers))
      a match {
        // Make Strings look similar to their literal form.
        case s: String =>
          '"' + Seq("\n" -> "\\n", "\r" -> "\\r", "\t" -> "\\t", "\"" -> "\\\"", "\\" -> "\\\\").foldLeft(s) {
            case (acc, (c, r)) => acc.replace(c, r) } + '"'
        case xs: Seq[_] =>
          xs.map(prettyPrint).toString
        case xs: Array[_] =>
          s"Array(${xs.map(prettyPrint) mkString ", "})"
        // This covers case classes.
        case p: Product =>
          s"${p.productPrefix}(${
            (getFields(p.getClass) map { f =>
              f setAccessible true
              s"${f.getName} = ${prettyPrint(f.get(p))}"
            }) mkString ", "
          })"
        // General objects and primitives end up here.
        case q =>
          Option(q).map(_.toString).getOrElse("¡null!")
      }
    }
    

提交回复
热议问题