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

fix: invalid generics in expanded macros #117

Merged
merged 6 commits into from
Jul 5, 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
2 changes: 1 addition & 1 deletion crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub mod prelude {
pub use ngyn_shared::{
core::NgynEngine,
server::{
Dto, FullResponse, NgynContext, NgynRequest, NgynResponse, Param, Query, Transducer,
Body, FullResponse, NgynContext, NgynRequest, NgynResponse, Param, Query, Transducer,
Transformer,
},
traits::{NgynGate, NgynInjectable, NgynMiddleware},
Expand Down
28 changes: 24 additions & 4 deletions crates/macros/src/common/controller_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,23 @@ pub(crate) fn controller_macro(args: TokenStream, input: TokenStream) -> TokenSt
init,
inject,
} = syn::parse_macro_input!(args as ControllerArgs);

let generics_params = if generics.params.iter().count() > 0 {
let generics_params = generics.params.iter().map(|param| {
if let syn::GenericParam::Type(ty) = param {
let ident = &ty.ident;
quote! { #ident }
} else {
quote! { #param }
}
});
quote! {
<#(#generics_params),*>
}
} else {
quote! {}
};

let controller_fields = parse_macro_data(data);

let fields: Vec<_> = controller_fields
Expand Down Expand Up @@ -120,10 +137,13 @@ pub(crate) fn controller_macro(args: TokenStream, input: TokenStream) -> TokenSt
ident,
ty,
colon_token,
attrs,
vis,
..
}| {
quote! {
#ident #colon_token #ty::default()
#(#attrs),*
#vis #ident #colon_token #ty::default()
}
},
)
Expand Down Expand Up @@ -184,9 +204,9 @@ pub(crate) fn controller_macro(args: TokenStream, input: TokenStream) -> TokenSt
#(#fields),*
}

impl #generics ngyn::shared::traits::NgynControllerHandler for #ident #generics {}
impl #generics ngyn::shared::traits::NgynControllerHandler for #ident #generics_params {}

impl #generics ngyn::shared::traits::NgynInjectable for #ident #generics {
impl #generics ngyn::shared::traits::NgynInjectable for #ident #generics_params {
fn new() -> Self {
#init_controller
}
Expand All @@ -197,7 +217,7 @@ pub(crate) fn controller_macro(args: TokenStream, input: TokenStream) -> TokenSt
}

#[ngyn::prelude::async_trait]
impl #generics ngyn::shared::traits::NgynController for #ident #generics {
impl #generics ngyn::shared::traits::NgynController for #ident #generics_params {
fn routes(&self) -> Vec<(String, String, String)> {
Self::ROUTES.iter().map(|(path, method, handler)| {
((format!("{}{}", #path_prefix, path)).replace("//", "/"), method.to_string(), handler.to_string())
Expand Down
25 changes: 22 additions & 3 deletions crates/macros/src/common/injectable_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,22 @@ pub(crate) fn injectable_macro(args: TokenStream, input: TokenStream) -> TokenSt
let InjectableArgs { init, inject } = syn::parse_macro_input!(args as InjectableArgs);
let injectable_fields = parse_macro_data(data);

let generics_params = if generics.params.iter().count() > 0 {
let generics_params = generics.params.iter().map(|param| {
if let syn::GenericParam::Type(ty) = param {
let ident = &ty.ident;
quote! { #ident }
} else {
quote! { #param }
}
});
quote! {
<#(#generics_params),*>
}
} else {
quote! {}
};

let fields: Vec<_> = injectable_fields
.iter()
.map(
Expand All @@ -73,10 +89,13 @@ pub(crate) fn injectable_macro(args: TokenStream, input: TokenStream) -> TokenSt
ident,
ty,
colon_token,
attrs,
vis,
..
}| {
quote! {
#ident #colon_token #ty::default()
#(#attrs),*
#vis #ident #colon_token #ty::default()
}
},
)
Expand Down Expand Up @@ -112,7 +131,7 @@ pub(crate) fn injectable_macro(args: TokenStream, input: TokenStream) -> TokenSt
#(#fields),*
}

impl #generics ngyn::prelude::NgynInjectable for #ident #generics {
impl #generics ngyn::prelude::NgynInjectable for #ident #generics_params {
fn new() -> Self {
#init_injectable
}
Expand All @@ -122,7 +141,7 @@ pub(crate) fn injectable_macro(args: TokenStream, input: TokenStream) -> TokenSt
}
}

impl #generics Default for #ident #generics {
impl #generics Default for #ident #generics_params {
fn default() -> Self {
Self::new()
}
Expand Down
63 changes: 52 additions & 11 deletions crates/macros/src/common/routes_macro.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
use ngyn_shared::{enums::Path, server::Method};
use ngyn_shared::server::Method;
use proc_macro::TokenStream;
use quote::quote;
use syn::{ItemImpl, Signature};

pub(crate) struct PathArg {
pub path: Option<Path>,
/// Path Enum
///
/// This enum represents the possible types of paths that can be used in the application.
/// It can either be a Single path represented as a String or Multiple paths represented as a Vector of Strings.
#[derive(Debug, Clone)]
pub(super) enum RoutePath {
/// Represents a single path as a String
Single(String),
/// Represents multiple paths as a Vector of Strings
Multiple(Vec<String>),
}

impl RoutePath {
pub fn each<F>(&self, mut f: F)
where
F: FnMut(&str),
{
match self {
RoutePath::Single(path) => f(path),
RoutePath::Multiple(paths) => paths.iter().for_each(|path| f(path)),
}
}
}

pub(super) struct PathArg {
pub path: Option<RoutePath>,
}

impl syn::parse::Parse for PathArg {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let path = if input.peek(syn::LitStr) {
let path = input.parse::<syn::LitStr>()?;
Some(Path::Single(path.value()))
Some(RoutePath::Single(path.value()))
} else if input.peek(syn::token::Bracket) {
let content;
syn::bracketed!(content in input);
Expand All @@ -23,7 +47,7 @@ impl syn::parse::Parse for PathArg {
content.parse::<syn::Token![,]>()?;
}
}
Some(Path::Multiple(paths))
Some(RoutePath::Multiple(paths))
} else {
None
};
Expand All @@ -32,12 +56,12 @@ impl syn::parse::Parse for PathArg {
}
}

pub(crate) struct Args {
pub path: Option<Path>,
pub(super) struct RouteArgs {
pub path: Option<RoutePath>,
pub http_method: String,
}

impl syn::parse::Parse for Args {
impl syn::parse::Parse for RouteArgs {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let http_method = input.parse::<syn::LitStr>()?.value();

Expand All @@ -49,7 +73,7 @@ impl syn::parse::Parse for Args {

let PathArg { path } = input.parse::<PathArg>()?;

Ok(Args { path, http_method })
Ok(RouteArgs { path, http_method })
}
}

Expand Down Expand Up @@ -94,6 +118,22 @@ pub(crate) fn routes_macro(raw_input: TokenStream) -> TokenStream {
panic!("Trait impls are not supported");
}

let generics_params = if generics.params.iter().count() > 0 {
let generics_params = generics.params.iter().map(|param| {
if let syn::GenericParam::Type(ty) = param {
let ident = &ty.ident;
quote! { #ident }
} else {
quote! { #param }
}
});
quote! {
<#(#generics_params),*>
}
} else {
quote! {}
};

let mut route_defs: Vec<_> = Vec::new();
let mut handle_routes: Vec<_> = Vec::new();

Expand All @@ -111,7 +151,8 @@ pub(crate) fn routes_macro(raw_input: TokenStream) -> TokenStream {
{
let (path, http_method) = {
if attr.path().is_ident("route") {
let Args { path, http_method } = attr.parse_args::<Args>().unwrap();
let RouteArgs { path, http_method } =
attr.parse_args::<RouteArgs>().unwrap();
(path, http_method)
} else {
let PathArg { path } = attr.parse_args::<PathArg>().unwrap();
Expand Down Expand Up @@ -240,7 +281,7 @@ pub(crate) fn routes_macro(raw_input: TokenStream) -> TokenStream {

let expanded = quote! {
#defaultness #unsafety #(#attrs)*
#impl_token #generics #self_ty #generics {
#impl_token #generics #self_ty #generics_params {
const ROUTES: &'static [(&'static str, &'static str, &'static str)] = &[
#(#route_defs),*
];
Expand Down
2 changes: 1 addition & 1 deletion crates/macros/src/core/dto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub(crate) fn dto_macro(input: TokenStream) -> TokenStream {
let expanded = quote! {
impl #generics ngyn::prelude::Transformer<'_> for #ident #generics {
fn transform(cx: &mut ngyn::prelude::NgynContext, res: &mut ngyn::prelude::NgynResponse) -> Self {
let dto = ngyn::prelude::Dto::transform(cx, res);
let dto = ngyn::prelude::Body::transform(cx, res);
dto.parse::<#ident>().unwrap()
}
}
Expand Down
3 changes: 0 additions & 3 deletions crates/shared/src/enums/mod.rs

This file was deleted.

23 changes: 0 additions & 23 deletions crates/shared/src/enums/path_enum.rs

This file was deleted.

1 change: 0 additions & 1 deletion crates/shared/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod core;
pub mod enums;
pub mod server;
pub mod traits;
2 changes: 1 addition & 1 deletion crates/shared/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub use body::{ParseBytes, ToBytes};
pub use context::NgynContext;
use http_body_util::Full;
pub use hyper::body::Bytes;
pub use transformer::{Dto, Param, Query, Transducer, Transformer};
pub use transformer::{Body, Param, Query, Transducer, Transformer};

pub type NgynRequest = hyper::Request<Vec<u8>>;
pub type NgynResponse = hyper::Response<Full<Bytes>>;
Expand Down
8 changes: 4 additions & 4 deletions crates/shared/src/server/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,11 @@ impl Transformer<'_> for Query {
}

/// Represents a data transfer object struct.
pub struct Dto {
pub struct Body {
data: String,
}

impl Dto {
impl Body {
/// Parses the data into the specified type using serde deserialization.
///
/// # Arguments
Expand Down Expand Up @@ -250,7 +250,7 @@ impl Dto {
}
}

impl Transformer<'_> for Dto {
impl Transformer<'_> for Body {
/// Transforms the given `NgynContext` and `_res` into a `Dto` instance.
///
/// # Arguments
Expand All @@ -274,6 +274,6 @@ impl Transformer<'_> for Dto {
/// ```
fn transform(cx: &mut NgynContext, _res: &mut NgynResponse) -> Self {
let data = String::from_utf8_lossy(cx.request().body()).to_string();
Dto { data }
Body { data }
}
}
4 changes: 2 additions & 2 deletions crates/shared/src/traits/gate_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
};

/// Trait for implementing a gate.
pub trait NgynGate: NgynInjectable {
pub trait NgynGate<'a>: NgynInjectable {
/// Determines if the gate can activate for the given request.
///
/// ### Arguments
Expand All @@ -15,7 +15,7 @@ pub trait NgynGate: NgynInjectable {
/// ### Returns
///
/// Returns `true` if the route can activate, `false` otherwise.
fn can_activate(&self, _cx: &mut NgynContext, _res: &mut NgynResponse) -> bool {
fn can_activate(&self, _cx: &'a mut NgynContext, _res: &'a mut NgynResponse) -> bool {
true
}
}
2 changes: 1 addition & 1 deletion examples/weather_app/src/modules/weather/weather_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use ngyn::prelude::*;
#[injectable]
pub struct WeatherGate;

impl NgynGate for WeatherGate {
impl NgynGate<'_> for WeatherGate {
fn can_activate(&self, cx: &mut NgynContext, res: &mut NgynResponse) -> bool {
let query = Query::transform(cx, res);
if query.get("location").is_some() {
Expand Down
Loading