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}