forked from astral-sh/ruff
-
Notifications
You must be signed in to change notification settings - Fork 0
/
trailing_whitespace.rs
121 lines (113 loc) · 3.57 KB
/
trailing_whitespace.rs
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
use ruff_diagnostics::{AlwaysFixableViolation, Applicability, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_index::Indexer;
use ruff_source_file::{Line, Locator};
use ruff_text_size::{TextLen, TextRange, TextSize};
use crate::registry::Rule;
use crate::settings::LinterSettings;
/// ## What it does
/// Checks for superfluous trailing whitespace.
///
/// ## Why is this bad?
/// According to [PEP 8], "avoid trailing whitespace anywhere. Because it’s usually
/// invisible, it can be confusing"
///
/// ## Example
/// ```python
/// spam(1) \n#
/// ```
///
/// Use instead:
/// ```python
/// spam(1)\n#
/// ```
///
/// [PEP 8]: https://peps.python.org/pep-0008/#other-recommendations
#[violation]
pub struct TrailingWhitespace;
impl AlwaysFixableViolation for TrailingWhitespace {
#[derive_message_formats]
fn message(&self) -> String {
format!("Trailing whitespace")
}
fn fix_title(&self) -> String {
"Remove trailing whitespace".to_string()
}
}
/// ## What it does
/// Checks for superfluous whitespace in blank lines.
///
/// ## Why is this bad?
/// According to [PEP 8], "avoid trailing whitespace anywhere. Because it’s usually
/// invisible, it can be confusing"
///
/// ## Example
/// ```python
/// class Foo(object):\n \n bang = 12
/// ```
///
/// Use instead:
/// ```python
/// class Foo(object):\n\n bang = 12
/// ```
///
/// [PEP 8]: https://peps.python.org/pep-0008/#other-recommendations
#[violation]
pub struct BlankLineWithWhitespace;
impl AlwaysFixableViolation for BlankLineWithWhitespace {
#[derive_message_formats]
fn message(&self) -> String {
format!("Blank line contains whitespace")
}
fn fix_title(&self) -> String {
"Remove whitespace from blank line".to_string()
}
}
/// W291, W293
pub(crate) fn trailing_whitespace(
line: &Line,
locator: &Locator,
indexer: &Indexer,
settings: &LinterSettings,
) -> Option<Diagnostic> {
let whitespace_len: TextSize = line
.chars()
.rev()
.take_while(|c| c.is_whitespace())
.map(TextLen::text_len)
.sum();
if whitespace_len > TextSize::from(0) {
let range = TextRange::new(line.end() - whitespace_len, line.end());
// Removing trailing whitespace is not safe inside multiline strings.
let applicability = if indexer.multiline_ranges().contains_range(range) {
Applicability::Unsafe
} else {
Applicability::Safe
};
if range == line.range() {
if settings.rules.enabled(Rule::BlankLineWithWhitespace) {
let mut diagnostic = Diagnostic::new(BlankLineWithWhitespace, range);
// Remove any preceding continuations, to avoid introducing a potential
// syntax error.
diagnostic.set_fix(Fix::applicable_edit(
Edit::range_deletion(TextRange::new(
indexer
.preceded_by_continuations(line.start(), locator)
.unwrap_or(range.start()),
range.end(),
)),
applicability,
));
return Some(diagnostic);
}
} else if settings.rules.enabled(Rule::TrailingWhitespace) {
let mut diagnostic = Diagnostic::new(TrailingWhitespace, range);
diagnostic.set_fix(Fix::applicable_edit(
Edit::range_deletion(range),
applicability,
));
return Some(diagnostic);
}
}
None
}