Skip to content

Commit

Permalink
Redesign derive_component to cgp_component with improved syntax (#38
Browse files Browse the repository at this point in the history
)

* Rename derive_component to cgp_component

* Redesign syntax for cgp_component macro

* Update tests

* Add changelog
  • Loading branch information
soareschen authored Dec 7, 2024
1 parent 106990f commit 7c680b7
Show file tree
Hide file tree
Showing 13 changed files with 138 additions and 28 deletions.
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

0 comments on commit 7c680b7

Please sign in to comment.