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 cannot delegating multiple methods when adding additional arguments #72

Merged
merged 1 commit into from
Jul 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
58 changes: 49 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@
//! ```
//! - Inserts `#[inline(always)]` automatically (unless you specify `#[inline]` manually on the method)
//! - You can use an attribute on a whole segment to automatically apply it to all methods in that
//! segment:
//! segment:
//! ```rust
//! use delegate::delegate;
//!
Expand Down Expand Up @@ -245,7 +245,7 @@
//! }
//! ```
//! - Modify how will an input parameter be passed to the delegated method with parameter attribute modifiers.
//! Currently, the following modifiers are supported:
//! Currently, the following modifiers are supported:
//! - `#[into]`: Calls `.into()` on the parameter passed to the delegated method.
//! - `#[as_ref]`: Calls `.as_ref()` on the parameter passed to the delegated method.
//! - `#[newtype]`: Calls `.0` on the parameter passed to the delegated method.
Expand Down Expand Up @@ -274,7 +274,7 @@
//! }
//! ```
//! - Specify a trait through which will the delegated method be called
//! (using [UFCS](https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls).
//! (using [UFCS](https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls).
//! ```rust
//! use delegate::delegate;
//!
Expand All @@ -301,6 +301,44 @@
//! }
//! }
//! ```
//!
//! - Add additional arguments to method
//!
//! ```rust
//! use delegate::delegate;
//! use std::cell::OnceCell;
//! struct Inner(u32);
//! impl Inner {
//! pub fn new(m: u32) -> Self {
//! // some "very complex" constructing work
//! Self(m)
//! }
//! pub fn method(&self, n: u32) -> u32 {
//! self.0 + n
//! }
//! }
//!
//! struct Wrapper {
//! inner: OnceCell<Inner>,
//! }
//!
//! impl Wrapper {
//! pub fn new() -> Self {
//! Self {
//! inner: OnceCell::new(),
//! }
//! }
//! fn content(&self, val: u32) -> &Inner {
//! self.inner.get_or_init(|| Inner(val))
//! }
//! delegate! {
//! to |k: u32| self.content(k) {
//! // `wrapper.method(k, num)` will call `self.content(k).method(num)`
//! pub fn method(&self, num: u32) -> u32;
//! }
//! }
//! }
//! ```
//! - Delegate associated functions
//! ```rust
//! use delegate::delegate;
Expand Down Expand Up @@ -733,7 +771,7 @@ impl<F: Fn(&Expr) -> proc_macro2::TokenStream> VisitMut for MatchVisitor<F> {
pub fn delegate(tokens: TokenStream) -> TokenStream {
let block: DelegationBlock = syn::parse_macro_input!(tokens);
let sections = block.segments.iter().map(|delegator| {
let mut delegated_expr = &delegator.delegator;
let delegated_expr = &delegator.delegator;
let functions = delegator.methods.iter().map(|method| {
let input = &method.method;
let mut signature = input.sig.clone();
Expand Down Expand Up @@ -797,9 +835,11 @@ pub fn delegate(tokens: TokenStream) -> TokenStream {
let is_method = method.method.sig.receiver().is_some();

// Use the body of a closure (like `|k: u32| <body>`) as the delegation expression
if let Expr::Closure(closure) = delegated_expr {
delegated_expr = &closure.body;
}
let delegated_body = if let Expr::Closure(closure) = delegated_expr {
&closure.body
} else {
delegated_expr
};

let span = input.span();
let generate_await = attributes
Expand Down Expand Up @@ -841,12 +881,12 @@ pub fn delegate(tokens: TokenStream) -> TokenStream {
}
body
};
let mut body = if let Expr::Match(expr_match) = delegated_expr {
let mut body = if let Expr::Match(expr_match) = delegated_body {
let mut expr_match = expr_match.clone();
MatchVisitor(modify_expr).visit_expr_match_mut(&mut expr_match);
expr_match.into_token_stream()
} else {
modify_expr(delegated_expr)
modify_expr(delegated_body)
};

if let syn::ReturnType::Default = &signature.output {
Expand Down
16 changes: 15 additions & 1 deletion tests/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
fn method(&self, n: u32) -> u32 {
self.0 + n
}

fn method2(&self, n: u32) -> u32 {
self.0 - n
}
}

struct Wrapper {
Expand All @@ -26,13 +30,16 @@
delegate! {
to |k: u32| self.content(k) {
pub fn method(&self, num: u32) -> u32;
pub fn method2(&self, num: u32) -> u32;
}
}
}

let wrapper = Wrapper::new();
assert_eq!(wrapper.method(1, 2), 3);
assert_eq!(wrapper.method2(1, 1), 0);
assert_eq!(wrapper.method(1, 3), 4);
assert_eq!(wrapper.method2(1, 0), 1);
}

#[test]
Expand All @@ -42,19 +49,26 @@
fn method(n: u32) -> u32 {
n + 1
}

fn method2(n: u32) -> u32 {
n - 1
}
}

struct Wrapper;

impl Wrapper {
// Doesn't really make sense, but should copmile
// Doesn't really make sense, but should compile
delegate! {
to |k: u32| Inner {

Check warning on line 63 in tests/closure.rs

View workflow job for this annotation

GitHub Actions / Test (beta)

unused variable: `k`

Check warning on line 63 in tests/closure.rs

View workflow job for this annotation

GitHub Actions / Test (beta)

unused variable: `k`
pub fn method(num: u32) -> u32;
pub fn method2(num: u32) -> u32;
}
}
}

assert_eq!(Wrapper::method(1, 2), 3);
assert_eq!(Wrapper::method2(1, 1), 0);
assert_eq!(Wrapper::method(1, 3), 4);
assert_eq!(Wrapper::method(1, 0), 1);
}
Loading