diff --git a/crates/solidity/inputs/language/bindings/rules.msgb b/crates/solidity/inputs/language/bindings/rules.msgb index 67b4f67ee..264e1d6eb 100644 --- a/crates/solidity/inputs/language/bindings/rules.msgb +++ b/crates/solidity/inputs/language/bindings/rules.msgb @@ -686,6 +686,12 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i } } +;; Emit statements + +@stmt [Statement [EmitStatement @event_ident [IdentifierPath]]] { + edge @event_ident.left -> @stmt.lexical_scope +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; State Variables @@ -847,6 +853,41 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i } +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Event definitions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +@event [EventDefinition @name name: [Identifier]] { + node def + attr (def) node_definition = @name + attr (def) definiens_node = @event + + edge @event.def -> def +} + +;; Make the enum available to the enclosing contract/interface/library. +;; NB. top-level enums (ie. those defined at the file's level) are already +;; covered above + +@contract [ContractDefinition members: [ContractMembers + item: [ContractMember @event variant: [EventDefinition]] +]] { + edge @contract.type_members -> @event.def +} + +@interface [InterfaceDefinition members: [InterfaceMembers + item: [ContractMember @event variant: [EventDefinition]] +]] { + edge @interface.type_members -> @event.def +} + +@library [LibraryDefinition members: [LibraryMembers + item: [ContractMember @event variant: [EventDefinition]] +]] { + edge @library.members -> @event.def +} + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Expressions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -982,6 +1023,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i attr (ref) node_reference = @name ;; TODO: bind the named argument to the parameters definition of the function ;; (is this possible given that function references are expressions?) + ;; Ditto for events emissions (where it should be possible for sure) } @args [ArgumentsDeclaration [NamedArgumentsDeclaration @@ -994,6 +1036,11 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @args.lexical_scope -> @funcall.lexical_scope } +;; Arguments to an event in an emit statement +@stmt [Statement [EmitStatement @args [ArgumentsDeclaration]]] { + edge @args.lexical_scope -> @stmt.lexical_scope +} + ;;; Type expressions diff --git a/crates/solidity/outputs/cargo/slang_solidity/src/generated/bindings/generated/binding_rules.rs b/crates/solidity/outputs/cargo/slang_solidity/src/generated/bindings/generated/binding_rules.rs index d370ea469..64ee2354a 100644 --- a/crates/solidity/outputs/cargo/slang_solidity/src/generated/bindings/generated/binding_rules.rs +++ b/crates/solidity/outputs/cargo/slang_solidity/src/generated/bindings/generated/binding_rules.rs @@ -691,6 +691,12 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i } } +;; Emit statements + +@stmt [Statement [EmitStatement @event_ident [IdentifierPath]]] { + edge @event_ident.left -> @stmt.lexical_scope +} + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; State Variables @@ -852,6 +858,41 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i } +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Event definitions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +@event [EventDefinition @name name: [Identifier]] { + node def + attr (def) node_definition = @name + attr (def) definiens_node = @event + + edge @event.def -> def +} + +;; Make the enum available to the enclosing contract/interface/library. +;; NB. top-level enums (ie. those defined at the file's level) are already +;; covered above + +@contract [ContractDefinition members: [ContractMembers + item: [ContractMember @event variant: [EventDefinition]] +]] { + edge @contract.type_members -> @event.def +} + +@interface [InterfaceDefinition members: [InterfaceMembers + item: [ContractMember @event variant: [EventDefinition]] +]] { + edge @interface.type_members -> @event.def +} + +@library [LibraryDefinition members: [LibraryMembers + item: [ContractMember @event variant: [EventDefinition]] +]] { + edge @library.members -> @event.def +} + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Expressions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -987,6 +1028,7 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i attr (ref) node_reference = @name ;; TODO: bind the named argument to the parameters definition of the function ;; (is this possible given that function references are expressions?) + ;; Ditto for events emissions (where it should be possible for sure) } @args [ArgumentsDeclaration [NamedArgumentsDeclaration @@ -999,6 +1041,11 @@ attribute symbol_reference = symbol => type = "push_symbol", symbol = symbol, i edge @args.lexical_scope -> @funcall.lexical_scope } +;; Arguments to an event in an emit statement +@stmt [Statement [EmitStatement @args [ArgumentsDeclaration]]] { + edge @args.lexical_scope -> @stmt.lexical_scope +} + ;;; Type expressions diff --git a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/assertions.rs b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/assertions.rs index 31b9c3c6d..ce0104a81 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/assertions.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/assertions.rs @@ -368,8 +368,6 @@ fn check_reference_assertion( version: &Version, assertion: &ReferenceAssertion<'_>, ) -> Result<(), String> { - let resolution = find_and_resolve_reference(bindings, assertion)?; - let ReferenceAssertion { id, version_req, .. } = assertion; @@ -380,6 +378,18 @@ fn check_reference_assertion( true }; + let resolution = match find_and_resolve_reference(bindings, assertion) { + Ok(resolution) => resolution, + Err(err) => { + if version_matches { + return Err(err); + } + // the reference was not found, but that's ok if the assertion + // should not match for this version + None + } + }; + match (version_matches, id) { (true, None) => { if let Some(resolved_handle) = resolution { diff --git a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/control.rs b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/control.rs index 278eff10e..b972d4d97 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/control.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_assertions/generated/control.rs @@ -9,6 +9,11 @@ fn do_while() -> Result<()> { run("control", "do_while") } +#[test] +fn emit_event() -> Result<()> { + run("control", "emit_event") +} + #[test] fn for_empty_init_or_cond() -> Result<()> { run("control", "for_empty_init_or_cond") diff --git a/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/control.rs b/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/control.rs index 3ce301ad6..0e2da5c47 100644 --- a/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/control.rs +++ b/crates/solidity/outputs/cargo/tests/src/bindings_output/generated/control.rs @@ -4,6 +4,11 @@ use anyhow::Result; use crate::bindings_output::runner::run; +#[test] +fn emit_event() -> Result<()> { + run("control", "emit_event") +} + #[test] fn for_empty_clauses() -> Result<()> { run("control", "for_empty_clauses") diff --git a/crates/solidity/testing/snapshots/bindings_assertions/control/emit_event.sol b/crates/solidity/testing/snapshots/bindings_assertions/control/emit_event.sol new file mode 100644 index 000000000..6a0cf6be3 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_assertions/control/emit_event.sol @@ -0,0 +1,23 @@ +contract Test { + event TestEvent(int id); + // ^def:1 + + function test_emit() public { + int x = 1; + // ^def:2 + + emit TestEvent(x); + // ^ref:2 (>= 0.4.21) + // ^ref:1 (>= 0.4.21) + emit Utils.Debug(x); + // ^ref:2 (>= 0.4.21) + // ^ref:4 (>= 0.4.21) + // ^ref:3 (>= 0.4.21) + } +} + +library Utils { + // ^def:3 + event Debug(int subject); + // ^def:4 +} diff --git a/crates/solidity/testing/snapshots/bindings_output/control/emit_event/generated/0.4.11-failure.txt b/crates/solidity/testing/snapshots/bindings_output/control/emit_event/generated/0.4.11-failure.txt new file mode 100644 index 000000000..2b5a354b9 --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/control/emit_event/generated/0.4.11-failure.txt @@ -0,0 +1,33 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +Parse errors: +Error: Expected Equal or Semicolon. + ╭─[input.sol:7:23] + │ + 7 │ emit TestEvent(x); + │ ─┬─ + │ ╰─── Error occurred here. +───╯ +References and definitions: + ╭─[input.sol:1:1] + │ + 1 │ contract Test { + │ ──┬─ + │ ╰─── def: 1 + 2 │ event TestEvent(int id); + │ ────┬──── + │ ╰────── def: 2 + │ + 4 │ function test_emit() public { + │ ────┬──── + │ ╰────── def: 3 + 5 │ int x = 1; + │ ┬ + │ ╰── def: 4 + │ + 7 │ emit TestEvent(x); + │ ──┬─ ────┬──── + │ ╰───────────── unresolved + │ │ + │ ╰────── def: 5 +───╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/control/emit_event/generated/0.4.21-success.txt b/crates/solidity/testing/snapshots/bindings_output/control/emit_event/generated/0.4.21-success.txt new file mode 100644 index 000000000..43d4a26bd --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/control/emit_event/generated/0.4.21-success.txt @@ -0,0 +1,25 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +References and definitions: + ╭─[input.sol:1:1] + │ + 1 │ contract Test { + │ ──┬─ + │ ╰─── def: 1 + 2 │ event TestEvent(int id); + │ ────┬──── + │ ╰────── def: 2 + │ + 4 │ function test_emit() public { + │ ────┬──── + │ ╰────── def: 3 + 5 │ int x = 1; + │ ┬ + │ ╰── def: 4 + │ + 7 │ emit TestEvent(x); + │ ────┬──── ┬ + │ ╰──────── ref: 2 + │ │ + │ ╰── ref: 4 +───╯ diff --git a/crates/solidity/testing/snapshots/bindings_output/control/emit_event/input.sol b/crates/solidity/testing/snapshots/bindings_output/control/emit_event/input.sol new file mode 100644 index 000000000..5edd938fe --- /dev/null +++ b/crates/solidity/testing/snapshots/bindings_output/control/emit_event/input.sol @@ -0,0 +1,9 @@ +contract Test { + event TestEvent(int id); + + function test_emit() public { + int x = 1; + + emit TestEvent(x); + } +}