Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redesign derive_component to cgp_component with improved syntax #38

Merged
merged 4 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

## Pre-Release

- Redesign `derive_component` to `cgp_component` with improved syntax - [#38](https://github.com/contextgeneric/cgp/pull/38)
- Rename the attribute `#[derive_component]` to `#[cgp_component]`
- The macro syntax has been changed as follows:
- Old: `#[derive_component(NameGetterComponent, NameGetter<MyContext>)]`
- New: `#[cgp_component { name: NameGetterComponent, context: MyContext, provider: NameGetter }]`
- For migration, the following regex can be used in a global search and replace:
- Search: `#\[derive_component\(([\w<>, ]+), (\w+)<(\w+)>\)\]`
- Replace: `#[cgp_component {\n name: $1,\n provider: $2,\n context: $3,\n}]`

- Support async-generic feature flags in cgp-async - [#37](https://github.com/contextgeneric/cgp/pull/37)
- Introduce the following feature flags to `cgp-async`:
- `async`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use proc_macro2::Span;
use quote::ToTokens;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::token::{Comma, Gt, Lt};
use syn::Ident;
use syn::{Error, Ident};

use crate::derive_component::entry::Entries;

pub struct ComponentSpec {
pub provider_name: Ident,
Expand All @@ -10,7 +14,60 @@ pub struct ComponentSpec {
pub component_params: Punctuated<Ident, Comma>,
}

pub struct ComponentNameSpec {
pub component_name: Ident,
pub component_params: Punctuated<Ident, Comma>,
}

impl Parse for ComponentSpec {
fn parse(input: ParseStream) -> syn::Result<Self> {
let Entries { entries } = input.parse()?;

let context_type: Ident = {
let raw_context_type = entries.get(&Ident::new("context", Span::call_site()));

if let Some(context_type) = raw_context_type {
syn::parse2(context_type.to_token_stream())?
} else {
Ident::new("Context", Span::call_site())
}
};

let provider_name: Ident = {
let raw_provider_name = entries
.get(&Ident::new("provider", Span::call_site()))
.ok_or_else(|| Error::new(input.span(), "expect provider name to be given"))?;

syn::parse2(raw_provider_name.to_token_stream())?
};

let (component_name, component_params) = {
let raw_component_name = entries.get(&Ident::new("name", Span::call_site()));

if let Some(raw_component_name) = raw_component_name {
let ComponentNameSpec {
component_name,
component_params,
} = syn::parse2(raw_component_name.to_token_stream())?;
(component_name, component_params)
} else {
(
Ident::new(&format!("{}Component", provider_name), provider_name.span()),
Punctuated::default(),
)
}
};

Ok(ComponentSpec {
component_name,
provider_name,
context_type,
component_params,
})
}
}

impl Parse for ComponentNameSpec {
fn parse(input: ParseStream) -> syn::Result<Self> {
let component_name: Ident = input.parse()?;

Expand All @@ -27,20 +84,8 @@ impl Parse for ComponentSpec {
Punctuated::default()
};

let _: Comma = input.parse()?;

let provider_name: Ident = input.parse()?;

let _: Lt = input.parse()?;

let context_type: Ident = input.parse()?;

let _: Gt = input.parse()?;

Ok(ComponentSpec {
Ok(Self {
component_name,
provider_name,
context_type,
component_params,
})
}
Expand Down
36 changes: 36 additions & 0 deletions crates/cgp-component-macro-lib/src/derive_component/entry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use std::collections::BTreeMap;

use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::token::{Colon, Comma};
use syn::{Ident, Type};

pub struct Entry {
pub key: Ident,
pub value: Type,
}

impl Parse for Entry {
fn parse(input: ParseStream) -> syn::Result<Self> {
let key = input.parse()?;
let _colon: Colon = input.parse()?;
let value = input.parse()?;

Ok(Entry { key, value })
}
}

pub struct Entries {
pub entries: BTreeMap<Ident, Type>,
}

impl Parse for Entries {
fn parse(input: ParseStream) -> syn::Result<Self> {
let entry_list: Punctuated<Entry, Comma> = Punctuated::parse_terminated(input)?;

let entries =
BTreeMap::from_iter(entry_list.into_iter().map(|entry| (entry.key, entry.value)));

Ok(Entries { entries })
}
}
1 change: 1 addition & 0 deletions crates/cgp-component-macro-lib/src/derive_component/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod consumer_impl;
pub mod delegate_fn;
pub mod delegate_type;
pub mod derive;
pub mod entry;
pub mod provider_impl;
pub mod provider_trait;
pub mod replace_self_receiver;
Expand Down
10 changes: 8 additions & 2 deletions crates/cgp-component-macro-lib/src/tests/derive_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use crate::tests::helper::equal::equal_token_stream;
#[test]
fn test_basic_derive_component() {
derive_component(
quote! { FooComponent, FooProvider<Context> },
quote! {
name: FooComponent,
provider: FooProvider,
},
quote! {
pub trait HasFoo<Bar> {
type Foo;
Expand All @@ -20,7 +23,10 @@ fn test_basic_derive_component() {
#[test]
fn test_derive_component_with_const_generic() {
let derived = derive_component(
quote! { FooComponent, FooProvider<Context> },
quote! {
name: FooComponent,
provider: FooProvider,
},
quote! {
pub trait HasFoo<const BAR: usize> {
type Foo;
Expand Down
2 changes: 1 addition & 1 deletion crates/cgp-component-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extern crate proc_macro;
use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn derive_component(attr: TokenStream, item: TokenStream) -> TokenStream {
pub fn cgp_component(attr: TokenStream, item: TokenStream) -> TokenStream {
cgp_component_macro_lib::derive_component(attr.into(), item.into()).into()
}

Expand Down
2 changes: 1 addition & 1 deletion crates/cgp-component/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
pub mod traits;
pub mod types;

pub use cgp_component_macro::{define_components, delegate_components, derive_component};
pub use cgp_component_macro::{cgp_component, define_components, delegate_components};
pub use traits::{DelegateComponent, HasComponents};
pub use types::{UseContext, UseDelegate, WithContext, WithProvider};
2 changes: 1 addition & 1 deletion crates/cgp-core/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub use cgp_async::{async_trait, Async, MaybeSend, MaybeStatic, MaybeSync};
pub use cgp_component::{
define_components, delegate_components, derive_component, DelegateComponent, HasComponents,
cgp_component, define_components, delegate_components, DelegateComponent, HasComponents,
};
pub use cgp_error::{CanRaiseError, HasErrorType};
pub use cgp_field::{
Expand Down
6 changes: 4 additions & 2 deletions crates/cgp-error/src/can_raise_error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cgp_component::{derive_component, DelegateComponent, HasComponents, UseDelegate};
use cgp_component::{cgp_component, DelegateComponent, HasComponents, UseDelegate};

use crate::has_error_type::HasErrorType;

Expand All @@ -10,7 +10,9 @@ use crate::has_error_type::HasErrorType;
[`err: ParseIntError`](core::num::ParseIntError) and get back
a [`Context::Error`](HasErrorType::Error) value.
*/
#[derive_component(ErrorRaiserComponent, ErrorRaiser<Context>)]
#[cgp_component {
provider: ErrorRaiser
}]
pub trait CanRaiseError<E>: HasErrorType {
fn raise_error(e: E) -> Self::Error;
}
Expand Down
7 changes: 5 additions & 2 deletions crates/cgp-error/src/has_error_type.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use core::fmt::Debug;

use cgp_async::Async;
use cgp_component::{derive_component, DelegateComponent, HasComponents, WithProvider};
use cgp_component::{cgp_component, DelegateComponent, HasComponents, WithProvider};
use cgp_type::traits::has_type::ProvideType;

/**
Expand All @@ -15,7 +15,10 @@ use cgp_type::traits::has_type::ProvideType;
parent traits, so that multiple traits can all refer to the same abstract
`Self::Error` type.
*/
#[derive_component(ErrorTypeComponent, ProvideErrorType<Context>)]
#[cgp_component {
name: ErrorTypeComponent,
provider: ProvideErrorType,
}]
pub trait HasErrorType {
/**
The `Error` associated type is also required to implement [`Debug`].
Expand Down
7 changes: 5 additions & 2 deletions crates/cgp-inner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

extern crate alloc;

use cgp_component::{derive_component, DelegateComponent, HasComponents};
use cgp_component::{cgp_component, DelegateComponent, HasComponents};

#[derive_component(InnerComponent, ProvideInner<Context>)]
#[cgp_component {
name: InnerComponent,
provider: ProvideInner,
}]
pub trait HasInner {
type Inner;

Expand Down
4 changes: 3 additions & 1 deletion crates/cgp-run/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ use cgp_async::*;
use cgp_component::*;
use cgp_error::HasErrorType;

#[derive_component(RunnerComponent, Runner<Context>)]
#[cgp_component {
provider: Runner,
}]
#[async_trait]
pub trait CanRun: Async + HasErrorType {
async fn run(&self) -> Result<(), Self::Error>;
Expand Down
7 changes: 5 additions & 2 deletions crates/cgp-type/src/traits/has_type.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use cgp_component::{derive_component, DelegateComponent, HasComponents, UseContext, UseDelegate};
use cgp_component::{cgp_component, DelegateComponent, HasComponents, UseContext, UseDelegate};

#[derive_component(TypeComponent, ProvideType<Context>)]
#[cgp_component {
name: TypeComponent,
provider: ProvideType,
}]
pub trait HasType<Tag> {
type Type;
}
Expand Down
Loading