wip: first commit

This commit is contained in:
Alexander Navarro 2025-05-01 19:21:41 -04:00
commit 98448060b9
24 changed files with 709 additions and 0 deletions

57
src/lib.rs Normal file
View file

@ -0,0 +1,57 @@
mod manifest;
extern crate proc_macro;
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};
use quote::quote;
use crate::manifest::impl_vite_manifest_macro;
/// Example of [function-like procedural macro][1].
///
/// [1]: https://doc.rust-lang.org/reference/procedural-macros.html#function-like-procedural-macros
#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let tokens = quote! {
#input
struct Hello;
};
tokens.into()
}
/// Example of user-defined [derive mode macro][1]
///
/// [1]: https://doc.rust-lang.org/reference/procedural-macros.html#derive-mode-macros
#[proc_macro_derive(ViteManifest, attributes(root))]
pub fn vite_manifest(input: TokenStream) -> TokenStream {
let ast = syn::parse_macro_input!(input as DeriveInput);
impl_vite_manifest_macro(&ast)
}
/// Example of user-defined [procedural macro attribute][1].
///
/// [1]: https://doc.rust-lang.org/reference/procedural-macros.html#attribute-macros
#[proc_macro_attribute]
pub fn root(_args: TokenStream, input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let tokens = quote! {
struct #name {
root: String,
}
impl Default for #name {
fn default() -> Self {
#name { root: String::new() }
}
}
};
tokens.into()
}

44
src/manifest.rs Normal file
View file

@ -0,0 +1,44 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{Attribute, Expr, Lit, Meta};
fn get_attr(path: &str, attrs: &Vec<Attribute>) -> Option<Lit> {
let attr = attrs.iter().find(|&a| a.path().is_ident(path))?;
match &attr.meta {
Meta::Path(_) => None,
Meta::List(_) => None,
Meta::NameValue(nv) => {
if let Expr::Lit(expr) = &nv.value {
return Some(expr.lit.clone());
}
None
}
}
}
pub(crate) fn impl_vite_manifest_macro(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let attr = ast
.attrs
.iter()
.find(|&a| a.path().is_ident("root"))
.unwrap();
let value = if let Lit::Str(lit) = get_attr("root", &ast.attrs).unwrap() {
lit.value()
} else {
panic!("root attribute must be a string literal")
};
let gen = quote! {
impl #name {
pub fn get_root(&self) -> &str {
#value
}
}
};
gen.into()
}