ast2str

crates.io Documentation Build Status

A proc macro for pretty-printing ASTs and other recursive data structures.

Basic Usage

Refer to the snippet below for a basic usage example, and see the integration test and these two repos (#1.1 + #1.2, #2.1) for larger samples.

```rust // Import the macro use ast2str::AstToStr;

type Span = std::ops::Range;

// Annotate some structs and enums as desired

[derive(AstToStr)]

struct Label { #[quoted] name: &'static str, #[default = "Unresolved"] location: Option, }

[derive(AstToStr)]

enum Expr { Binary { left: Box, #[quoted] operator: &'static str, right: Box }, Literal(#[rename = "value"] i32, #[skip] Span), List { items: Vec }, Label(#[forward] Label), Optional { #[skipif = "Option::isnone"] value: Option<&'static str> } }

let expr = Expr::Binary { left: Box::new(Expr::Literal(5, Span::default())), operator: "+", right: Box::new(Expr::List { items: vec![ Expr::Label(Label { name: "x", location: Some(0) }), Expr::Label(Label { name: "y", location: Some(1) }), Expr::Label(Label { name: "z", location: None }), Expr::Optional { value: None }, Expr::Optional { value: Some("a string") }, ]}) }; asserteq!(expr.astto_str(), r#" Expr::Binary ├─left: Expr::Literal │ ╰─value: 5 ├─operator: + ╰─right: Expr::List ╰─items=↓ ├─Label │ ├─name: x │ ╰─location: 0 ├─Label │ ├─name: y │ ╰─location: 1 ├─Label │ ├─name: z │ ╰─location: Unresolved ├─Expr::Optional ╰─Expr::Optional ╰─value: "a string" "#.trim());

// The symbols used to draw the tree can be configured using the [Symbols] trait: asserteq!(expr.asttostrimpl(&ast2str::TestSymbols), r#" Expr::Binary left: Expr::Literal value: 5 operator: + right: Expr::List items= Label name: x location: 0 Label name: y location: 1 Label name: z location: Unresolved Expr::Optional Expr::Optional value: "a string" "#.trim()); ```

Available Attributes

| Attribute | | |--------------|--------------------------------------------------------------------------| | None | Format the value with [AstToStr] | | #[forward] | Skip all other fields and return the [AstToStr] of the annotated field | | #[skip] | Skip the annotated field | | #[display] | Format the annotated field with [Display] instead of [AstToStr] | | #[debug] | Format the annotated field with [Debug] instead of [AstToStr] | | #[quoted] | Like #[display] but also wraps the value with backticks | | #[list] | Format the annotated field by executing AstToStr on every element of (&field).into_iter() | | #[list(name_or_closure) | Format the annotated field by applying the callback on every element of (&field).into_iter() | | #[callback(name_or_closure)] | Apply the given function or closure to &field and return the result | | #[delegate = "getter"] | Call self.getter() and format the result as a field | | #[default = "value"] | Only applies to Option types. If the value is Some(T), format &T with AstToStr. Otherwise, return the value of default | | #[skip_if = "my_condition_fn"] | Skip the annotated field if the specified function returns true |