1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! 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](https://github.com/optimalstrategy/ast2str/blob/main/tests/ast.rs) and
//! these two repos ([#1.1](https://github.com/ves-lang/ves/blob/master/ves-parser/src/ast/mod.rs) +
//! [#1.2](https://github.com/ves-lang/ves/blob/master/ves-parser/tests/t32_fn_if_expr_regression.test),
//! [#2.1](https://github.com/langjam/jam0001/blob/main/dank/src/ast.rs)) for larger samples.
//!
//! ```rust
//! // Import the macro
//! use ast2str::AstToStr;
//!
//! type Span = std::ops::Range<usize>;
//!
//! // Annotate some structs and enums as desired
//! #[derive(AstToStr)]
//! struct Label {
//! #[quoted]
//! name: &'static str,
//! #[default = "Unresolved"]
//! location: Option<usize>,
//! }
//!
//! #[derive(AstToStr)]
//! enum Expr {
//! Binary {
//! left: Box<Expr>,
//! #[quoted]
//! operator: &'static str,
//! right: Box<Expr>
//! },
//! Literal(#[rename = "value"] i32, #[skip] Span),
//! List { items: Vec<Expr> },
//! Label(#[forward] Label),
//! Optional {
//! #[skip_if = "Option::is_none"]
//! 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") },
//! ]})
//! };
//! assert_eq!(expr.ast_to_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:
//! assert_eq!(expr.ast_to_str_impl(&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` |
//!
//! [`AstToStr`]: struct.AstToStr.html
//! [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
//! [`Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
//! [`Symbols`]: trait.Symbols.html
pub use ast2str_derive;
pub use ast2str_lib;
pub use AstToStr;
pub use ;
pub use ;