Use one standard Iris resource bundle
This commit is contained in:
1 parent
6dbc800739
commit
7e5a4c0071
16 files changed
+129
-100
No files matched your search
+69
-14
@@ -103,31 +103,72 @@ pub fn widget_trait(input: TokenStream) -> TokenStream {
|
||||
|
||||
#[proc_macro_derive(DesktopUiState, attributes(desktop_ui_state))]
|
||||
pub fn derive_desktop_ui_state(input: TokenStream) -> TokenStream {
|
||||
let mut output = proc_macro2::TokenStream::new();
|
||||
|
||||
let state: ItemStruct = parse_macro_input!(input);
|
||||
derive_ui_state(
|
||||
state,
|
||||
UiStateDerive {
|
||||
module: "desktop",
|
||||
state_type: "DesktopUiState",
|
||||
state_trait: "HasDesktopUiState",
|
||||
field_attr: "desktop_ui_state",
|
||||
get: "desktop_state",
|
||||
get_mut: "desktop_state_mut",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(AndroidUiState, attributes(android_ui_state))]
|
||||
pub fn derive_android_ui_state(input: TokenStream) -> TokenStream {
|
||||
let state: ItemStruct = parse_macro_input!(input);
|
||||
derive_ui_state(
|
||||
state,
|
||||
UiStateDerive {
|
||||
module: "android",
|
||||
state_type: "AndroidUiState",
|
||||
state_trait: "HasAndroidUiState",
|
||||
field_attr: "android_ui_state",
|
||||
get: "android_state",
|
||||
get_mut: "android_state_mut",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
struct UiStateDerive {
|
||||
module: &'static str,
|
||||
state_type: &'static str,
|
||||
state_trait: &'static str,
|
||||
field_attr: &'static str,
|
||||
get: &'static str,
|
||||
get_mut: &'static str,
|
||||
}
|
||||
|
||||
fn derive_ui_state(state: ItemStruct, names: UiStateDerive) -> TokenStream {
|
||||
let UiStateDerive {
|
||||
module,
|
||||
state_type,
|
||||
state_trait,
|
||||
field_attr,
|
||||
get,
|
||||
get_mut,
|
||||
} = names;
|
||||
let mut output = proc_macro2::TokenStream::new();
|
||||
let mut found_attr = false;
|
||||
let mut state_field = None;
|
||||
for field in &state.fields {
|
||||
if !found_attr
|
||||
&& let Type::Path(path) = &field.ty
|
||||
&& path.path.is_ident("DesktopUiState")
|
||||
&& path.path.is_ident(state_type)
|
||||
{
|
||||
state_field = Some(field);
|
||||
}
|
||||
let Some(attr) = field
|
||||
.attrs
|
||||
.iter()
|
||||
.find(|a| a.path().is_ident("desktop_ui_state"))
|
||||
else {
|
||||
let Some(attr) = field.attrs.iter().find(|a| a.path().is_ident(field_attr)) else {
|
||||
continue;
|
||||
};
|
||||
if found_attr {
|
||||
output.extend(
|
||||
Error::new(
|
||||
attr.span(),
|
||||
"cannot have more than one desktop_ui_state attribute",
|
||||
format!("cannot have more than one {field_attr} attribute"),
|
||||
)
|
||||
.into_compile_error(),
|
||||
);
|
||||
@@ -138,18 +179,32 @@ pub fn derive_desktop_ui_state(input: TokenStream) -> TokenStream {
|
||||
}
|
||||
let Some(field) = state_field else {
|
||||
output.extend(
|
||||
Error::new(state.ident.span(), "no DesktopUiState field found").into_compile_error(),
|
||||
Error::new(state.ident.span(), format!("no {state_type} field found"))
|
||||
.into_compile_error(),
|
||||
);
|
||||
return output.into();
|
||||
};
|
||||
let sname = &state.ident;
|
||||
let fname = field.ident.as_ref().unwrap();
|
||||
let Some(fname) = field.ident.as_ref() else {
|
||||
return Error::new(
|
||||
field.span(),
|
||||
format!("the {state_type} field must be named"),
|
||||
)
|
||||
.into_compile_error()
|
||||
.into();
|
||||
};
|
||||
let module = Ident::new(module, sname.span());
|
||||
let state_type = Ident::new(state_type, sname.span());
|
||||
let state_trait = Ident::new(state_trait, sname.span());
|
||||
let get = Ident::new(get, sname.span());
|
||||
let get_mut = Ident::new(get_mut, sname.span());
|
||||
let (impl_generics, type_generics, where_clause) = state.generics.split_for_impl();
|
||||
output.extend(quote! {
|
||||
impl iris::desktop::HasDesktopUiState for #sname {
|
||||
fn desktop_state(&self) -> &iris::desktop::DesktopUiState {
|
||||
impl #impl_generics iris::#module::#state_trait for #sname #type_generics #where_clause {
|
||||
fn #get(&self) -> &iris::#module::#state_type {
|
||||
&self.#fname
|
||||
}
|
||||
fn desktop_state_mut(&mut self) -> &mut iris::desktop::DesktopUiState {
|
||||
fn #get_mut(&mut self) -> &mut iris::#module::#state_type {
|
||||
&mut self.#fname
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user