mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-15 06:45:17 +00:00
Modify visibility and shuffle around some modules (#1807)
This commit is contained in:
parent
d8162ce79d
commit
b36d4a15b0
144 changed files with 734 additions and 798 deletions
|
@ -5,9 +5,7 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
use ruff::source_code_generator::SourceCodeGenerator;
|
use ruff::source_code::{Generator, Locator, Stylist};
|
||||||
use ruff::source_code_locator::SourceCodeLocator;
|
|
||||||
use ruff::source_code_style::SourceCodeStyleDetector;
|
|
||||||
use rustpython_parser::parser;
|
use rustpython_parser::parser;
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
@ -20,9 +18,9 @@ pub struct Cli {
|
||||||
pub fn main(cli: &Cli) -> Result<()> {
|
pub fn main(cli: &Cli) -> Result<()> {
|
||||||
let contents = fs::read_to_string(&cli.file)?;
|
let contents = fs::read_to_string(&cli.file)?;
|
||||||
let python_ast = parser::parse_program(&contents, &cli.file.to_string_lossy())?;
|
let python_ast = parser::parse_program(&contents, &cli.file.to_string_lossy())?;
|
||||||
let locator = SourceCodeLocator::new(&contents);
|
let locator = Locator::new(&contents);
|
||||||
let stylist = SourceCodeStyleDetector::from_contents(&contents, &locator);
|
let stylist = Stylist::from_contents(&contents, &locator);
|
||||||
let mut generator: SourceCodeGenerator = (&stylist).into();
|
let mut generator: Generator = (&stylist).into();
|
||||||
generator.unparse_suite(&python_ast);
|
generator.unparse_suite(&python_ast);
|
||||||
println!("{}", generator.generate());
|
println!("{}", generator.generate());
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -34,7 +34,7 @@ def main(*, plugin: str, url: str) -> None:
|
||||||
with open(os.path.join(ROOT_DIR, f"src/{dir_name(plugin)}/rules.rs"), "w+") as fp:
|
with open(os.path.join(ROOT_DIR, f"src/{dir_name(plugin)}/rules.rs"), "w+") as fp:
|
||||||
fp.write("use crate::checkers::ast::Checker;\n")
|
fp.write("use crate::checkers::ast::Checker;\n")
|
||||||
with open(os.path.join(ROOT_DIR, f"src/{dir_name(plugin)}/mod.rs"), "w+") as fp:
|
with open(os.path.join(ROOT_DIR, f"src/{dir_name(plugin)}/mod.rs"), "w+") as fp:
|
||||||
fp.write("pub mod rules;\n")
|
fp.write("pub(crate) mod rules;\n")
|
||||||
fp.write("\n")
|
fp.write("\n")
|
||||||
fp.write(
|
fp.write(
|
||||||
"""#[cfg(test)]
|
"""#[cfg(test)]
|
||||||
|
|
|
@ -12,9 +12,7 @@ use rustpython_parser::lexer::Tok;
|
||||||
use rustpython_parser::token::StringKind;
|
use rustpython_parser::token::StringKind;
|
||||||
|
|
||||||
use crate::ast::types::{Binding, BindingKind, Range};
|
use crate::ast::types::{Binding, BindingKind, Range};
|
||||||
use crate::source_code_generator::SourceCodeGenerator;
|
use crate::source_code::{Generator, Locator, Stylist};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
|
||||||
use crate::SourceCodeLocator;
|
|
||||||
|
|
||||||
/// Create an `Expr` with default location from an `ExprKind`.
|
/// Create an `Expr` with default location from an `ExprKind`.
|
||||||
pub fn create_expr(node: ExprKind) -> Expr {
|
pub fn create_expr(node: ExprKind) -> Expr {
|
||||||
|
@ -27,15 +25,15 @@ pub fn create_stmt(node: StmtKind) -> Stmt {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate source code from an `Expr`.
|
/// Generate source code from an `Expr`.
|
||||||
pub fn unparse_expr(expr: &Expr, stylist: &SourceCodeStyleDetector) -> String {
|
pub fn unparse_expr(expr: &Expr, stylist: &Stylist) -> String {
|
||||||
let mut generator: SourceCodeGenerator = stylist.into();
|
let mut generator: Generator = stylist.into();
|
||||||
generator.unparse_expr(expr, 0);
|
generator.unparse_expr(expr, 0);
|
||||||
generator.generate()
|
generator.generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate source code from an `Stmt`.
|
/// Generate source code from an `Stmt`.
|
||||||
pub fn unparse_stmt(stmt: &Stmt, stylist: &SourceCodeStyleDetector) -> String {
|
pub fn unparse_stmt(stmt: &Stmt, stylist: &Stylist) -> String {
|
||||||
let mut generator: SourceCodeGenerator = stylist.into();
|
let mut generator: Generator = stylist.into();
|
||||||
generator.unparse_stmt(stmt);
|
generator.unparse_stmt(stmt);
|
||||||
generator.generate()
|
generator.generate()
|
||||||
}
|
}
|
||||||
|
@ -431,7 +429,7 @@ pub fn collect_arg_names<'a>(arguments: &'a Arguments) -> FxHashSet<&'a str> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if a statement or expression includes at least one comment.
|
/// Returns `true` if a statement or expression includes at least one comment.
|
||||||
pub fn has_comments<T>(located: &Located<T>, locator: &SourceCodeLocator) -> bool {
|
pub fn has_comments<T>(located: &Located<T>, locator: &Locator) -> bool {
|
||||||
lexer::make_tokenizer(&locator.slice_source_code_range(&Range::from_located(located)))
|
lexer::make_tokenizer(&locator.slice_source_code_range(&Range::from_located(located)))
|
||||||
.flatten()
|
.flatten()
|
||||||
.any(|(_, tok, _)| matches!(tok, Tok::Comment(..)))
|
.any(|(_, tok, _)| matches!(tok, Tok::Comment(..)))
|
||||||
|
@ -483,14 +481,14 @@ pub fn to_absolute(relative: Location, base: Location) -> Location {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if a `Stmt` has leading content.
|
/// Return `true` if a `Stmt` has leading content.
|
||||||
pub fn match_leading_content(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
pub fn match_leading_content(stmt: &Stmt, locator: &Locator) -> bool {
|
||||||
let range = Range::new(Location::new(stmt.location.row(), 0), stmt.location);
|
let range = Range::new(Location::new(stmt.location.row(), 0), stmt.location);
|
||||||
let prefix = locator.slice_source_code_range(&range);
|
let prefix = locator.slice_source_code_range(&range);
|
||||||
prefix.chars().any(|char| !char.is_whitespace())
|
prefix.chars().any(|char| !char.is_whitespace())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if a `Stmt` has trailing content.
|
/// Return `true` if a `Stmt` has trailing content.
|
||||||
pub fn match_trailing_content(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
pub fn match_trailing_content(stmt: &Stmt, locator: &Locator) -> bool {
|
||||||
let range = Range::new(
|
let range = Range::new(
|
||||||
stmt.end_location.unwrap(),
|
stmt.end_location.unwrap(),
|
||||||
Location::new(stmt.end_location.unwrap().row() + 1, 0),
|
Location::new(stmt.end_location.unwrap().row() + 1, 0),
|
||||||
|
@ -508,7 +506,7 @@ pub fn match_trailing_content(stmt: &Stmt, locator: &SourceCodeLocator) -> bool
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the number of trailing empty lines following a statement.
|
/// Return the number of trailing empty lines following a statement.
|
||||||
pub fn count_trailing_lines(stmt: &Stmt, locator: &SourceCodeLocator) -> usize {
|
pub fn count_trailing_lines(stmt: &Stmt, locator: &Locator) -> usize {
|
||||||
let suffix =
|
let suffix =
|
||||||
locator.slice_source_code_at(&Location::new(stmt.end_location.unwrap().row() + 1, 0));
|
locator.slice_source_code_at(&Location::new(stmt.end_location.unwrap().row() + 1, 0));
|
||||||
suffix
|
suffix
|
||||||
|
@ -520,7 +518,7 @@ pub fn count_trailing_lines(stmt: &Stmt, locator: &SourceCodeLocator) -> usize {
|
||||||
/// Return the appropriate visual `Range` for any message that spans a `Stmt`.
|
/// Return the appropriate visual `Range` for any message that spans a `Stmt`.
|
||||||
/// Specifically, this method returns the range of a function or class name,
|
/// Specifically, this method returns the range of a function or class name,
|
||||||
/// rather than that of the entire function or class body.
|
/// rather than that of the entire function or class body.
|
||||||
pub fn identifier_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Range {
|
pub fn identifier_range(stmt: &Stmt, locator: &Locator) -> Range {
|
||||||
if matches!(
|
if matches!(
|
||||||
stmt.node,
|
stmt.node,
|
||||||
StmtKind::ClassDef { .. }
|
StmtKind::ClassDef { .. }
|
||||||
|
@ -539,7 +537,7 @@ pub fn identifier_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Range {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like `identifier_range`, but accepts a `Binding`.
|
/// Like `identifier_range`, but accepts a `Binding`.
|
||||||
pub fn binding_range(binding: &Binding, locator: &SourceCodeLocator) -> Range {
|
pub fn binding_range(binding: &Binding, locator: &Locator) -> Range {
|
||||||
if matches!(
|
if matches!(
|
||||||
binding.kind,
|
binding.kind,
|
||||||
BindingKind::ClassDefinition | BindingKind::FunctionDefinition
|
BindingKind::ClassDefinition | BindingKind::FunctionDefinition
|
||||||
|
@ -555,7 +553,7 @@ pub fn binding_range(binding: &Binding, locator: &SourceCodeLocator) -> Range {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the ranges of `Name` tokens within a specified node.
|
// Return the ranges of `Name` tokens within a specified node.
|
||||||
pub fn find_names<T>(located: &Located<T>, locator: &SourceCodeLocator) -> Vec<Range> {
|
pub fn find_names<T>(located: &Located<T>, locator: &Locator) -> Vec<Range> {
|
||||||
let contents = locator.slice_source_code_range(&Range::from_located(located));
|
let contents = locator.slice_source_code_range(&Range::from_located(located));
|
||||||
lexer::make_tokenizer_located(&contents, located.location)
|
lexer::make_tokenizer_located(&contents, located.location)
|
||||||
.flatten()
|
.flatten()
|
||||||
|
@ -568,10 +566,7 @@ pub fn find_names<T>(located: &Located<T>, locator: &SourceCodeLocator) -> Vec<R
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the `Range` of `name` in `Excepthandler`.
|
/// Return the `Range` of `name` in `Excepthandler`.
|
||||||
pub fn excepthandler_name_range(
|
pub fn excepthandler_name_range(handler: &Excepthandler, locator: &Locator) -> Option<Range> {
|
||||||
handler: &Excepthandler,
|
|
||||||
locator: &SourceCodeLocator,
|
|
||||||
) -> Option<Range> {
|
|
||||||
let ExcepthandlerKind::ExceptHandler {
|
let ExcepthandlerKind::ExceptHandler {
|
||||||
name, type_, body, ..
|
name, type_, body, ..
|
||||||
} = &handler.node;
|
} = &handler.node;
|
||||||
|
@ -594,7 +589,7 @@ pub fn excepthandler_name_range(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the `Range` of `except` in `Excepthandler`.
|
/// Return the `Range` of `except` in `Excepthandler`.
|
||||||
pub fn except_range(handler: &Excepthandler, locator: &SourceCodeLocator) -> Range {
|
pub fn except_range(handler: &Excepthandler, locator: &Locator) -> Range {
|
||||||
let ExcepthandlerKind::ExceptHandler { body, type_, .. } = &handler.node;
|
let ExcepthandlerKind::ExceptHandler { body, type_, .. } = &handler.node;
|
||||||
let end = if let Some(type_) = type_ {
|
let end = if let Some(type_) = type_ {
|
||||||
type_.location
|
type_.location
|
||||||
|
@ -619,7 +614,7 @@ pub fn except_range(handler: &Excepthandler, locator: &SourceCodeLocator) -> Ran
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find f-strings that don't contain any formatted values in a `JoinedStr`.
|
/// Find f-strings that don't contain any formatted values in a `JoinedStr`.
|
||||||
pub fn find_useless_f_strings(expr: &Expr, locator: &SourceCodeLocator) -> Vec<(Range, Range)> {
|
pub fn find_useless_f_strings(expr: &Expr, locator: &Locator) -> Vec<(Range, Range)> {
|
||||||
let contents = locator.slice_source_code_range(&Range::from_located(expr));
|
let contents = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
lexer::make_tokenizer_located(&contents, expr.location)
|
lexer::make_tokenizer_located(&contents, expr.location)
|
||||||
.flatten()
|
.flatten()
|
||||||
|
@ -656,7 +651,7 @@ pub fn find_useless_f_strings(expr: &Expr, locator: &SourceCodeLocator) -> Vec<(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the `Range` of `else` in `For`, `AsyncFor`, and `While` statements.
|
/// Return the `Range` of `else` in `For`, `AsyncFor`, and `While` statements.
|
||||||
pub fn else_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Option<Range> {
|
pub fn else_range(stmt: &Stmt, locator: &Locator) -> Option<Range> {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::For { body, orelse, .. }
|
StmtKind::For { body, orelse, .. }
|
||||||
| StmtKind::AsyncFor { body, orelse, .. }
|
| StmtKind::AsyncFor { body, orelse, .. }
|
||||||
|
@ -690,7 +685,7 @@ pub fn else_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Option<Range> {
|
||||||
|
|
||||||
/// Return `true` if a `Stmt` appears to be part of a multi-statement line, with
|
/// Return `true` if a `Stmt` appears to be part of a multi-statement line, with
|
||||||
/// other statements preceding it.
|
/// other statements preceding it.
|
||||||
pub fn preceded_by_continuation(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
pub fn preceded_by_continuation(stmt: &Stmt, locator: &Locator) -> bool {
|
||||||
// Does the previous line end in a continuation? This will have a specific
|
// Does the previous line end in a continuation? This will have a specific
|
||||||
// false-positive, which is that if the previous line ends in a comment, it
|
// false-positive, which is that if the previous line ends in a comment, it
|
||||||
// will be treated as a continuation. So we should only use this information to
|
// will be treated as a continuation. So we should only use this information to
|
||||||
|
@ -711,13 +706,13 @@ pub fn preceded_by_continuation(stmt: &Stmt, locator: &SourceCodeLocator) -> boo
|
||||||
|
|
||||||
/// Return `true` if a `Stmt` appears to be part of a multi-statement line, with
|
/// Return `true` if a `Stmt` appears to be part of a multi-statement line, with
|
||||||
/// other statements preceding it.
|
/// other statements preceding it.
|
||||||
pub fn preceded_by_multi_statement_line(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
pub fn preceded_by_multi_statement_line(stmt: &Stmt, locator: &Locator) -> bool {
|
||||||
match_leading_content(stmt, locator) || preceded_by_continuation(stmt, locator)
|
match_leading_content(stmt, locator) || preceded_by_continuation(stmt, locator)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if a `Stmt` appears to be part of a multi-statement line, with
|
/// Return `true` if a `Stmt` appears to be part of a multi-statement line, with
|
||||||
/// other statements following it.
|
/// other statements following it.
|
||||||
pub fn followed_by_multi_statement_line(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
pub fn followed_by_multi_statement_line(stmt: &Stmt, locator: &Locator) -> bool {
|
||||||
match_trailing_content(stmt, locator)
|
match_trailing_content(stmt, locator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,7 +794,7 @@ mod tests {
|
||||||
else_range, identifier_range, match_module_member, match_trailing_content,
|
else_range, identifier_range, match_module_member, match_trailing_content,
|
||||||
};
|
};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn builtin() -> Result<()> {
|
fn builtin() -> Result<()> {
|
||||||
|
@ -949,25 +944,25 @@ mod tests {
|
||||||
let contents = "x = 1";
|
let contents = "x = 1";
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert!(!match_trailing_content(stmt, &locator));
|
assert!(!match_trailing_content(stmt, &locator));
|
||||||
|
|
||||||
let contents = "x = 1; y = 2";
|
let contents = "x = 1; y = 2";
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert!(match_trailing_content(stmt, &locator));
|
assert!(match_trailing_content(stmt, &locator));
|
||||||
|
|
||||||
let contents = "x = 1 ";
|
let contents = "x = 1 ";
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert!(!match_trailing_content(stmt, &locator));
|
assert!(!match_trailing_content(stmt, &locator));
|
||||||
|
|
||||||
let contents = "x = 1 # Comment";
|
let contents = "x = 1 # Comment";
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert!(!match_trailing_content(stmt, &locator));
|
assert!(!match_trailing_content(stmt, &locator));
|
||||||
|
|
||||||
let contents = r#"
|
let contents = r#"
|
||||||
|
@ -977,7 +972,7 @@ y = 2
|
||||||
.trim();
|
.trim();
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert!(!match_trailing_content(stmt, &locator));
|
assert!(!match_trailing_content(stmt, &locator));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -988,7 +983,7 @@ y = 2
|
||||||
let contents = "def f(): pass".trim();
|
let contents = "def f(): pass".trim();
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
identifier_range(stmt, &locator),
|
identifier_range(stmt, &locator),
|
||||||
Range::new(Location::new(1, 4), Location::new(1, 5),)
|
Range::new(Location::new(1, 4), Location::new(1, 5),)
|
||||||
|
@ -1002,7 +997,7 @@ def \
|
||||||
.trim();
|
.trim();
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
identifier_range(stmt, &locator),
|
identifier_range(stmt, &locator),
|
||||||
Range::new(Location::new(2, 2), Location::new(2, 3),)
|
Range::new(Location::new(2, 2), Location::new(2, 3),)
|
||||||
|
@ -1011,7 +1006,7 @@ def \
|
||||||
let contents = "class Class(): pass".trim();
|
let contents = "class Class(): pass".trim();
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
identifier_range(stmt, &locator),
|
identifier_range(stmt, &locator),
|
||||||
Range::new(Location::new(1, 6), Location::new(1, 11),)
|
Range::new(Location::new(1, 6), Location::new(1, 11),)
|
||||||
|
@ -1020,7 +1015,7 @@ def \
|
||||||
let contents = "class Class: pass".trim();
|
let contents = "class Class: pass".trim();
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
identifier_range(stmt, &locator),
|
identifier_range(stmt, &locator),
|
||||||
Range::new(Location::new(1, 6), Location::new(1, 11),)
|
Range::new(Location::new(1, 6), Location::new(1, 11),)
|
||||||
|
@ -1034,7 +1029,7 @@ class Class():
|
||||||
.trim();
|
.trim();
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
identifier_range(stmt, &locator),
|
identifier_range(stmt, &locator),
|
||||||
Range::new(Location::new(2, 6), Location::new(2, 11),)
|
Range::new(Location::new(2, 6), Location::new(2, 11),)
|
||||||
|
@ -1043,7 +1038,7 @@ class Class():
|
||||||
let contents = r#"x = y + 1"#.trim();
|
let contents = r#"x = y + 1"#.trim();
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
identifier_range(stmt, &locator),
|
identifier_range(stmt, &locator),
|
||||||
Range::new(Location::new(1, 0), Location::new(1, 9),)
|
Range::new(Location::new(1, 0), Location::new(1, 9),)
|
||||||
|
@ -1063,7 +1058,7 @@ else:
|
||||||
.trim();
|
.trim();
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
let range = else_range(stmt, &locator).unwrap();
|
let range = else_range(stmt, &locator).unwrap();
|
||||||
assert_eq!(range.location.row(), 3);
|
assert_eq!(range.location.row(), 3);
|
||||||
assert_eq!(range.location.column(), 0);
|
assert_eq!(range.location.column(), 0);
|
||||||
|
|
|
@ -74,7 +74,6 @@ pub enum ScopeKind<'a> {
|
||||||
Function(FunctionDef<'a>),
|
Function(FunctionDef<'a>),
|
||||||
Generator,
|
Generator,
|
||||||
Module,
|
Module,
|
||||||
Arg,
|
|
||||||
Lambda(Lambda<'a>),
|
Lambda(Lambda<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,225 +1 @@
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::collections::BTreeSet;
|
|
||||||
|
|
||||||
use itertools::Itertools;
|
|
||||||
use ropey::RopeBuilder;
|
|
||||||
use rustpython_parser::ast::Location;
|
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::registry::Diagnostic;
|
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash)]
|
|
||||||
pub enum Mode {
|
|
||||||
Generate,
|
|
||||||
Apply,
|
|
||||||
Diff,
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<bool> for Mode {
|
|
||||||
fn from(value: bool) -> Self {
|
|
||||||
if value {
|
|
||||||
Mode::Apply
|
|
||||||
} else {
|
|
||||||
Mode::None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Auto-fix errors in a file, and write the fixed source code to disk.
|
|
||||||
pub fn fix_file<'a>(
|
|
||||||
diagnostics: &'a [Diagnostic],
|
|
||||||
locator: &'a SourceCodeLocator<'a>,
|
|
||||||
) -> Option<(Cow<'a, str>, usize)> {
|
|
||||||
if diagnostics.iter().all(|check| check.fix.is_none()) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(apply_fixes(
|
|
||||||
diagnostics.iter().filter_map(|check| check.fix.as_ref()),
|
|
||||||
locator,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Apply a series of fixes.
|
|
||||||
fn apply_fixes<'a>(
|
|
||||||
fixes: impl Iterator<Item = &'a Fix>,
|
|
||||||
locator: &'a SourceCodeLocator<'a>,
|
|
||||||
) -> (Cow<'a, str>, usize) {
|
|
||||||
let mut output = RopeBuilder::new();
|
|
||||||
let mut last_pos: Location = Location::new(1, 0);
|
|
||||||
let mut applied: BTreeSet<&Fix> = BTreeSet::default();
|
|
||||||
let mut num_fixed: usize = 0;
|
|
||||||
|
|
||||||
for fix in fixes.sorted_by_key(|fix| fix.location) {
|
|
||||||
// If we already applied an identical fix as part of another correction, skip
|
|
||||||
// any re-application.
|
|
||||||
if applied.contains(&fix) {
|
|
||||||
num_fixed += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Best-effort approach: if this fix overlaps with a fix we've already applied,
|
|
||||||
// skip it.
|
|
||||||
if last_pos > fix.location {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all contents from `last_pos` to `fix.location`.
|
|
||||||
let slice = locator.slice_source_code_range(&Range::new(last_pos, fix.location));
|
|
||||||
output.append(&slice);
|
|
||||||
|
|
||||||
// Add the patch itself.
|
|
||||||
output.append(&fix.content);
|
|
||||||
|
|
||||||
// Track that the fix was applied.
|
|
||||||
last_pos = fix.end_location;
|
|
||||||
applied.insert(fix);
|
|
||||||
num_fixed += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the remaining content.
|
|
||||||
let slice = locator.slice_source_code_at(&last_pos);
|
|
||||||
output.append(&slice);
|
|
||||||
|
|
||||||
(Cow::from(output.finish()), num_fixed)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use rustpython_parser::ast::Location;
|
|
||||||
|
|
||||||
use crate::autofix::fixer::apply_fixes;
|
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::SourceCodeLocator;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn empty_file() {
|
|
||||||
let fixes = vec![];
|
|
||||||
let locator = SourceCodeLocator::new(r#""#);
|
|
||||||
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
|
||||||
assert_eq!(contents, "");
|
|
||||||
assert_eq!(fixed, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn apply_single_replacement() {
|
|
||||||
let fixes = vec![Fix {
|
|
||||||
content: "Bar".to_string(),
|
|
||||||
location: Location::new(1, 8),
|
|
||||||
end_location: Location::new(1, 14),
|
|
||||||
}];
|
|
||||||
let locator = SourceCodeLocator::new(
|
|
||||||
r#"
|
|
||||||
class A(object):
|
|
||||||
...
|
|
||||||
"#
|
|
||||||
.trim(),
|
|
||||||
);
|
|
||||||
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
|
||||||
assert_eq!(
|
|
||||||
contents,
|
|
||||||
r#"
|
|
||||||
class A(Bar):
|
|
||||||
...
|
|
||||||
"#
|
|
||||||
.trim(),
|
|
||||||
);
|
|
||||||
assert_eq!(fixed, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn apply_single_removal() {
|
|
||||||
let fixes = vec![Fix {
|
|
||||||
content: String::new(),
|
|
||||||
location: Location::new(1, 7),
|
|
||||||
end_location: Location::new(1, 15),
|
|
||||||
}];
|
|
||||||
let locator = SourceCodeLocator::new(
|
|
||||||
r#"
|
|
||||||
class A(object):
|
|
||||||
...
|
|
||||||
"#
|
|
||||||
.trim(),
|
|
||||||
);
|
|
||||||
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
|
||||||
assert_eq!(
|
|
||||||
contents,
|
|
||||||
r#"
|
|
||||||
class A:
|
|
||||||
...
|
|
||||||
"#
|
|
||||||
.trim()
|
|
||||||
);
|
|
||||||
assert_eq!(fixed, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn apply_double_removal() {
|
|
||||||
let fixes = vec![
|
|
||||||
Fix {
|
|
||||||
content: String::new(),
|
|
||||||
location: Location::new(1, 7),
|
|
||||||
end_location: Location::new(1, 16),
|
|
||||||
},
|
|
||||||
Fix {
|
|
||||||
content: String::new(),
|
|
||||||
location: Location::new(1, 16),
|
|
||||||
end_location: Location::new(1, 23),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
let locator = SourceCodeLocator::new(
|
|
||||||
r#"
|
|
||||||
class A(object, object):
|
|
||||||
...
|
|
||||||
"#
|
|
||||||
.trim(),
|
|
||||||
);
|
|
||||||
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
contents,
|
|
||||||
r#"
|
|
||||||
class A:
|
|
||||||
...
|
|
||||||
"#
|
|
||||||
.trim()
|
|
||||||
);
|
|
||||||
assert_eq!(fixed, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ignore_overlapping_fixes() {
|
|
||||||
let fixes = vec![
|
|
||||||
Fix {
|
|
||||||
content: String::new(),
|
|
||||||
location: Location::new(1, 7),
|
|
||||||
end_location: Location::new(1, 15),
|
|
||||||
},
|
|
||||||
Fix {
|
|
||||||
content: "ignored".to_string(),
|
|
||||||
location: Location::new(1, 9),
|
|
||||||
end_location: Location::new(1, 11),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
let locator = SourceCodeLocator::new(
|
|
||||||
r#"
|
|
||||||
class A(object):
|
|
||||||
...
|
|
||||||
"#
|
|
||||||
.trim(),
|
|
||||||
);
|
|
||||||
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
|
||||||
assert_eq!(
|
|
||||||
contents,
|
|
||||||
r#"
|
|
||||||
class A:
|
|
||||||
...
|
|
||||||
"#
|
|
||||||
.trim(),
|
|
||||||
);
|
|
||||||
assert_eq!(fixed, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,10 +9,10 @@ use crate::ast::helpers;
|
||||||
use crate::ast::helpers::to_absolute;
|
use crate::ast::helpers::to_absolute;
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::ast::whitespace::LinesWithTrailingNewline;
|
use crate::ast::whitespace::LinesWithTrailingNewline;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::cst::helpers::compose_module_path;
|
use crate::cst::helpers::compose_module_path;
|
||||||
use crate::cst::matchers::match_module;
|
use crate::cst::matchers::match_module;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::fix::Fix;
|
||||||
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
/// Determine if a body contains only a single statement, taking into account
|
/// Determine if a body contains only a single statement, taking into account
|
||||||
/// deleted.
|
/// deleted.
|
||||||
|
@ -78,7 +78,7 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool>
|
||||||
|
|
||||||
/// Return the location of a trailing semicolon following a `Stmt`, if it's part
|
/// Return the location of a trailing semicolon following a `Stmt`, if it's part
|
||||||
/// of a multi-statement line.
|
/// of a multi-statement line.
|
||||||
fn trailing_semicolon(stmt: &Stmt, locator: &SourceCodeLocator) -> Option<Location> {
|
fn trailing_semicolon(stmt: &Stmt, locator: &Locator) -> Option<Location> {
|
||||||
let contents = locator.slice_source_code_at(&stmt.end_location.unwrap());
|
let contents = locator.slice_source_code_at(&stmt.end_location.unwrap());
|
||||||
for (row, line) in LinesWithTrailingNewline::from(&contents).enumerate() {
|
for (row, line) in LinesWithTrailingNewline::from(&contents).enumerate() {
|
||||||
let trimmed = line.trim();
|
let trimmed = line.trim();
|
||||||
|
@ -100,7 +100,7 @@ fn trailing_semicolon(stmt: &Stmt, locator: &SourceCodeLocator) -> Option<Locati
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the next valid break for a `Stmt` after a semicolon.
|
/// Find the next valid break for a `Stmt` after a semicolon.
|
||||||
fn next_stmt_break(semicolon: Location, locator: &SourceCodeLocator) -> Location {
|
fn next_stmt_break(semicolon: Location, locator: &Locator) -> Location {
|
||||||
let start_location = Location::new(semicolon.row(), semicolon.column() + 1);
|
let start_location = Location::new(semicolon.row(), semicolon.column() + 1);
|
||||||
let contents = locator.slice_source_code_at(&start_location);
|
let contents = locator.slice_source_code_at(&start_location);
|
||||||
for (row, line) in LinesWithTrailingNewline::from(&contents).enumerate() {
|
for (row, line) in LinesWithTrailingNewline::from(&contents).enumerate() {
|
||||||
|
@ -133,7 +133,7 @@ fn next_stmt_break(semicolon: Location, locator: &SourceCodeLocator) -> Location
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if a `Stmt` occurs at the end of a file.
|
/// Return `true` if a `Stmt` occurs at the end of a file.
|
||||||
fn is_end_of_file(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
fn is_end_of_file(stmt: &Stmt, locator: &Locator) -> bool {
|
||||||
let contents = locator.slice_source_code_at(&stmt.end_location.unwrap());
|
let contents = locator.slice_source_code_at(&stmt.end_location.unwrap());
|
||||||
contents.is_empty()
|
contents.is_empty()
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ pub fn delete_stmt(
|
||||||
stmt: &Stmt,
|
stmt: &Stmt,
|
||||||
parent: Option<&Stmt>,
|
parent: Option<&Stmt>,
|
||||||
deleted: &[&Stmt],
|
deleted: &[&Stmt],
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
if parent
|
if parent
|
||||||
.map(|parent| is_lone_child(stmt, parent, deleted))
|
.map(|parent| is_lone_child(stmt, parent, deleted))
|
||||||
|
@ -197,7 +197,7 @@ pub fn remove_unused_imports<'a>(
|
||||||
stmt: &Stmt,
|
stmt: &Stmt,
|
||||||
parent: Option<&Stmt>,
|
parent: Option<&Stmt>,
|
||||||
deleted: &[&Stmt],
|
deleted: &[&Stmt],
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(stmt));
|
let module_text = locator.slice_source_code_range(&Range::from_located(stmt));
|
||||||
let mut tree = match_module(&module_text)?;
|
let mut tree = match_module(&module_text)?;
|
||||||
|
@ -299,20 +299,20 @@ mod tests {
|
||||||
use rustpython_parser::parser;
|
use rustpython_parser::parser;
|
||||||
|
|
||||||
use crate::autofix::helpers::{next_stmt_break, trailing_semicolon};
|
use crate::autofix::helpers::{next_stmt_break, trailing_semicolon};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn find_semicolon() -> Result<()> {
|
fn find_semicolon() -> Result<()> {
|
||||||
let contents = "x = 1";
|
let contents = "x = 1";
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(trailing_semicolon(stmt, &locator), None);
|
assert_eq!(trailing_semicolon(stmt, &locator), None);
|
||||||
|
|
||||||
let contents = "x = 1; y = 1";
|
let contents = "x = 1; y = 1";
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
trailing_semicolon(stmt, &locator),
|
trailing_semicolon(stmt, &locator),
|
||||||
Some(Location::new(1, 5))
|
Some(Location::new(1, 5))
|
||||||
|
@ -321,7 +321,7 @@ mod tests {
|
||||||
let contents = "x = 1 ; y = 1";
|
let contents = "x = 1 ; y = 1";
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
trailing_semicolon(stmt, &locator),
|
trailing_semicolon(stmt, &locator),
|
||||||
Some(Location::new(1, 6))
|
Some(Location::new(1, 6))
|
||||||
|
@ -334,7 +334,7 @@ x = 1 \
|
||||||
.trim();
|
.trim();
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let stmt = program.first().unwrap();
|
let stmt = program.first().unwrap();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
trailing_semicolon(stmt, &locator),
|
trailing_semicolon(stmt, &locator),
|
||||||
Some(Location::new(2, 2))
|
Some(Location::new(2, 2))
|
||||||
|
@ -346,14 +346,14 @@ x = 1 \
|
||||||
#[test]
|
#[test]
|
||||||
fn find_next_stmt_break() {
|
fn find_next_stmt_break() {
|
||||||
let contents = "x = 1; y = 1";
|
let contents = "x = 1; y = 1";
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
next_stmt_break(Location::new(1, 4), &locator),
|
next_stmt_break(Location::new(1, 4), &locator),
|
||||||
Location::new(1, 5)
|
Location::new(1, 5)
|
||||||
);
|
);
|
||||||
|
|
||||||
let contents = "x = 1 ; y = 1";
|
let contents = "x = 1 ; y = 1";
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
next_stmt_break(Location::new(1, 5), &locator),
|
next_stmt_break(Location::new(1, 5), &locator),
|
||||||
Location::new(1, 6)
|
Location::new(1, 6)
|
||||||
|
@ -364,7 +364,7 @@ x = 1 \
|
||||||
; y = 1
|
; y = 1
|
||||||
"#
|
"#
|
||||||
.trim();
|
.trim();
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
next_stmt_break(Location::new(2, 2), &locator),
|
next_stmt_break(Location::new(2, 2), &locator),
|
||||||
Location::new(2, 4)
|
Location::new(2, 4)
|
||||||
|
|
|
@ -1,38 +1,210 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
use ropey::RopeBuilder;
|
||||||
use rustpython_ast::Location;
|
use rustpython_ast::Location;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::fix::Fix;
|
||||||
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
pub mod fixer;
|
pub mod fixer;
|
||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
/// Auto-fix errors in a file, and write the fixed source code to disk.
|
||||||
pub struct Fix {
|
pub fn fix_file<'a>(
|
||||||
pub content: String,
|
diagnostics: &'a [Diagnostic],
|
||||||
pub location: Location,
|
locator: &'a Locator<'a>,
|
||||||
pub end_location: Location,
|
) -> Option<(Cow<'a, str>, usize)> {
|
||||||
|
if diagnostics.iter().all(|check| check.fix.is_none()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(apply_fixes(
|
||||||
|
diagnostics.iter().filter_map(|check| check.fix.as_ref()),
|
||||||
|
locator,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fix {
|
/// Apply a series of fixes.
|
||||||
pub fn deletion(start: Location, end: Location) -> Self {
|
fn apply_fixes<'a>(
|
||||||
Self {
|
fixes: impl Iterator<Item = &'a Fix>,
|
||||||
|
locator: &'a Locator<'a>,
|
||||||
|
) -> (Cow<'a, str>, usize) {
|
||||||
|
let mut output = RopeBuilder::new();
|
||||||
|
let mut last_pos: Location = Location::new(1, 0);
|
||||||
|
let mut applied: BTreeSet<&Fix> = BTreeSet::default();
|
||||||
|
let mut num_fixed: usize = 0;
|
||||||
|
|
||||||
|
for fix in fixes.sorted_by_key(|fix| fix.location) {
|
||||||
|
// If we already applied an identical fix as part of another correction, skip
|
||||||
|
// any re-application.
|
||||||
|
if applied.contains(&fix) {
|
||||||
|
num_fixed += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Best-effort approach: if this fix overlaps with a fix we've already applied,
|
||||||
|
// skip it.
|
||||||
|
if last_pos > fix.location {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all contents from `last_pos` to `fix.location`.
|
||||||
|
let slice = locator.slice_source_code_range(&Range::new(last_pos, fix.location));
|
||||||
|
output.append(&slice);
|
||||||
|
|
||||||
|
// Add the patch itself.
|
||||||
|
output.append(&fix.content);
|
||||||
|
|
||||||
|
// Track that the fix was applied.
|
||||||
|
last_pos = fix.end_location;
|
||||||
|
applied.insert(fix);
|
||||||
|
num_fixed += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the remaining content.
|
||||||
|
let slice = locator.slice_source_code_at(&last_pos);
|
||||||
|
output.append(&slice);
|
||||||
|
|
||||||
|
(Cow::from(output.finish()), num_fixed)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use rustpython_parser::ast::Location;
|
||||||
|
|
||||||
|
use crate::autofix::apply_fixes;
|
||||||
|
use crate::fix::Fix;
|
||||||
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_file() {
|
||||||
|
let fixes = vec![];
|
||||||
|
let locator = Locator::new(r#""#);
|
||||||
|
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
||||||
|
assert_eq!(contents, "");
|
||||||
|
assert_eq!(fixed, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_single_replacement() {
|
||||||
|
let fixes = vec![Fix {
|
||||||
|
content: "Bar".to_string(),
|
||||||
|
location: Location::new(1, 8),
|
||||||
|
end_location: Location::new(1, 14),
|
||||||
|
}];
|
||||||
|
let locator = Locator::new(
|
||||||
|
r#"
|
||||||
|
class A(object):
|
||||||
|
...
|
||||||
|
"#
|
||||||
|
.trim(),
|
||||||
|
);
|
||||||
|
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
||||||
|
assert_eq!(
|
||||||
|
contents,
|
||||||
|
r#"
|
||||||
|
class A(Bar):
|
||||||
|
...
|
||||||
|
"#
|
||||||
|
.trim(),
|
||||||
|
);
|
||||||
|
assert_eq!(fixed, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_single_removal() {
|
||||||
|
let fixes = vec![Fix {
|
||||||
content: String::new(),
|
content: String::new(),
|
||||||
location: start,
|
location: Location::new(1, 7),
|
||||||
end_location: end,
|
end_location: Location::new(1, 15),
|
||||||
}
|
}];
|
||||||
|
let locator = Locator::new(
|
||||||
|
r#"
|
||||||
|
class A(object):
|
||||||
|
...
|
||||||
|
"#
|
||||||
|
.trim(),
|
||||||
|
);
|
||||||
|
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
||||||
|
assert_eq!(
|
||||||
|
contents,
|
||||||
|
r#"
|
||||||
|
class A:
|
||||||
|
...
|
||||||
|
"#
|
||||||
|
.trim()
|
||||||
|
);
|
||||||
|
assert_eq!(fixed, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replacement(content: String, start: Location, end: Location) -> Self {
|
#[test]
|
||||||
Self {
|
fn apply_double_removal() {
|
||||||
content,
|
let fixes = vec![
|
||||||
location: start,
|
Fix {
|
||||||
end_location: end,
|
content: String::new(),
|
||||||
}
|
location: Location::new(1, 7),
|
||||||
|
end_location: Location::new(1, 16),
|
||||||
|
},
|
||||||
|
Fix {
|
||||||
|
content: String::new(),
|
||||||
|
location: Location::new(1, 16),
|
||||||
|
end_location: Location::new(1, 23),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let locator = Locator::new(
|
||||||
|
r#"
|
||||||
|
class A(object, object):
|
||||||
|
...
|
||||||
|
"#
|
||||||
|
.trim(),
|
||||||
|
);
|
||||||
|
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
contents,
|
||||||
|
r#"
|
||||||
|
class A:
|
||||||
|
...
|
||||||
|
"#
|
||||||
|
.trim()
|
||||||
|
);
|
||||||
|
assert_eq!(fixed, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insertion(content: String, at: Location) -> Self {
|
#[test]
|
||||||
Self {
|
fn ignore_overlapping_fixes() {
|
||||||
content,
|
let fixes = vec![
|
||||||
location: at,
|
Fix {
|
||||||
end_location: at,
|
content: String::new(),
|
||||||
}
|
location: Location::new(1, 7),
|
||||||
|
end_location: Location::new(1, 15),
|
||||||
|
},
|
||||||
|
Fix {
|
||||||
|
content: "ignored".to_string(),
|
||||||
|
location: Location::new(1, 9),
|
||||||
|
end_location: Location::new(1, 11),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let locator = Locator::new(
|
||||||
|
r#"
|
||||||
|
class A(object):
|
||||||
|
...
|
||||||
|
"#
|
||||||
|
.trim(),
|
||||||
|
);
|
||||||
|
let (contents, fixed) = apply_fixes(fixes.iter(), &locator);
|
||||||
|
assert_eq!(
|
||||||
|
contents,
|
||||||
|
r#"
|
||||||
|
class A:
|
||||||
|
...
|
||||||
|
"#
|
||||||
|
.trim(),
|
||||||
|
);
|
||||||
|
assert_eq!(fixed, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ fn cache_key<P: AsRef<Path>>(path: P, settings: &Settings, autofix: flags::Autof
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
/// Initialize the cache at the specified `Path`.
|
/// Initialize the cache at the specified `Path`.
|
||||||
pub fn init(path: &Path) -> Result<()> {
|
pub fn init(path: &Path) -> Result<()> {
|
||||||
// Create the cache directories.
|
// Create the cache directories.
|
||||||
|
|
|
@ -33,8 +33,7 @@ use crate::python::typing::SubscriptKind;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::settings::types::PythonVersion;
|
use crate::settings::types::PythonVersion;
|
||||||
use crate::settings::{flags, Settings};
|
use crate::settings::{flags, Settings};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::{Locator, Stylist};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
|
||||||
use crate::violations::DeferralKeyword;
|
use crate::violations::DeferralKeyword;
|
||||||
use crate::visibility::{module_visibility, transition_scope, Modifier, Visibility, VisibleScope};
|
use crate::visibility::{module_visibility, transition_scope, Modifier, Visibility, VisibleScope};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -59,8 +58,8 @@ pub struct Checker<'a> {
|
||||||
noqa: flags::Noqa,
|
noqa: flags::Noqa,
|
||||||
pub(crate) settings: &'a Settings,
|
pub(crate) settings: &'a Settings,
|
||||||
pub(crate) noqa_line_for: &'a IntMap<usize, usize>,
|
pub(crate) noqa_line_for: &'a IntMap<usize, usize>,
|
||||||
pub(crate) locator: &'a SourceCodeLocator<'a>,
|
pub(crate) locator: &'a Locator<'a>,
|
||||||
pub(crate) style: &'a SourceCodeStyleDetector<'a>,
|
pub(crate) style: &'a Stylist<'a>,
|
||||||
// Computed diagnostics.
|
// Computed diagnostics.
|
||||||
pub(crate) diagnostics: Vec<Diagnostic>,
|
pub(crate) diagnostics: Vec<Diagnostic>,
|
||||||
// Function and class definition tracking (e.g., for docstring enforcement).
|
// Function and class definition tracking (e.g., for docstring enforcement).
|
||||||
|
@ -110,8 +109,8 @@ impl<'a> Checker<'a> {
|
||||||
autofix: flags::Autofix,
|
autofix: flags::Autofix,
|
||||||
noqa: flags::Noqa,
|
noqa: flags::Noqa,
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
locator: &'a SourceCodeLocator,
|
locator: &'a Locator,
|
||||||
style: &'a SourceCodeStyleDetector,
|
style: &'a Stylist,
|
||||||
) -> Checker<'a> {
|
) -> Checker<'a> {
|
||||||
Checker {
|
Checker {
|
||||||
settings,
|
settings,
|
||||||
|
@ -3238,16 +3237,6 @@ impl<'a> Checker<'a> {
|
||||||
self.parents.iter().rev().nth(1)
|
self.parents.iter().rev().nth(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the grandparent `Stmt` of the current `Stmt`, if any.
|
|
||||||
pub fn current_stmt_grandparent(&self) -> Option<&RefEquality<'a, Stmt>> {
|
|
||||||
self.parents.iter().rev().nth(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the current `Expr`.
|
|
||||||
pub fn current_expr(&self) -> Option<&RefEquality<'a, Expr>> {
|
|
||||||
self.exprs.iter().rev().next()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the parent `Expr` of the current `Expr`.
|
/// Return the parent `Expr` of the current `Expr`.
|
||||||
pub fn current_expr_parent(&self) -> Option<&RefEquality<'a, Expr>> {
|
pub fn current_expr_parent(&self) -> Option<&RefEquality<'a, Expr>> {
|
||||||
self.exprs.iter().rev().nth(1)
|
self.exprs.iter().rev().nth(1)
|
||||||
|
@ -4308,8 +4297,8 @@ impl<'a> Checker<'a> {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn check_ast(
|
pub fn check_ast(
|
||||||
python_ast: &Suite,
|
python_ast: &Suite,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
stylist: &SourceCodeStyleDetector,
|
stylist: &Stylist,
|
||||||
noqa_line_for: &IntMap<usize, usize>,
|
noqa_line_for: &IntMap<usize, usize>,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
autofix: flags::Autofix,
|
autofix: flags::Autofix,
|
||||||
|
|
|
@ -10,16 +10,15 @@ use crate::isort;
|
||||||
use crate::isort::track::{Block, ImportTracker};
|
use crate::isort::track::{Block, ImportTracker};
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::settings::{flags, Settings};
|
use crate::settings::{flags, Settings};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::{Locator, Stylist};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn check_imports(
|
pub fn check_imports(
|
||||||
python_ast: &Suite,
|
python_ast: &Suite,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
directives: &IsortDirectives,
|
directives: &IsortDirectives,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
stylist: &SourceCodeStyleDetector,
|
stylist: &Stylist,
|
||||||
autofix: flags::Autofix,
|
autofix: flags::Autofix,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
package: Option<&Path>,
|
package: Option<&Path>,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use nohash_hasher::IntMap;
|
||||||
use rustpython_parser::ast::Location;
|
use rustpython_parser::ast::Location;
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
use crate::fix::Fix;
|
||||||
use crate::noqa::{is_file_exempt, Directive};
|
use crate::noqa::{is_file_exempt, Directive};
|
||||||
use crate::registry::{Diagnostic, DiagnosticKind, RuleCode, CODE_REDIRECTS};
|
use crate::registry::{Diagnostic, DiagnosticKind, RuleCode, CODE_REDIRECTS};
|
||||||
use crate::settings::{flags, Settings};
|
use crate::settings::{flags, Settings};
|
||||||
|
|
|
@ -5,12 +5,12 @@ use rustpython_parser::lexer::{LexResult, Tok};
|
||||||
use crate::lex::docstring_detection::StateMachine;
|
use crate::lex::docstring_detection::StateMachine;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::ruff::rules::Context;
|
use crate::ruff::rules::Context;
|
||||||
use crate::settings::flags;
|
use crate::settings::{flags, Settings};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
use crate::{eradicate, flake8_implicit_str_concat, flake8_quotes, pycodestyle, ruff, Settings};
|
use crate::{eradicate, flake8_implicit_str_concat, flake8_quotes, pycodestyle, ruff};
|
||||||
|
|
||||||
pub fn check_tokens(
|
pub fn check_tokens(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
tokens: &[LexResult],
|
tokens: &[LexResult],
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
autofix: flags::Autofix,
|
autofix: flags::Autofix,
|
||||||
|
|
|
@ -15,7 +15,6 @@ use rustpython_ast::Location;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
use crate::autofix::fixer;
|
|
||||||
use crate::cache::CACHE_DIR_NAME;
|
use crate::cache::CACHE_DIR_NAME;
|
||||||
use crate::cli::Overrides;
|
use crate::cli::Overrides;
|
||||||
use crate::iterators::par_iter;
|
use crate::iterators::par_iter;
|
||||||
|
@ -26,7 +25,7 @@ use crate::registry::RuleCode;
|
||||||
use crate::resolver::{FileDiscovery, PyprojectDiscovery};
|
use crate::resolver::{FileDiscovery, PyprojectDiscovery};
|
||||||
use crate::settings::flags;
|
use crate::settings::flags;
|
||||||
use crate::settings::types::SerializationFormat;
|
use crate::settings::types::SerializationFormat;
|
||||||
use crate::{cache, fs, packages, resolver, violations, warn_user_once};
|
use crate::{cache, fix, fs, packaging, resolver, violations, warn_user_once};
|
||||||
|
|
||||||
/// Run the linter over a collection of files.
|
/// Run the linter over a collection of files.
|
||||||
pub fn run(
|
pub fn run(
|
||||||
|
@ -35,7 +34,7 @@ pub fn run(
|
||||||
file_strategy: &FileDiscovery,
|
file_strategy: &FileDiscovery,
|
||||||
overrides: &Overrides,
|
overrides: &Overrides,
|
||||||
cache: flags::Cache,
|
cache: flags::Cache,
|
||||||
autofix: fixer::Mode,
|
autofix: fix::FixMode,
|
||||||
) -> Result<Diagnostics> {
|
) -> Result<Diagnostics> {
|
||||||
// Collect all the Python files to check.
|
// Collect all the Python files to check.
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
@ -77,7 +76,7 @@ pub fn run(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Discover the package root for each Python file.
|
// Discover the package root for each Python file.
|
||||||
let package_roots = packages::detect_package_roots(
|
let package_roots = packaging::detect_package_roots(
|
||||||
&paths
|
&paths
|
||||||
.iter()
|
.iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
|
@ -156,7 +155,7 @@ pub fn run_stdin(
|
||||||
pyproject_strategy: &PyprojectDiscovery,
|
pyproject_strategy: &PyprojectDiscovery,
|
||||||
file_strategy: &FileDiscovery,
|
file_strategy: &FileDiscovery,
|
||||||
overrides: &Overrides,
|
overrides: &Overrides,
|
||||||
autofix: fixer::Mode,
|
autofix: fix::FixMode,
|
||||||
) -> Result<Diagnostics> {
|
) -> Result<Diagnostics> {
|
||||||
if let Some(filename) = filename {
|
if let Some(filename) = filename {
|
||||||
if !resolver::python_file_at_path(filename, pyproject_strategy, file_strategy, overrides)? {
|
if !resolver::python_file_at_path(filename, pyproject_strategy, file_strategy, overrides)? {
|
||||||
|
@ -169,7 +168,7 @@ pub fn run_stdin(
|
||||||
};
|
};
|
||||||
let package_root = filename
|
let package_root = filename
|
||||||
.and_then(Path::parent)
|
.and_then(Path::parent)
|
||||||
.and_then(packages::detect_package_root);
|
.and_then(packaging::detect_package_root);
|
||||||
let stdin = read_from_stdin()?;
|
let stdin = read_from_stdin()?;
|
||||||
let mut diagnostics = lint_stdin(filename, package_root, &stdin, settings, autofix)?;
|
let mut diagnostics = lint_stdin(filename, package_root, &stdin, settings, autofix)?;
|
||||||
diagnostics.messages.sort_unstable();
|
diagnostics.messages.sort_unstable();
|
||||||
|
|
|
@ -6,7 +6,7 @@ use rustpython_ast::Location;
|
||||||
use rustpython_parser::lexer::{LexResult, Tok};
|
use rustpython_parser::lexer::{LexResult, Tok};
|
||||||
|
|
||||||
use crate::registry::LintSource;
|
use crate::registry::LintSource;
|
||||||
use crate::Settings;
|
use crate::settings::Settings;
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
pub struct Flags: u32 {
|
pub struct Flags: u32 {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod detection;
|
pub(crate) mod detection;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use rustpython_ast::Location;
|
use rustpython_ast::Location;
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::eradicate::detection::comment_contains_code;
|
use crate::eradicate::detection::comment_contains_code;
|
||||||
use crate::registry::RuleCode;
|
use crate::fix::Fix;
|
||||||
use crate::settings::flags;
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::{violations, Diagnostic, Settings, SourceCodeLocator};
|
use crate::settings::{flags, Settings};
|
||||||
|
use crate::source_code::Locator;
|
||||||
|
use crate::violations;
|
||||||
|
|
||||||
fn is_standalone_comment(line: &str) -> bool {
|
fn is_standalone_comment(line: &str) -> bool {
|
||||||
for char in line.chars() {
|
for char in line.chars() {
|
||||||
|
@ -20,7 +21,7 @@ fn is_standalone_comment(line: &str) -> bool {
|
||||||
|
|
||||||
/// ERA001
|
/// ERA001
|
||||||
pub fn commented_out_code(
|
pub fn commented_out_code(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
start: Location,
|
start: Location,
|
||||||
end: Location,
|
end: Location,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
|
|
53
src/fix.rs
Normal file
53
src/fix.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use rustpython_ast::Location;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash)]
|
||||||
|
pub enum FixMode {
|
||||||
|
Generate,
|
||||||
|
Apply,
|
||||||
|
Diff,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<bool> for FixMode {
|
||||||
|
fn from(value: bool) -> Self {
|
||||||
|
if value {
|
||||||
|
FixMode::Apply
|
||||||
|
} else {
|
||||||
|
FixMode::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub struct Fix {
|
||||||
|
pub content: String,
|
||||||
|
pub location: Location,
|
||||||
|
pub end_location: Location,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Fix {
|
||||||
|
pub fn deletion(start: Location, end: Location) -> Self {
|
||||||
|
Self {
|
||||||
|
content: String::new(),
|
||||||
|
location: start,
|
||||||
|
end_location: end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replacement(content: String, start: Location, end: Location) -> Self {
|
||||||
|
Self {
|
||||||
|
content,
|
||||||
|
location: start,
|
||||||
|
end_location: end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insertion(content: String, at: Location) -> Self {
|
||||||
|
Self {
|
||||||
|
content,
|
||||||
|
location: at,
|
||||||
|
end_location: at,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -4,11 +4,11 @@ use rustpython_parser::lexer;
|
||||||
use rustpython_parser::lexer::Tok;
|
use rustpython_parser::lexer::Tok;
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
use crate::fix::Fix;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
/// ANN204
|
/// ANN204
|
||||||
pub fn add_return_none_annotation(locator: &SourceCodeLocator, stmt: &Stmt) -> Result<Fix> {
|
pub fn add_return_none_annotation(locator: &Locator, stmt: &Stmt) -> Result<Fix> {
|
||||||
let range = Range::from_located(stmt);
|
let range = Range::from_located(stmt);
|
||||||
let contents = locator.slice_source_code_range(&range);
|
let contents = locator.slice_source_code_range(&range);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
mod fixes;
|
mod fixes;
|
||||||
pub mod helpers;
|
pub(crate) mod helpers;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -9,9 +9,10 @@ mod tests {
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::flake8_annotations;
|
||||||
use crate::linter::test_path;
|
use crate::linter::test_path;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::{flake8_annotations, Settings};
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn defaults() -> Result<()> {
|
fn defaults() -> Result<()> {
|
||||||
|
|
|
@ -8,9 +8,9 @@ use crate::checkers::ast::Checker;
|
||||||
use crate::docstrings::definition::{Definition, DefinitionKind};
|
use crate::docstrings::definition::{Definition, DefinitionKind};
|
||||||
use crate::flake8_annotations::fixes;
|
use crate::flake8_annotations::fixes;
|
||||||
use crate::flake8_annotations::helpers::match_function_def;
|
use crate::flake8_annotations::helpers::match_function_def;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::visibility::Visibility;
|
use crate::visibility::Visibility;
|
||||||
use crate::{violations, visibility, Diagnostic};
|
use crate::{violations, visibility};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ReturnStatementVisitor<'a> {
|
struct ReturnStatementVisitor<'a> {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod helpers;
|
mod helpers;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -9,9 +9,10 @@ mod tests {
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use test_case::test_case;
|
use test_case::test_case;
|
||||||
|
|
||||||
|
use crate::flake8_bandit;
|
||||||
use crate::linter::test_path;
|
use crate::linter::test_path;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::{flake8_bandit, Settings};
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[test_case(RuleCode::S101, Path::new("S101.py"); "S101")]
|
#[test_case(RuleCode::S101, Path::new("S101.py"); "S101")]
|
||||||
#[test_case(RuleCode::S102, Path::new("S102.py"); "S102")]
|
#[test_case(RuleCode::S102, Path::new("S102.py"); "S102")]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -8,9 +8,10 @@ mod tests {
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use test_case::test_case;
|
use test_case::test_case;
|
||||||
|
|
||||||
|
use crate::flake8_bugbear;
|
||||||
use crate::linter::test_path;
|
use crate::linter::test_path;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::{flake8_bugbear, Settings};
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[test_case(RuleCode::B002, Path::new("B002.py"); "B002")]
|
#[test_case(RuleCode::B002, Path::new("B002.py"); "B002")]
|
||||||
#[test_case(RuleCode::B003, Path::new("B003.py"); "B003")]
|
#[test_case(RuleCode::B003, Path::new("B003.py"); "B003")]
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use rustpython_ast::{Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind};
|
use rustpython_ast::{Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_generator::SourceCodeGenerator;
|
use crate::source_code::Generator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
fn assertion_error(msg: Option<&Expr>) -> Stmt {
|
fn assertion_error(msg: Option<&Expr>) -> Stmt {
|
||||||
|
@ -48,7 +48,7 @@ pub fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: Option
|
||||||
|
|
||||||
let mut diagnostic = Diagnostic::new(violations::DoNotAssertFalse, Range::from_located(test));
|
let mut diagnostic = Diagnostic::new(violations::DoNotAssertFalse, Range::from_located(test));
|
||||||
if checker.patch(diagnostic.kind.code()) {
|
if checker.patch(diagnostic.kind.code()) {
|
||||||
let mut generator: SourceCodeGenerator = checker.style.into();
|
let mut generator: Generator = checker.style.into();
|
||||||
generator.unparse_stmt(&assertion_error(msg));
|
generator.unparse_stmt(&assertion_error(msg));
|
||||||
diagnostic.amend(Fix::replacement(
|
diagnostic.amend(Fix::replacement(
|
||||||
generator.generate(),
|
generator.generate(),
|
||||||
|
|
|
@ -4,10 +4,10 @@ use rustpython_ast::{Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKi
|
||||||
|
|
||||||
use crate::ast::helpers;
|
use crate::ast::helpers;
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::source_code_generator::SourceCodeGenerator;
|
use crate::source_code::Generator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
fn type_pattern(elts: Vec<&Expr>) -> Expr {
|
fn type_pattern(elts: Vec<&Expr>) -> Expr {
|
||||||
|
@ -55,7 +55,7 @@ fn duplicate_handler_exceptions<'a>(
|
||||||
Range::from_located(expr),
|
Range::from_located(expr),
|
||||||
);
|
);
|
||||||
if checker.patch(diagnostic.kind.code()) {
|
if checker.patch(diagnostic.kind.code()) {
|
||||||
let mut generator: SourceCodeGenerator = checker.style.into();
|
let mut generator: Generator = checker.style.into();
|
||||||
if unique_elts.len() == 1 {
|
if unique_elts.len() == 1 {
|
||||||
generator.unparse_expr(unique_elts[0], 0);
|
generator.unparse_expr(unique_elts[0], 0);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use rustpython_ast::{Constant, Expr, ExprContext, ExprKind, Location};
|
use rustpython_ast::{Constant, Expr, ExprContext, ExprKind, Location};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::python::identifiers::IDENTIFIER_REGEX;
|
use crate::python::identifiers::IDENTIFIER_REGEX;
|
||||||
use crate::python::keyword::KWLIST;
|
use crate::python::keyword::KWLIST;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_generator::SourceCodeGenerator;
|
use crate::source_code::Generator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
fn attribute(value: &Expr, attr: &str) -> Expr {
|
fn attribute(value: &Expr, attr: &str) -> Expr {
|
||||||
|
@ -48,7 +48,7 @@ pub fn getattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
|
||||||
let mut diagnostic =
|
let mut diagnostic =
|
||||||
Diagnostic::new(violations::GetAttrWithConstant, Range::from_located(expr));
|
Diagnostic::new(violations::GetAttrWithConstant, Range::from_located(expr));
|
||||||
if checker.patch(diagnostic.kind.code()) {
|
if checker.patch(diagnostic.kind.code()) {
|
||||||
let mut generator: SourceCodeGenerator = checker.style.into();
|
let mut generator: Generator = checker.style.into();
|
||||||
generator.unparse_expr(&attribute(obj, value), 0);
|
generator.unparse_expr(&attribute(obj, value), 0);
|
||||||
diagnostic.amend(Fix::replacement(
|
diagnostic.amend(Fix::replacement(
|
||||||
generator.generate(),
|
generator.generate(),
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use rustpython_ast::{Excepthandler, ExcepthandlerKind, ExprKind};
|
use rustpython_ast::{Excepthandler, ExcepthandlerKind, ExprKind};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_generator::SourceCodeGenerator;
|
use crate::source_code::Generator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
/// B013
|
/// B013
|
||||||
|
@ -24,7 +24,7 @@ pub fn redundant_tuple_in_exception_handler(checker: &mut Checker, handlers: &[E
|
||||||
Range::from_located(type_),
|
Range::from_located(type_),
|
||||||
);
|
);
|
||||||
if checker.patch(diagnostic.kind.code()) {
|
if checker.patch(diagnostic.kind.code()) {
|
||||||
let mut generator: SourceCodeGenerator = checker.style.into();
|
let mut generator: Generator = checker.style.into();
|
||||||
generator.unparse_expr(elt, 0);
|
generator.unparse_expr(elt, 0);
|
||||||
diagnostic.amend(Fix::replacement(
|
diagnostic.amend(Fix::replacement(
|
||||||
generator.generate(),
|
generator.generate(),
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
use rustpython_ast::{Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind};
|
use rustpython_ast::{Constant, Expr, ExprContext, ExprKind, Location, Stmt, StmtKind};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::python::identifiers::IDENTIFIER_REGEX;
|
use crate::python::identifiers::IDENTIFIER_REGEX;
|
||||||
use crate::python::keyword::KWLIST;
|
use crate::python::keyword::KWLIST;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_generator::SourceCodeGenerator;
|
use crate::source_code::{Generator, Stylist};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
fn assignment(obj: &Expr, name: &str, value: &Expr, stylist: &SourceCodeStyleDetector) -> String {
|
fn assignment(obj: &Expr, name: &str, value: &Expr, stylist: &Stylist) -> String {
|
||||||
let stmt = Stmt::new(
|
let stmt = Stmt::new(
|
||||||
Location::default(),
|
Location::default(),
|
||||||
Location::default(),
|
Location::default(),
|
||||||
|
@ -28,7 +27,7 @@ fn assignment(obj: &Expr, name: &str, value: &Expr, stylist: &SourceCodeStyleDet
|
||||||
type_comment: None,
|
type_comment: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let mut generator: SourceCodeGenerator = stylist.into();
|
let mut generator: Generator = stylist.into();
|
||||||
generator.unparse_stmt(&stmt);
|
generator.unparse_stmt(&stmt);
|
||||||
generator.generate()
|
generator.generate()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ use rustpython_ast::{Expr, ExprKind, Stmt};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::ast::visitor;
|
use crate::ast::visitor;
|
||||||
use crate::ast::visitor::Visitor;
|
use crate::ast::visitor::Visitor;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod types;
|
pub(crate) mod types;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -7,9 +7,9 @@ use libcst_native::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::cst::matchers::{match_expr, match_module};
|
use crate::cst::matchers::{match_expr, match_module};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::fix::Fix;
|
||||||
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
fn match_call<'a, 'b>(expr: &'a mut Expr<'b>) -> Result<&'a mut Call<'b>> {
|
fn match_call<'a, 'b>(expr: &'a mut Expr<'b>) -> Result<&'a mut Call<'b>> {
|
||||||
if let Expression::Call(call) = &mut expr.value {
|
if let Expression::Call(call) = &mut expr.value {
|
||||||
|
@ -29,7 +29,7 @@ fn match_arg<'a, 'b>(call: &'a Call<'b>) -> Result<&'a Arg<'b>> {
|
||||||
|
|
||||||
/// (C400) Convert `list(x for x in y)` to `[x for x in y]`.
|
/// (C400) Convert `list(x for x in y)` to `[x for x in y]`.
|
||||||
pub fn fix_unnecessary_generator_list(
|
pub fn fix_unnecessary_generator_list(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
expr: &rustpython_ast::Expr,
|
expr: &rustpython_ast::Expr,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
// Expr(Call(GeneratorExp)))) -> Expr(ListComp)))
|
// Expr(Call(GeneratorExp)))) -> Expr(ListComp)))
|
||||||
|
@ -70,7 +70,7 @@ pub fn fix_unnecessary_generator_list(
|
||||||
|
|
||||||
/// (C401) Convert `set(x for x in y)` to `{x for x in y}`.
|
/// (C401) Convert `set(x for x in y)` to `{x for x in y}`.
|
||||||
pub fn fix_unnecessary_generator_set(
|
pub fn fix_unnecessary_generator_set(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
expr: &rustpython_ast::Expr,
|
expr: &rustpython_ast::Expr,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
// Expr(Call(GeneratorExp)))) -> Expr(SetComp)))
|
// Expr(Call(GeneratorExp)))) -> Expr(SetComp)))
|
||||||
|
@ -112,7 +112,7 @@ pub fn fix_unnecessary_generator_set(
|
||||||
/// (C402) Convert `dict((x, x) for x in range(3))` to `{x: x for x in
|
/// (C402) Convert `dict((x, x) for x in range(3))` to `{x: x for x in
|
||||||
/// range(3)}`.
|
/// range(3)}`.
|
||||||
pub fn fix_unnecessary_generator_dict(
|
pub fn fix_unnecessary_generator_dict(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
expr: &rustpython_ast::Expr,
|
expr: &rustpython_ast::Expr,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
|
@ -169,7 +169,7 @@ pub fn fix_unnecessary_generator_dict(
|
||||||
|
|
||||||
/// (C403) Convert `set([x for x in y])` to `{x for x in y}`.
|
/// (C403) Convert `set([x for x in y])` to `{x for x in y}`.
|
||||||
pub fn fix_unnecessary_list_comprehension_set(
|
pub fn fix_unnecessary_list_comprehension_set(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
expr: &rustpython_ast::Expr,
|
expr: &rustpython_ast::Expr,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
// Expr(Call(ListComp)))) ->
|
// Expr(Call(ListComp)))) ->
|
||||||
|
@ -210,7 +210,7 @@ pub fn fix_unnecessary_list_comprehension_set(
|
||||||
/// (C404) Convert `dict([(i, i) for i in range(3)])` to `{i: i for i in
|
/// (C404) Convert `dict([(i, i) for i in range(3)])` to `{i: i for i in
|
||||||
/// range(3)}`.
|
/// range(3)}`.
|
||||||
pub fn fix_unnecessary_list_comprehension_dict(
|
pub fn fix_unnecessary_list_comprehension_dict(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
expr: &rustpython_ast::Expr,
|
expr: &rustpython_ast::Expr,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
|
@ -259,10 +259,7 @@ pub fn fix_unnecessary_list_comprehension_dict(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// (C405) Convert `set((1, 2))` to `{1, 2}`.
|
/// (C405) Convert `set((1, 2))` to `{1, 2}`.
|
||||||
pub fn fix_unnecessary_literal_set(
|
pub fn fix_unnecessary_literal_set(locator: &Locator, expr: &rustpython_ast::Expr) -> Result<Fix> {
|
||||||
locator: &SourceCodeLocator,
|
|
||||||
expr: &rustpython_ast::Expr,
|
|
||||||
) -> Result<Fix> {
|
|
||||||
// Expr(Call(List|Tuple)))) -> Expr(Set)))
|
// Expr(Call(List|Tuple)))) -> Expr(Set)))
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
let mut tree = match_module(&module_text)?;
|
let mut tree = match_module(&module_text)?;
|
||||||
|
@ -305,10 +302,7 @@ pub fn fix_unnecessary_literal_set(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// (C406) Convert `dict([(1, 2)])` to `{1: 2}`.
|
/// (C406) Convert `dict([(1, 2)])` to `{1: 2}`.
|
||||||
pub fn fix_unnecessary_literal_dict(
|
pub fn fix_unnecessary_literal_dict(locator: &Locator, expr: &rustpython_ast::Expr) -> Result<Fix> {
|
||||||
locator: &SourceCodeLocator,
|
|
||||||
expr: &rustpython_ast::Expr,
|
|
||||||
) -> Result<Fix> {
|
|
||||||
// Expr(Call(List|Tuple)))) -> Expr(Dict)))
|
// Expr(Call(List|Tuple)))) -> Expr(Dict)))
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
let mut tree = match_module(&module_text)?;
|
let mut tree = match_module(&module_text)?;
|
||||||
|
@ -374,7 +368,7 @@ pub fn fix_unnecessary_literal_dict(
|
||||||
|
|
||||||
/// (C408)
|
/// (C408)
|
||||||
pub fn fix_unnecessary_collection_call(
|
pub fn fix_unnecessary_collection_call(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
expr: &rustpython_ast::Expr,
|
expr: &rustpython_ast::Expr,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
// Expr(Call("list" | "tuple" | "dict")))) -> Expr(List|Tuple|Dict)
|
// Expr(Call("list" | "tuple" | "dict")))) -> Expr(List|Tuple|Dict)
|
||||||
|
@ -483,7 +477,7 @@ pub fn fix_unnecessary_collection_call(
|
||||||
|
|
||||||
/// (C409) Convert `tuple([1, 2])` to `tuple(1, 2)`
|
/// (C409) Convert `tuple([1, 2])` to `tuple(1, 2)`
|
||||||
pub fn fix_unnecessary_literal_within_tuple_call(
|
pub fn fix_unnecessary_literal_within_tuple_call(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
expr: &rustpython_ast::Expr,
|
expr: &rustpython_ast::Expr,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
|
@ -537,7 +531,7 @@ pub fn fix_unnecessary_literal_within_tuple_call(
|
||||||
|
|
||||||
/// (C410) Convert `list([1, 2])` to `[1, 2]`
|
/// (C410) Convert `list([1, 2])` to `[1, 2]`
|
||||||
pub fn fix_unnecessary_literal_within_list_call(
|
pub fn fix_unnecessary_literal_within_list_call(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
expr: &rustpython_ast::Expr,
|
expr: &rustpython_ast::Expr,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
|
@ -592,10 +586,7 @@ pub fn fix_unnecessary_literal_within_list_call(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// (C411) Convert `list([i * i for i in x])` to `[i * i for i in x]`.
|
/// (C411) Convert `list([i * i for i in x])` to `[i * i for i in x]`.
|
||||||
pub fn fix_unnecessary_list_call(
|
pub fn fix_unnecessary_list_call(locator: &Locator, expr: &rustpython_ast::Expr) -> Result<Fix> {
|
||||||
locator: &SourceCodeLocator,
|
|
||||||
expr: &rustpython_ast::Expr,
|
|
||||||
) -> Result<Fix> {
|
|
||||||
// Expr(Call(List|Tuple)))) -> Expr(List|Tuple)))
|
// Expr(Call(List|Tuple)))) -> Expr(List|Tuple)))
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
let mut tree = match_module(&module_text)?;
|
let mut tree = match_module(&module_text)?;
|
||||||
|
@ -619,7 +610,7 @@ pub fn fix_unnecessary_list_call(
|
||||||
/// (C413) Convert `reversed(sorted([2, 3, 1]))` to `sorted([2, 3, 1],
|
/// (C413) Convert `reversed(sorted([2, 3, 1]))` to `sorted([2, 3, 1],
|
||||||
/// reverse=True)`.
|
/// reverse=True)`.
|
||||||
pub fn fix_unnecessary_call_around_sorted(
|
pub fn fix_unnecessary_call_around_sorted(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
expr: &rustpython_ast::Expr,
|
expr: &rustpython_ast::Expr,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
|
@ -701,7 +692,7 @@ pub fn fix_unnecessary_call_around_sorted(
|
||||||
|
|
||||||
/// (C416) Convert `[i for i in x]` to `list(x)`.
|
/// (C416) Convert `[i for i in x]` to `list(x)`.
|
||||||
pub fn fix_unnecessary_comprehension(
|
pub fn fix_unnecessary_comprehension(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
expr: &rustpython_ast::Expr,
|
expr: &rustpython_ast::Expr,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
let module_text = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod fixes;
|
mod fixes;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod types;
|
pub(crate) mod types;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -4,11 +4,11 @@ use rustpython_parser::lexer::{LexResult, Tok};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
/// ISC001, ISC002
|
/// ISC001, ISC002
|
||||||
pub fn implicit(tokens: &[LexResult], locator: &SourceCodeLocator) -> Vec<Diagnostic> {
|
pub fn implicit(tokens: &[LexResult], locator: &Locator) -> Vec<Diagnostic> {
|
||||||
let mut diagnostics = vec![];
|
let mut diagnostics = vec![];
|
||||||
for ((a_start, a_tok, a_end), (b_start, b_tok, b_end)) in
|
for ((a_start, a_tok, a_end), (b_start, b_tok, b_end)) in
|
||||||
tokens.iter().flatten().tuple_windows()
|
tokens.iter().flatten().tuple_windows()
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
use crate::flake8_import_conventions;
|
||||||
use crate::linter::test_path;
|
use crate::linter::test_path;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::{flake8_import_conventions, Settings};
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn defaults() -> Result<()> {
|
fn defaults() -> Result<()> {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -4,8 +4,8 @@ use rustpython_ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use crate::ast::types::{Range, RefEquality};
|
use crate::ast::types::{Range, RefEquality};
|
||||||
use crate::autofix::helpers::delete_stmt;
|
use crate::autofix::helpers::delete_stmt;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ use crate::ast::helpers::unparse_stmt;
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::ast::visitor;
|
use crate::ast::visitor;
|
||||||
use crate::ast::visitor::Visitor;
|
use crate::ast::visitor::Visitor;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ use crate::ast::helpers::{collect_arg_names, collect_call_paths};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::ast::visitor;
|
use crate::ast::visitor;
|
||||||
use crate::ast::visitor::Visitor;
|
use crate::ast::visitor::Visitor;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ use rustpython_ast::{Expr, ExprKind, Location};
|
||||||
|
|
||||||
use super::helpers::{get_mark_decorators, get_mark_name};
|
use super::helpers::{get_mark_decorators, get_mark_name};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ use rustpython_ast::{Constant, Expr, ExprContext, ExprKind};
|
||||||
use super::helpers::is_pytest_parametrize;
|
use super::helpers::is_pytest_parametrize;
|
||||||
use crate::ast::helpers::create_expr;
|
use crate::ast::helpers::create_expr;
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::flake8_pytest_style::types;
|
use crate::flake8_pytest_style::types;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::source_code_generator::SourceCodeGenerator;
|
use crate::source_code::Generator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
fn get_parametrize_decorator<'a>(checker: &Checker, decorators: &'a [Expr]) -> Option<&'a Expr> {
|
fn get_parametrize_decorator<'a>(checker: &Checker, decorators: &'a [Expr]) -> Option<&'a Expr> {
|
||||||
|
@ -31,7 +31,7 @@ fn elts_to_csv(elts: &[Expr], checker: &Checker) -> Option<String> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut generator: SourceCodeGenerator = checker.style.into();
|
let mut generator: Generator = checker.style.into();
|
||||||
generator.unparse_expr(
|
generator.unparse_expr(
|
||||||
&create_expr(ExprKind::Constant {
|
&create_expr(ExprKind::Constant {
|
||||||
value: Constant::Str(elts.iter().fold(String::new(), |mut acc, elt| {
|
value: Constant::Str(elts.iter().fold(String::new(), |mut acc, elt| {
|
||||||
|
@ -85,7 +85,7 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
|
||||||
Range::from_located(expr),
|
Range::from_located(expr),
|
||||||
);
|
);
|
||||||
if checker.patch(diagnostic.kind.code()) {
|
if checker.patch(diagnostic.kind.code()) {
|
||||||
let mut generator: SourceCodeGenerator = checker.style.into();
|
let mut generator: Generator = checker.style.into();
|
||||||
generator.unparse_expr(
|
generator.unparse_expr(
|
||||||
&create_expr(ExprKind::Tuple {
|
&create_expr(ExprKind::Tuple {
|
||||||
elts: names
|
elts: names
|
||||||
|
@ -115,7 +115,7 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
|
||||||
Range::from_located(expr),
|
Range::from_located(expr),
|
||||||
);
|
);
|
||||||
if checker.patch(diagnostic.kind.code()) {
|
if checker.patch(diagnostic.kind.code()) {
|
||||||
let mut generator: SourceCodeGenerator = checker.style.into();
|
let mut generator: Generator = checker.style.into();
|
||||||
generator.unparse_expr(
|
generator.unparse_expr(
|
||||||
&create_expr(ExprKind::List {
|
&create_expr(ExprKind::List {
|
||||||
elts: names
|
elts: names
|
||||||
|
@ -157,7 +157,7 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
|
||||||
Range::from_located(expr),
|
Range::from_located(expr),
|
||||||
);
|
);
|
||||||
if checker.patch(diagnostic.kind.code()) {
|
if checker.patch(diagnostic.kind.code()) {
|
||||||
let mut generator: SourceCodeGenerator = checker.style.into();
|
let mut generator: Generator = checker.style.into();
|
||||||
generator.unparse_expr(
|
generator.unparse_expr(
|
||||||
&create_expr(ExprKind::List {
|
&create_expr(ExprKind::List {
|
||||||
elts: elts.clone(),
|
elts: elts.clone(),
|
||||||
|
@ -206,7 +206,7 @@ fn check_names(checker: &mut Checker, expr: &Expr) {
|
||||||
Range::from_located(expr),
|
Range::from_located(expr),
|
||||||
);
|
);
|
||||||
if checker.patch(diagnostic.kind.code()) {
|
if checker.patch(diagnostic.kind.code()) {
|
||||||
let mut generator: SourceCodeGenerator = checker.style.into();
|
let mut generator: Generator = checker.style.into();
|
||||||
generator.unparse_expr(
|
generator.unparse_expr(
|
||||||
&create_expr(ExprKind::Tuple {
|
&create_expr(ExprKind::Tuple {
|
||||||
elts: elts.clone(),
|
elts: elts.clone(),
|
||||||
|
@ -284,7 +284,7 @@ fn handle_single_name(checker: &mut Checker, expr: &Expr, value: &Expr) {
|
||||||
);
|
);
|
||||||
|
|
||||||
if checker.patch(diagnostic.kind.code()) {
|
if checker.patch(diagnostic.kind.code()) {
|
||||||
let mut generator: SourceCodeGenerator = checker.style.into();
|
let mut generator: Generator = checker.style.into();
|
||||||
generator.unparse_expr(&create_expr(value.node.clone()), 0);
|
generator.unparse_expr(&create_expr(value.node.clone()), 0);
|
||||||
diagnostic.amend(Fix::replacement(
|
diagnostic.amend(Fix::replacement(
|
||||||
generator.generate(),
|
generator.generate(),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -8,10 +8,11 @@ mod tests {
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use test_case::test_case;
|
use test_case::test_case;
|
||||||
|
|
||||||
|
use crate::flake8_quotes;
|
||||||
use crate::flake8_quotes::settings::Quote;
|
use crate::flake8_quotes::settings::Quote;
|
||||||
use crate::linter::test_path;
|
use crate::linter::test_path;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::{flake8_quotes, Settings};
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[test_case(Path::new("doubles.py"))]
|
#[test_case(Path::new("doubles.py"))]
|
||||||
#[test_case(Path::new("doubles_escaped.py"))]
|
#[test_case(Path::new("doubles_escaped.py"))]
|
||||||
|
|
|
@ -3,7 +3,7 @@ use rustpython_ast::Location;
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::flake8_quotes::settings::{Quote, Settings};
|
use crate::flake8_quotes::settings::{Quote, Settings};
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
fn good_single(quote: &Quote) -> char {
|
fn good_single(quote: &Quote) -> char {
|
||||||
|
@ -42,7 +42,7 @@ fn good_docstring(quote: &Quote) -> &str {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn quotes(
|
pub fn quotes(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
start: Location,
|
start: Location,
|
||||||
end: Location,
|
end: Location,
|
||||||
is_docstring: bool,
|
is_docstring: bool,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod helpers;
|
mod helpers;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
mod visitor;
|
mod visitor;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -11,7 +11,7 @@ mod tests {
|
||||||
|
|
||||||
use crate::linter::test_path;
|
use crate::linter::test_path;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::Settings;
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[test_case(RuleCode::RET501, Path::new("RET501.py"); "RET501")]
|
#[test_case(RuleCode::RET501, Path::new("RET501.py"); "RET501")]
|
||||||
#[test_case(RuleCode::RET502, Path::new("RET502.py"); "RET502")]
|
#[test_case(RuleCode::RET502, Path::new("RET502.py"); "RET502")]
|
||||||
|
|
|
@ -4,13 +4,13 @@ use rustpython_ast::{Constant, Expr, ExprKind, Location, Stmt, StmtKind};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::ast::visitor::Visitor;
|
use crate::ast::visitor::Visitor;
|
||||||
use crate::ast::whitespace::indentation;
|
use crate::ast::whitespace::indentation;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::flake8_return::helpers::result_exists;
|
use crate::flake8_return::helpers::result_exists;
|
||||||
use crate::flake8_return::visitor::{ReturnVisitor, Stack};
|
use crate::flake8_return::visitor::{ReturnVisitor, Stack};
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
|
use crate::violations;
|
||||||
use crate::violations::Branch;
|
use crate::violations::Branch;
|
||||||
use crate::{violations, Diagnostic};
|
|
||||||
|
|
||||||
/// RET501
|
/// RET501
|
||||||
fn unnecessary_return_none(checker: &mut Checker, stack: &Stack) {
|
fn unnecessary_return_none(checker: &mut Checker, stack: &Stack) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -7,8 +7,8 @@ use rustpython_ast::{Boolop, Cmpop, Constant, Expr, ExprContext, ExprKind, Unary
|
||||||
|
|
||||||
use crate::ast::helpers::{create_expr, unparse_expr};
|
use crate::ast::helpers::{create_expr, unparse_expr};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ use rustpython_ast::{Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use crate::ast::helpers::{create_expr, match_module_member, unparse_expr};
|
use crate::ast::helpers::{create_expr, match_module_member, unparse_expr};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,10 @@ use rustpython_ast::{
|
||||||
|
|
||||||
use crate::ast::helpers::{create_expr, create_stmt};
|
use crate::ast::helpers::{create_expr, create_stmt};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::source_code_generator::SourceCodeGenerator;
|
use crate::source_code::{Generator, Stylist};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
struct Loop<'a> {
|
struct Loop<'a> {
|
||||||
|
@ -77,14 +76,8 @@ fn return_values<'a>(stmt: &'a Stmt, sibling: &'a Stmt) -> Option<Loop<'a>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a return statement for an `any` or `all` builtin comprehension.
|
/// Generate a return statement for an `any` or `all` builtin comprehension.
|
||||||
fn return_stmt(
|
fn return_stmt(id: &str, test: &Expr, target: &Expr, iter: &Expr, stylist: &Stylist) -> String {
|
||||||
id: &str,
|
let mut generator: Generator = stylist.into();
|
||||||
test: &Expr,
|
|
||||||
target: &Expr,
|
|
||||||
iter: &Expr,
|
|
||||||
stylist: &SourceCodeStyleDetector,
|
|
||||||
) -> String {
|
|
||||||
let mut generator: SourceCodeGenerator = stylist.into();
|
|
||||||
generator.unparse_stmt(&create_stmt(StmtKind::Return {
|
generator.unparse_stmt(&create_stmt(StmtKind::Return {
|
||||||
value: Some(Box::new(create_expr(ExprKind::Call {
|
value: Some(Box::new(create_expr(ExprKind::Call {
|
||||||
func: Box::new(create_expr(ExprKind::Name {
|
func: Box::new(create_expr(ExprKind::Name {
|
||||||
|
|
|
@ -5,8 +5,8 @@ use crate::ast::helpers::{
|
||||||
contains_call_path, create_expr, create_stmt, has_comments, unparse_expr, unparse_stmt,
|
contains_call_path, create_expr, create_stmt, has_comments, unparse_expr, unparse_stmt,
|
||||||
};
|
};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ use rustpython_ast::{Constant, Expr, ExprContext, ExprKind, Unaryop};
|
||||||
|
|
||||||
use crate::ast::helpers::{create_expr, unparse_expr};
|
use crate::ast::helpers::{create_expr, unparse_expr};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ use rustpython_ast::{Cmpop, Expr, ExprKind, Stmt, StmtKind, Unaryop};
|
||||||
|
|
||||||
use crate::ast::helpers::{create_expr, unparse_expr};
|
use crate::ast::helpers::{create_expr, unparse_expr};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use rustpython_ast::{Cmpop, Expr, ExprKind};
|
use rustpython_ast::{Cmpop, Expr, ExprKind};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use rustpython_ast::{Cmpop, Expr, ExprKind};
|
use rustpython_ast::{Cmpop, Expr, ExprKind};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -8,10 +8,11 @@ mod tests {
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
use crate::flake8_tidy_imports;
|
||||||
use crate::flake8_tidy_imports::settings::{BannedApi, Strictness};
|
use crate::flake8_tidy_imports::settings::{BannedApi, Strictness};
|
||||||
use crate::linter::test_path;
|
use crate::linter::test_path;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::{flake8_tidy_imports, Settings};
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ban_parent_imports() -> Result<()> {
|
fn ban_parent_imports() -> Result<()> {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod helpers;
|
mod helpers;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,8 @@ use crate::ast::types::{Binding, BindingKind, FunctionDef, Lambda, Scope, ScopeK
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::flake8_unused_arguments::helpers;
|
use crate::flake8_unused_arguments::helpers;
|
||||||
use crate::flake8_unused_arguments::types::Argumentable;
|
use crate::flake8_unused_arguments::types::Argumentable;
|
||||||
use crate::{visibility, Diagnostic};
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::visibility;
|
||||||
|
|
||||||
/// Check a plain function for unused arguments.
|
/// Check a plain function for unused arguments.
|
||||||
fn function(
|
fn function(
|
||||||
|
|
|
@ -5,7 +5,7 @@ use rustpython_parser::lexer;
|
||||||
use rustpython_parser::lexer::Tok;
|
use rustpython_parser::lexer::Tok;
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Comment<'a> {
|
pub struct Comment<'a> {
|
||||||
|
@ -15,7 +15,7 @@ pub struct Comment<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect all comments in an import block.
|
/// Collect all comments in an import block.
|
||||||
pub fn collect_comments<'a>(range: &Range, locator: &'a SourceCodeLocator) -> Vec<Comment<'a>> {
|
pub fn collect_comments<'a>(range: &Range, locator: &'a Locator) -> Vec<Comment<'a>> {
|
||||||
let contents = locator.slice_source_code_range(range);
|
let contents = locator.slice_source_code_range(range);
|
||||||
lexer::make_tokenizer_located(&contents, range.location)
|
lexer::make_tokenizer_located(&contents, range.location)
|
||||||
.flatten()
|
.flatten()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::isort::types::{AliasData, CommentSet, ImportFromData, Importable};
|
use crate::isort::types::{AliasData, CommentSet, ImportFromData, Importable};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
use crate::source_code::Stylist;
|
||||||
|
|
||||||
// Hard-code four-space indentation for the imports themselves, to match Black.
|
// Hard-code four-space indentation for the imports themselves, to match Black.
|
||||||
const INDENT: &str = " ";
|
const INDENT: &str = " ";
|
||||||
|
@ -12,7 +12,7 @@ pub fn format_import(
|
||||||
alias: &AliasData,
|
alias: &AliasData,
|
||||||
comments: &CommentSet,
|
comments: &CommentSet,
|
||||||
is_first: bool,
|
is_first: bool,
|
||||||
stylist: &SourceCodeStyleDetector,
|
stylist: &Stylist,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut output = String::with_capacity(CAPACITY);
|
let mut output = String::with_capacity(CAPACITY);
|
||||||
if !is_first && !comments.atop.is_empty() {
|
if !is_first && !comments.atop.is_empty() {
|
||||||
|
@ -46,7 +46,7 @@ pub fn format_import_from(
|
||||||
comments: &CommentSet,
|
comments: &CommentSet,
|
||||||
aliases: &[(AliasData, CommentSet)],
|
aliases: &[(AliasData, CommentSet)],
|
||||||
line_length: usize,
|
line_length: usize,
|
||||||
stylist: &SourceCodeStyleDetector,
|
stylist: &Stylist,
|
||||||
force_wrap_aliases: bool,
|
force_wrap_aliases: bool,
|
||||||
is_first: bool,
|
is_first: bool,
|
||||||
trailing_comma: bool,
|
trailing_comma: bool,
|
||||||
|
@ -89,7 +89,7 @@ fn format_single_line(
|
||||||
comments: &CommentSet,
|
comments: &CommentSet,
|
||||||
aliases: &[(AliasData, CommentSet)],
|
aliases: &[(AliasData, CommentSet)],
|
||||||
is_first: bool,
|
is_first: bool,
|
||||||
stylist: &SourceCodeStyleDetector,
|
stylist: &Stylist,
|
||||||
) -> (String, usize) {
|
) -> (String, usize) {
|
||||||
let mut output = String::with_capacity(CAPACITY);
|
let mut output = String::with_capacity(CAPACITY);
|
||||||
let mut line_length = 0;
|
let mut line_length = 0;
|
||||||
|
@ -149,7 +149,7 @@ fn format_multi_line(
|
||||||
comments: &CommentSet,
|
comments: &CommentSet,
|
||||||
aliases: &[(AliasData, CommentSet)],
|
aliases: &[(AliasData, CommentSet)],
|
||||||
is_first: bool,
|
is_first: bool,
|
||||||
stylist: &SourceCodeStyleDetector,
|
stylist: &Stylist,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut output = String::with_capacity(CAPACITY);
|
let mut output = String::with_capacity(CAPACITY);
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@ use rustpython_parser::lexer::Tok;
|
||||||
use crate::ast::helpers::is_docstring_stmt;
|
use crate::ast::helpers::is_docstring_stmt;
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::isort::types::TrailingComma;
|
use crate::isort::types::TrailingComma;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
/// Return `true` if a `StmtKind::ImportFrom` statement ends with a magic
|
/// Return `true` if a `StmtKind::ImportFrom` statement ends with a magic
|
||||||
/// trailing comma.
|
/// trailing comma.
|
||||||
pub fn trailing_comma(stmt: &Stmt, locator: &SourceCodeLocator) -> TrailingComma {
|
pub fn trailing_comma(stmt: &Stmt, locator: &Locator) -> TrailingComma {
|
||||||
let contents = locator.slice_source_code_range(&Range::from_located(stmt));
|
let contents = locator.slice_source_code_range(&Range::from_located(stmt));
|
||||||
let mut count: usize = 0;
|
let mut count: usize = 0;
|
||||||
let mut trailing_comma = TrailingComma::Absent;
|
let mut trailing_comma = TrailingComma::Absent;
|
||||||
|
@ -37,7 +37,7 @@ pub fn trailing_comma(stmt: &Stmt, locator: &SourceCodeLocator) -> TrailingComma
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if a `Stmt` is preceded by a "comment break"
|
/// Return `true` if a `Stmt` is preceded by a "comment break"
|
||||||
pub fn has_comment_break(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
pub fn has_comment_break(stmt: &Stmt, locator: &Locator) -> bool {
|
||||||
// Starting from the `Stmt` (`def f(): pass`), we want to detect patterns like
|
// Starting from the `Stmt` (`def f(): pass`), we want to detect patterns like
|
||||||
// this:
|
// this:
|
||||||
//
|
//
|
||||||
|
@ -108,7 +108,7 @@ fn match_docstring_end(body: &[Stmt]) -> Option<Location> {
|
||||||
|
|
||||||
/// Find the end of the first token that isn't a docstring, comment, or
|
/// Find the end of the first token that isn't a docstring, comment, or
|
||||||
/// whitespace.
|
/// whitespace.
|
||||||
pub fn find_splice_location(body: &[Stmt], locator: &SourceCodeLocator) -> Location {
|
pub fn find_splice_location(body: &[Stmt], locator: &Locator) -> Location {
|
||||||
// Find the first AST node that isn't a docstring.
|
// Find the first AST node that isn't a docstring.
|
||||||
let mut splice = match_docstring_end(body).unwrap_or_default();
|
let mut splice = match_docstring_end(body).unwrap_or_default();
|
||||||
|
|
||||||
|
@ -132,11 +132,11 @@ mod tests {
|
||||||
use rustpython_parser::parser;
|
use rustpython_parser::parser;
|
||||||
|
|
||||||
use crate::isort::helpers::find_splice_location;
|
use crate::isort::helpers::find_splice_location;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
fn splice_contents(contents: &str) -> Result<Location> {
|
fn splice_contents(contents: &str) -> Result<Location> {
|
||||||
let program = parser::parse_program(contents, "<filename>")?;
|
let program = parser::parse_program(contents, "<filename>")?;
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
Ok(find_splice_location(&program, &locator))
|
Ok(find_splice_location(&program, &locator))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,18 +18,17 @@ use crate::isort::types::{
|
||||||
AliasData, CommentSet, EitherImport, ImportBlock, ImportFromData, Importable,
|
AliasData, CommentSet, EitherImport, ImportBlock, ImportFromData, Importable,
|
||||||
OrderedImportBlock, TrailingComma,
|
OrderedImportBlock, TrailingComma,
|
||||||
};
|
};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
use crate::source_code::{Locator, Stylist};
|
||||||
use crate::SourceCodeLocator;
|
|
||||||
|
|
||||||
mod categorize;
|
mod categorize;
|
||||||
mod comments;
|
mod comments;
|
||||||
pub mod format;
|
mod format;
|
||||||
pub mod helpers;
|
mod helpers;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
mod sorting;
|
mod sorting;
|
||||||
pub mod track;
|
pub(crate) mod track;
|
||||||
pub mod types;
|
mod types;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AnnotatedAliasData<'a> {
|
pub struct AnnotatedAliasData<'a> {
|
||||||
|
@ -59,7 +58,7 @@ pub enum AnnotatedImport<'a> {
|
||||||
fn annotate_imports<'a>(
|
fn annotate_imports<'a>(
|
||||||
imports: &'a [&'a Stmt],
|
imports: &'a [&'a Stmt],
|
||||||
comments: Vec<Comment<'a>>,
|
comments: Vec<Comment<'a>>,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
split_on_trailing_comma: bool,
|
split_on_trailing_comma: bool,
|
||||||
) -> Vec<AnnotatedImport<'a>> {
|
) -> Vec<AnnotatedImport<'a>> {
|
||||||
let mut annotated = vec![];
|
let mut annotated = vec![];
|
||||||
|
@ -536,9 +535,9 @@ fn force_single_line_imports<'a>(
|
||||||
pub fn format_imports(
|
pub fn format_imports(
|
||||||
block: &Block,
|
block: &Block,
|
||||||
comments: Vec<Comment>,
|
comments: Vec<Comment>,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
line_length: usize,
|
line_length: usize,
|
||||||
stylist: &SourceCodeStyleDetector,
|
stylist: &Stylist,
|
||||||
src: &[PathBuf],
|
src: &[PathBuf],
|
||||||
package: Option<&Path>,
|
package: Option<&Path>,
|
||||||
known_first_party: &BTreeSet<String>,
|
known_first_party: &BTreeSet<String>,
|
||||||
|
@ -647,9 +646,10 @@ mod tests {
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use test_case::test_case;
|
use test_case::test_case;
|
||||||
|
|
||||||
|
use crate::isort;
|
||||||
use crate::linter::test_path;
|
use crate::linter::test_path;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::{isort, Settings};
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[test_case(Path::new("add_newline_before_comments.py"))]
|
#[test_case(Path::new("add_newline_before_comments.py"))]
|
||||||
#[test_case(Path::new("combine_as_imports.py"))]
|
#[test_case(Path::new("combine_as_imports.py"))]
|
||||||
|
|
|
@ -5,12 +5,12 @@ use rustpython_ast::{Location, StmtKind, Suite};
|
||||||
|
|
||||||
use crate::ast::helpers::is_docstring_stmt;
|
use crate::ast::helpers::is_docstring_stmt;
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
use crate::fix::Fix;
|
||||||
use crate::isort::helpers;
|
use crate::isort::helpers;
|
||||||
use crate::isort::track::Block;
|
use crate::isort::track::Block;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::settings::{flags, Settings};
|
use crate::settings::{flags, Settings};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
struct Alias<'a> {
|
struct Alias<'a> {
|
||||||
|
@ -101,7 +101,7 @@ fn add_required_import(
|
||||||
required_import: &AnyImport,
|
required_import: &AnyImport,
|
||||||
blocks: &[&Block],
|
blocks: &[&Block],
|
||||||
python_ast: &Suite,
|
python_ast: &Suite,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
autofix: flags::Autofix,
|
autofix: flags::Autofix,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
|
@ -157,7 +157,7 @@ fn add_required_import(
|
||||||
pub fn add_required_imports(
|
pub fn add_required_imports(
|
||||||
blocks: &[&Block],
|
blocks: &[&Block],
|
||||||
python_ast: &Suite,
|
python_ast: &Suite,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
autofix: flags::Autofix,
|
autofix: flags::Autofix,
|
||||||
) -> Vec<Diagnostic> {
|
) -> Vec<Diagnostic> {
|
||||||
|
|
|
@ -8,12 +8,13 @@ use crate::ast::helpers::{
|
||||||
};
|
};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::ast::whitespace::leading_space;
|
use crate::ast::whitespace::leading_space;
|
||||||
use crate::autofix::Fix;
|
use crate::fix::Fix;
|
||||||
use crate::isort::track::Block;
|
use crate::isort::track::Block;
|
||||||
use crate::isort::{comments, format_imports};
|
use crate::isort::{comments, format_imports};
|
||||||
use crate::settings::flags;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
use crate::settings::{flags, Settings};
|
||||||
use crate::{violations, Diagnostic, Settings, SourceCodeLocator};
|
use crate::source_code::{Locator, Stylist};
|
||||||
|
use crate::violations;
|
||||||
|
|
||||||
fn extract_range(body: &[&Stmt]) -> Range {
|
fn extract_range(body: &[&Stmt]) -> Range {
|
||||||
let location = body.first().unwrap().location;
|
let location = body.first().unwrap().location;
|
||||||
|
@ -29,9 +30,9 @@ fn extract_indentation_range(body: &[&Stmt]) -> Range {
|
||||||
/// I001
|
/// I001
|
||||||
pub fn organize_imports(
|
pub fn organize_imports(
|
||||||
block: &Block,
|
block: &Block,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
stylist: &SourceCodeStyleDetector,
|
stylist: &Stylist,
|
||||||
autofix: flags::Autofix,
|
autofix: flags::Autofix,
|
||||||
package: Option<&Path>,
|
package: Option<&Path>,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use rustpython_ast::{
|
||||||
use crate::ast::visitor::Visitor;
|
use crate::ast::visitor::Visitor;
|
||||||
use crate::directives::IsortDirectives;
|
use crate::directives::IsortDirectives;
|
||||||
use crate::isort::helpers;
|
use crate::isort::helpers;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Trailer {
|
pub enum Trailer {
|
||||||
|
@ -26,7 +26,7 @@ pub struct Block<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ImportTracker<'a> {
|
pub struct ImportTracker<'a> {
|
||||||
locator: &'a SourceCodeLocator<'a>,
|
locator: &'a Locator<'a>,
|
||||||
directives: &'a IsortDirectives,
|
directives: &'a IsortDirectives,
|
||||||
pyi: bool,
|
pyi: bool,
|
||||||
blocks: Vec<Block<'a>>,
|
blocks: Vec<Block<'a>>,
|
||||||
|
@ -35,11 +35,7 @@ pub struct ImportTracker<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ImportTracker<'a> {
|
impl<'a> ImportTracker<'a> {
|
||||||
pub fn new(
|
pub fn new(locator: &'a Locator<'a>, directives: &'a IsortDirectives, path: &'a Path) -> Self {
|
||||||
locator: &'a SourceCodeLocator<'a>,
|
|
||||||
directives: &'a IsortDirectives,
|
|
||||||
path: &'a Path,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
locator,
|
locator,
|
||||||
directives,
|
directives,
|
||||||
|
|
26
src/lib.rs
26
src/lib.rs
|
@ -12,21 +12,17 @@
|
||||||
)]
|
)]
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
use cfg_if::cfg_if;
|
|
||||||
|
|
||||||
use crate::registry::Diagnostic;
|
|
||||||
use crate::settings::Settings;
|
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
pub mod autofix;
|
mod autofix;
|
||||||
pub mod cache;
|
mod cache;
|
||||||
mod checkers;
|
mod checkers;
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
mod cst;
|
mod cst;
|
||||||
mod directives;
|
mod directives;
|
||||||
|
mod doc_lines;
|
||||||
mod docstrings;
|
mod docstrings;
|
||||||
mod eradicate;
|
mod eradicate;
|
||||||
|
pub mod fix;
|
||||||
mod flake8_2020;
|
mod flake8_2020;
|
||||||
pub mod flake8_annotations;
|
pub mod flake8_annotations;
|
||||||
pub mod flake8_bandit;
|
pub mod flake8_bandit;
|
||||||
|
@ -40,6 +36,7 @@ mod flake8_debugger;
|
||||||
pub mod flake8_errmsg;
|
pub mod flake8_errmsg;
|
||||||
mod flake8_implicit_str_concat;
|
mod flake8_implicit_str_concat;
|
||||||
mod flake8_import_conventions;
|
mod flake8_import_conventions;
|
||||||
|
pub mod flake8_pie;
|
||||||
mod flake8_print;
|
mod flake8_print;
|
||||||
pub mod flake8_pytest_style;
|
pub mod flake8_pytest_style;
|
||||||
pub mod flake8_quotes;
|
pub mod flake8_quotes;
|
||||||
|
@ -71,18 +68,19 @@ pub mod resolver;
|
||||||
mod ruff;
|
mod ruff;
|
||||||
mod rustpython_helpers;
|
mod rustpython_helpers;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod source_code_generator;
|
pub mod source_code;
|
||||||
pub mod source_code_locator;
|
|
||||||
pub mod source_code_style;
|
|
||||||
mod vendor;
|
mod vendor;
|
||||||
mod violation;
|
mod violation;
|
||||||
mod violations;
|
mod violations;
|
||||||
pub mod visibility;
|
mod visibility;
|
||||||
|
|
||||||
|
use cfg_if::cfg_if;
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(not(target_family = "wasm"))] {
|
if #[cfg(not(target_family = "wasm"))] {
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
mod packages;
|
mod packaging;
|
||||||
|
|
||||||
#[cfg(all(feature = "update-informer"))]
|
#[cfg(all(feature = "update-informer"))]
|
||||||
pub mod updates;
|
pub mod updates;
|
||||||
|
|
||||||
|
@ -93,5 +91,3 @@ cfg_if! {
|
||||||
pub use lib_wasm::check;
|
pub use lib_wasm::check;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub mod doc_lines;
|
|
||||||
pub mod flake8_pie;
|
|
||||||
|
|
|
@ -10,9 +10,8 @@ use crate::resolver::Relativity;
|
||||||
use crate::rustpython_helpers::tokenize;
|
use crate::rustpython_helpers::tokenize;
|
||||||
use crate::settings::configuration::Configuration;
|
use crate::settings::configuration::Configuration;
|
||||||
use crate::settings::{flags, pyproject, Settings};
|
use crate::settings::{flags, pyproject, Settings};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::{Locator, Stylist};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
use crate::{directives, packaging, resolver};
|
||||||
use crate::{directives, packages, resolver};
|
|
||||||
|
|
||||||
/// Load the relevant `Settings` for a given `Path`.
|
/// Load the relevant `Settings` for a given `Path`.
|
||||||
fn resolve(path: &Path) -> Result<Settings> {
|
fn resolve(path: &Path) -> Result<Settings> {
|
||||||
|
@ -40,10 +39,10 @@ pub fn check(path: &Path, contents: &str, autofix: bool) -> Result<Vec<Diagnosti
|
||||||
let tokens: Vec<LexResult> = tokenize(contents);
|
let tokens: Vec<LexResult> = tokenize(contents);
|
||||||
|
|
||||||
// Map row and column locations to byte slices (lazily).
|
// Map row and column locations to byte slices (lazily).
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
|
|
||||||
// Detect the current code style (lazily).
|
// Detect the current code style (lazily).
|
||||||
let stylist = SourceCodeStyleDetector::from_contents(contents, &locator);
|
let stylist = Stylist::from_contents(contents, &locator);
|
||||||
|
|
||||||
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
||||||
let directives =
|
let directives =
|
||||||
|
@ -52,7 +51,7 @@ pub fn check(path: &Path, contents: &str, autofix: bool) -> Result<Vec<Diagnosti
|
||||||
// Generate diagnostics.
|
// Generate diagnostics.
|
||||||
let diagnostics = check_path(
|
let diagnostics = check_path(
|
||||||
path,
|
path,
|
||||||
packages::detect_package_root(path),
|
packaging::detect_package_root(path),
|
||||||
contents,
|
contents,
|
||||||
tokens,
|
tokens,
|
||||||
&locator,
|
&locator,
|
||||||
|
|
|
@ -12,8 +12,7 @@ use crate::settings::configuration::Configuration;
|
||||||
use crate::settings::options::Options;
|
use crate::settings::options::Options;
|
||||||
use crate::settings::types::PythonVersion;
|
use crate::settings::types::PythonVersion;
|
||||||
use crate::settings::{flags, Settings};
|
use crate::settings::{flags, Settings};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::{Locator, Stylist};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
directives, flake8_annotations, flake8_bandit, flake8_bugbear, flake8_errmsg,
|
directives, flake8_annotations, flake8_bandit, flake8_bugbear, flake8_errmsg,
|
||||||
flake8_import_conventions, flake8_pytest_style, flake8_quotes, flake8_tidy_imports,
|
flake8_import_conventions, flake8_pytest_style, flake8_quotes, flake8_tidy_imports,
|
||||||
|
@ -151,10 +150,10 @@ pub fn check(contents: &str, options: JsValue) -> Result<JsValue, JsValue> {
|
||||||
let tokens: Vec<LexResult> = tokenize(contents);
|
let tokens: Vec<LexResult> = tokenize(contents);
|
||||||
|
|
||||||
// Map row and column locations to byte slices (lazily).
|
// Map row and column locations to byte slices (lazily).
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
|
|
||||||
// Detect the current code style (lazily).
|
// Detect the current code style (lazily).
|
||||||
let stylist = SourceCodeStyleDetector::from_contents(contents, &locator);
|
let stylist = Stylist::from_contents(contents, &locator);
|
||||||
|
|
||||||
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
||||||
let directives = directives::extract_directives(&tokens, directives::Flags::empty());
|
let directives = directives::extract_directives(&tokens, directives::Flags::empty());
|
||||||
|
|
|
@ -11,8 +11,7 @@ use rustpython_parser::lexer::LexResult;
|
||||||
use similar::TextDiff;
|
use similar::TextDiff;
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::fixer;
|
use crate::autofix::fix_file;
|
||||||
use crate::autofix::fixer::fix_file;
|
|
||||||
use crate::checkers::ast::check_ast;
|
use crate::checkers::ast::check_ast;
|
||||||
use crate::checkers::imports::check_imports;
|
use crate::checkers::imports::check_imports;
|
||||||
use crate::checkers::lines::check_lines;
|
use crate::checkers::lines::check_lines;
|
||||||
|
@ -24,9 +23,8 @@ use crate::message::{Message, Source};
|
||||||
use crate::noqa::add_noqa;
|
use crate::noqa::add_noqa;
|
||||||
use crate::registry::{Diagnostic, LintSource, RuleCode};
|
use crate::registry::{Diagnostic, LintSource, RuleCode};
|
||||||
use crate::settings::{flags, Settings};
|
use crate::settings::{flags, Settings};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::{Locator, Stylist};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
use crate::{cache, directives, fix, fs, rustpython_helpers, violations};
|
||||||
use crate::{cache, directives, fs, rustpython_helpers, violations};
|
|
||||||
|
|
||||||
const CARGO_PKG_NAME: &str = env!("CARGO_PKG_NAME");
|
const CARGO_PKG_NAME: &str = env!("CARGO_PKG_NAME");
|
||||||
const CARGO_PKG_REPOSITORY: &str = env!("CARGO_PKG_REPOSITORY");
|
const CARGO_PKG_REPOSITORY: &str = env!("CARGO_PKG_REPOSITORY");
|
||||||
|
@ -58,8 +56,8 @@ pub(crate) fn check_path(
|
||||||
package: Option<&Path>,
|
package: Option<&Path>,
|
||||||
contents: &str,
|
contents: &str,
|
||||||
tokens: Vec<LexResult>,
|
tokens: Vec<LexResult>,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
stylist: &SourceCodeStyleDetector,
|
stylist: &Stylist,
|
||||||
directives: &Directives,
|
directives: &Directives,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
autofix: flags::Autofix,
|
autofix: flags::Autofix,
|
||||||
|
@ -200,7 +198,7 @@ pub fn lint_path(
|
||||||
package: Option<&Path>,
|
package: Option<&Path>,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
cache: flags::Cache,
|
cache: flags::Cache,
|
||||||
autofix: fixer::Mode,
|
autofix: fix::FixMode,
|
||||||
) -> Result<Diagnostics> {
|
) -> Result<Diagnostics> {
|
||||||
// Validate the `Settings` and return any errors.
|
// Validate the `Settings` and return any errors.
|
||||||
settings.validate()?;
|
settings.validate()?;
|
||||||
|
@ -212,7 +210,7 @@ pub fn lint_path(
|
||||||
// write the fixes to disk, thus invalidating the cache. But it's a bit hard
|
// write the fixes to disk, thus invalidating the cache. But it's a bit hard
|
||||||
// to reason about. We need to come up with a better solution here.)
|
// to reason about. We need to come up with a better solution here.)
|
||||||
let metadata = if matches!(cache, flags::Cache::Enabled)
|
let metadata = if matches!(cache, flags::Cache::Enabled)
|
||||||
&& matches!(autofix, fixer::Mode::None | fixer::Mode::Generate)
|
&& matches!(autofix, fix::FixMode::None | fix::FixMode::Generate)
|
||||||
{
|
{
|
||||||
let metadata = path.metadata()?;
|
let metadata = path.metadata()?;
|
||||||
if let Some(messages) = cache::get(path, &metadata, settings, autofix.into()) {
|
if let Some(messages) = cache::get(path, &metadata, settings, autofix.into()) {
|
||||||
|
@ -228,12 +226,12 @@ pub fn lint_path(
|
||||||
let contents = fs::read_file(path)?;
|
let contents = fs::read_file(path)?;
|
||||||
|
|
||||||
// Lint the file.
|
// Lint the file.
|
||||||
let (messages, fixed) = if matches!(autofix, fixer::Mode::Apply | fixer::Mode::Diff) {
|
let (messages, fixed) = if matches!(autofix, fix::FixMode::Apply | fix::FixMode::Diff) {
|
||||||
let (transformed, fixed, messages) = lint_fix(&contents, path, package, settings)?;
|
let (transformed, fixed, messages) = lint_fix(&contents, path, package, settings)?;
|
||||||
if fixed > 0 {
|
if fixed > 0 {
|
||||||
if matches!(autofix, fixer::Mode::Apply) {
|
if matches!(autofix, fix::FixMode::Apply) {
|
||||||
write(path, transformed)?;
|
write(path, transformed)?;
|
||||||
} else if matches!(autofix, fixer::Mode::Diff) {
|
} else if matches!(autofix, fix::FixMode::Diff) {
|
||||||
let mut stdout = io::stdout().lock();
|
let mut stdout = io::stdout().lock();
|
||||||
TextDiff::from_lines(&contents, &transformed)
|
TextDiff::from_lines(&contents, &transformed)
|
||||||
.unified_diff()
|
.unified_diff()
|
||||||
|
@ -270,10 +268,10 @@ pub fn add_noqa_to_path(path: &Path, settings: &Settings) -> Result<usize> {
|
||||||
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
||||||
|
|
||||||
// Map row and column locations to byte slices (lazily).
|
// Map row and column locations to byte slices (lazily).
|
||||||
let locator = SourceCodeLocator::new(&contents);
|
let locator = Locator::new(&contents);
|
||||||
|
|
||||||
// Detect the current code style (lazily).
|
// Detect the current code style (lazily).
|
||||||
let stylist = SourceCodeStyleDetector::from_contents(&contents, &locator);
|
let stylist = Stylist::from_contents(&contents, &locator);
|
||||||
|
|
||||||
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
||||||
let directives =
|
let directives =
|
||||||
|
@ -310,13 +308,13 @@ pub fn lint_stdin(
|
||||||
package: Option<&Path>,
|
package: Option<&Path>,
|
||||||
contents: &str,
|
contents: &str,
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
autofix: fixer::Mode,
|
autofix: fix::FixMode,
|
||||||
) -> Result<Diagnostics> {
|
) -> Result<Diagnostics> {
|
||||||
// Validate the `Settings` and return any errors.
|
// Validate the `Settings` and return any errors.
|
||||||
settings.validate()?;
|
settings.validate()?;
|
||||||
|
|
||||||
// Lint the inputs.
|
// Lint the inputs.
|
||||||
let (messages, fixed) = if matches!(autofix, fixer::Mode::Apply | fixer::Mode::Diff) {
|
let (messages, fixed) = if matches!(autofix, fix::FixMode::Apply | fix::FixMode::Diff) {
|
||||||
let (transformed, fixed, messages) = lint_fix(
|
let (transformed, fixed, messages) = lint_fix(
|
||||||
contents,
|
contents,
|
||||||
path.unwrap_or_else(|| Path::new("-")),
|
path.unwrap_or_else(|| Path::new("-")),
|
||||||
|
@ -324,10 +322,10 @@ pub fn lint_stdin(
|
||||||
settings,
|
settings,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if matches!(autofix, fixer::Mode::Apply) {
|
if matches!(autofix, fix::FixMode::Apply) {
|
||||||
// Write the contents to stdout, regardless of whether any errors were fixed.
|
// Write the contents to stdout, regardless of whether any errors were fixed.
|
||||||
io::stdout().write_all(transformed.as_bytes())?;
|
io::stdout().write_all(transformed.as_bytes())?;
|
||||||
} else if matches!(autofix, fixer::Mode::Diff) {
|
} else if matches!(autofix, fix::FixMode::Diff) {
|
||||||
// But only write a diff if it's non-empty.
|
// But only write a diff if it's non-empty.
|
||||||
if fixed > 0 {
|
if fixed > 0 {
|
||||||
let text_diff = TextDiff::from_lines(contents, &transformed);
|
let text_diff = TextDiff::from_lines(contents, &transformed);
|
||||||
|
@ -372,10 +370,10 @@ fn lint_only(
|
||||||
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(contents);
|
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(contents);
|
||||||
|
|
||||||
// Map row and column locations to byte slices (lazily).
|
// Map row and column locations to byte slices (lazily).
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = Locator::new(contents);
|
||||||
|
|
||||||
// Detect the current code style (lazily).
|
// Detect the current code style (lazily).
|
||||||
let stylist = SourceCodeStyleDetector::from_contents(contents, &locator);
|
let stylist = Stylist::from_contents(contents, &locator);
|
||||||
|
|
||||||
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
||||||
let directives =
|
let directives =
|
||||||
|
@ -432,10 +430,10 @@ fn lint_fix(
|
||||||
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
||||||
|
|
||||||
// Map row and column locations to byte slices (lazily).
|
// Map row and column locations to byte slices (lazily).
|
||||||
let locator = SourceCodeLocator::new(&contents);
|
let locator = Locator::new(&contents);
|
||||||
|
|
||||||
// Detect the current code style (lazily).
|
// Detect the current code style (lazily).
|
||||||
let stylist = SourceCodeStyleDetector::from_contents(&contents, &locator);
|
let stylist = Stylist::from_contents(&contents, &locator);
|
||||||
|
|
||||||
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
||||||
let directives =
|
let directives =
|
||||||
|
@ -511,8 +509,8 @@ quoting the contents of `{}`, along with the `pyproject.toml` settings and execu
|
||||||
pub fn test_path(path: &Path, settings: &Settings) -> Result<Vec<Diagnostic>> {
|
pub fn test_path(path: &Path, settings: &Settings) -> Result<Vec<Diagnostic>> {
|
||||||
let contents = fs::read_file(path)?;
|
let contents = fs::read_file(path)?;
|
||||||
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
||||||
let locator = SourceCodeLocator::new(&contents);
|
let locator = Locator::new(&contents);
|
||||||
let stylist = SourceCodeStyleDetector::from_contents(&contents, &locator);
|
let stylist = Stylist::from_contents(&contents, &locator);
|
||||||
let directives =
|
let directives =
|
||||||
directives::extract_directives(&tokens, directives::Flags::from_settings(settings));
|
directives::extract_directives(&tokens, directives::Flags::from_settings(settings));
|
||||||
let mut diagnostics = check_path(
|
let mut diagnostics = check_path(
|
||||||
|
@ -540,8 +538,8 @@ pub fn test_path(path: &Path, settings: &Settings) -> Result<Vec<Diagnostic>> {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
||||||
let locator = SourceCodeLocator::new(&contents);
|
let locator = Locator::new(&contents);
|
||||||
let stylist = SourceCodeStyleDetector::from_contents(&contents, &locator);
|
let stylist = Stylist::from_contents(&contents, &locator);
|
||||||
let directives =
|
let directives =
|
||||||
directives::extract_directives(&tokens, directives::Flags::from_settings(settings));
|
directives::extract_directives(&tokens, directives::Flags::from_settings(settings));
|
||||||
let diagnostics = check_path(
|
let diagnostics = check_path(
|
||||||
|
|
|
@ -3,7 +3,6 @@ use std::path::{Path, PathBuf};
|
||||||
use std::process::ExitCode;
|
use std::process::ExitCode;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
use ::ruff::autofix::fixer;
|
|
||||||
use ::ruff::cli::{extract_log_level, Cli, Overrides};
|
use ::ruff::cli::{extract_log_level, Cli, Overrides};
|
||||||
use ::ruff::logging::{set_up_logging, LogLevel};
|
use ::ruff::logging::{set_up_logging, LogLevel};
|
||||||
use ::ruff::printer::{Printer, Violations};
|
use ::ruff::printer::{Printer, Violations};
|
||||||
|
@ -13,7 +12,7 @@ use ::ruff::settings::types::SerializationFormat;
|
||||||
use ::ruff::settings::{pyproject, Settings};
|
use ::ruff::settings::{pyproject, Settings};
|
||||||
#[cfg(feature = "update-informer")]
|
#[cfg(feature = "update-informer")]
|
||||||
use ::ruff::updates;
|
use ::ruff::updates;
|
||||||
use ::ruff::{commands, warn_user_once};
|
use ::ruff::{commands, fix, warn_user_once};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{CommandFactory, Parser};
|
use clap::{CommandFactory, Parser};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
@ -152,13 +151,13 @@ pub(crate) fn inner_main() -> Result<ExitCode> {
|
||||||
// but not apply fixes. That would allow us to avoid special-casing JSON
|
// but not apply fixes. That would allow us to avoid special-casing JSON
|
||||||
// here.
|
// here.
|
||||||
let autofix = if cli.diff {
|
let autofix = if cli.diff {
|
||||||
fixer::Mode::Diff
|
fix::FixMode::Diff
|
||||||
} else if fix || fix_only {
|
} else if fix || fix_only {
|
||||||
fixer::Mode::Apply
|
fix::FixMode::Apply
|
||||||
} else if matches!(format, SerializationFormat::Json) {
|
} else if matches!(format, SerializationFormat::Json) {
|
||||||
fixer::Mode::Generate
|
fix::FixMode::Generate
|
||||||
} else {
|
} else {
|
||||||
fixer::Mode::None
|
fix::FixMode::None
|
||||||
};
|
};
|
||||||
let violations = if cli.diff || fix_only {
|
let violations = if cli.diff || fix_only {
|
||||||
Violations::Hide
|
Violations::Hide
|
||||||
|
@ -176,7 +175,7 @@ pub(crate) fn inner_main() -> Result<ExitCode> {
|
||||||
|
|
||||||
let printer = Printer::new(&format, &log_level, &autofix, &violations);
|
let printer = Printer::new(&format, &log_level, &autofix, &violations);
|
||||||
if cli.watch {
|
if cli.watch {
|
||||||
if !matches!(autofix, fixer::Mode::None) {
|
if !matches!(autofix, fix::FixMode::None) {
|
||||||
warn_user_once!("--fix is not enabled in watch mode.");
|
warn_user_once!("--fix is not enabled in watch mode.");
|
||||||
}
|
}
|
||||||
if format != SerializationFormat::Text {
|
if format != SerializationFormat::Text {
|
||||||
|
@ -193,7 +192,7 @@ pub(crate) fn inner_main() -> Result<ExitCode> {
|
||||||
&file_strategy,
|
&file_strategy,
|
||||||
&overrides,
|
&overrides,
|
||||||
cache.into(),
|
cache.into(),
|
||||||
fixer::Mode::None,
|
fix::FixMode::None,
|
||||||
)?;
|
)?;
|
||||||
printer.write_continuously(&messages)?;
|
printer.write_continuously(&messages)?;
|
||||||
|
|
||||||
|
@ -223,7 +222,7 @@ pub(crate) fn inner_main() -> Result<ExitCode> {
|
||||||
&file_strategy,
|
&file_strategy,
|
||||||
&overrides,
|
&overrides,
|
||||||
cache.into(),
|
cache.into(),
|
||||||
fixer::Mode::None,
|
fix::FixMode::None,
|
||||||
)?;
|
)?;
|
||||||
printer.write_continuously(&messages)?;
|
printer.write_continuously(&messages)?;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +262,7 @@ pub(crate) fn inner_main() -> Result<ExitCode> {
|
||||||
// Always try to print violations (the printer itself may suppress output),
|
// Always try to print violations (the printer itself may suppress output),
|
||||||
// unless we're writing fixes via stdin (in which case, the transformed
|
// unless we're writing fixes via stdin (in which case, the transformed
|
||||||
// source code goes to stdout).
|
// source code goes to stdout).
|
||||||
if !(is_stdin && matches!(autofix, fixer::Mode::Apply | fixer::Mode::Diff)) {
|
if !(is_stdin && matches!(autofix, fix::FixMode::Apply | fix::FixMode::Diff)) {
|
||||||
printer.write_once(&diagnostics)?;
|
printer.write_once(&diagnostics)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -9,8 +9,9 @@ mod tests {
|
||||||
use test_case::test_case;
|
use test_case::test_case;
|
||||||
|
|
||||||
use crate::linter::test_path;
|
use crate::linter::test_path;
|
||||||
|
use crate::mccabe;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::{mccabe, Settings};
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[test_case(0)]
|
#[test_case(0)]
|
||||||
#[test_case(3)]
|
#[test_case(3)]
|
||||||
|
|
|
@ -2,7 +2,7 @@ use rustpython_ast::{ExcepthandlerKind, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use crate::ast::helpers::identifier_range;
|
use crate::ast::helpers::identifier_range;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
fn get_complexity_number(stmts: &[Stmt]) -> usize {
|
fn get_complexity_number(stmts: &[Stmt]) -> usize {
|
||||||
|
@ -61,7 +61,7 @@ pub fn function_is_too_complex(
|
||||||
name: &str,
|
name: &str,
|
||||||
body: &[Stmt],
|
body: &[Stmt],
|
||||||
max_complexity: usize,
|
max_complexity: usize,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
let complexity = get_complexity_number(body) + 1;
|
let complexity = get_complexity_number(body) + 1;
|
||||||
if complexity > max_complexity {
|
if complexity > max_complexity {
|
||||||
|
|
|
@ -4,9 +4,9 @@ use rustpython_parser::ast::Location;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, DiagnosticKind};
|
use crate::registry::{Diagnostic, DiagnosticKind};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
|
@ -61,7 +61,7 @@ pub struct Source {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Source {
|
impl Source {
|
||||||
pub fn from_diagnostic(diagnostic: &Diagnostic, locator: &SourceCodeLocator) -> Self {
|
pub fn from_diagnostic(diagnostic: &Diagnostic, locator: &Locator) -> Self {
|
||||||
let location = Location::new(diagnostic.location.row(), 0);
|
let location = Location::new(diagnostic.location.row(), 0);
|
||||||
// Diagnostics can already extend one-past-the-end per Ropey's semantics. If
|
// Diagnostics can already extend one-past-the-end per Ropey's semantics. If
|
||||||
// they do, though, then they'll end at the start of a line. We need to
|
// they do, though, then they'll end at the start of a line. We need to
|
||||||
|
|
|
@ -9,7 +9,7 @@ use regex::Regex;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use crate::registry::{Diagnostic, RuleCode, CODE_REDIRECTS};
|
use crate::registry::{Diagnostic, RuleCode, CODE_REDIRECTS};
|
||||||
use crate::source_code_style::LineEnding;
|
use crate::source_code::LineEnding;
|
||||||
|
|
||||||
static NOQA_LINE_REGEX: Lazy<Regex> = Lazy::new(|| {
|
static NOQA_LINE_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||||
Regex::new(
|
Regex::new(
|
||||||
|
@ -207,7 +207,6 @@ fn add_noqa_inner(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use nohash_hasher::IntMap;
|
use nohash_hasher::IntMap;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use rustpython_parser::ast::Location;
|
use rustpython_parser::ast::Location;
|
||||||
|
@ -215,7 +214,7 @@ mod tests {
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::noqa::{add_noqa_inner, NOQA_LINE_REGEX};
|
use crate::noqa::{add_noqa_inner, NOQA_LINE_REGEX};
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_style::LineEnding;
|
use crate::source_code::LineEnding;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -102,7 +102,7 @@ pub fn detect_package_roots<'a>(files: &[&'a Path]) -> FxHashMap<&'a Path, Optio
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::packages::detect_package_root;
|
use crate::packaging::detect_package_root;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn package_detection() {
|
fn package_detection() {
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod helpers;
|
pub(crate) mod helpers;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -13,16 +13,15 @@ mod tests {
|
||||||
use crate::linter::check_path;
|
use crate::linter::check_path;
|
||||||
use crate::registry::{RuleCode, RuleCodePrefix};
|
use crate::registry::{RuleCode, RuleCodePrefix};
|
||||||
use crate::settings::flags;
|
use crate::settings::flags;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::{Locator, Stylist};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
|
||||||
use crate::{directives, rustpython_helpers, settings};
|
use crate::{directives, rustpython_helpers, settings};
|
||||||
|
|
||||||
fn rule_code(contents: &str, expected: &[RuleCode]) -> Result<()> {
|
fn rule_code(contents: &str, expected: &[RuleCode]) -> Result<()> {
|
||||||
let contents = dedent(contents);
|
let contents = dedent(contents);
|
||||||
let settings = settings::Settings::for_rules(RuleCodePrefix::PD.codes());
|
let settings = settings::Settings::for_rules(RuleCodePrefix::PD.codes());
|
||||||
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
||||||
let locator = SourceCodeLocator::new(&contents);
|
let locator = Locator::new(&contents);
|
||||||
let stylist = SourceCodeStyleDetector::from_contents(&contents, &locator);
|
let stylist = Stylist::from_contents(&contents, &locator);
|
||||||
let directives =
|
let directives =
|
||||||
directives::extract_directives(&tokens, directives::Flags::from_settings(&settings));
|
directives::extract_directives(&tokens, directives::Flags::from_settings(&settings));
|
||||||
let diagnostics = check_path(
|
let diagnostics = check_path(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod helpers;
|
mod helpers;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -9,15 +9,11 @@ use crate::pep8_naming::helpers;
|
||||||
use crate::pep8_naming::settings::Settings;
|
use crate::pep8_naming::settings::Settings;
|
||||||
use crate::python::string::{self};
|
use crate::python::string::{self};
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
/// N801
|
/// N801
|
||||||
pub fn invalid_class_name(
|
pub fn invalid_class_name(class_def: &Stmt, name: &str, locator: &Locator) -> Option<Diagnostic> {
|
||||||
class_def: &Stmt,
|
|
||||||
name: &str,
|
|
||||||
locator: &SourceCodeLocator,
|
|
||||||
) -> Option<Diagnostic> {
|
|
||||||
let stripped = name.strip_prefix('_').unwrap_or(name);
|
let stripped = name.strip_prefix('_').unwrap_or(name);
|
||||||
if !stripped.chars().next().map_or(false, char::is_uppercase) || stripped.contains('_') {
|
if !stripped.chars().next().map_or(false, char::is_uppercase) || stripped.contains('_') {
|
||||||
return Some(Diagnostic::new(
|
return Some(Diagnostic::new(
|
||||||
|
@ -33,7 +29,7 @@ pub fn invalid_function_name(
|
||||||
func_def: &Stmt,
|
func_def: &Stmt,
|
||||||
name: &str,
|
name: &str,
|
||||||
ignore_names: &[String],
|
ignore_names: &[String],
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
if name.to_lowercase() != name && !ignore_names.iter().any(|ignore_name| ignore_name == name) {
|
if name.to_lowercase() != name && !ignore_names.iter().any(|ignore_name| ignore_name == name) {
|
||||||
return Some(Diagnostic::new(
|
return Some(Diagnostic::new(
|
||||||
|
@ -153,7 +149,7 @@ pub fn dunder_function_name(
|
||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
stmt: &Stmt,
|
stmt: &Stmt,
|
||||||
name: &str,
|
name: &str,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
if matches!(scope.kind, ScopeKind::Class(_)) {
|
if matches!(scope.kind, ScopeKind::Class(_)) {
|
||||||
return None;
|
return None;
|
||||||
|
@ -177,7 +173,7 @@ pub fn constant_imported_as_non_constant(
|
||||||
import_from: &Stmt,
|
import_from: &Stmt,
|
||||||
name: &str,
|
name: &str,
|
||||||
asname: &str,
|
asname: &str,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
if string::is_upper(name) && !string::is_upper(asname) {
|
if string::is_upper(name) && !string::is_upper(asname) {
|
||||||
return Some(Diagnostic::new(
|
return Some(Diagnostic::new(
|
||||||
|
@ -193,7 +189,7 @@ pub fn lowercase_imported_as_non_lowercase(
|
||||||
import_from: &Stmt,
|
import_from: &Stmt,
|
||||||
name: &str,
|
name: &str,
|
||||||
asname: &str,
|
asname: &str,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
if !string::is_upper(name) && string::is_lower(name) && asname.to_lowercase() != asname {
|
if !string::is_upper(name) && string::is_lower(name) && asname.to_lowercase() != asname {
|
||||||
return Some(Diagnostic::new(
|
return Some(Diagnostic::new(
|
||||||
|
@ -209,7 +205,7 @@ pub fn camelcase_imported_as_lowercase(
|
||||||
import_from: &Stmt,
|
import_from: &Stmt,
|
||||||
name: &str,
|
name: &str,
|
||||||
asname: &str,
|
asname: &str,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
if helpers::is_camelcase(name) && string::is_lower(asname) {
|
if helpers::is_camelcase(name) && string::is_lower(asname) {
|
||||||
return Some(Diagnostic::new(
|
return Some(Diagnostic::new(
|
||||||
|
@ -225,7 +221,7 @@ pub fn camelcase_imported_as_constant(
|
||||||
import_from: &Stmt,
|
import_from: &Stmt,
|
||||||
name: &str,
|
name: &str,
|
||||||
asname: &str,
|
asname: &str,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
if helpers::is_camelcase(name)
|
if helpers::is_camelcase(name)
|
||||||
&& !string::is_lower(asname)
|
&& !string::is_lower(asname)
|
||||||
|
@ -279,7 +275,7 @@ pub fn camelcase_imported_as_acronym(
|
||||||
import_from: &Stmt,
|
import_from: &Stmt,
|
||||||
name: &str,
|
name: &str,
|
||||||
asname: &str,
|
asname: &str,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
if helpers::is_camelcase(name)
|
if helpers::is_camelcase(name)
|
||||||
&& !string::is_lower(asname)
|
&& !string::is_lower(asname)
|
||||||
|
@ -299,7 +295,7 @@ pub fn error_suffix_on_exception_name(
|
||||||
class_def: &Stmt,
|
class_def: &Stmt,
|
||||||
bases: &[Expr],
|
bases: &[Expr],
|
||||||
name: &str,
|
name: &str,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
if !bases.iter().any(|base| {
|
if !bases.iter().any(|base| {
|
||||||
if let ExprKind::Name { id, .. } = &base.node {
|
if let ExprKind::Name { id, .. } = &base.node {
|
||||||
|
|
|
@ -10,14 +10,13 @@ use rustpython_parser::ast::Location;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::autofix::fixer;
|
|
||||||
use crate::fs::relativize_path;
|
use crate::fs::relativize_path;
|
||||||
use crate::linter::Diagnostics;
|
use crate::linter::Diagnostics;
|
||||||
use crate::logging::LogLevel;
|
use crate::logging::LogLevel;
|
||||||
use crate::message::Message;
|
use crate::message::Message;
|
||||||
use crate::notify_user;
|
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::settings::types::SerializationFormat;
|
use crate::settings::types::SerializationFormat;
|
||||||
|
use crate::{fix, notify_user};
|
||||||
|
|
||||||
/// Enum to control whether lint violations are shown to the user.
|
/// Enum to control whether lint violations are shown to the user.
|
||||||
pub enum Violations {
|
pub enum Violations {
|
||||||
|
@ -46,7 +45,7 @@ struct ExpandedMessage<'a> {
|
||||||
pub struct Printer<'a> {
|
pub struct Printer<'a> {
|
||||||
format: &'a SerializationFormat,
|
format: &'a SerializationFormat,
|
||||||
log_level: &'a LogLevel,
|
log_level: &'a LogLevel,
|
||||||
autofix: &'a fixer::Mode,
|
autofix: &'a fix::FixMode,
|
||||||
violations: &'a Violations,
|
violations: &'a Violations,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +53,7 @@ impl<'a> Printer<'a> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
format: &'a SerializationFormat,
|
format: &'a SerializationFormat,
|
||||||
log_level: &'a LogLevel,
|
log_level: &'a LogLevel,
|
||||||
autofix: &'a fixer::Mode,
|
autofix: &'a fix::FixMode,
|
||||||
violations: &'a Violations,
|
violations: &'a Violations,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -84,7 +83,7 @@ impl<'a> Printer<'a> {
|
||||||
println!("Found {remaining} error(s).");
|
println!("Found {remaining} error(s).");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !matches!(self.autofix, fixer::Mode::Apply) {
|
if !matches!(self.autofix, fix::FixMode::Apply) {
|
||||||
let num_fixable = diagnostics
|
let num_fixable = diagnostics
|
||||||
.messages
|
.messages
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -98,9 +97,9 @@ impl<'a> Printer<'a> {
|
||||||
Violations::Hide => {
|
Violations::Hide => {
|
||||||
let fixed = diagnostics.fixed;
|
let fixed = diagnostics.fixed;
|
||||||
if fixed > 0 {
|
if fixed > 0 {
|
||||||
if matches!(self.autofix, fixer::Mode::Apply) {
|
if matches!(self.autofix, fix::FixMode::Apply) {
|
||||||
println!("Fixed {fixed} error(s).");
|
println!("Fixed {fixed} error(s).");
|
||||||
} else if matches!(self.autofix, fixer::Mode::Diff) {
|
} else if matches!(self.autofix, fix::FixMode::Diff) {
|
||||||
println!("Would fix {fixed} error(s).");
|
println!("Would fix {fixed} error(s).");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -11,13 +11,11 @@ use crate::ast::helpers::{
|
||||||
};
|
};
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::ast::whitespace::leading_space;
|
use crate::ast::whitespace::leading_space;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
use crate::source_code_generator::SourceCodeGenerator;
|
use crate::source_code::{Generator, Locator, Stylist};
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
static URL_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^https?://\S+$").unwrap());
|
static URL_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"^https?://\S+$").unwrap());
|
||||||
|
@ -106,12 +104,7 @@ pub fn doc_line_too_long(lineno: usize, line: &str, settings: &Settings) -> Opti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compare(
|
fn compare(left: &Expr, ops: &[Cmpop], comparators: &[Expr], stylist: &Stylist) -> String {
|
||||||
left: &Expr,
|
|
||||||
ops: &[Cmpop],
|
|
||||||
comparators: &[Expr],
|
|
||||||
stylist: &SourceCodeStyleDetector,
|
|
||||||
) -> String {
|
|
||||||
unparse_expr(
|
unparse_expr(
|
||||||
&create_expr(ExprKind::Compare {
|
&create_expr(ExprKind::Compare {
|
||||||
left: Box::new(left.clone()),
|
left: Box::new(left.clone()),
|
||||||
|
@ -413,7 +406,7 @@ pub fn do_not_use_bare_except(
|
||||||
type_: Option<&Expr>,
|
type_: Option<&Expr>,
|
||||||
body: &[Stmt],
|
body: &[Stmt],
|
||||||
handler: &Excepthandler,
|
handler: &Excepthandler,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
if type_.is_none()
|
if type_.is_none()
|
||||||
&& !body
|
&& !body
|
||||||
|
@ -429,12 +422,7 @@ pub fn do_not_use_bare_except(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn function(
|
fn function(name: &str, args: &Arguments, body: &Expr, stylist: &Stylist) -> String {
|
||||||
name: &str,
|
|
||||||
args: &Arguments,
|
|
||||||
body: &Expr,
|
|
||||||
stylist: &SourceCodeStyleDetector,
|
|
||||||
) -> String {
|
|
||||||
let body = Stmt::new(
|
let body = Stmt::new(
|
||||||
Location::default(),
|
Location::default(),
|
||||||
Location::default(),
|
Location::default(),
|
||||||
|
@ -454,7 +442,7 @@ fn function(
|
||||||
type_comment: None,
|
type_comment: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let mut generator: SourceCodeGenerator = stylist.into();
|
let mut generator: Generator = stylist.into();
|
||||||
generator.unparse_stmt(&func);
|
generator.unparse_stmt(&func);
|
||||||
generator.generate()
|
generator.generate()
|
||||||
}
|
}
|
||||||
|
@ -585,7 +573,7 @@ fn extract_quote(text: &str) -> &str {
|
||||||
|
|
||||||
/// W605
|
/// W605
|
||||||
pub fn invalid_escape_sequence(
|
pub fn invalid_escape_sequence(
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
start: Location,
|
start: Location,
|
||||||
end: Location,
|
end: Location,
|
||||||
autofix: bool,
|
autofix: bool,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod helpers;
|
pub(crate) mod helpers;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -8,12 +8,12 @@ use crate::ast::helpers::identifier_range;
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::ast::whitespace::LinesWithTrailingNewline;
|
use crate::ast::whitespace::LinesWithTrailingNewline;
|
||||||
use crate::ast::{cast, whitespace};
|
use crate::ast::{cast, whitespace};
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::docstrings::constants;
|
use crate::docstrings::constants;
|
||||||
use crate::docstrings::definition::{Definition, DefinitionKind, Docstring};
|
use crate::docstrings::definition::{Definition, DefinitionKind, Docstring};
|
||||||
use crate::docstrings::sections::{section_contexts, SectionContext};
|
use crate::docstrings::sections::{section_contexts, SectionContext};
|
||||||
use crate::docstrings::styles::SectionStyle;
|
use crate::docstrings::styles::SectionStyle;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::pydocstyle::helpers::{leading_quote, logical_line};
|
use crate::pydocstyle::helpers::{leading_quote, logical_line};
|
||||||
use crate::pydocstyle::settings::Convention;
|
use crate::pydocstyle::settings::Convention;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
|
|
|
@ -5,16 +5,16 @@ use rustpython_parser::lexer;
|
||||||
use rustpython_parser::lexer::Tok;
|
use rustpython_parser::lexer::Tok;
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::cst::matchers::{match_expr, match_module};
|
use crate::cst::matchers::{match_expr, match_module};
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::python::string::strip_quotes_and_prefixes;
|
use crate::python::string::strip_quotes_and_prefixes;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
/// Generate a `Fix` to remove unused keys from format dict.
|
/// Generate a `Fix` to remove unused keys from format dict.
|
||||||
pub fn remove_unused_format_arguments_from_dict(
|
pub fn remove_unused_format_arguments_from_dict(
|
||||||
unused_arguments: &[&str],
|
unused_arguments: &[&str],
|
||||||
stmt: &Expr,
|
stmt: &Expr,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
let module_text = locator.slice_source_code_range(&Range::from_located(stmt));
|
let module_text = locator.slice_source_code_range(&Range::from_located(stmt));
|
||||||
let mut tree = match_module(&module_text)?;
|
let mut tree = match_module(&module_text)?;
|
||||||
|
@ -60,7 +60,7 @@ pub fn remove_unused_format_arguments_from_dict(
|
||||||
pub fn remove_unused_keyword_arguments_from_format_call(
|
pub fn remove_unused_keyword_arguments_from_format_call(
|
||||||
unused_arguments: &[&str],
|
unused_arguments: &[&str],
|
||||||
location: Range,
|
location: Range,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
let module_text = locator.slice_source_code_range(&location);
|
let module_text = locator.slice_source_code_range(&location);
|
||||||
let mut tree = match_module(&module_text)?;
|
let mut tree = match_module(&module_text)?;
|
||||||
|
@ -103,7 +103,7 @@ pub fn remove_unused_keyword_arguments_from_format_call(
|
||||||
/// Generate a `Fix` to remove the binding from an exception handler.
|
/// Generate a `Fix` to remove the binding from an exception handler.
|
||||||
pub fn remove_exception_handler_assignment(
|
pub fn remove_exception_handler_assignment(
|
||||||
excepthandler: &Excepthandler,
|
excepthandler: &Excepthandler,
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Result<Fix> {
|
) -> Result<Fix> {
|
||||||
let contents = locator.slice_source_code_range(&Range::from_located(excepthandler));
|
let contents = locator.slice_source_code_range(&Range::from_located(excepthandler));
|
||||||
let mut fix_start = None;
|
let mut fix_start = None;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
pub mod cformat;
|
pub(crate) mod cformat;
|
||||||
pub mod fixes;
|
pub(crate) mod fixes;
|
||||||
pub mod format;
|
pub(crate) mod format;
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -17,8 +17,7 @@ mod tests {
|
||||||
use crate::linter::{check_path, test_path};
|
use crate::linter::{check_path, test_path};
|
||||||
use crate::registry::{RuleCode, RuleCodePrefix};
|
use crate::registry::{RuleCode, RuleCodePrefix};
|
||||||
use crate::settings::flags;
|
use crate::settings::flags;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::{Locator, Stylist};
|
||||||
use crate::source_code_style::SourceCodeStyleDetector;
|
|
||||||
use crate::{directives, rustpython_helpers, settings};
|
use crate::{directives, rustpython_helpers, settings};
|
||||||
|
|
||||||
#[test_case(RuleCode::F401, Path::new("F401_0.py"); "F401_0")]
|
#[test_case(RuleCode::F401, Path::new("F401_0.py"); "F401_0")]
|
||||||
|
@ -212,8 +211,8 @@ mod tests {
|
||||||
let contents = dedent(contents);
|
let contents = dedent(contents);
|
||||||
let settings = settings::Settings::for_rules(RuleCodePrefix::F.codes());
|
let settings = settings::Settings::for_rules(RuleCodePrefix::F.codes());
|
||||||
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
||||||
let locator = SourceCodeLocator::new(&contents);
|
let locator = Locator::new(&contents);
|
||||||
let stylist = SourceCodeStyleDetector::from_contents(&contents, &locator);
|
let stylist = Stylist::from_contents(&contents, &locator);
|
||||||
let directives =
|
let directives =
|
||||||
directives::extract_directives(&tokens, directives::Flags::from_settings(&settings));
|
directives::extract_directives(&tokens, directives::Flags::from_settings(&settings));
|
||||||
let mut diagnostics = check_path(
|
let mut diagnostics = check_path(
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use rustpython_ast::{Expr, ExprKind};
|
use rustpython_ast::{Expr, ExprKind};
|
||||||
|
|
||||||
use crate::ast::helpers::find_useless_f_strings;
|
use crate::ast::helpers::find_useless_f_strings;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ use rustpython_ast::{Cmpop, Expr};
|
||||||
use crate::ast::helpers;
|
use crate::ast::helpers;
|
||||||
use crate::ast::operations::locate_cmpops;
|
use crate::ast::operations::locate_cmpops;
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, Expr, ExprKind, S
|
||||||
use crate::ast::helpers::except_range;
|
use crate::ast::helpers::except_range;
|
||||||
use crate::ast::types::{Binding, Range, Scope, ScopeKind};
|
use crate::ast::types::{Binding, Range, Scope, ScopeKind};
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::source_code_locator::SourceCodeLocator;
|
use crate::source_code::Locator;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
/// F821
|
/// F821
|
||||||
|
@ -62,7 +62,7 @@ pub fn undefined_local(name: &str, scopes: &[&Scope], bindings: &[Binding]) -> O
|
||||||
/// F707
|
/// F707
|
||||||
pub fn default_except_not_last(
|
pub fn default_except_not_last(
|
||||||
handlers: &[Excepthandler],
|
handlers: &[Excepthandler],
|
||||||
locator: &SourceCodeLocator,
|
locator: &Locator,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
for (idx, handler) in handlers.iter().enumerate() {
|
for (idx, handler) in handlers.iter().enumerate() {
|
||||||
let ExcepthandlerKind::ExceptHandler { type_, .. } = &handler.node;
|
let ExcepthandlerKind::ExceptHandler { type_, .. } = &handler.node;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use rustpython_ast::{Expr, ExprKind};
|
use rustpython_ast::{Expr, ExprKind};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ use rustpython_ast::{Expr, ExprKind};
|
||||||
use crate::ast::comparable::{ComparableConstant, ComparableExpr};
|
use crate::ast::comparable::{ComparableConstant, ComparableExpr};
|
||||||
use crate::ast::helpers::unparse_expr;
|
use crate::ast::helpers::unparse_expr;
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ use rustpython_ast::{Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use crate::ast::types::{BindingKind, Range, RefEquality, ScopeKind};
|
use crate::ast::types::{BindingKind, Range, RefEquality, ScopeKind};
|
||||||
use crate::autofix::helpers::delete_stmt;
|
use crate::autofix::helpers::delete_stmt;
|
||||||
use crate::autofix::Fix;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::fix::Fix;
|
||||||
use crate::registry::{Diagnostic, RuleCode};
|
use crate::registry::{Diagnostic, RuleCode};
|
||||||
use crate::violations;
|
use crate::violations;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod rules;
|
pub(crate) mod rules;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -9,7 +9,7 @@ mod tests {
|
||||||
|
|
||||||
use crate::linter::test_path;
|
use crate::linter::test_path;
|
||||||
use crate::registry::RuleCode;
|
use crate::registry::RuleCode;
|
||||||
use crate::Settings;
|
use crate::settings::Settings;
|
||||||
|
|
||||||
#[test_case(RuleCode::PLC0414, Path::new("import_aliasing.py"); "PLC0414")]
|
#[test_case(RuleCode::PLC0414, Path::new("import_aliasing.py"); "PLC0414")]
|
||||||
#[test_case(RuleCode::PLC2201, Path::new("misplaced_comparison_constant.py"); "PLC2201")]
|
#[test_case(RuleCode::PLC2201, Path::new("misplaced_comparison_constant.py"); "PLC2201")]
|
||||||
|
|
|
@ -2,7 +2,8 @@ use rustpython_ast::Expr;
|
||||||
|
|
||||||
use crate::ast::types::{FunctionDef, Range, ScopeKind};
|
use crate::ast::types::{FunctionDef, Range, ScopeKind};
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::{violations, Diagnostic};
|
use crate::registry::Diagnostic;
|
||||||
|
use crate::violations;
|
||||||
|
|
||||||
/// PLE1142
|
/// PLE1142
|
||||||
pub fn await_outside_async(checker: &mut Checker, expr: &Expr) {
|
pub fn await_outside_async(checker: &mut Checker, expr: &Expr) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue