1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
mod parser;
pub use self::parser::*;
use crate::{rule_tests, CstRule, CstRuleStore, Diagnostic, SyntaxNode};
use rslint_parser::util::*;
pub fn apply_top_level_directives(
directives: &[Directive],
store: &mut CstRuleStore,
diagnostics: &mut Vec<Diagnostic>,
file_id: usize,
) {
let mut ignored = Vec::new();
let mut cleared = None;
for directive in directives {
for command in &directive.commands {
if command.top_level() {
match command {
Command::IgnoreFile => {
store.rules.clear();
cleared = Some(directive.comment.token.text_range());
}
Command::IgnoreRulesFile(rules) => {
ignored.push(directive.comment.token.text_range());
store.rules.retain(|rule| {
!rules.iter().any(|allowed| allowed.name() == rule.name())
});
}
_ => unreachable!(),
}
}
}
}
if let Some(range) = cleared {
for ignored_range in ignored {
let warn = Diagnostic::warning(
file_id,
"linter",
"ignoring redundant rule ignore directive",
)
.secondary(range, "this directive ignores all rules")
.primary(ignored_range, "this directive is ignored");
diagnostics.push(warn);
}
}
}
pub fn apply_node_directives(
directives: &[Directive],
node: &SyntaxNode,
store: &CstRuleStore,
) -> Option<CstRuleStore> {
let comment = node.first_token().and_then(|t| t.comment())?;
let directive = directives.iter().find(|dir| dir.comment == comment)?;
let mut store = store.clone();
for command in &directive.commands {
match command {
Command::IgnoreNode(_) => {
store.rules.clear();
}
Command::IgnoreRules(rules, _) => {
store
.rules
.retain(|rule| !rules.iter().any(|allowed| allowed.name() == rule.name()));
}
_ => {}
}
}
Some(store)
}
pub fn skip_node(directives: &[Directive], node: &SyntaxNode, rule: &dyn CstRule) -> bool {
if let Some(comment) = node.first_token().and_then(|t| t.comment()) {
if let Some(directive) = directives.iter().find(|dir| dir.comment == comment) {
for command in &directive.commands {
match command {
Command::IgnoreNode(_) => {
return true;
}
Command::IgnoreRules(rules, _) => {
if rules.iter().any(|allowed| allowed.name() == rule.name()) {
return true;
}
}
_ => {}
}
}
}
}
false
}
rule_tests! {
crate::groups::errors::NoEmpty::default(),
err: {
"{}",
"
// rslint-ignore no-empty
{}
{}
"
},
ok: {
"
// rslint-ignore no-empty
{}
",
"
// rslint-ignore no-empty
{}
",
"
// rslint-ignore
{}
"
}
}