Skip to content

Commit 4285e6a

Browse files
ok
1 parent 3a0bd03 commit 4285e6a

File tree

6 files changed

+128
-202
lines changed

6 files changed

+128
-202
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/pgt_suppressions/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ version = "0.0.0"
1515
pgt_text_size = {workspace = true }
1616
pgt_diagnostics = {workspace = true }
1717
pgt_analyse = {workspace = true }
18+
tracing = { workspace = true }
1819

1920

crates/pgt_suppressions/src/lib.rs

Lines changed: 78 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::{
33
str::Lines,
44
};
55

6-
use pgt_analyse::RuleCategory;
6+
use pgt_analyse::{RuleCategory, RuleFilter};
77
use pgt_diagnostics::{Diagnostic, Location, MessageAndDescription};
88
use pgt_text_size::{TextRange, TextSize};
99

@@ -24,15 +24,15 @@ pub struct SuppressionDiagnostic {
2424
message: MessageAndDescription,
2525
}
2626

27-
#[derive(Debug)]
27+
#[derive(Debug, Clone)]
2828
pub enum SuppressionKind {
2929
File,
3030
Line,
3131
Start,
3232
End,
3333
}
3434

35-
#[derive(Debug, PartialEq)]
35+
#[derive(Debug, PartialEq, Clone)]
3636
enum RuleSpecifier {
3737
Category(RuleCategory),
3838
Group(RuleCategory, String),
@@ -62,6 +62,21 @@ impl RuleSpecifier {
6262
_ => None,
6363
}
6464
}
65+
66+
fn is_disabled(&self, disabled_rules: &[RuleFilter<'_>]) -> bool {
67+
// note: it is not possible to disable entire categories via the config
68+
let group = self.group();
69+
let rule = self.rule();
70+
71+
tracing::error!("group and rule: {:#?} {:#?}", group, rule);
72+
73+
disabled_rules.iter().any(|r| match r {
74+
RuleFilter::Group(gr) => group.is_some_and(|specifier_group| specifier_group == *gr),
75+
RuleFilter::Rule(gr, ru) => group.is_some_and(|specifier_group| {
76+
rule.is_some_and(|specifier_rule| specifier_group == *gr && specifier_rule == *ru)
77+
}),
78+
})
79+
}
6580
}
6681

6782
impl TryFrom<&str> for RuleSpecifier {
@@ -84,12 +99,12 @@ impl TryFrom<&str> for RuleSpecifier {
8499
}
85100
}
86101

87-
#[derive(Debug)]
102+
#[derive(Debug, Clone)]
88103
pub struct Suppression {
89104
suppression_range: TextRange,
90-
/// `None` means that all categories are suppressed
91105
kind: SuppressionKind,
92106
rule_specifier: RuleSpecifier,
107+
#[allow(unused)]
93108
explanation: Option<String>,
94109
}
95110

@@ -191,17 +206,26 @@ impl Suppression {
191206

192207
false
193208
}
209+
210+
fn to_disabled_diagnostic(self) -> SuppressionDiagnostic {
211+
SuppressionDiagnostic {
212+
span: self.suppression_range,
213+
message: MessageAndDescription::from(format!(
214+
"This rule has been disabled via the configuration. The suppression has no effect."
215+
)),
216+
}
217+
}
194218
}
195219

196-
#[derive(Debug)]
220+
#[derive(Debug, Clone)]
197221
pub struct RangeSuppression {
198222
suppressed_range: TextRange,
199223
start_suppression: Suppression,
200224
}
201225

202226
type Line = usize;
203227

204-
#[derive(Debug, Default)]
228+
#[derive(Debug, Default, Clone)]
205229
pub struct Suppressions {
206230
file_suppressions: Vec<Suppression>,
207231
line_suppressions: std::collections::HashMap<Line, Suppression>,
@@ -211,6 +235,53 @@ pub struct Suppressions {
211235
}
212236

213237
impl Suppressions {
238+
pub fn considering_disabled_rules(mut self, disabled_rules: &[RuleFilter<'_>]) -> Self {
239+
tracing::error!("disabled rules: {:#?}", disabled_rules);
240+
241+
{
242+
let (enabled, disabled) = self
243+
.file_suppressions
244+
.into_iter()
245+
.partition(|s| !s.rule_specifier.is_disabled(disabled_rules));
246+
247+
self.file_suppressions = enabled;
248+
249+
for suppr in disabled {
250+
self.diagnostics.push(suppr.to_disabled_diagnostic());
251+
}
252+
}
253+
254+
{
255+
let (enabled, disabled) = self
256+
.line_suppressions
257+
.into_iter()
258+
.partition(|(_, s)| !s.rule_specifier.is_disabled(disabled_rules));
259+
260+
self.line_suppressions = enabled;
261+
262+
for (_, suppr) in disabled {
263+
self.diagnostics.push(suppr.to_disabled_diagnostic());
264+
}
265+
}
266+
267+
{
268+
let (enabled, disabled) = self.range_suppressions.into_iter().partition(|s| {
269+
!s.start_suppression
270+
.rule_specifier
271+
.is_disabled(disabled_rules)
272+
});
273+
274+
self.range_suppressions = enabled;
275+
276+
for range_suppr in disabled {
277+
self.diagnostics
278+
.push(range_suppr.start_suppression.to_disabled_diagnostic());
279+
}
280+
}
281+
282+
self
283+
}
284+
214285
pub fn is_suppressed<D: Diagnostic>(&self, diagnostic: &D) -> bool {
215286
let location = diagnostic.location();
216287

@@ -402,196 +473,3 @@ impl<'a> SuppressionsParser<'a> {
402473
}
403474
}
404475
}
405-
406-
// #[cfg(test)]
407-
// mod tests {
408-
// use super::*;
409-
410-
// fn parse(doc: &str) -> Suppressions {
411-
// SuppressionsParser::parse(doc)
412-
// }
413-
414-
// #[test]
415-
// fn test_ignore_with_extra_colons_in_explanation() {
416-
// let doc = "// pgt-ignore lint/safety: reason: with: colons";
417-
// let sups = parse(doc);
418-
// let suppr = sups.line_suppressions.values().next().unwrap();
419-
// assert_eq!(suppr.explanation, Some("reason: with: colons"));
420-
// }
421-
422-
// #[test]
423-
// fn test_ignore_with_trailing_whitespace() {
424-
// let doc = "// pgt-ignore lint/safety ";
425-
// let sups = parse(doc);
426-
// assert_eq!(sups.line_suppressions.len(), 1);
427-
// assert!(sups.diagnostics.is_empty());
428-
// }
429-
430-
// #[test]
431-
// fn test_ignore_with_leading_whitespace() {
432-
// let doc = " // pgt-ignore lint/safety";
433-
// let sups = parse(doc);
434-
// assert_eq!(sups.line_suppressions.len(), 1);
435-
// assert!(sups.diagnostics.is_empty());
436-
// }
437-
438-
// #[test]
439-
// fn test_multiple_unmatched_ends() {
440-
// let doc = r#"
441-
// // pgt-ignore-end lint/safety
442-
// // pgt-ignore-end lint/performance
443-
// "#;
444-
// let sups = parse(doc);
445-
// assert_eq!(sups.diagnostics.len(), 2);
446-
// for diag in sups.diagnostics {
447-
// assert!(
448-
// diag.message
449-
// .to_string()
450-
// .contains("does not have a matching start")
451-
// );
452-
// }
453-
// }
454-
455-
// #[test]
456-
// fn test_multiple_unmatched_starts() {
457-
// let doc = r#"
458-
// // pgt-ignore-start lint/safety
459-
// // pgt-ignore-start lint/performance
460-
// "#;
461-
// let sups = parse(doc);
462-
// assert_eq!(sups.diagnostics.len(), 2);
463-
// for diag in sups.diagnostics {
464-
// assert!(
465-
// diag.message
466-
// .to_string()
467-
// .contains("does not have a matching end")
468-
// );
469-
// }
470-
// }
471-
472-
// #[test]
473-
// fn test_ignore_with_invalid_tag_and_valid_tag() {
474-
// let doc = r#"
475-
// // pgt-ignore-foo lint/safety
476-
// // pgt-ignore lint/safety
477-
// "#;
478-
// let sups = parse(doc);
479-
// assert_eq!(sups.diagnostics.len(), 1);
480-
// assert_eq!(sups.line_suppressions.len(), 1);
481-
// }
482-
483-
// #[test]
484-
// fn test_ignore_with_missing_category_and_valid_tag() {
485-
// let doc = r#"
486-
// // pgt-ignore
487-
// // pgt-ignore lint/safety
488-
// "#;
489-
// let sups = parse(doc);
490-
// assert_eq!(sups.diagnostics.len(), 1);
491-
// assert_eq!(sups.line_suppressions.len(), 1);
492-
// }
493-
494-
// #[test]
495-
// fn test_ignore_with_group_and_rule_and_explanation() {
496-
// let doc = "// pgt-ignore lint/safety/banDropColumn: explanation";
497-
// let sups = parse(doc);
498-
// let suppr = sups.line_suppressions.values().next().unwrap();
499-
// assert_eq!(suppr.explanation, Some("explanation"));
500-
// match suppr.rule_filter {
501-
// Some(RuleFilter::Rule(group, rule)) => {
502-
// assert_eq!(group, "safety");
503-
// assert_eq!(rule, "banDropColumn");
504-
// }
505-
// _ => panic!("Expected RuleFilter::Rule"),
506-
// }
507-
// }
508-
509-
// #[test]
510-
// fn test_ignore_with_group_only_and_explanation() {
511-
// let doc = "// pgt-ignore lint/safety: explanation";
512-
// let sups = parse(doc);
513-
// let suppr = sups.line_suppressions.values().next().unwrap();
514-
// assert_eq!(suppr.explanation, Some("explanation"));
515-
// match suppr.rule_filter {
516-
// Some(RuleFilter::Group(group)) => {
517-
// assert_eq!(group, "safety");
518-
// }
519-
// _ => panic!("Expected RuleFilter::Group"),
520-
// }
521-
// }
522-
523-
// #[test]
524-
// fn test_ignore_with_no_group_or_rule_and_explanation() {
525-
// let doc = "// pgt-ignore lint: explanation";
526-
// let sups = parse(doc);
527-
// let suppr = sups.line_suppressions.values().next().unwrap();
528-
// assert_eq!(suppr.explanation, Some("explanation"));
529-
// assert!(suppr.rule_filter.is_none());
530-
// }
531-
532-
// #[test]
533-
// fn test_ignore_with_empty_explanation() {
534-
// let doc = "// pgt-ignore lint/safety:";
535-
// let sups = parse(doc);
536-
// let suppr = sups.line_suppressions.values().next().unwrap();
537-
// assert_eq!(suppr.explanation, Some(""));
538-
// }
539-
540-
// #[test]
541-
// fn test_ignore_with_multiple_colons_and_spaces() {
542-
// let doc = "// pgt-ignore lint/safety: explanation: with spaces ";
543-
// let sups = parse(doc);
544-
// let suppr = sups.line_suppressions.values().next().unwrap();
545-
// assert_eq!(suppr.explanation, Some("explanation: with spaces"));
546-
// }
547-
548-
// #[test]
549-
// fn test_ignore_with_invalid_category() {
550-
// let doc = "// pgt-ignore foo/safety";
551-
// let sups = parse(doc);
552-
// assert_eq!(sups.line_suppressions.len(), 0);
553-
// assert_eq!(sups.diagnostics.len(), 1);
554-
// let diag = &sups.diagnostics[0];
555-
// assert_eq!(diag.message.to_string(), "Invalid Rule Category: foo");
556-
// }
557-
558-
// #[test]
559-
// fn test_ignore_with_missing_specifier() {
560-
// let doc = "// pgt-ignore";
561-
// let sups = parse(doc);
562-
// assert_eq!(sups.line_suppressions.len(), 0);
563-
// assert_eq!(sups.diagnostics.len(), 1);
564-
// let diag = &sups.diagnostics[0];
565-
// assert!(
566-
// diag.message
567-
// .to_string()
568-
// .contains("must specify which lints to suppress")
569-
// || diag.message.to_string().contains("must specify")
570-
// );
571-
// }
572-
573-
// #[test]
574-
// fn test_range_suppression_basic() {
575-
// let doc = r#"
576-
// // pgt-ignore-start lint/safety/banDropColumn: start explanation
577-
// SELECT * FROM foo;
578-
// // pgt-ignore-end lint/safety/banDropColumn: end explanation
579-
// "#;
580-
// let sups = parse(doc);
581-
// // Should have one range suppression
582-
// assert_eq!(sups.range_suppressions.len(), 1);
583-
// let range = &sups.range_suppressions[0];
584-
// assert_eq!(range.rule_category, RuleCategory::Lint);
585-
// assert_eq!(
586-
// range.rule_filter,
587-
// Some(RuleFilter::Rule("safety", "banDropColumn"))
588-
// );
589-
// assert_eq!(range.explanation, Some("start explanation"));
590-
// // The start and end suppressions should be present and correct
591-
// assert_eq!(
592-
// range.start_suppression.explanation,
593-
// Some("start explanation")
594-
// );
595-
// assert_eq!(range.end_suppression.explanation, Some("end explanation"));
596-
// }
597-
// }

crates/pgt_suppressions/src/line_index.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use pgt_text_size::TextSize;
22

3-
#[derive(Debug, Default)]
3+
#[derive(Debug, Default, Clone)]
44
pub(crate) struct LineIndex {
55
line_offset: Vec<pgt_text_size::TextSize>,
66
}

crates/pgt_workspace/src/workspace/server.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,10 @@ impl Workspace for WorkspaceServer {
570570
},
571571
));
572572

573-
let suppressions = parser.document_suppressions();
573+
let suppressions = parser
574+
.document_suppressions()
575+
.clone()
576+
.considering_disabled_rules(&disabled_rules);
574577

575578
diagnostics.retain(|d| !suppressions.is_suppressed(d));
576579

0 commit comments

Comments
 (0)