Add autofix for W292 [NoNewLineAtEndOfFile] (#1354)

This commit is contained in:
Sawbez 2022-12-23 20:14:17 -08:00 committed by GitHub
parent 201e1250de
commit 4ded155dc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 59 additions and 11 deletions

View File

@ -540,7 +540,7 @@ For more, see [pycodestyle](https://pypi.org/project/pycodestyle/2.9.1/) on PyPI
| E743 | AmbiguousFunctionName | Ambiguous function name: `...` | | | E743 | AmbiguousFunctionName | Ambiguous function name: `...` | |
| E902 | IOError | IOError: `...` | | | E902 | IOError | IOError: `...` | |
| E999 | SyntaxError | SyntaxError: `...` | | | E999 | SyntaxError | SyntaxError: `...` | |
| W292 | NoNewLineAtEndOfFile | No newline at end of file | | | W292 | NoNewLineAtEndOfFile | No newline at end of file | 🛠 |
| W605 | InvalidEscapeSequence | Invalid escape sequence: '\c' | | | W605 | InvalidEscapeSequence | Invalid escape sequence: '\c' | |
### mccabe (C90) ### mccabe (C90)

View File

@ -1,2 +1,2 @@
def fn() -> None: def fn() -> None:
pass print("Newline present (no W292)")

View File

View File

@ -0,0 +1 @@

View File

@ -55,7 +55,11 @@ pub fn check_lines(
} }
if enforce_no_newline_at_end_of_file { if enforce_no_newline_at_end_of_file {
if let Some(check) = no_newline_at_end_of_file(contents) { if let Some(check) = no_newline_at_end_of_file(
contents,
matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(&CheckCode::W292),
) {
checks.push(check); checks.push(check);
} }
} }

View File

@ -2983,6 +2983,7 @@ impl CheckKind {
| CheckKind::NoBlankLineBeforeClass(..) | CheckKind::NoBlankLineBeforeClass(..)
| CheckKind::NoBlankLineBeforeFunction(..) | CheckKind::NoBlankLineBeforeFunction(..)
| CheckKind::NoBlankLinesBetweenHeaderAndContent(..) | CheckKind::NoBlankLinesBetweenHeaderAndContent(..)
| CheckKind::NoNewLineAtEndOfFile
| CheckKind::NoOverIndentation | CheckKind::NoOverIndentation
| CheckKind::NoSurroundingWhitespace | CheckKind::NoSurroundingWhitespace
| CheckKind::NoUnderIndentation | CheckKind::NoUnderIndentation

View File

@ -5,6 +5,7 @@ use rustpython_ast::{Located, Location, Stmt, StmtKind};
use rustpython_parser::ast::{Cmpop, Expr, ExprKind}; use rustpython_parser::ast::{Cmpop, Expr, ExprKind};
use crate::ast::types::Range; use crate::ast::types::Range;
use crate::autofix::Fix;
use crate::checks::{Check, CheckKind}; use crate::checks::{Check, CheckKind};
use crate::source_code_locator::SourceCodeLocator; use crate::source_code_locator::SourceCodeLocator;
@ -134,18 +135,24 @@ pub fn ambiguous_function_name(name: &str, location: Range) -> Option<Check> {
} }
/// W292 /// W292
pub fn no_newline_at_end_of_file(contents: &str) -> Option<Check> { pub fn no_newline_at_end_of_file(contents: &str, autofix: bool) -> Option<Check> {
if !contents.ends_with('\n') { if !contents.ends_with('\n') {
// Note: if `lines.last()` is `None`, then `contents` is empty (and so we don't // Note: if `lines.last()` is `None`, then `contents` is empty (and so we don't
// want to raise W292 anyway). // want to raise W292 anyway).
if let Some(line) = contents.lines().last() { if let Some(line) = contents.lines().last() {
return Some(Check::new( // Both locations are at the end of the file (and thus the same).
let location = Location::new(contents.lines().count(), line.len());
let mut check = Check::new(
CheckKind::NoNewLineAtEndOfFile, CheckKind::NoNewLineAtEndOfFile,
Range { Range {
location: Location::new(contents.lines().count(), line.len() + 1), location,
end_location: Location::new(contents.lines().count(), line.len() + 1), end_location: location,
}, },
)); );
if autofix {
check.amend(Fix::insertion("\n".to_string(), location));
}
return Some(check);
} }
} }
None None

View File

@ -31,6 +31,8 @@ mod tests {
#[test_case(CheckCode::W292, Path::new("W292_0.py"))] #[test_case(CheckCode::W292, Path::new("W292_0.py"))]
#[test_case(CheckCode::W292, Path::new("W292_1.py"))] #[test_case(CheckCode::W292, Path::new("W292_1.py"))]
#[test_case(CheckCode::W292, Path::new("W292_2.py"))] #[test_case(CheckCode::W292, Path::new("W292_2.py"))]
#[test_case(CheckCode::W292, Path::new("W292_3.py"))]
#[test_case(CheckCode::W292, Path::new("W292_4.py"))]
#[test_case(CheckCode::W605, Path::new("W605_0.py"))] #[test_case(CheckCode::W605, Path::new("W605_0.py"))]
#[test_case(CheckCode::W605, Path::new("W605_1.py"))] #[test_case(CheckCode::W605, Path::new("W605_1.py"))]
fn checks(check_code: CheckCode, path: &Path) -> Result<()> { fn checks(check_code: CheckCode, path: &Path) -> Result<()> {

View File

@ -5,9 +5,16 @@ expression: checks
- kind: NoNewLineAtEndOfFile - kind: NoNewLineAtEndOfFile
location: location:
row: 2 row: 2
column: 9 column: 8
end_location: end_location:
row: 2 row: 2
column: 9 column: 8
fix: ~ fix:
content: "\n"
location:
row: 2
column: 8
end_location:
row: 2
column: 8

View File

@ -0,0 +1,6 @@
---
source: src/pycodestyle/mod.rs
expression: checks
---
[]

View File

@ -0,0 +1,20 @@
---
source: src/pycodestyle/mod.rs
expression: checks
---
- kind: NoNewLineAtEndOfFile
location:
row: 1
column: 1
end_location:
row: 1
column: 1
fix:
content: "\n"
location:
row: 1
column: 1
end_location:
row: 1
column: 1