tree_type_proc_macro/
lib.rs

1//! Procedural macro for defining type-safe directory trees
2
3use proc_macro::TokenStream;
4use syn::parse_macro_input;
5
6mod codegen;
7mod core;
8mod parser;
9mod simple;
10mod validation;
11
12use crate::core::TreeDef;
13
14/// Procedural macro for defining type-safe directory trees.
15///
16/// # Syntax
17///
18/// ```ignore
19/// tree_type! {
20///     RootName => {
21///         file_name,
22///         file_with_custom("custom.txt"),
23///         dir_name/ => {
24///             nested_file
25///         },
26///         [id: String] => DynamicDir => {
27///             content
28///         }
29///     }
30/// }
31/// ```
32///
33/// # Attributes
34///
35/// - `#[required]` - Path must exist during validation
36/// - `#[optional]` - Path is optional (default behavior)
37/// - `#[default]` - Create with default content
38/// - `#[validate(fn)]` - Custom validation function
39/// - `#[pattern(regex)]` - Regex validation (requires `pattern-validation` feature)
40/// - `#[symlink = target]` - Create symlink to target
41///
42/// # Note
43///
44/// This macro generates code that references types from the `tree-type` crate.
45/// Make sure to add both crates as dependencies:
46///
47/// ```toml
48/// [dependencies]
49/// tree-type = "0.1"
50/// tree-type-proc-macro = "0.1"
51/// ```
52#[proc_macro]
53pub fn tree_type(input: TokenStream) -> TokenStream {
54    let tree_def = parse_macro_input!(input as TreeDef);
55
56    // Validate the tree structure
57    if let Err(err) = validation::validate_tree(&tree_def) {
58        return TokenStream::from(err.to_compile_error());
59    }
60
61    // Generate code
62    let expanded = codegen::generate_code(&tree_def);
63    TokenStream::from(expanded)
64}
65
66/// Procedural macro for creating a simple file type.
67///
68/// Creates a type representing a single file with standard file operations.
69/// Automatically includes serde derives when the serde feature is enabled.
70///
71/// # Example
72///
73/// ```ignore
74/// file_type!(ConfigFile);
75///
76/// let config = ConfigFile::new("/etc/app/config.toml");
77/// let contents = config.read_to_string()?;
78/// ```
79#[proc_macro]
80pub fn file_type(input: TokenStream) -> TokenStream {
81    let name = parse_macro_input!(input as syn::Ident);
82    let expanded = simple::generate_file_type(&name);
83    TokenStream::from(expanded)
84}
85
86/// Procedural macro for creating a simple directory type.
87///
88/// Creates a type representing a directory with standard directory operations.
89/// Automatically includes serde derives when the serde feature is enabled.
90///
91/// # Example
92///
93/// ```ignore
94/// dir_type!(CacheDir);
95///
96/// let cache = CacheDir::new("/var/cache/app");
97/// cache.create_all()?;
98/// ```
99#[proc_macro]
100pub fn dir_type(input: TokenStream) -> TokenStream {
101    let name = parse_macro_input!(input as syn::Ident);
102    let expanded = simple::generate_dir_type(&name);
103    TokenStream::from(expanded)
104}