From a5b5253c423e7872541790b7db9ff39a391c4ea8 Mon Sep 17 00:00:00 2001 From: Tilak Madichetti Date: Wed, 11 Dec 2024 20:28:22 +0530 Subject: [PATCH] feat: syntax checker for functions with modifiers (#164) --- crates/ast/src/ast/item.rs | 7 +++++++ crates/sema/src/ast_passes.rs | 11 +++++++++++ tests/ui/resolve/func_modifiers.sol | 15 +++++++++++++++ tests/ui/resolve/func_modifiers.stderr | 16 ++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 tests/ui/resolve/func_modifiers.sol create mode 100644 tests/ui/resolve/func_modifiers.stderr diff --git a/crates/ast/src/ast/item.rs b/crates/ast/src/ast/item.rs index d31768c3..34490f3f 100644 --- a/crates/ast/src/ast/item.rs +++ b/crates/ast/src/ast/item.rs @@ -390,6 +390,13 @@ pub struct ItemFunction<'ast> { pub body: Option>, } +impl ItemFunction<'_> { + /// Returns `true` if the function is implemented + pub fn is_implemented(&self) -> bool { + self.body.is_some() + } +} + /// A function header: `function helloWorld() external pure returns(string memory)`. #[derive(Debug, Default)] pub struct FunctionHeader<'ast> { diff --git a/crates/sema/src/ast_passes.rs b/crates/sema/src/ast_passes.rs index 64ea0813..89afc456 100644 --- a/crates/sema/src/ast_passes.rs +++ b/crates/sema/src/ast_passes.rs @@ -211,6 +211,17 @@ impl<'ast> Visit<'ast> for AstValidator<'_, 'ast> { } } } + if contract.kind.is_interface() && !func.header.modifiers.is_empty() { + self.dcx() + .err("functions in interfaces cannot have modifiers") + .span(self.span) + .emit(); + } else if !func.is_implemented() && !func.header.modifiers.is_empty() { + self.dcx() + .err("functions without implementation cannot have modifiers") + .span(self.span) + .emit(); + } } if func.header.visibility.is_none() { diff --git a/tests/ui/resolve/func_modifiers.sol b/tests/ui/resolve/func_modifiers.sol new file mode 100644 index 00000000..f3d47da5 --- /dev/null +++ b/tests/ui/resolve/func_modifiers.sol @@ -0,0 +1,15 @@ +abstract contract A { + modifier x() { + _; + } + + function updateState() external virtual x; //~ERROR: functions without implementation cannot have modifiers +} + +interface B { + modifier x() { + _; + } + + function j() external x; //~ERROR: functions in interfaces cannot have modifiers +} diff --git a/tests/ui/resolve/func_modifiers.stderr b/tests/ui/resolve/func_modifiers.stderr new file mode 100644 index 00000000..d2aa2aac --- /dev/null +++ b/tests/ui/resolve/func_modifiers.stderr @@ -0,0 +1,16 @@ +error: functions without implementation cannot have modifiers + --> ROOT/tests/ui/resolve/func_modifiers.sol:LL:CC + | +LL | function updateState() external virtual x; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + +error: functions in interfaces cannot have modifiers + --> ROOT/tests/ui/resolve/func_modifiers.sol:LL:CC + | +LL | function j() external x; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + +error: aborting due to 2 previous errors +