//! Pretty-printed format for the rnix AST representation. //! //! The AST is serialised into a JSON structure that can then be //! printed in either minimised or well-formatted style. use rnix::ast::{self, AstToken, HasEntry}; use serde::{ser::SerializeMap, Serialize, Serializer}; pub fn pretty_print_expr(expr: &ast::Expr) -> String { serde_json::ser::to_string_pretty(&SerializeAST(expr)) .expect("serializing AST should always succeed") } #[repr(transparent)] struct SerializeAST(S); impl<'a> Serialize for SerializeAST<&'a ast::Apply> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(3))?; map.serialize_entry("kind", "apply")?; map.serialize_entry("fn", &SerializeAST(&self.0.lambda().unwrap()))?; map.serialize_entry("arg", &SerializeAST(&self.0.argument().unwrap()))?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::Assert> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(3))?; map.serialize_entry("kind", "assert")?; map.serialize_entry("condition", &SerializeAST(&self.0.condition().unwrap()))?; map.serialize_entry("body", &SerializeAST(&self.0.body().unwrap()))?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::Error> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("kind", "error")?; map.serialize_entry("node", &self.0.to_string())?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::IfElse> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(4))?; map.serialize_entry("kind", "if_else")?; map.serialize_entry("condition", &SerializeAST(&self.0.condition().unwrap()))?; map.serialize_entry("then_body", &SerializeAST(&self.0.body().unwrap()))?; map.serialize_entry("else_body", &SerializeAST(&self.0.else_body().unwrap()))?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::Select> { fn serialize(&self, serializer: S) -> Result { let size = match self.0.default_expr() { Some(_) => 4, None => 3, }; let mut map = serializer.serialize_map(Some(size))?; map.serialize_entry("kind", "select")?; map.serialize_entry("set", &SerializeAST(&self.0.expr().unwrap()))?; map.serialize_entry("path", &SerializeAST(self.0.attrpath().unwrap()))?; if let Some(default) = self.0.default_expr() { map.serialize_entry("default", &SerializeAST(&default))?; } map.end() } } impl Serialize for SerializeAST> { fn serialize(&self, serializer: S) -> Result { match &self.0 { ast::InterpolPart::Literal(s) => Serialize::serialize(s, serializer), ast::InterpolPart::Interpolation(node) => { Serialize::serialize(&SerializeAST(&node.expr().unwrap()), serializer) } } } } impl<'a> Serialize for SerializeAST<&'a ast::Str> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("kind", "string")?; map.serialize_entry( "parts", &self .0 .normalized_parts() .into_iter() .map(SerializeAST) .collect::>(), )?; map.end() } } impl Serialize for SerializeAST> { fn serialize(&self, serializer: S) -> Result { match &self.0 { ast::InterpolPart::Literal(p) => Serialize::serialize(p.syntax().text(), serializer), ast::InterpolPart::Interpolation(node) => { Serialize::serialize(&SerializeAST(&node.expr().unwrap()), serializer) } } } } impl<'a> Serialize for SerializeAST<&'a ast::Path> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("kind", "path")?; map.serialize_entry( "parts", &self.0.parts().map(SerializeAST).collect::>(), )?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::Literal> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("kind", "literal")?; match self.0.kind() { ast::LiteralKind::Float(val) => map.serialize_entry("float", &val.value().unwrap()), ast::LiteralKind::Integer(val) => map.serialize_entry("int", &val.value().unwrap()), ast::LiteralKind::Uri(val) => map.serialize_entry("uri", val.syntax().text()), }?; map.end() } } impl Serialize for SerializeAST { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(None)?; map.serialize_entry("ident", &SerializeAST(&self.0.ident().unwrap()))?; if let Some(default) = self.0.default() { map.serialize_entry("default", &SerializeAST(&default))?; } map.end() } } impl Serialize for SerializeAST { fn serialize(&self, serializer: S) -> Result { match &self.0 { ast::Param::Pattern(pat) => { let mut map = serializer.serialize_map(None)?; map.serialize_entry("kind", "formals")?; map.serialize_entry( "entries", &pat.pat_entries().map(SerializeAST).collect::>(), )?; if let Some(bind) = pat.pat_bind() { map.serialize_entry("bind", &SerializeAST(&bind.ident().unwrap()))?; } map.serialize_entry("ellipsis", &pat.ellipsis_token().is_some())?; map.end() } ast::Param::IdentParam(node) => { Serialize::serialize(&SerializeAST(&node.ident().unwrap()), serializer) } } } } impl<'a> Serialize for SerializeAST<&'a ast::Lambda> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(3))?; map.serialize_entry("kind", "lambda")?; map.serialize_entry("param", &SerializeAST(self.0.param().unwrap()))?; map.serialize_entry("body", &SerializeAST(self.0.body().unwrap()))?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::LegacyLet> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(3))?; map.serialize_entry("kind", "legacy_let")?; map.serialize_entry( "entries", &self .0 .attrpath_values() .map(SerializeAST) .collect::>(), )?; map.serialize_entry( "inherits", &self.0.inherits().map(SerializeAST).collect::>(), )?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::LetIn> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(3))?; map.serialize_entry("kind", "let")?; map.serialize_entry( "entries", &self .0 .attrpath_values() .map(SerializeAST) .collect::>(), )?; map.serialize_entry( "inherits", &self.0.inherits().map(SerializeAST).collect::>(), )?; map.serialize_entry("body", &SerializeAST(&self.0.body().unwrap()))?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::List> { fn serialize(&self, serializer: S) -> Result { let list = self.0.items().map(SerializeAST).collect::>(); let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("kind", "list")?; map.serialize_entry("items", &list)?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::BinOp> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(4))?; map.serialize_entry("kind", "binary_op")?; map.serialize_entry( "operator", match self.0.operator().unwrap() { ast::BinOpKind::Concat => "concat", ast::BinOpKind::Update => "update", ast::BinOpKind::Add => "add", ast::BinOpKind::Sub => "sub", ast::BinOpKind::Mul => "mul", ast::BinOpKind::Div => "div", ast::BinOpKind::And => "and", ast::BinOpKind::Equal => "equal", ast::BinOpKind::Implication => "implication", ast::BinOpKind::Less => "less", ast::BinOpKind::LessOrEq => "less_or_eq", ast::BinOpKind::More => "more", ast::BinOpKind::MoreOrEq => "more_or_eq", ast::BinOpKind::NotEqual => "not_equal", ast::BinOpKind::Or => "or", }, )?; map.serialize_entry("lhs", &SerializeAST(&self.0.lhs().unwrap()))?; map.serialize_entry("rhs", &SerializeAST(&self.0.rhs().unwrap()))?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::Paren> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("kind", "paren")?; map.serialize_entry("expr", &SerializeAST(&self.0.expr().unwrap()))?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::Root> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("kind", "root")?; map.serialize_entry("expr", &SerializeAST(&self.0.expr().unwrap()))?; map.end() } } impl Serialize for SerializeAST { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("name", &SerializeAST(self.0.attrpath().unwrap()))?; map.serialize_entry("value", &SerializeAST(self.0.value().unwrap()))?; map.end() } } impl Serialize for SerializeAST { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(None)?; if let Some(from) = self.0.from() { map.serialize_entry("namespace", &SerializeAST(&from.expr().unwrap()))?; } map.serialize_entry( "names", &self.0.attrs().map(SerializeAST).collect::>(), )?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::AttrSet> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(None)?; map.serialize_entry("kind", "attrset")?; map.serialize_entry("recursive", &self.0.rec_token().is_some())?; map.serialize_entry( "entries", &self .0 .attrpath_values() .map(SerializeAST) .collect::>(), )?; map.serialize_entry( "inherits", &self.0.inherits().map(SerializeAST).collect::>(), )?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::UnaryOp> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(3))?; map.serialize_entry("kind", "unary_op")?; map.serialize_entry( "operator", match self.0.operator().unwrap() { ast::UnaryOpKind::Invert => "invert", ast::UnaryOpKind::Negate => "negate", }, )?; map.serialize_entry("expr", &SerializeAST(&self.0.expr().unwrap()))?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::Ident> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("kind", "ident")?; map.serialize_entry("ident", self.0.ident_token().unwrap().text())?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::With> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(3))?; map.serialize_entry("kind", "with")?; map.serialize_entry("with", &SerializeAST(&self.0.namespace().unwrap()))?; map.serialize_entry("body", &SerializeAST(&self.0.body().unwrap()))?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::Dynamic> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("kind", "dynamic")?; map.serialize_entry("expr", &SerializeAST(&self.0.expr().unwrap()))?; map.end() } } impl Serialize for SerializeAST { fn serialize(&self, serializer: S) -> Result { match &self.0 { ast::Attr::Ident(ident) => Serialize::serialize(&SerializeAST(ident), serializer), ast::Attr::Dynamic(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Attr::Str(node) => Serialize::serialize(&SerializeAST(node), serializer), } } } impl Serialize for SerializeAST { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(2))?; map.serialize_entry("kind", "attrpath")?; map.serialize_entry( "path", &self.0.attrs().map(SerializeAST).collect::>(), )?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::HasAttr> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(3))?; map.serialize_entry("kind", "has_attr")?; map.serialize_entry("expr", &SerializeAST(&self.0.expr().unwrap()))?; map.serialize_entry("attrpath", &SerializeAST(self.0.attrpath().unwrap()))?; map.end() } } impl<'a> Serialize for SerializeAST<&'a ast::Expr> { fn serialize(&self, serializer: S) -> Result { match self.0 { ast::Expr::Apply(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::Assert(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::Error(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::IfElse(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::Select(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::Str(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::Path(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::Literal(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::Lambda(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::LegacyLet(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::LetIn(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::List(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::BinOp(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::Paren(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::Root(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::AttrSet(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::UnaryOp(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::Ident(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::With(node) => Serialize::serialize(&SerializeAST(node), serializer), ast::Expr::HasAttr(node) => Serialize::serialize(&SerializeAST(node), serializer), } } } impl Serialize for SerializeAST { fn serialize(&self, serializer: S) -> Result { SerializeAST(&self.0).serialize(serializer) } }