Skip to main content

zyn_core/debug/
mod.rs

1//! Debug formatting utilities for macro expansions.
2//!
3//! Provides a pipeline API for formatting generated `TokenStream`s into
4//! human-readable strings. Used internally by the `debug` attribute argument
5//! on `#[zyn::element]`, `#[zyn::pipe]`, `#[zyn::derive]`, and `#[zyn::attribute]`.
6//!
7//! # Formats
8//!
9//! - **Raw** (always available) — calls `TokenStream::to_string()`, producing
10//!   a flat single-line string with fully-qualified paths. No extra dependencies.
11//!
12//! - **Pretty** (requires the `pretty` feature) — parses the token stream into
13//!   a [`syn::File`] and formats it with [`prettyplease`], producing properly
14//!   indented Rust code. Enable with:
15//!
16//!   ```toml
17//!   zyn = { version = "0.3", features = ["pretty"] }
18//!   ```
19//!
20//! # Usage
21//!
22//! The [`DebugExt`] trait adds a `.debug()` method to [`proc_macro2::TokenStream`],
23//! returning a [`DebugTokens`] builder with `.raw()` and `.pretty()` methods:
24//!
25//! ```ignore
26//! use zyn::debug::DebugExt;
27//!
28//! let raw: String = tokens.debug().raw();
29//!
30//! #[cfg(feature = "pretty")]
31//! let pretty: String = tokens.debug().pretty();
32//! ```
33//!
34//! # Macro integration
35//!
36//! In attribute macros, add `debug` or `debug = "pretty"` to emit the generated
37//! code as a compiler `note` diagnostic. Requires `ZYN_DEBUG` to be set:
38//!
39//! ```ignore
40//! #[zyn::element(debug)]
41//! fn greeting(name: syn::Ident) -> zyn::TokenStream { ... }
42//!
43//! // ZYN_DEBUG="*" cargo build
44//! // → note: zyn::element ─── Greeting
45//! //         struct Greeting { pub name : syn :: Ident , } impl ...
46//! ```
47
48#[cfg(feature = "pretty")]
49mod pretty;
50
51/// Wraps a reference to a [`proc_macro2::TokenStream`] and provides formatting
52/// methods for debug output.
53///
54/// Created by [`DebugExt::debug()`]. Use [`.raw()`](Self::raw) for unformatted
55/// output or [`.pretty()`](Self::pretty) for `prettyplease`-formatted output.
56pub struct DebugTokens<'a> {
57    tokens: &'a proc_macro2::TokenStream,
58}
59
60/// Extension trait that adds `.debug()` to [`proc_macro2::TokenStream`].
61///
62/// # Example
63///
64/// ```ignore
65/// use zyn::debug::DebugExt;
66///
67/// let output: String = tokens.debug().raw();
68/// ```
69pub trait DebugExt {
70    fn debug(&self) -> DebugTokens<'_>;
71}
72
73impl DebugExt for proc_macro2::TokenStream {
74    fn debug(&self) -> DebugTokens<'_> {
75        DebugTokens { tokens: self }
76    }
77}
78
79impl DebugTokens<'_> {
80    /// Returns the raw `TokenStream::to_string()` output.
81    ///
82    /// This is a flat, single-line string with fully-qualified paths and spaces
83    /// between all tokens. No extra dependencies required.
84    pub fn raw(&self) -> String {
85        self.tokens.to_string()
86    }
87
88    /// Returns the token stream formatted as proper Rust code using `prettyplease`.
89    ///
90    /// Falls back to `TokenStream::to_string()` if the tokens cannot be parsed
91    /// as a valid Rust file.
92    ///
93    /// Requires the `pretty` feature:
94    ///
95    /// ```toml
96    /// zyn = { version = "0.3", features = ["pretty"] }
97    /// ```
98    #[cfg(feature = "pretty")]
99    pub fn pretty(&self) -> String {
100        pretty::pretty(self.tokens)
101    }
102}