51 lines
1.6 KiB
Rust
51 lines
1.6 KiB
Rust
use std::{fs, io, path::Path};
|
|
|
|
use proc_macro2::TokenStream;
|
|
use sabry_procmacro_impl::impls::styly;
|
|
use syn::{spanned::Spanned, visit::Visit};
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum FileVisitError {
|
|
#[error("Could not read file")]
|
|
Read(#[from] io::Error),
|
|
#[error("styly! macro found, yet invalid")]
|
|
Styly(#[from] syn::Error),
|
|
}
|
|
|
|
/// Visit file, returning either [StylyVisitor] or error
|
|
pub fn visit_file(path: &Path) -> Result<StylyVisitor, FileVisitError> {
|
|
let content = fs::read_to_string(path)?;
|
|
let code_file = syn::parse_file(&content)?;
|
|
|
|
let mut styly_visitor = StylyVisitor {
|
|
found_stylys: vec![],
|
|
};
|
|
styly_visitor.visit_file(&code_file);
|
|
|
|
Ok(styly_visitor)
|
|
}
|
|
|
|
/// Syn Visitor, which will look at every `styly!` macro,
|
|
/// parse its input tokenstream and avaluate it, capturing [styly::MacroSyntax] result
|
|
///
|
|
/// ## Panics
|
|
///
|
|
/// If either macro body is not a [TokenStream], or [styly::parse_macro_syntax] is not [Ok]
|
|
#[derive(Debug)]
|
|
pub struct StylyVisitor {
|
|
pub found_stylys: Vec<styly::MacroSyntax>,
|
|
}
|
|
|
|
impl<'ast> Visit<'ast> for StylyVisitor {
|
|
fn visit_item_macro(&mut self, node: &'ast syn::ItemMacro) {
|
|
if node.mac.path.get_ident().is_some_and(|i| i == "styly") {
|
|
let body = node.mac.parse_body::<TokenStream>().unwrap_or_else(|_| {
|
|
panic!("could not parse `styly!` macro at {:?}", node.mac.span())
|
|
});
|
|
let macro_data = styly::parse_macro_syntax(body).unwrap_or_else(|_| {
|
|
panic!("could not parse `styly!` macro at {:?}", node.mac.span())
|
|
});
|
|
self.found_stylys.push(macro_data);
|
|
}
|
|
}
|
|
}
|