-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce Accessor Component Macros (#56)
* Refactor derive_component * Use into_compile_error instead of unwrap * Validate entries in component spec * Implement parser for getter fields * Define GetterField struct * Draft derive_use_fields_impl * Check that return type must be reference * Export cgp_getter macro * Replace Self:: with Context:: inside provider impl * Properly concatenate HasField constraints * Implement UseDelegate if there is only one method * Derive macro is now working * Break down implementation into smaller modules * Implement derive auto getter * cgp_auto_getter macro is now working * Fix clippy * Fix formatting * Add changelog * Fix CI
- Loading branch information
1 parent
8fe487c
commit c86ec51
Showing
30 changed files
with
564 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,4 @@ | ||
max_width = 100 | ||
reorder_imports = true | ||
|
||
# nightly only | ||
|
||
# group_imports = "StdExternalCrate" | ||
# imports_granularity = "Module" | ||
group_imports = "StdExternalCrate" | ||
imports_granularity = "Module" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
crates/cgp-component-macro-lib/src/getter_component/blanket.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
use alloc::string::ToString; | ||
|
||
use proc_macro2::TokenStream; | ||
use quote::quote; | ||
use syn::{parse_quote, Ident, ItemImpl, ItemTrait}; | ||
|
||
use crate::getter_component::getter_field::GetterField; | ||
use crate::getter_component::symbol::symbol_from_string; | ||
|
||
pub fn derive_blanket_impl( | ||
context_type: &Ident, | ||
consumer_trait: &ItemTrait, | ||
fields: &[GetterField], | ||
) -> ItemImpl { | ||
let consumer_name = &consumer_trait.ident; | ||
|
||
let mut constraints = consumer_trait.supertraits.clone(); | ||
|
||
let mut methods: TokenStream = TokenStream::new(); | ||
|
||
for field in fields { | ||
let field_name = &field.field_name; | ||
let provider_type = &field.provider_type; | ||
let field_symbol = symbol_from_string(&field.field_name.to_string()); | ||
|
||
if field.field_mut.is_none() { | ||
constraints.push(parse_quote! { | ||
HasField< #field_symbol, Value = #provider_type > | ||
}); | ||
|
||
methods.extend(quote! { | ||
fn #field_name( &self ) -> & #provider_type { | ||
self.get_field( ::core::marker::PhantomData::< #field_symbol > ) | ||
} | ||
}); | ||
} else { | ||
constraints.push(parse_quote! { | ||
HasFieldMut< #field_symbol, Value = #provider_type > | ||
}); | ||
|
||
methods.extend(quote! { | ||
fn #field_name( &mut self ) -> &mut #provider_type { | ||
self.get_field_mut( ::core::marker::PhantomData::< #field_symbol > ) | ||
} | ||
}); | ||
} | ||
} | ||
|
||
parse_quote! { | ||
impl< #context_type > #consumer_name for #context_type | ||
where | ||
#context_type: #constraints | ||
{ | ||
#methods | ||
} | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
crates/cgp-component-macro-lib/src/getter_component/derive.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use proc_macro2::{Span, TokenStream}; | ||
use quote::quote; | ||
use syn::{Error, Ident, ItemTrait}; | ||
|
||
use crate::derive_component::component_spec::ComponentSpec; | ||
use crate::derive_component::derive::derive_component_with_ast; | ||
use crate::getter_component::blanket::derive_blanket_impl; | ||
use crate::getter_component::getter_field::GetterField; | ||
use crate::getter_component::parse::parse_getter_fields; | ||
use crate::getter_component::use_field::derive_use_field_impl; | ||
use crate::getter_component::use_fields::derive_use_fields_impl; | ||
use crate::getter_component::with_provider::derive_with_provider_impl; | ||
|
||
pub fn derive_getter_component(attr: TokenStream, body: TokenStream) -> syn::Result<TokenStream> { | ||
let spec: ComponentSpec = syn::parse2(attr)?; | ||
let consumer_trait: ItemTrait = syn::parse2(body)?; | ||
|
||
let derived_component = derive_component_with_ast(&spec, &consumer_trait)?; | ||
|
||
let fields = parse_getter_fields(&spec.context_type, &consumer_trait)?; | ||
|
||
let use_fields_impl = derive_use_fields_impl(&spec, &consumer_trait, &fields); | ||
|
||
let m_field: Option<[GetterField; 1]> = fields.try_into().ok(); | ||
|
||
let mut derived = quote! { | ||
#derived_component | ||
|
||
#use_fields_impl | ||
}; | ||
|
||
if let Some([field]) = m_field { | ||
let use_field_impl = derive_use_field_impl(&spec, &consumer_trait, &field); | ||
let use_provider_impl = derive_with_provider_impl(&spec, &consumer_trait, &field); | ||
|
||
derived.extend(use_field_impl); | ||
derived.extend(use_provider_impl); | ||
} | ||
|
||
Ok(derived) | ||
} | ||
|
||
pub fn derive_auto_getter_component( | ||
attr: TokenStream, | ||
body: TokenStream, | ||
) -> syn::Result<TokenStream> { | ||
if !attr.is_empty() { | ||
return Err(Error::new( | ||
Span::call_site(), | ||
"#[derive_auto_getter] does not accept any attribute argument", | ||
)); | ||
} | ||
|
||
let consumer_trait: ItemTrait = syn::parse2(body)?; | ||
|
||
let context_type = Ident::new("Context", Span::call_site()); | ||
|
||
let fields = parse_getter_fields(&context_type, &consumer_trait)?; | ||
|
||
let blanket_impl = derive_blanket_impl(&context_type, &consumer_trait, &fields); | ||
|
||
Ok(quote! { | ||
#consumer_trait | ||
#blanket_impl | ||
}) | ||
} |
9 changes: 9 additions & 0 deletions
9
crates/cgp-component-macro-lib/src/getter_component/getter_field.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
use syn::token::Mut; | ||
use syn::{Ident, Type}; | ||
|
||
pub struct GetterField { | ||
pub field_name: Ident, | ||
pub field_type: Type, | ||
pub provider_type: Type, | ||
pub field_mut: Option<Mut>, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
pub mod blanket; | ||
pub mod derive; | ||
pub mod getter_field; | ||
pub mod parse; | ||
pub mod symbol; | ||
pub mod use_field; | ||
pub mod use_fields; | ||
pub mod with_provider; |
Oops, something went wrong.