From d9ee00468deb28d807bafd487d453d5b5803bf96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Wo=C5=BAniak?= Date: Tue, 19 Nov 2024 15:20:15 +0100 Subject: [PATCH] feat: Assert no attributes used on `self` and `ctx` --- sylvia-derive/src/parser/mod.rs | 29 +++++++++++++++++++ .../ui/attributes/payload/invalid_usage.rs | 28 ++++++++++++++++++ .../attributes/payload/invalid_usage.stderr | 20 +++++++++++++ 3 files changed, 77 insertions(+) diff --git a/sylvia-derive/src/parser/mod.rs b/sylvia-derive/src/parser/mod.rs index 5a8e955e..e4f496e4 100644 --- a/sylvia-derive/src/parser/mod.rs +++ b/sylvia-derive/src/parser/mod.rs @@ -67,6 +67,35 @@ pub fn process_fields<'s, Generic>( where Generic: GetPath + PartialEq, { + // Assert no accidental usage of Sylvia attributes on `self` and `ctx` parameters. + sig.inputs.iter().take(2).for_each(|arg| match arg { + FnArg::Receiver(item) => { + item.attrs.iter().for_each(|attr| { + if SylviaAttribute::new(attr).is_none() { + return; + } + emit_error!(attr.span(), + "Invalid usage of Sylvia attribute."; + note = "First and second arguments of the method should be `self` and `ctx` respectively."; + note = "Unexpected attribute on `self` parameter." + ); + }); + } + + FnArg::Typed(item) => { + item.attrs.iter().for_each(|attr| { + if SylviaAttribute::new(attr).is_none() { + return; + } + emit_error!(attr.span(), + "Invalid usage of Sylvia attribute."; + note = "First and second arguments of the method should be `self` and `ctx` respectively."; + note = "Unexpected attribute on `ctx` parameter." + ); + }); + } + }); + sig.inputs .iter() .skip(2) diff --git a/sylvia/tests/ui/attributes/payload/invalid_usage.rs b/sylvia/tests/ui/attributes/payload/invalid_usage.rs index 70297070..1946aa27 100644 --- a/sylvia/tests/ui/attributes/payload/invalid_usage.rs +++ b/sylvia/tests/ui/attributes/payload/invalid_usage.rs @@ -26,4 +26,32 @@ pub mod used_on_context { } } +pub mod used_on_self { + use super::*; + + pub struct Contract {} + + #[sylvia::contract] + #[sv::features(replies)] + impl Contract { + pub const fn new() -> Self { + Self {} + } + + #[sv::msg(instantiate)] + fn instantiate(&self, _ctx: InstantiateCtx) -> StdResult { + Ok(Response::new()) + } + + #[sv::msg(reply, reply_on=success)] + fn reply( + #[sv::payload(raw)] &self, + _ctx: ReplyCtx, + payload: Binary, + ) -> StdResult { + Ok(Response::new()) + } + } +} + fn main() {} diff --git a/sylvia/tests/ui/attributes/payload/invalid_usage.stderr b/sylvia/tests/ui/attributes/payload/invalid_usage.stderr index 6896e3a4..5b670502 100644 --- a/sylvia/tests/ui/attributes/payload/invalid_usage.stderr +++ b/sylvia/tests/ui/attributes/payload/invalid_usage.stderr @@ -1,3 +1,13 @@ +error: Invalid usage of Sylvia attribute. + + = note: First and second arguments of the method should be `self` and `ctx` respectively. + = note: Unexpected attribute on `ctx` parameter. + + --> tests/ui/attributes/payload/invalid_usage.rs:23:25 + | +23 | fn reply(&self, #[sv::payload(raw)] _ctx: ReplyCtx) -> StdResult { + | ^ + error: Missing payload parameter. = note: Expected at least one payload parameter at the end of parameter list. @@ -6,3 +16,13 @@ error: Missing payload parameter. | 23 | fn reply(&self, #[sv::payload(raw)] _ctx: ReplyCtx) -> StdResult { | ^^^^^ + +error: Invalid usage of Sylvia attribute. + + = note: First and second arguments of the method should be `self` and `ctx` respectively. + = note: Unexpected attribute on `self` parameter. + + --> tests/ui/attributes/payload/invalid_usage.rs:48:13 + | +48 | #[sv::payload(raw)] &self, + | ^