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
|
#![allow(unused)]
use crate::linter::mlint_report::{MlintLevel, MlintReport};
>>>>>>>>>> impls;
>>>>>>>>>> file_lints;
/// Run all registered lints on a parsed file with its source text.
pub fn run_all_lints(file: &syn::File, source: &str) -> Vec<MlintReport> {
use crate::linter::mlint_attr::{get_mlint_override, MlintLevelOverride};
// File-level lints (check types, modules, etc.)
let mut reports: Vec<MlintReport> = vec![];
>>>>>>>>>> file_calls;
// Item-level lints (check each function)
for item in &file.items {
if let syn::Item::Fn(f) = item {
>>>>>>>>>> calls;
}
}
// Apply file-level #![mlint(allow/warn/deny(...))] overrides
for r in &mut reports {
if let Some(override_level) = get_mlint_override(&file.attrs, &r.lint_code) {
match override_level {
MlintLevelOverride::Allow => r.level = MlintLevel::Help,
MlintLevelOverride::Deny => r.level = MlintLevel::Error,
MlintLevelOverride::Warn => {
if r.level != MlintLevel::Error { r.level = MlintLevel::Warning; }
}
}
}
}
reports.retain(|r| r.level != MlintLevel::Help);
reports
}
#[macro_export]
macro_rules! assert_detected {
($linter:expr, $ast_type:ty => { $($code:tt)* }) => {
let source = stringify!($($code)*);
let ast: $ast_type = syn::parse_str(&source).unwrap();
assert!(!$linter(ast, &source).is_empty());
};
}
#[macro_export]
macro_rules! assert_not_detected {
($linter:expr, $ast_type:ty => { $($code:tt)* }) => {
let source = stringify!($($code)*);
let ast: $ast_type = syn::parse_str(&source).unwrap();
assert!($linter(ast, &source).is_empty());
};
}
@@@ >>> file_calls
reports.extend(<<<name>>>::check_file(file, source));
@@@ <<<
@@@ >>> file_lints
pub use <<<name>>>::check_file as <<<name>>>_file;
@@@ <<<
@@@ >>> impls
mod <<<mod_name>>>;
pub use <<<mod_name>>>::linter as <<<mod_name>>>;
@@@ <<<
@@@ >>> calls
let skip = get_mlint_override(&f.attrs, "<<<name>>>") == Some(MlintLevelOverride::Allow);
if !skip {
let mut rs = <<<name>>>::linter(f.clone(), source);
if get_mlint_override(&f.attrs, "<<<name>>>") == Some(MlintLevelOverride::Deny) {
for r in &mut rs { r.level = MlintLevel::Error; }
}
reports.extend(rs);
}
@@@ <<<
|