@frozenproductions/niteo 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +458 -0
- package/Cargo.toml +13 -0
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/bin/niteo.js +51 -0
- package/package.json +27 -0
- package/scripts/build-binary.js +23 -0
- package/src/app.rs +132 -0
- package/src/cli.rs +43 -0
- package/src/config.rs +989 -0
- package/src/discovery.rs +42 -0
- package/src/git.rs +63 -0
- package/src/main.rs +13 -0
- package/src/report.rs +490 -0
- package/src/rules/max_directory_depth.rs +125 -0
- package/src/rules/max_file_exports.rs +478 -0
- package/src/rules/max_items_per_directory.rs +145 -0
- package/src/rules/min_items_per_directory.rs +146 -0
- package/src/rules/no_barrel_files.rs +284 -0
- package/src/rules/no_comments.rs +222 -0
- package/src/rules/no_console.rs +242 -0
- package/src/rules/no_debugger.rs +209 -0
- package/src/rules/no_default_export.rs +241 -0
- package/src/rules/no_duplicate_file_names.rs +196 -0
- package/src/rules/no_empty_directories.rs +467 -0
- package/src/rules/no_empty_interface.rs +280 -0
- package/src/rules/no_enums.rs +208 -0
- package/src/rules/no_eval.rs +268 -0
- package/src/rules/no_export_star.rs +252 -0
- package/src/rules/no_inline_types.rs +367 -0
- package/src/rules/no_interface.rs +570 -0
- package/src/rules/no_large_file.rs +98 -0
- package/src/rules/no_logic_in_barrel.rs +346 -0
- package/src/rules/no_logic_in_domain.rs +987 -0
- package/src/rules/no_mutable_exports.rs +253 -0
- package/src/rules/no_upward_import.rs +427 -0
- package/src/rules/prefer_satisfies.rs +319 -0
- package/src/rules.rs +247 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
use std::path::Path;
|
|
2
|
+
|
|
3
|
+
use crate::config::{RuleConfig, Severity};
|
|
4
|
+
use crate::rules::Violation;
|
|
5
|
+
|
|
6
|
+
const RULE_NAME: &str = "prefer-satisfies";
|
|
7
|
+
const MESSAGE: &str =
|
|
8
|
+
"Prefer 'satisfies' over 'as' for type validation without changing the inferred type.";
|
|
9
|
+
|
|
10
|
+
pub fn check_file(file: &Path, source: &str, config: &RuleConfig) -> Vec<Violation> {
|
|
11
|
+
let bytes = source.as_bytes();
|
|
12
|
+
let mut violations = Vec::new();
|
|
13
|
+
let mut cursor = Cursor::default();
|
|
14
|
+
let mut string_quote: Option<u8> = None;
|
|
15
|
+
|
|
16
|
+
while cursor.index < bytes.len() {
|
|
17
|
+
let current = bytes[cursor.index];
|
|
18
|
+
let next = bytes.get(cursor.index + 1).copied();
|
|
19
|
+
|
|
20
|
+
if let Some(quote) = string_quote {
|
|
21
|
+
if current == b'\\' {
|
|
22
|
+
cursor.advance(bytes);
|
|
23
|
+
if cursor.index < bytes.len() {
|
|
24
|
+
cursor.advance(bytes);
|
|
25
|
+
}
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if current == quote {
|
|
30
|
+
string_quote = None;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
cursor.advance(bytes);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
match (current, next) {
|
|
38
|
+
(b'\'', _) | (b'"', _) | (b'`', _) => {
|
|
39
|
+
string_quote = Some(current);
|
|
40
|
+
cursor.advance(bytes);
|
|
41
|
+
}
|
|
42
|
+
(b'/', Some(b'/')) => skip_line_comment(bytes, &mut cursor),
|
|
43
|
+
(b'/', Some(b'*')) => skip_block_comment(bytes, &mut cursor),
|
|
44
|
+
_ if starts_as_cast(bytes, cursor.index) => {
|
|
45
|
+
if should_prefer_satisfies(bytes, cursor.index) {
|
|
46
|
+
violations.push(as_cast_violation(file, &cursor, config.severity));
|
|
47
|
+
}
|
|
48
|
+
advance_past_as(bytes, &mut cursor);
|
|
49
|
+
}
|
|
50
|
+
_ => cursor.advance(bytes),
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
violations
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
#[derive(Debug, Clone, Copy)]
|
|
58
|
+
struct Cursor {
|
|
59
|
+
index: usize,
|
|
60
|
+
line: usize,
|
|
61
|
+
column: usize,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
impl Default for Cursor {
|
|
65
|
+
fn default() -> Self {
|
|
66
|
+
Self {
|
|
67
|
+
index: 0,
|
|
68
|
+
line: 1,
|
|
69
|
+
column: 1,
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
impl Cursor {
|
|
75
|
+
fn advance(&mut self, bytes: &[u8]) {
|
|
76
|
+
if bytes[self.index] == b'\n' {
|
|
77
|
+
self.line += 1;
|
|
78
|
+
self.column = 1;
|
|
79
|
+
} else {
|
|
80
|
+
self.column += 1;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
self.index += 1;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
fn as_cast_violation(file: &Path, cursor: &Cursor, severity: Severity) -> Violation {
|
|
88
|
+
Violation {
|
|
89
|
+
file: file.to_path_buf(),
|
|
90
|
+
line: Some(cursor.line),
|
|
91
|
+
column: Some(cursor.column),
|
|
92
|
+
rule: RULE_NAME,
|
|
93
|
+
message: MESSAGE,
|
|
94
|
+
severity,
|
|
95
|
+
detail: None,
|
|
96
|
+
subject: None,
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fn starts_as_cast(bytes: &[u8], index: usize) -> bool {
|
|
101
|
+
if !starts_keyword(bytes, index, b"as") {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let after_as = index + b"as".len();
|
|
106
|
+
let next_byte = bytes.get(after_as).copied();
|
|
107
|
+
!is_identifier_byte(next_byte)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fn should_prefer_satisfies(bytes: &[u8], as_index: usize) -> bool {
|
|
111
|
+
let after_as = as_index + b"as".len();
|
|
112
|
+
let next_index = skip_inline_whitespace(bytes, after_as);
|
|
113
|
+
|
|
114
|
+
if starts_keyword(bytes, next_index, b"const")
|
|
115
|
+
|| starts_keyword(bytes, next_index, b"any")
|
|
116
|
+
|| starts_keyword(bytes, next_index, b"unknown")
|
|
117
|
+
{
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let before_as = as_index.wrapping_sub(1);
|
|
122
|
+
let prev_index = skip_trailing_whitespace(bytes, before_as);
|
|
123
|
+
|
|
124
|
+
matches!(
|
|
125
|
+
bytes.get(prev_index).copied(),
|
|
126
|
+
Some(b'}') | Some(b']') | Some(b'"') | Some(b'\'') | Some(b'`') | Some(b'0'..=b'9')
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
fn starts_keyword(bytes: &[u8], index: usize, keyword: &[u8]) -> bool {
|
|
131
|
+
bytes.get(index..index + keyword.len()) == Some(keyword)
|
|
132
|
+
&& !is_identifier_byte(bytes.get(index.wrapping_sub(1)).copied())
|
|
133
|
+
&& !is_identifier_byte(bytes.get(index + keyword.len()).copied())
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
fn is_identifier_byte(byte: Option<u8>) -> bool {
|
|
137
|
+
matches!(
|
|
138
|
+
byte,
|
|
139
|
+
Some(b'a'..=b'z') | Some(b'A'..=b'Z') | Some(b'0'..=b'9') | Some(b'_') | Some(b'$')
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
fn skip_inline_whitespace(bytes: &[u8], mut index: usize) -> usize {
|
|
144
|
+
while matches!(bytes.get(index), Some(b' ' | b'\t' | b'\r' | b'\n')) {
|
|
145
|
+
index += 1;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
index
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
fn skip_trailing_whitespace(bytes: &[u8], mut index: usize) -> usize {
|
|
152
|
+
while index > 0 && matches!(bytes.get(index), Some(b' ' | b'\t' | b'\r' | b'\n')) {
|
|
153
|
+
index -= 1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
index
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
fn advance_past_as(bytes: &[u8], cursor: &mut Cursor) {
|
|
160
|
+
let target_index = cursor.index + b"as".len();
|
|
161
|
+
while cursor.index < bytes.len() && cursor.index < target_index {
|
|
162
|
+
cursor.advance(bytes);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
fn skip_line_comment(bytes: &[u8], cursor: &mut Cursor) {
|
|
167
|
+
while cursor.index < bytes.len() && bytes[cursor.index] != b'\n' {
|
|
168
|
+
cursor.advance(bytes);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
fn skip_block_comment(bytes: &[u8], cursor: &mut Cursor) {
|
|
173
|
+
cursor.advance(bytes);
|
|
174
|
+
cursor.advance(bytes);
|
|
175
|
+
|
|
176
|
+
while cursor.index < bytes.len() {
|
|
177
|
+
let current = bytes[cursor.index];
|
|
178
|
+
let next = bytes.get(cursor.index + 1).copied();
|
|
179
|
+
|
|
180
|
+
cursor.advance(bytes);
|
|
181
|
+
|
|
182
|
+
if current == b'*' && next == Some(b'/') {
|
|
183
|
+
cursor.advance(bytes);
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
#[cfg(test)]
|
|
190
|
+
mod tests {
|
|
191
|
+
use super::check_file;
|
|
192
|
+
use crate::config::{RuleConfig, Severity};
|
|
193
|
+
use std::path::Path;
|
|
194
|
+
|
|
195
|
+
#[test]
|
|
196
|
+
fn reports_object_literal_as_cast() {
|
|
197
|
+
let violations = check_file(
|
|
198
|
+
Path::new("value.ts"),
|
|
199
|
+
"const config = { port: 3000 } as Config;\n",
|
|
200
|
+
&test_config(),
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
assert_eq!(violations.len(), 1);
|
|
204
|
+
assert_eq!(violations[0].line, Some(1));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
#[test]
|
|
208
|
+
fn reports_array_literal_as_cast() {
|
|
209
|
+
let violations = check_file(
|
|
210
|
+
Path::new("value.ts"),
|
|
211
|
+
"const items = [1, 2, 3] as number[];\n",
|
|
212
|
+
&test_config(),
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
assert_eq!(violations.len(), 1);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
#[test]
|
|
219
|
+
fn reports_string_literal_as_cast() {
|
|
220
|
+
let violations = check_file(
|
|
221
|
+
Path::new("value.ts"),
|
|
222
|
+
"const event = \"click\" as EventName;\n",
|
|
223
|
+
&test_config(),
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
assert_eq!(violations.len(), 1);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
#[test]
|
|
230
|
+
fn reports_numeric_literal_as_cast() {
|
|
231
|
+
let violations = check_file(
|
|
232
|
+
Path::new("value.ts"),
|
|
233
|
+
"const code = 404 as StatusCode;\n",
|
|
234
|
+
&test_config(),
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
assert_eq!(violations.len(), 1);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
#[test]
|
|
241
|
+
fn allows_as_const() {
|
|
242
|
+
let violations = check_file(
|
|
243
|
+
Path::new("value.ts"),
|
|
244
|
+
"const config = { port: 3000 } as const;\n",
|
|
245
|
+
&test_config(),
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
assert!(violations.is_empty());
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
#[test]
|
|
252
|
+
fn allows_as_any() {
|
|
253
|
+
let violations = check_file(
|
|
254
|
+
Path::new("value.ts"),
|
|
255
|
+
"const value = something as any;\n",
|
|
256
|
+
&test_config(),
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
assert!(violations.is_empty());
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
#[test]
|
|
263
|
+
fn allows_as_unknown() {
|
|
264
|
+
let violations = check_file(
|
|
265
|
+
Path::new("value.ts"),
|
|
266
|
+
"const value = something as unknown as Target;\n",
|
|
267
|
+
&test_config(),
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
assert!(violations.is_empty());
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
#[test]
|
|
274
|
+
fn allows_variable_as_cast() {
|
|
275
|
+
let violations = check_file(
|
|
276
|
+
Path::new("value.ts"),
|
|
277
|
+
"const value = someVar as Target;\n",
|
|
278
|
+
&test_config(),
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
assert!(violations.is_empty());
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
#[test]
|
|
285
|
+
fn allows_function_call_as_cast() {
|
|
286
|
+
let violations = check_file(
|
|
287
|
+
Path::new("value.ts"),
|
|
288
|
+
"const result = getData() as Response;\n",
|
|
289
|
+
&test_config(),
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
assert!(violations.is_empty());
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
#[test]
|
|
296
|
+
fn ignores_as_in_comments_and_strings() {
|
|
297
|
+
let source = r#"// const x = {} as Config;
|
|
298
|
+
const text = "as Config";
|
|
299
|
+
/* const x = {} as Config; */
|
|
300
|
+
"#;
|
|
301
|
+
let violations = check_file(Path::new("value.ts"), source, &test_config());
|
|
302
|
+
|
|
303
|
+
assert!(violations.is_empty());
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
#[test]
|
|
307
|
+
fn does_not_match_as_in_identifier() {
|
|
308
|
+
let source = "const task = 'hello';\n";
|
|
309
|
+
let violations = check_file(Path::new("value.ts"), source, &test_config());
|
|
310
|
+
|
|
311
|
+
assert!(violations.is_empty());
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
fn test_config() -> RuleConfig {
|
|
315
|
+
RuleConfig {
|
|
316
|
+
severity: Severity::Warn,
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
package/src/rules.rs
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
mod max_directory_depth;
|
|
2
|
+
mod max_file_exports;
|
|
3
|
+
mod max_items_per_directory;
|
|
4
|
+
mod min_items_per_directory;
|
|
5
|
+
mod no_barrel_files;
|
|
6
|
+
mod no_comments;
|
|
7
|
+
mod no_console;
|
|
8
|
+
mod no_debugger;
|
|
9
|
+
mod no_default_export;
|
|
10
|
+
mod no_duplicate_file_names;
|
|
11
|
+
mod no_empty_directories;
|
|
12
|
+
mod no_empty_interface;
|
|
13
|
+
mod no_enums;
|
|
14
|
+
mod no_eval;
|
|
15
|
+
mod no_export_star;
|
|
16
|
+
mod no_inline_types;
|
|
17
|
+
mod no_interface;
|
|
18
|
+
mod no_large_file;
|
|
19
|
+
mod no_logic_in_barrel;
|
|
20
|
+
mod no_logic_in_domain;
|
|
21
|
+
mod no_mutable_exports;
|
|
22
|
+
mod no_upward_import;
|
|
23
|
+
mod prefer_satisfies;
|
|
24
|
+
|
|
25
|
+
use anyhow::{Context, Result};
|
|
26
|
+
use std::fs;
|
|
27
|
+
use std::path::PathBuf;
|
|
28
|
+
|
|
29
|
+
use crate::config::{
|
|
30
|
+
CommentsRuleConfig, FileExportsRuleConfig, FileLengthRuleConfig, MaxDirectoryDepthRuleConfig,
|
|
31
|
+
MaxItemsPerDirectoryRuleConfig, MinItemsPerDirectoryRuleConfig, NoConsoleRuleConfig,
|
|
32
|
+
NoDuplicateFileNamesRuleConfig, NoEmptyDirectoriesRuleConfig, NoInterfaceRuleConfig,
|
|
33
|
+
NoLogicInDomainRuleConfig, RuleConfig, Severity, UpwardImportRuleConfig,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
#[derive(Debug, Clone)]
|
|
37
|
+
pub struct Violation {
|
|
38
|
+
pub file: PathBuf,
|
|
39
|
+
pub line: Option<usize>,
|
|
40
|
+
pub column: Option<usize>,
|
|
41
|
+
pub rule: &'static str,
|
|
42
|
+
pub message: &'static str,
|
|
43
|
+
pub severity: Severity,
|
|
44
|
+
pub detail: Option<String>,
|
|
45
|
+
pub subject: Option<String>,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
pub fn check_files(
|
|
49
|
+
files: &[PathBuf],
|
|
50
|
+
no_comments: CommentsRuleConfig,
|
|
51
|
+
no_logic_in_barrel: RuleConfig,
|
|
52
|
+
no_default_export: RuleConfig,
|
|
53
|
+
no_export_star: RuleConfig,
|
|
54
|
+
no_inline_types: RuleConfig,
|
|
55
|
+
max_file_exports: FileExportsRuleConfig,
|
|
56
|
+
no_upward_import: UpwardImportRuleConfig,
|
|
57
|
+
no_large_file: FileLengthRuleConfig,
|
|
58
|
+
no_enums: RuleConfig,
|
|
59
|
+
no_barrel_files: RuleConfig,
|
|
60
|
+
no_console: NoConsoleRuleConfig,
|
|
61
|
+
no_debugger: RuleConfig,
|
|
62
|
+
no_eval: RuleConfig,
|
|
63
|
+
no_logic_in_domain: NoLogicInDomainRuleConfig,
|
|
64
|
+
no_empty_interface: RuleConfig,
|
|
65
|
+
no_interface: NoInterfaceRuleConfig,
|
|
66
|
+
no_mutable_exports: RuleConfig,
|
|
67
|
+
prefer_satisfies: RuleConfig,
|
|
68
|
+
) -> Result<Vec<Violation>> {
|
|
69
|
+
let mut violations = Vec::new();
|
|
70
|
+
|
|
71
|
+
if !no_comments.severity.is_enabled()
|
|
72
|
+
&& !no_logic_in_barrel.severity.is_enabled()
|
|
73
|
+
&& !no_default_export.severity.is_enabled()
|
|
74
|
+
&& !no_export_star.severity.is_enabled()
|
|
75
|
+
&& !no_inline_types.severity.is_enabled()
|
|
76
|
+
&& !max_file_exports.severity.is_enabled()
|
|
77
|
+
&& !no_upward_import.severity.is_enabled()
|
|
78
|
+
&& !no_large_file.severity.is_enabled()
|
|
79
|
+
&& !no_enums.severity.is_enabled()
|
|
80
|
+
&& !no_barrel_files.severity.is_enabled()
|
|
81
|
+
&& !no_console.severity.is_enabled()
|
|
82
|
+
&& !no_debugger.severity.is_enabled()
|
|
83
|
+
&& !no_eval.severity.is_enabled()
|
|
84
|
+
&& !no_logic_in_domain.severity.is_enabled()
|
|
85
|
+
&& !no_empty_interface.severity.is_enabled()
|
|
86
|
+
&& !no_interface.severity.is_enabled()
|
|
87
|
+
&& !no_mutable_exports.severity.is_enabled()
|
|
88
|
+
&& !prefer_satisfies.severity.is_enabled()
|
|
89
|
+
{
|
|
90
|
+
return Ok(violations);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let type_location_style = no_inline_types::TypeLocationStyle::detect(files);
|
|
94
|
+
|
|
95
|
+
for file in files {
|
|
96
|
+
let source = fs::read_to_string(file)
|
|
97
|
+
.with_context(|| format!("failed to read {}", file.display()))?;
|
|
98
|
+
if no_comments.severity.is_enabled() {
|
|
99
|
+
violations.extend(no_comments::check_file(file, &source, &no_comments));
|
|
100
|
+
}
|
|
101
|
+
if no_logic_in_barrel.severity.is_enabled() {
|
|
102
|
+
violations.extend(no_logic_in_barrel::check_file(
|
|
103
|
+
file,
|
|
104
|
+
&source,
|
|
105
|
+
&no_logic_in_barrel,
|
|
106
|
+
));
|
|
107
|
+
}
|
|
108
|
+
if no_default_export.severity.is_enabled() {
|
|
109
|
+
violations.extend(no_default_export::check_file(
|
|
110
|
+
file,
|
|
111
|
+
&source,
|
|
112
|
+
&no_default_export,
|
|
113
|
+
));
|
|
114
|
+
}
|
|
115
|
+
if no_export_star.severity.is_enabled() {
|
|
116
|
+
violations.extend(no_export_star::check_file(file, &source, &no_export_star));
|
|
117
|
+
}
|
|
118
|
+
if no_inline_types.severity.is_enabled() {
|
|
119
|
+
violations.extend(no_inline_types::check_file(
|
|
120
|
+
file,
|
|
121
|
+
&source,
|
|
122
|
+
&no_inline_types,
|
|
123
|
+
type_location_style,
|
|
124
|
+
));
|
|
125
|
+
}
|
|
126
|
+
if max_file_exports.severity.is_enabled() {
|
|
127
|
+
violations.extend(max_file_exports::check_file(
|
|
128
|
+
file,
|
|
129
|
+
&source,
|
|
130
|
+
&max_file_exports,
|
|
131
|
+
));
|
|
132
|
+
}
|
|
133
|
+
if no_upward_import.severity.is_enabled() {
|
|
134
|
+
violations.extend(no_upward_import::check_file(
|
|
135
|
+
file,
|
|
136
|
+
&source,
|
|
137
|
+
&no_upward_import,
|
|
138
|
+
));
|
|
139
|
+
}
|
|
140
|
+
if no_large_file.severity.is_enabled() {
|
|
141
|
+
violations.extend(no_large_file::check_file(file, &source, &no_large_file));
|
|
142
|
+
}
|
|
143
|
+
if no_enums.severity.is_enabled() {
|
|
144
|
+
violations.extend(no_enums::check_file(file, &source, &no_enums));
|
|
145
|
+
}
|
|
146
|
+
if no_barrel_files.severity.is_enabled() {
|
|
147
|
+
violations.extend(no_barrel_files::check_file(file, &source, &no_barrel_files));
|
|
148
|
+
}
|
|
149
|
+
if no_console.severity.is_enabled() {
|
|
150
|
+
violations.extend(no_console::check_file(file, &source, &no_console));
|
|
151
|
+
}
|
|
152
|
+
if no_debugger.severity.is_enabled() {
|
|
153
|
+
violations.extend(no_debugger::check_file(file, &source, &no_debugger));
|
|
154
|
+
}
|
|
155
|
+
if no_eval.severity.is_enabled() {
|
|
156
|
+
violations.extend(no_eval::check_file(file, &source, &no_eval));
|
|
157
|
+
}
|
|
158
|
+
if no_logic_in_domain.severity.is_enabled() {
|
|
159
|
+
violations.extend(no_logic_in_domain::check_file(
|
|
160
|
+
file,
|
|
161
|
+
&source,
|
|
162
|
+
&no_logic_in_domain,
|
|
163
|
+
));
|
|
164
|
+
}
|
|
165
|
+
if no_empty_interface.severity.is_enabled() {
|
|
166
|
+
violations.extend(no_empty_interface::check_file(
|
|
167
|
+
file,
|
|
168
|
+
&source,
|
|
169
|
+
&no_empty_interface,
|
|
170
|
+
));
|
|
171
|
+
}
|
|
172
|
+
if no_interface.severity.is_enabled() {
|
|
173
|
+
violations.extend(no_interface::check_file(file, &source, &no_interface));
|
|
174
|
+
}
|
|
175
|
+
if no_mutable_exports.severity.is_enabled() {
|
|
176
|
+
violations.extend(no_mutable_exports::check_file(
|
|
177
|
+
file,
|
|
178
|
+
&source,
|
|
179
|
+
&no_mutable_exports,
|
|
180
|
+
));
|
|
181
|
+
}
|
|
182
|
+
if prefer_satisfies.severity.is_enabled() {
|
|
183
|
+
violations.extend(prefer_satisfies::check_file(
|
|
184
|
+
file,
|
|
185
|
+
&source,
|
|
186
|
+
&prefer_satisfies,
|
|
187
|
+
));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
Ok(violations)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
pub fn check_directories(
|
|
195
|
+
root: &std::path::Path,
|
|
196
|
+
no_empty_directories: NoEmptyDirectoriesRuleConfig,
|
|
197
|
+
) -> Vec<Violation> {
|
|
198
|
+
if !no_empty_directories.severity.is_enabled() {
|
|
199
|
+
return Vec::new();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
no_empty_directories::check_directories(root, &no_empty_directories)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
pub fn check_duplicate_file_names(
|
|
206
|
+
files: &[PathBuf],
|
|
207
|
+
no_duplicate_file_names: NoDuplicateFileNamesRuleConfig,
|
|
208
|
+
) -> Vec<Violation> {
|
|
209
|
+
if !no_duplicate_file_names.severity.is_enabled() {
|
|
210
|
+
return Vec::new();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
no_duplicate_file_names::check_files(files, &no_duplicate_file_names)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
pub fn check_max_items_per_directory(
|
|
217
|
+
root: &std::path::Path,
|
|
218
|
+
config: MaxItemsPerDirectoryRuleConfig,
|
|
219
|
+
) -> Vec<Violation> {
|
|
220
|
+
if !config.severity.is_enabled() {
|
|
221
|
+
return Vec::new();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
max_items_per_directory::check_directories(root, &config)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
pub fn check_min_items_per_directory(
|
|
228
|
+
root: &std::path::Path,
|
|
229
|
+
config: MinItemsPerDirectoryRuleConfig,
|
|
230
|
+
) -> Vec<Violation> {
|
|
231
|
+
if !config.severity.is_enabled() {
|
|
232
|
+
return Vec::new();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
min_items_per_directory::check_directories(root, &config)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
pub fn check_max_directory_depth(
|
|
239
|
+
root: &std::path::Path,
|
|
240
|
+
config: MaxDirectoryDepthRuleConfig,
|
|
241
|
+
) -> Vec<Violation> {
|
|
242
|
+
if !config.severity.is_enabled() {
|
|
243
|
+
return Vec::new();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
max_directory_depth::check_directories(root, &config)
|
|
247
|
+
}
|