diff --git a/MANUAL.md b/MANUAL.md index cc63d7c9..12942b07 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -4429,6 +4429,41 @@ The most relevant clauses of IEEE1800-2017 are: +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +## Syntax Rule: `package_item_not_in_package` + +### Hint + +Place item into a package, module, interface, program, udp, or config. + +### Reason + +Globally-scoped items are not supported by some tools. + +### Pass Example (1 of 1) +```systemverilog +package P; + localparam int A = 1; +endpackage +``` + +### Fail Example (1 of 1) +```systemverilog +localparam int A = 1; +``` + +### Explanation + +Some tools support items, like variables, nets, `task`, `function`, `class`, +`localparam`, `covergroup`, etc. to be defined outside of a `package`, +`module`, `program`, `interface` etc. which can lead to namespace issues. + +The most relevant clauses of IEEE1800-2017 are: +- A.1.11 Package items + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ## Syntax Rule: `parameter_default_value` diff --git a/md/syntaxrules-explanation-package_item_not_in_package.md b/md/syntaxrules-explanation-package_item_not_in_package.md new file mode 100644 index 00000000..17ee9304 --- /dev/null +++ b/md/syntaxrules-explanation-package_item_not_in_package.md @@ -0,0 +1,6 @@ +Some tools support items, like variables, nets, `task`, `function`, `class`, +`localparam`, `covergroup`, etc. to be defined outside of a `package`, +`module`, `program`, `interface` etc. which can lead to namespace issues. + +The most relevant clauses of IEEE1800-2017 are: +- A.1.11 Package items diff --git a/src/syntaxrules/package_item_not_in_package.rs b/src/syntaxrules/package_item_not_in_package.rs new file mode 100644 index 00000000..9f5da352 --- /dev/null +++ b/src/syntaxrules/package_item_not_in_package.rs @@ -0,0 +1,60 @@ +use crate::config::ConfigOption; +use crate::linter::{SyntaxRule, SyntaxRuleResult}; +use sv_parser::{NodeEvent, PackageItem, RefNode, SyntaxTree}; + +#[derive(Default)] +pub struct PackageItemNotUnderPackage { + under_package_declaration: bool, +} + +impl SyntaxRule for PackageItemNotUnderPackage { + fn check( + &mut self, + _syntax_tree: &SyntaxTree, + event: &NodeEvent, + _option: &ConfigOption, + ) -> SyntaxRuleResult { + let node = match event { + NodeEvent::Enter(x) => { + match x { + RefNode::PackageDeclaration(_) => { + self.under_package_declaration = true; + } + _ => () + } + x + } + NodeEvent::Leave(x) => { + match x { + RefNode::PackageDeclaration(_) => { + self.under_package_declaration = false; + } + _ => () + } + return SyntaxRuleResult::Pass; + } + }; + + if self.under_package_declaration { + SyntaxRuleResult::Pass + } else { + match node { + RefNode::PackageItem(PackageItem::PackageOrGenerateItemDeclaration(_)) | + RefNode::PackageItem(PackageItem::PackageExportDeclaration(_)) => SyntaxRuleResult::Fail, + _ => SyntaxRuleResult::Pass + } + } + } + + fn name(&self) -> String { + String::from("package_item_not_in_package") + } + + fn hint(&self, _option: &ConfigOption) -> String { + String::from("Place item into a package, module, interface, program, udp, or config.") + } + + fn reason(&self) -> String { + String::from("Globally-scoped items are not supported by some tools.") + } +} diff --git a/testcases/syntaxrules/fail/package_item_not_in_package.sv b/testcases/syntaxrules/fail/package_item_not_in_package.sv new file mode 100644 index 00000000..45e3314c --- /dev/null +++ b/testcases/syntaxrules/fail/package_item_not_in_package.sv @@ -0,0 +1 @@ +localparam int A = 1; diff --git a/testcases/syntaxrules/pass/package_item_not_in_package.sv b/testcases/syntaxrules/pass/package_item_not_in_package.sv new file mode 100644 index 00000000..35aa8477 --- /dev/null +++ b/testcases/syntaxrules/pass/package_item_not_in_package.sv @@ -0,0 +1,3 @@ +package P; + localparam int A = 1; +endpackage