Report errors using syn::Error

This commit is contained in:
Mario Carbajal 2024-01-11 14:23:04 -03:00
parent b905a32c4a
commit 1ef05ec04d
3 changed files with 48 additions and 39 deletions

1
Cargo.lock generated
View File

@ -387,6 +387,7 @@ dependencies = [
name = "stylance-macros" name = "stylance-macros"
version = "0.0.7" version = "0.0.7"
dependencies = [ dependencies = [
"anyhow",
"proc-macro2", "proc-macro2",
"quote", "quote",
"stylance-core", "stylance-core",

View File

@ -14,6 +14,7 @@ nightly = []
[dependencies] [dependencies]
stylance-core = { workspace = true } stylance-core = { workspace = true }
anyhow = "1.0.79"
proc-macro2 = "1.0.71" proc-macro2 = "1.0.71"
quote = "1.0.33" quote = "1.0.33"
syn = { version = "2.0.43", features = ["extra-traits"] } syn = { version = "2.0.43", features = ["extra-traits"] }

View File

@ -2,20 +2,17 @@
use std::{env, path::Path}; use std::{env, path::Path};
use anyhow::Context as _;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use proc_macro2::{Ident, Span}; use proc_macro2::{Ident, Span};
use quote::quote; use quote::quote;
use syn::{parse_macro_input, LitStr}; use syn::{parse_macro_input, LitStr};
#[proc_macro] fn try_import_style_classes_with_path(
pub fn import_style_classes(input: TokenStream) -> TokenStream { manifest_path: &Path,
let input = parse_macro_input!(input as LitStr); file_path: &Path,
) -> anyhow::Result<TokenStream> {
let manifest_dir_env = env::var_os("CARGO_MANIFEST_DIR").expect("we need CARGO_MANIFEST_DIR"); let (_, classes) = stylance_core::get_classes(manifest_path, &file_path)?;
let manifest_path = Path::new(&manifest_dir_env);
let file_path = manifest_path.join(Path::new(&input.value()));
let (_, classes) = stylance_core::get_classes(manifest_path, &file_path).expect("Load classes");
let binding = file_path.canonicalize().unwrap(); let binding = file_path.canonicalize().unwrap();
let full_path = binding.to_string_lossy(); let full_path = binding.to_string_lossy();
@ -33,19 +30,38 @@ pub fn import_style_classes(input: TokenStream) -> TokenStream {
} }
}); });
quote! { Ok(quote! {
const _ : &[u8] = include_bytes!(#full_path); const _ : &[u8] = include_bytes!(#full_path);
#(#output_fields )* #(#output_fields )*
} }
.into() .into())
}
fn try_import_style_classes(input: &LitStr) -> anyhow::Result<TokenStream> {
let manifest_dir_env =
env::var_os("CARGO_MANIFEST_DIR").context("CARGO_MANIFEST_DIR env var not found")?;
let manifest_path = Path::new(&manifest_dir_env);
let file_path = manifest_path.join(Path::new(&input.value()));
try_import_style_classes_with_path(manifest_path, &file_path)
}
#[proc_macro]
pub fn import_style_classes(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as LitStr);
match try_import_style_classes(&input) {
Ok(ts) => ts,
Err(err) => syn::Error::new_spanned(&input, err.to_string())
.to_compile_error()
.into(),
}
} }
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
#[proc_macro] fn try_import_style_classes_rel(input: &LitStr) -> anyhow::Result<TokenStream> {
pub fn import_style_classes_rel(input: TokenStream) -> TokenStream { let manifest_dir_env =
let input = parse_macro_input!(input as LitStr); env::var_os("CARGO_MANIFEST_DIR").context("CARGO_MANIFEST_DIR env var not found")?;
let manifest_dir_env = env::var_os("CARGO_MANIFEST_DIR").expect("we need CARGO_MANIFEST_DIR");
let manifest_path = Path::new(&manifest_dir_env); let manifest_path = Path::new(&manifest_dir_env);
let call_site_path = proc_macro::Span::call_site().source().source_file().path(); let call_site_path = proc_macro::Span::call_site().source().source_file().path();
@ -54,27 +70,18 @@ pub fn import_style_classes_rel(input: TokenStream) -> TokenStream {
.expect("No current path") .expect("No current path")
.join(input.value()); .join(input.value());
let (_, classes) = stylance_core::get_classes(manifest_path, &file_path).expect("Load classes"); try_import_style_classes_with_path(manifest_path, &file_path)
}
let binding = file_path.canonicalize().unwrap();
let full_path = binding.to_string_lossy(); #[cfg(feature = "nightly")]
#[proc_macro]
let identifiers = classes pub fn import_style_classes_rel(input: TokenStream) -> TokenStream {
.iter() let input = parse_macro_input!(input as LitStr);
.map(|class| Ident::new(&class.original_name.replace('-', "_"), Span::call_site()))
.collect::<Vec<_>>(); match try_import_style_classes_rel(&input) {
Ok(ts) => ts,
let output_fields = classes.iter().zip(identifiers).map(|(class, class_ident)| { Err(err) => syn::Error::new_spanned(&input, err.to_string())
let class_str = &class.hashed_name; .to_compile_error()
quote! { .into(),
#[allow(non_upper_case_globals)] }
pub const #class_ident: &str = #class_str;
}
});
quote! {
const _ : &[u8] = include_bytes!(#full_path);
#(#output_fields )*
}
.into()
} }