From e47561398c128fd6d4dfa53b8443ce15551f8b57 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Tue, 15 Oct 2024 00:56:26 -0500 Subject: [PATCH 1/4] sqf: Add lint for unneeded not --- libs/sqf/src/analyze/lints/s19_extra_not.rs | 134 ++++++++++++++++++ libs/sqf/tests/lints.rs | 1 + libs/sqf/tests/lints/s19_extra_not/source.sqf | 1 + .../sqf/tests/lints/s19_extra_not/stdout.ansi | 6 + 4 files changed, 142 insertions(+) create mode 100644 libs/sqf/src/analyze/lints/s19_extra_not.rs create mode 100644 libs/sqf/tests/lints/s19_extra_not/source.sqf create mode 100644 libs/sqf/tests/lints/s19_extra_not/stdout.ansi diff --git a/libs/sqf/src/analyze/lints/s19_extra_not.rs b/libs/sqf/src/analyze/lints/s19_extra_not.rs new file mode 100644 index 00000000..170f5a0d --- /dev/null +++ b/libs/sqf/src/analyze/lints/s19_extra_not.rs @@ -0,0 +1,134 @@ +use std::{ops::Range, sync::Arc}; + +use hemtt_common::config::LintConfig; +use hemtt_workspace::{ + lint::{AnyLintRunner, Lint, LintRunner}, + reporting::{Code, Codes, Diagnostic, Processed, Severity}, +}; + +use crate::{analyze::SqfLintData, Expression, UnaryCommand}; + +crate::lint!(LintS19ExtraNot); + +impl Lint for LintS19ExtraNot { + fn ident(&self) -> &str { + "extra_not" + } + + fn sort(&self) -> u32 { + 190 + } + + fn description(&self) -> &str { + "Checks for extra not before a comparison" + } + + fn documentation(&self) -> &str { + r"### Example + +**Incorrect** +```sqf +! (5 isEqualTo 6) +``` +**Correct** +```sqf +(5 isNotEqualTo 6) +``` +" + } + + fn default_config(&self) -> LintConfig { + LintConfig::help() + } + + fn runners(&self) -> Vec>> { + vec![Box::new(Runner)] + } +} + +struct Runner; +impl LintRunner for Runner { + type Target = crate::Expression; + + fn run( + &self, + _project: Option<&hemtt_common::config::ProjectConfig>, + config: &LintConfig, + processed: Option<&hemtt_workspace::reporting::Processed>, + target: &Self::Target, + _data: &SqfLintData, + ) -> Codes { + const COMPARISON_CMDS: &[&str] = &[ + "==", + "!=", + "isEqualTo", + "isNotEqualTo", + "<", + "<=", + ">", + ">=", + ]; + let Some(processed) = processed else { + return Vec::new(); + }; + let Expression::UnaryCommand(UnaryCommand::Not, rhs, range) = target else { + return Vec::new(); + }; + let Expression::BinaryCommand(ref last_cmd, _, _, _) = **rhs else { + return Vec::new(); + }; + if !COMPARISON_CMDS.contains(&last_cmd.as_str()) { + return Vec::new(); + } + + vec![Arc::new(Code19ExtraNot::new( + range.clone(), + processed, + config.severity(), + ))] + } +} + +#[allow(clippy::module_name_repetitions)] +pub struct Code19ExtraNot { + span: Range, + severity: Severity, + diagnostic: Option, +} + +impl Code for Code19ExtraNot { + fn ident(&self) -> &'static str { + "L-S19" + } + fn link(&self) -> Option<&str> { + Some("/analysis/sqf.html#extra_not") + } + fn severity(&self) -> Severity { + self.severity + } + fn message(&self) -> String { + "Unneeded Not".to_string() + } + // fn label_message(&self) -> String { + // "".to_string() + // } + fn diagnostic(&self) -> Option { + self.diagnostic.clone() + } +} + +impl Code19ExtraNot { + #[must_use] + pub fn new(span: Range, processed: &Processed, severity: Severity) -> Self { + Self { + span, + severity, + diagnostic: None, + } + .generate_processed(processed) + } + fn generate_processed(mut self, processed: &Processed) -> Self { + self.diagnostic = Diagnostic::new_for_processed(&self, self.span.clone(), processed); + self + } +} diff --git a/libs/sqf/tests/lints.rs b/libs/sqf/tests/lints.rs index 447d05d6..307d7998 100644 --- a/libs/sqf/tests/lints.rs +++ b/libs/sqf/tests/lints.rs @@ -84,5 +84,6 @@ analyze!(s09_banned_command); analyze!(s11_if_not_else); analyze!(s17_var_all_caps); analyze!(s18_in_vehicle_check); +analyze!(s19_extra_not); analyze!(s20_bool_static_comparison); analyze!(s21_invalid_comparisons); diff --git a/libs/sqf/tests/lints/s19_extra_not/source.sqf b/libs/sqf/tests/lints/s19_extra_not/source.sqf new file mode 100644 index 00000000..e2fd34d9 --- /dev/null +++ b/libs/sqf/tests/lints/s19_extra_not/source.sqf @@ -0,0 +1 @@ +! (5 isEqualTo 6) \ No newline at end of file diff --git a/libs/sqf/tests/lints/s19_extra_not/stdout.ansi b/libs/sqf/tests/lints/s19_extra_not/stdout.ansi new file mode 100644 index 00000000..8442cfef --- /dev/null +++ b/libs/sqf/tests/lints/s19_extra_not/stdout.ansi @@ -0,0 +1,6 @@ +help[L-S19]: Unneeded Not + ┌─ source.sqf:1:1 + │ +1 │ ! (5 isEqualTo 6) + │ ^ Unneeded Not + From 8656e9c4ef4f795a35ab8a8a9ef83acc3b24af03 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Sun, 20 Oct 2024 18:56:47 -0500 Subject: [PATCH 2/4] update tests --- libs/sqf/tests/lints/s19_extra_not.sqf | 1 + libs/sqf/tests/lints/s19_extra_not/source.sqf | 1 - .../lints__simple_s19_extra_not.snap} | 7 +++++-- 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 libs/sqf/tests/lints/s19_extra_not.sqf delete mode 100644 libs/sqf/tests/lints/s19_extra_not/source.sqf rename libs/sqf/tests/{lints/s19_extra_not/stdout.ansi => snapshots/lints__simple_s19_extra_not.snap} (60%) diff --git a/libs/sqf/tests/lints/s19_extra_not.sqf b/libs/sqf/tests/lints/s19_extra_not.sqf new file mode 100644 index 00000000..a0eac2a3 --- /dev/null +++ b/libs/sqf/tests/lints/s19_extra_not.sqf @@ -0,0 +1 @@ +! (5 isEqualTo 6) diff --git a/libs/sqf/tests/lints/s19_extra_not/source.sqf b/libs/sqf/tests/lints/s19_extra_not/source.sqf deleted file mode 100644 index e2fd34d9..00000000 --- a/libs/sqf/tests/lints/s19_extra_not/source.sqf +++ /dev/null @@ -1 +0,0 @@ -! (5 isEqualTo 6) \ No newline at end of file diff --git a/libs/sqf/tests/lints/s19_extra_not/stdout.ansi b/libs/sqf/tests/snapshots/lints__simple_s19_extra_not.snap similarity index 60% rename from libs/sqf/tests/lints/s19_extra_not/stdout.ansi rename to libs/sqf/tests/snapshots/lints__simple_s19_extra_not.snap index 8442cfef..340a9513 100644 --- a/libs/sqf/tests/lints/s19_extra_not/stdout.ansi +++ b/libs/sqf/tests/snapshots/lints__simple_s19_extra_not.snap @@ -1,6 +1,9 @@ +--- +source: libs/sqf/tests/lints.rs +expression: lint(stringify! (s19_extra_not)) +--- help[L-S19]: Unneeded Not - ┌─ source.sqf:1:1 + ┌─ s19_extra_not.sqf:1:1 │ 1 │ ! (5 isEqualTo 6) │ ^ Unneeded Not - From ccc1e874f0db288d29bc6747594370fdad8f344b Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Mon, 21 Oct 2024 23:59:24 -0500 Subject: [PATCH 3/4] Update s19_extra_not.rs --- libs/sqf/src/analyze/lints/s19_extra_not.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/sqf/src/analyze/lints/s19_extra_not.rs b/libs/sqf/src/analyze/lints/s19_extra_not.rs index 170f5a0d..fd4e46f1 100644 --- a/libs/sqf/src/analyze/lints/s19_extra_not.rs +++ b/libs/sqf/src/analyze/lints/s19_extra_not.rs @@ -8,7 +8,7 @@ use hemtt_workspace::{ use crate::{analyze::SqfLintData, Expression, UnaryCommand}; -crate::lint!(LintS19ExtraNot); +crate::analyze::lint!(LintS19ExtraNot); impl Lint for LintS19ExtraNot { fn ident(&self) -> &str { @@ -128,7 +128,7 @@ impl Code19ExtraNot { .generate_processed(processed) } fn generate_processed(mut self, processed: &Processed) -> Self { - self.diagnostic = Diagnostic::new_for_processed(&self, self.span.clone(), processed); + self.diagnostic = Diagnostic::from_code_processed(&self, self.span.clone(), processed); self } } From cca5851277f0bfbd22d64d583c67ce229bc23cb1 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Wed, 18 Dec 2024 01:15:20 -0600 Subject: [PATCH 4/4] make label_message lowercase --- libs/sqf/src/analyze/lints/s19_extra_not.rs | 12 ++++++------ .../tests/snapshots/lints__simple_s19_extra_not.snap | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/sqf/src/analyze/lints/s19_extra_not.rs b/libs/sqf/src/analyze/lints/s19_extra_not.rs index fd4e46f1..c1b51547 100644 --- a/libs/sqf/src/analyze/lints/s19_extra_not.rs +++ b/libs/sqf/src/analyze/lints/s19_extra_not.rs @@ -11,7 +11,7 @@ use crate::{analyze::SqfLintData, Expression, UnaryCommand}; crate::analyze::lint!(LintS19ExtraNot); impl Lint for LintS19ExtraNot { - fn ident(&self) -> &str { + fn ident(&self) -> &'static str { "extra_not" } @@ -19,11 +19,11 @@ impl Lint for LintS19ExtraNot { 190 } - fn description(&self) -> &str { + fn description(&self) -> &'static str { "Checks for extra not before a comparison" } - fn documentation(&self) -> &str { + fn documentation(&self) -> &'static str { r"### Example **Incorrect** @@ -109,9 +109,9 @@ impl Code for Code19ExtraNot { fn message(&self) -> String { "Unneeded Not".to_string() } - // fn label_message(&self) -> String { - // "".to_string() - // } + fn label_message(&self) -> String { + "unneeded not".to_string() + } fn diagnostic(&self) -> Option { self.diagnostic.clone() } diff --git a/libs/sqf/tests/snapshots/lints__simple_s19_extra_not.snap b/libs/sqf/tests/snapshots/lints__simple_s19_extra_not.snap index 340a9513..af4d04ff 100644 --- a/libs/sqf/tests/snapshots/lints__simple_s19_extra_not.snap +++ b/libs/sqf/tests/snapshots/lints__simple_s19_extra_not.snap @@ -6,4 +6,4 @@ expression: lint(stringify! (s19_extra_not)) ┌─ s19_extra_not.sqf:1:1 │ 1 │ ! (5 isEqualTo 6) - │ ^ Unneeded Not + │ ^ unneeded not