mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 22:01:18 +00:00
Skip BOM when inserting start-of-file imports (#7622)
See: https://github.com/astral-sh/ruff/issues/7455#issuecomment-1732387485.
This commit is contained in:
parent
b194f59aab
commit
8ba8896a7f
5 changed files with 39 additions and 4 deletions
4
crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM105_4.py
vendored
Executable file
4
crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM105_4.py
vendored
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
try:
|
||||||
|
from __builtin__ import bytes, str, open, super, range, zip, round, int, pow, object, input
|
||||||
|
except ImportError: pass
|
|
@ -64,7 +64,7 @@ impl<'a> Insertion<'a> {
|
||||||
// Otherwise, advance to the next row.
|
// Otherwise, advance to the next row.
|
||||||
locator.full_line_end(location)
|
locator.full_line_end(location)
|
||||||
} else {
|
} else {
|
||||||
TextSize::default()
|
locator.contents_start()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Skip over commented lines, with whitespace separation.
|
// Skip over commented lines, with whitespace separation.
|
||||||
|
|
|
@ -19,6 +19,7 @@ mod tests {
|
||||||
#[test_case(Rule::SuppressibleException, Path::new("SIM105_1.py"))]
|
#[test_case(Rule::SuppressibleException, Path::new("SIM105_1.py"))]
|
||||||
#[test_case(Rule::SuppressibleException, Path::new("SIM105_2.py"))]
|
#[test_case(Rule::SuppressibleException, Path::new("SIM105_2.py"))]
|
||||||
#[test_case(Rule::SuppressibleException, Path::new("SIM105_3.py"))]
|
#[test_case(Rule::SuppressibleException, Path::new("SIM105_3.py"))]
|
||||||
|
#[test_case(Rule::SuppressibleException, Path::new("SIM105_4.py"))]
|
||||||
#[test_case(Rule::ReturnInTryExceptFinally, Path::new("SIM107.py"))]
|
#[test_case(Rule::ReturnInTryExceptFinally, Path::new("SIM107.py"))]
|
||||||
#[test_case(Rule::IfElseBlockInsteadOfIfExp, Path::new("SIM108.py"))]
|
#[test_case(Rule::IfElseBlockInsteadOfIfExp, Path::new("SIM108.py"))]
|
||||||
#[test_case(Rule::CompareWithTuple, Path::new("SIM109.py"))]
|
#[test_case(Rule::CompareWithTuple, Path::new("SIM109.py"))]
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/flake8_simplify/mod.rs
|
||||||
|
---
|
||||||
|
SIM105_4.py:2:1: SIM105 [*] Use `contextlib.suppress(ImportError)` instead of `try`-`except`-`pass`
|
||||||
|
|
|
||||||
|
1 | #!/usr/bin/env python
|
||||||
|
2 | / try:
|
||||||
|
3 | | from __builtin__ import bytes, str, open, super, range, zip, round, int, pow, object, input
|
||||||
|
4 | | except ImportError: pass
|
||||||
|
| |___________________________^ SIM105
|
||||||
|
|
|
||||||
|
= help: Replace with `contextlib.suppress(ImportError)`
|
||||||
|
|
||||||
|
ℹ Suggested fix
|
||||||
|
1 1 | #!/usr/bin/env python
|
||||||
|
2 |-try:
|
||||||
|
2 |+import contextlib
|
||||||
|
3 |+with contextlib.suppress(ImportError):
|
||||||
|
3 4 | from __builtin__ import bytes, str, open, super, range, zip, round, int, pow, object, input
|
||||||
|
4 |-except ImportError: pass
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,15 @@ impl<'a> Locator<'a> {
|
||||||
if let Some(index) = memrchr2(b'\n', b'\r', bytes) {
|
if let Some(index) = memrchr2(b'\n', b'\r', bytes) {
|
||||||
// SAFETY: Safe because `index < offset`
|
// SAFETY: Safe because `index < offset`
|
||||||
TextSize::try_from(index).unwrap().add(TextSize::from(1))
|
TextSize::try_from(index).unwrap().add(TextSize::from(1))
|
||||||
} else if self.contents.starts_with('\u{feff}') {
|
} else {
|
||||||
|
self.contents_start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the start position of the file contents: either the first byte, or the byte after
|
||||||
|
/// the BOM.
|
||||||
|
pub fn contents_start(&self) -> TextSize {
|
||||||
|
if self.contents.starts_with('\u{feff}') {
|
||||||
// Skip the BOM.
|
// Skip the BOM.
|
||||||
'\u{feff}'.text_len()
|
'\u{feff}'.text_len()
|
||||||
} else {
|
} else {
|
||||||
|
@ -85,9 +93,9 @@ impl<'a> Locator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `offset` is at the start of a line.
|
||||||
pub fn is_at_start_of_line(&self, offset: TextSize) -> bool {
|
pub fn is_at_start_of_line(&self, offset: TextSize) -> bool {
|
||||||
offset == TextSize::from(0)
|
self.line_start(offset) == offset
|
||||||
|| self.contents[TextRange::up_to(offset)].ends_with(['\n', '\r'])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the offset that is right after the newline character that ends `offset`'s line.
|
/// Computes the offset that is right after the newline character that ends `offset`'s line.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue