mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:10:09 +00:00
Use lazy initialization for SourceCodeLocator (#472)
This commit is contained in:
parent
2679db1d10
commit
4beea0484a
19 changed files with 112 additions and 94 deletions
|
@ -122,56 +122,50 @@ pub fn is_unpacking_assignment(stmt: &Stmt) -> bool {
|
||||||
pub struct SourceCodeLocator<'a> {
|
pub struct SourceCodeLocator<'a> {
|
||||||
content: &'a str,
|
content: &'a str,
|
||||||
offsets: Vec<Vec<usize>>,
|
offsets: Vec<Vec<usize>>,
|
||||||
initialized: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SourceCodeLocator<'a> {
|
impl<'a> SourceCodeLocator<'a> {
|
||||||
pub fn new(content: &'a str) -> Self {
|
pub fn new(content: &'a str) -> Self {
|
||||||
SourceCodeLocator {
|
SourceCodeLocator {
|
||||||
content,
|
content,
|
||||||
offsets: vec![],
|
offsets: Self::compute_offsets(content),
|
||||||
initialized: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&mut self) {
|
fn compute_offsets(content: &str) -> Vec<Vec<usize>> {
|
||||||
if !self.initialized {
|
let mut offsets = vec![];
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for line in self.content.lines() {
|
for line in content.lines() {
|
||||||
let mut newline = 0;
|
let mut newline = 0;
|
||||||
let mut line_offsets: Vec<usize> = vec![];
|
let mut line_offsets: Vec<usize> = vec![];
|
||||||
for (i, char) in line.char_indices() {
|
for (i, char) in line.char_indices() {
|
||||||
line_offsets.push(offset + i);
|
line_offsets.push(offset + i);
|
||||||
newline = i + char.len_utf8();
|
newline = i + char.len_utf8();
|
||||||
}
|
|
||||||
line_offsets.push(offset + newline);
|
|
||||||
self.offsets.push(line_offsets);
|
|
||||||
offset += newline + 1;
|
|
||||||
}
|
}
|
||||||
self.offsets.push(vec![offset]);
|
line_offsets.push(offset + newline);
|
||||||
self.initialized = true;
|
offsets.push(line_offsets);
|
||||||
|
offset += newline + 1;
|
||||||
}
|
}
|
||||||
|
offsets.push(vec![offset]);
|
||||||
|
offsets
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slice_source_code_at(&mut self, location: &Location) -> &'a str {
|
pub fn slice_source_code_at(&self, location: &Location) -> &'a str {
|
||||||
self.init();
|
|
||||||
let offset = self.offsets[location.row() - 1][location.column() - 1];
|
let offset = self.offsets[location.row() - 1][location.column() - 1];
|
||||||
&self.content[offset..]
|
&self.content[offset..]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slice_source_code_range(&mut self, range: &Range) -> &'a str {
|
pub fn slice_source_code_range(&self, range: &Range) -> &'a str {
|
||||||
self.init();
|
|
||||||
let start = self.offsets[range.location.row() - 1][range.location.column() - 1];
|
let start = self.offsets[range.location.row() - 1][range.location.column() - 1];
|
||||||
let end = self.offsets[range.end_location.row() - 1][range.end_location.column() - 1];
|
let end = self.offsets[range.end_location.row() - 1][range.end_location.column() - 1];
|
||||||
&self.content[start..end]
|
&self.content[start..end]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn partition_source_code_at(
|
pub fn partition_source_code_at(
|
||||||
&mut self,
|
&self,
|
||||||
outer: &Range,
|
outer: &Range,
|
||||||
inner: &Range,
|
inner: &Range,
|
||||||
) -> (&'a str, &'a str, &'a str) {
|
) -> (&'a str, &'a str, &'a str) {
|
||||||
self.init();
|
|
||||||
let outer_start = self.offsets[outer.location.row() - 1][outer.location.column() - 1];
|
let outer_start = self.offsets[outer.location.row() - 1][outer.location.column() - 1];
|
||||||
let outer_end = self.offsets[outer.end_location.row() - 1][outer.end_location.column() - 1];
|
let outer_end = self.offsets[outer.end_location.row() - 1][outer.end_location.column() - 1];
|
||||||
let inner_start = self.offsets[inner.location.row() - 1][inner.location.column() - 1];
|
let inner_start = self.offsets[inner.location.row() - 1][inner.location.column() - 1];
|
||||||
|
@ -191,8 +185,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn source_code_locator_init() {
|
fn source_code_locator_init() {
|
||||||
let content = "# \u{4e9c}\nclass Foo:\n \"\"\".\"\"\"";
|
let content = "# \u{4e9c}\nclass Foo:\n \"\"\".\"\"\"";
|
||||||
let mut locator = SourceCodeLocator::new(content);
|
let locator = SourceCodeLocator::new(content);
|
||||||
locator.init();
|
|
||||||
assert_eq!(locator.offsets.len(), 4);
|
assert_eq!(locator.offsets.len(), 4);
|
||||||
assert_eq!(locator.offsets[0], [0, 1, 2, 5]);
|
assert_eq!(locator.offsets[0], [0, 1, 2, 5]);
|
||||||
assert_eq!(locator.offsets[1], [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
|
assert_eq!(locator.offsets[1], [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub enum Mode {
|
||||||
|
|
||||||
impl Mode {
|
impl Mode {
|
||||||
/// Return `true` if a patch should be generated under the given `Mode`.
|
/// Return `true` if a patch should be generated under the given `Mode`.
|
||||||
pub fn enabled(&self) -> bool {
|
pub fn patch(&self) -> bool {
|
||||||
match &self {
|
match &self {
|
||||||
Mode::Generate => true,
|
Mode::Generate => true,
|
||||||
Mode::Apply => true,
|
Mode::Apply => true,
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::ops::Deref;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use log::error;
|
use log::error;
|
||||||
|
use once_cell::unsync::OnceCell;
|
||||||
use rustpython_parser::ast::{
|
use rustpython_parser::ast::{
|
||||||
Arg, Arguments, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind,
|
Arg, Arguments, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind,
|
||||||
KeywordData, Operator, Stmt, StmtKind, Suite,
|
KeywordData, Operator, Stmt, StmtKind, Suite,
|
||||||
|
@ -34,12 +35,14 @@ pub const GLOBAL_SCOPE_INDEX: usize = 0;
|
||||||
|
|
||||||
pub struct Checker<'a> {
|
pub struct Checker<'a> {
|
||||||
// Input data.
|
// Input data.
|
||||||
pub(crate) path: &'a Path,
|
path: &'a Path,
|
||||||
pub(crate) locator: SourceCodeLocator<'a>,
|
content: &'a str,
|
||||||
|
autofix: &'a fixer::Mode,
|
||||||
pub(crate) settings: &'a Settings,
|
pub(crate) settings: &'a Settings,
|
||||||
pub(crate) autofix: &'a fixer::Mode,
|
|
||||||
// Computed checks.
|
// Computed checks.
|
||||||
checks: Vec<Check>,
|
checks: Vec<Check>,
|
||||||
|
// Efficient source-code slicing.
|
||||||
|
locator: OnceCell<SourceCodeLocator<'a>>,
|
||||||
// Docstring tracking.
|
// Docstring tracking.
|
||||||
docstrings: Vec<(Definition<'a>, Visibility)>,
|
docstrings: Vec<(Definition<'a>, Visibility)>,
|
||||||
// Edit tracking.
|
// Edit tracking.
|
||||||
|
@ -79,7 +82,8 @@ impl<'a> Checker<'a> {
|
||||||
settings,
|
settings,
|
||||||
autofix,
|
autofix,
|
||||||
path,
|
path,
|
||||||
locator: SourceCodeLocator::new(content),
|
content,
|
||||||
|
locator: OnceCell::new(),
|
||||||
checks: Default::default(),
|
checks: Default::default(),
|
||||||
docstrings: Default::default(),
|
docstrings: Default::default(),
|
||||||
deletions: Default::default(),
|
deletions: Default::default(),
|
||||||
|
@ -106,6 +110,17 @@ impl<'a> Checker<'a> {
|
||||||
except_handlers: Default::default(),
|
except_handlers: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get access to a lazily-initialized `SourceCodeLocator` for the file contents.
|
||||||
|
pub fn get_locator(&self) -> &SourceCodeLocator {
|
||||||
|
self.locator
|
||||||
|
.get_or_init(|| SourceCodeLocator::new(self.content))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `true` if a patch should be generated under the given autofix `Mode`.
|
||||||
|
pub fn patch(&self) -> bool {
|
||||||
|
self.autofix.patch()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Visitor<'b> for Checker<'a>
|
impl<'a, 'b> Visitor<'b> for Checker<'a>
|
||||||
|
@ -2070,7 +2085,7 @@ impl<'a> Checker<'a> {
|
||||||
let child = self.parents[defined_by];
|
let child = self.parents[defined_by];
|
||||||
let parent = defined_in.map(|defined_in| self.parents[defined_in]);
|
let parent = defined_in.map(|defined_in| self.parents[defined_in]);
|
||||||
|
|
||||||
let fix = if self.autofix.enabled() {
|
let fix = if self.patch() {
|
||||||
let deleted: Vec<&Stmt> = self
|
let deleted: Vec<&Stmt> = self
|
||||||
.deletions
|
.deletions
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -2082,7 +2097,7 @@ impl<'a> Checker<'a> {
|
||||||
ImportKind::ImportFrom => pyflakes::fixes::remove_unused_import_froms,
|
ImportKind::ImportFrom => pyflakes::fixes::remove_unused_import_froms,
|
||||||
};
|
};
|
||||||
|
|
||||||
match removal_fn(&mut self.locator, &full_names, child, parent, &deleted) {
|
match removal_fn(self.get_locator(), &full_names, child, parent, &deleted) {
|
||||||
Ok(fix) => Some(fix),
|
Ok(fix) => Some(fix),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Failed to fix unused imports: {}", e);
|
error!("Failed to fix unused imports: {}", e);
|
||||||
|
|
|
@ -166,7 +166,7 @@ pub fn check_lines(
|
||||||
end_location: Location::new(row + 1, end + 1),
|
end_location: Location::new(row + 1, end + 1),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if autofix.enabled() {
|
if autofix.patch() {
|
||||||
check.amend(Fix::deletion(
|
check.amend(Fix::deletion(
|
||||||
Location::new(row + 1, start + 1),
|
Location::new(row + 1, start + 1),
|
||||||
Location::new(row + 1, lines[row].chars().count() + 1),
|
Location::new(row + 1, lines[row].chars().count() + 1),
|
||||||
|
@ -194,7 +194,7 @@ pub fn check_lines(
|
||||||
end_location: Location::new(row + 1, end + 1),
|
end_location: Location::new(row + 1, end + 1),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if autofix.enabled() {
|
if autofix.patch() {
|
||||||
if valid_codes.is_empty() {
|
if valid_codes.is_empty() {
|
||||||
check.amend(Fix::deletion(
|
check.amend(Fix::deletion(
|
||||||
Location::new(row + 1, start + 1),
|
Location::new(row + 1, start + 1),
|
||||||
|
|
|
@ -25,9 +25,9 @@ pub fn leading_space(line: &str) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract the leading indentation from a docstring.
|
/// Extract the leading indentation from a docstring.
|
||||||
pub fn indentation<'a>(checker: &'a mut Checker, docstring: &Expr) -> &'a str {
|
pub fn indentation<'a>(checker: &'a Checker, docstring: &Expr) -> &'a str {
|
||||||
let range = Range::from_located(docstring);
|
let range = Range::from_located(docstring);
|
||||||
checker.locator.slice_source_code_range(&Range {
|
checker.get_locator().slice_source_code_range(&Range {
|
||||||
location: Location::new(range.location.row(), 1),
|
location: Location::new(range.location.row(), 1),
|
||||||
end_location: Location::new(range.location.row(), range.location.column()),
|
end_location: Location::new(range.location.row(), range.location.column()),
|
||||||
})
|
})
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: &Optio
|
||||||
} = &test.node
|
} = &test.node
|
||||||
{
|
{
|
||||||
let mut check = Check::new(CheckKind::DoNotAssertFalse, Range::from_located(test));
|
let mut check = Check::new(CheckKind::DoNotAssertFalse, Range::from_located(test));
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
let mut generator = SourceGenerator::new();
|
let mut generator = SourceGenerator::new();
|
||||||
if let Ok(()) = generator.unparse_stmt(&assertion_error(msg)) {
|
if let Ok(()) = generator.unparse_stmt(&assertion_error(msg)) {
|
||||||
if let Ok(content) = generator.generate() {
|
if let Ok(content) = generator.generate() {
|
||||||
|
|
|
@ -49,7 +49,7 @@ pub fn duplicate_handler_exceptions(
|
||||||
),
|
),
|
||||||
checker.locate_check(Range::from_located(expr)),
|
checker.locate_check(Range::from_located(expr)),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// TODO(charlie): If we have a single element, remove the tuple.
|
// TODO(charlie): If we have a single element, remove the tuple.
|
||||||
let mut generator = SourceGenerator::new();
|
let mut generator = SourceGenerator::new();
|
||||||
if let Ok(()) = generator.unparse_expr(&type_pattern(unique_elts), 0) {
|
if let Ok(()) = generator.unparse_expr(&type_pattern(unique_elts), 0) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub fn print_call(checker: &mut Checker, expr: &Expr, func: &Expr) {
|
||||||
checker.settings.enabled.contains(&CheckCode::T201),
|
checker.settings.enabled.contains(&CheckCode::T201),
|
||||||
checker.settings.enabled.contains(&CheckCode::T203),
|
checker.settings.enabled.contains(&CheckCode::T203),
|
||||||
) {
|
) {
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
let context = checker.binding_context();
|
let context = checker.binding_context();
|
||||||
if matches!(
|
if matches!(
|
||||||
checker.parents[context.defined_by].node,
|
checker.parents[context.defined_by].node,
|
||||||
|
|
|
@ -161,12 +161,12 @@ pub fn blank_before_after_function(checker: &mut Checker, definition: &Definitio
|
||||||
..
|
..
|
||||||
} = &docstring.node
|
} = &docstring.node
|
||||||
{
|
{
|
||||||
let (before, _, after) = checker.locator.partition_source_code_at(
|
|
||||||
&Range::from_located(parent),
|
|
||||||
&Range::from_located(docstring),
|
|
||||||
);
|
|
||||||
|
|
||||||
if checker.settings.enabled.contains(&CheckCode::D201) {
|
if checker.settings.enabled.contains(&CheckCode::D201) {
|
||||||
|
let (before, _, _) = checker.get_locator().partition_source_code_at(
|
||||||
|
&Range::from_located(parent),
|
||||||
|
&Range::from_located(docstring),
|
||||||
|
);
|
||||||
|
|
||||||
let blank_lines_before = before
|
let blank_lines_before = before
|
||||||
.lines()
|
.lines()
|
||||||
.rev()
|
.rev()
|
||||||
|
@ -178,7 +178,7 @@ pub fn blank_before_after_function(checker: &mut Checker, definition: &Definitio
|
||||||
CheckKind::NoBlankLineBeforeFunction(blank_lines_before),
|
CheckKind::NoBlankLineBeforeFunction(blank_lines_before),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Delete the blank line before the docstring.
|
// Delete the blank line before the docstring.
|
||||||
check.amend(Fix::deletion(
|
check.amend(Fix::deletion(
|
||||||
Location::new(docstring.location.row() - blank_lines_before, 1),
|
Location::new(docstring.location.row() - blank_lines_before, 1),
|
||||||
|
@ -190,6 +190,11 @@ pub fn blank_before_after_function(checker: &mut Checker, definition: &Definitio
|
||||||
}
|
}
|
||||||
|
|
||||||
if checker.settings.enabled.contains(&CheckCode::D202) {
|
if checker.settings.enabled.contains(&CheckCode::D202) {
|
||||||
|
let (_, _, after) = checker.get_locator().partition_source_code_at(
|
||||||
|
&Range::from_located(parent),
|
||||||
|
&Range::from_located(docstring),
|
||||||
|
);
|
||||||
|
|
||||||
let all_blank_after = after
|
let all_blank_after = after
|
||||||
.lines()
|
.lines()
|
||||||
.skip(1)
|
.skip(1)
|
||||||
|
@ -216,7 +221,7 @@ pub fn blank_before_after_function(checker: &mut Checker, definition: &Definitio
|
||||||
CheckKind::NoBlankLineAfterFunction(blank_lines_after),
|
CheckKind::NoBlankLineAfterFunction(blank_lines_after),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Delete the blank line after the docstring.
|
// Delete the blank line after the docstring.
|
||||||
check.amend(Fix::deletion(
|
check.amend(Fix::deletion(
|
||||||
Location::new(
|
Location::new(
|
||||||
|
@ -245,14 +250,14 @@ pub fn blank_before_after_class(checker: &mut Checker, definition: &Definition)
|
||||||
..
|
..
|
||||||
} = &docstring.node
|
} = &docstring.node
|
||||||
{
|
{
|
||||||
let (before, _, after) = checker.locator.partition_source_code_at(
|
|
||||||
&Range::from_located(parent),
|
|
||||||
&Range::from_located(docstring),
|
|
||||||
);
|
|
||||||
|
|
||||||
if checker.settings.enabled.contains(&CheckCode::D203)
|
if checker.settings.enabled.contains(&CheckCode::D203)
|
||||||
|| checker.settings.enabled.contains(&CheckCode::D211)
|
|| checker.settings.enabled.contains(&CheckCode::D211)
|
||||||
{
|
{
|
||||||
|
let (before, _, _) = checker.get_locator().partition_source_code_at(
|
||||||
|
&Range::from_located(parent),
|
||||||
|
&Range::from_located(docstring),
|
||||||
|
);
|
||||||
|
|
||||||
let blank_lines_before = before
|
let blank_lines_before = before
|
||||||
.lines()
|
.lines()
|
||||||
.rev()
|
.rev()
|
||||||
|
@ -265,7 +270,7 @@ pub fn blank_before_after_class(checker: &mut Checker, definition: &Definition)
|
||||||
CheckKind::NoBlankLineBeforeClass(blank_lines_before),
|
CheckKind::NoBlankLineBeforeClass(blank_lines_before),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Delete the blank line before the class.
|
// Delete the blank line before the class.
|
||||||
check.amend(Fix::deletion(
|
check.amend(Fix::deletion(
|
||||||
Location::new(docstring.location.row() - blank_lines_before, 1),
|
Location::new(docstring.location.row() - blank_lines_before, 1),
|
||||||
|
@ -281,7 +286,7 @@ pub fn blank_before_after_class(checker: &mut Checker, definition: &Definition)
|
||||||
CheckKind::OneBlankLineBeforeClass(blank_lines_before),
|
CheckKind::OneBlankLineBeforeClass(blank_lines_before),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Insert one blank line before the class.
|
// Insert one blank line before the class.
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
"\n".to_string(),
|
"\n".to_string(),
|
||||||
|
@ -295,6 +300,11 @@ pub fn blank_before_after_class(checker: &mut Checker, definition: &Definition)
|
||||||
}
|
}
|
||||||
|
|
||||||
if checker.settings.enabled.contains(&CheckCode::D204) {
|
if checker.settings.enabled.contains(&CheckCode::D204) {
|
||||||
|
let (_, _, after) = checker.get_locator().partition_source_code_at(
|
||||||
|
&Range::from_located(parent),
|
||||||
|
&Range::from_located(docstring),
|
||||||
|
);
|
||||||
|
|
||||||
let all_blank_after = after
|
let all_blank_after = after
|
||||||
.lines()
|
.lines()
|
||||||
.skip(1)
|
.skip(1)
|
||||||
|
@ -313,7 +323,7 @@ pub fn blank_before_after_class(checker: &mut Checker, definition: &Definition)
|
||||||
CheckKind::OneBlankLineAfterClass(blank_lines_after),
|
CheckKind::OneBlankLineAfterClass(blank_lines_after),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Insert a blank line before the class (replacing any existing lines).
|
// Insert a blank line before the class (replacing any existing lines).
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
"\n".to_string(),
|
"\n".to_string(),
|
||||||
|
@ -355,7 +365,7 @@ pub fn blank_after_summary(checker: &mut Checker, definition: &Definition) {
|
||||||
CheckKind::BlankLineAfterSummary,
|
CheckKind::BlankLineAfterSummary,
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Insert one blank line after the summary (replacing any existing lines).
|
// Insert one blank line after the summary (replacing any existing lines).
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
"\n".to_string(),
|
"\n".to_string(),
|
||||||
|
@ -414,7 +424,7 @@ pub fn indent(checker: &mut Checker, definition: &Definition) {
|
||||||
end_location: Location::new(docstring.location.row() + i, 1),
|
end_location: Location::new(docstring.location.row() + i, 1),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
helpers::clean(&docstring_indent),
|
helpers::clean(&docstring_indent),
|
||||||
Location::new(docstring.location.row() + i, 1),
|
Location::new(docstring.location.row() + i, 1),
|
||||||
|
@ -463,7 +473,7 @@ pub fn indent(checker: &mut Checker, definition: &Definition) {
|
||||||
end_location: Location::new(docstring.location.row() + i, 1),
|
end_location: Location::new(docstring.location.row() + i, 1),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
helpers::clean(&docstring_indent),
|
helpers::clean(&docstring_indent),
|
||||||
Location::new(docstring.location.row() + i, 1),
|
Location::new(docstring.location.row() + i, 1),
|
||||||
|
@ -490,7 +500,7 @@ pub fn indent(checker: &mut Checker, definition: &Definition) {
|
||||||
end_location: Location::new(docstring.location.row() + i, 1),
|
end_location: Location::new(docstring.location.row() + i, 1),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
helpers::clean(&docstring_indent),
|
helpers::clean(&docstring_indent),
|
||||||
Location::new(docstring.location.row() + i, 1),
|
Location::new(docstring.location.row() + i, 1),
|
||||||
|
@ -520,7 +530,7 @@ pub fn newline_after_last_paragraph(checker: &mut Checker, definition: &Definiti
|
||||||
}
|
}
|
||||||
if line_count > 1 {
|
if line_count > 1 {
|
||||||
let content = checker
|
let content = checker
|
||||||
.locator
|
.get_locator()
|
||||||
.slice_source_code_range(&Range::from_located(docstring));
|
.slice_source_code_range(&Range::from_located(docstring));
|
||||||
if let Some(last_line) = content.lines().last().map(|line| line.trim()) {
|
if let Some(last_line) = content.lines().last().map(|line| line.trim()) {
|
||||||
if last_line != "\"\"\"" && last_line != "'''" {
|
if last_line != "\"\"\"" && last_line != "'''" {
|
||||||
|
@ -528,7 +538,7 @@ pub fn newline_after_last_paragraph(checker: &mut Checker, definition: &Definiti
|
||||||
CheckKind::NewLineAfterLastParagraph,
|
CheckKind::NewLineAfterLastParagraph,
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Insert a newline just before the end-quote(s).
|
// Insert a newline just before the end-quote(s).
|
||||||
let content = format!(
|
let content = format!(
|
||||||
"\n{}",
|
"\n{}",
|
||||||
|
@ -571,9 +581,9 @@ pub fn no_surrounding_whitespace(checker: &mut Checker, definition: &Definition)
|
||||||
CheckKind::NoSurroundingWhitespace,
|
CheckKind::NoSurroundingWhitespace,
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
if let Some(first_line) = checker
|
if let Some(first_line) = checker
|
||||||
.locator
|
.get_locator()
|
||||||
.slice_source_code_range(&Range::from_located(docstring))
|
.slice_source_code_range(&Range::from_located(docstring))
|
||||||
.lines()
|
.lines()
|
||||||
.next()
|
.next()
|
||||||
|
@ -619,7 +629,7 @@ pub fn multi_line_summary_start(checker: &mut Checker, definition: &Definition)
|
||||||
{
|
{
|
||||||
if string.lines().nth(1).is_some() {
|
if string.lines().nth(1).is_some() {
|
||||||
if let Some(first_line) = checker
|
if let Some(first_line) = checker
|
||||||
.locator
|
.get_locator()
|
||||||
.slice_source_code_range(&Range::from_located(docstring))
|
.slice_source_code_range(&Range::from_located(docstring))
|
||||||
.lines()
|
.lines()
|
||||||
.next()
|
.next()
|
||||||
|
@ -655,7 +665,7 @@ pub fn triple_quotes(checker: &mut Checker, definition: &Definition) {
|
||||||
} = &docstring.node
|
} = &docstring.node
|
||||||
{
|
{
|
||||||
if let Some(first_line) = checker
|
if let Some(first_line) = checker
|
||||||
.locator
|
.get_locator()
|
||||||
.slice_source_code_range(&Range::from_located(docstring))
|
.slice_source_code_range(&Range::from_located(docstring))
|
||||||
.lines()
|
.lines()
|
||||||
.next()
|
.next()
|
||||||
|
@ -906,7 +916,7 @@ fn blanks_and_section_underline(
|
||||||
CheckKind::DashedUnderlineAfterSection(context.section_name.to_string()),
|
CheckKind::DashedUnderlineAfterSection(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Add a dashed line (of the appropriate length) under the section header.
|
// Add a dashed line (of the appropriate length) under the section header.
|
||||||
let content = format!(
|
let content = format!(
|
||||||
"{}{}\n",
|
"{}{}\n",
|
||||||
|
@ -940,7 +950,7 @@ fn blanks_and_section_underline(
|
||||||
CheckKind::DashedUnderlineAfterSection(context.section_name.to_string()),
|
CheckKind::DashedUnderlineAfterSection(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Add a dashed line (of the appropriate length) under the section header.
|
// Add a dashed line (of the appropriate length) under the section header.
|
||||||
let content = format!(
|
let content = format!(
|
||||||
"{}{}\n",
|
"{}{}\n",
|
||||||
|
@ -962,7 +972,7 @@ fn blanks_and_section_underline(
|
||||||
),
|
),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Delete any blank lines between the header and content.
|
// Delete any blank lines between the header and content.
|
||||||
check.amend(Fix::deletion(
|
check.amend(Fix::deletion(
|
||||||
Location::new(docstring.location.row() + context.original_index + 1, 1),
|
Location::new(docstring.location.row() + context.original_index + 1, 1),
|
||||||
|
@ -985,7 +995,7 @@ fn blanks_and_section_underline(
|
||||||
CheckKind::SectionUnderlineAfterName(context.section_name.to_string()),
|
CheckKind::SectionUnderlineAfterName(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Delete any blank lines between the header and the underline.
|
// Delete any blank lines between the header and the underline.
|
||||||
check.amend(Fix::deletion(
|
check.amend(Fix::deletion(
|
||||||
Location::new(docstring.location.row() + context.original_index + 1, 1),
|
Location::new(docstring.location.row() + context.original_index + 1, 1),
|
||||||
|
@ -1016,7 +1026,7 @@ fn blanks_and_section_underline(
|
||||||
),
|
),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Replace the existing underline with a line of the appropriate length.
|
// Replace the existing underline with a line of the appropriate length.
|
||||||
let content = format!(
|
let content = format!(
|
||||||
"{}{}\n",
|
"{}{}\n",
|
||||||
|
@ -1054,7 +1064,7 @@ fn blanks_and_section_underline(
|
||||||
CheckKind::SectionUnderlineNotOverIndented(context.section_name.to_string()),
|
CheckKind::SectionUnderlineNotOverIndented(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Replace the existing indentation with whitespace of the appropriate length.
|
// Replace the existing indentation with whitespace of the appropriate length.
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
helpers::clean(&indentation),
|
helpers::clean(&indentation),
|
||||||
|
@ -1103,7 +1113,7 @@ fn blanks_and_section_underline(
|
||||||
),
|
),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Delete any blank lines between the header and content.
|
// Delete any blank lines between the header and content.
|
||||||
check.amend(Fix::deletion(
|
check.amend(Fix::deletion(
|
||||||
Location::new(
|
Location::new(
|
||||||
|
@ -1162,7 +1172,7 @@ fn common_section(
|
||||||
CheckKind::CapitalizeSectionName(context.section_name.to_string()),
|
CheckKind::CapitalizeSectionName(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Replace the section title with the capitalized variant. This requires
|
// Replace the section title with the capitalized variant. This requires
|
||||||
// locating the start and end of the section name.
|
// locating the start and end of the section name.
|
||||||
if let Some(index) = context.line.find(&context.section_name) {
|
if let Some(index) = context.line.find(&context.section_name) {
|
||||||
|
@ -1195,7 +1205,7 @@ fn common_section(
|
||||||
CheckKind::SectionNotOverIndented(context.section_name.to_string()),
|
CheckKind::SectionNotOverIndented(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Replace the existing indentation with whitespace of the appropriate length.
|
// Replace the existing indentation with whitespace of the appropriate length.
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
helpers::clean(&indentation),
|
helpers::clean(&indentation),
|
||||||
|
@ -1222,7 +1232,7 @@ fn common_section(
|
||||||
CheckKind::BlankLineAfterLastSection(context.section_name.to_string()),
|
CheckKind::BlankLineAfterLastSection(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Add a newline after the section.
|
// Add a newline after the section.
|
||||||
check.amend(Fix::insertion(
|
check.amend(Fix::insertion(
|
||||||
"\n".to_string(),
|
"\n".to_string(),
|
||||||
|
@ -1243,7 +1253,7 @@ fn common_section(
|
||||||
CheckKind::BlankLineAfterSection(context.section_name.to_string()),
|
CheckKind::BlankLineAfterSection(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Add a newline after the section.
|
// Add a newline after the section.
|
||||||
check.amend(Fix::insertion(
|
check.amend(Fix::insertion(
|
||||||
"\n".to_string(),
|
"\n".to_string(),
|
||||||
|
@ -1267,7 +1277,7 @@ fn common_section(
|
||||||
CheckKind::BlankLineBeforeSection(context.section_name.to_string()),
|
CheckKind::BlankLineBeforeSection(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Add a blank line before the section.
|
// Add a blank line before the section.
|
||||||
check.amend(Fix::insertion(
|
check.amend(Fix::insertion(
|
||||||
"\n".to_string(),
|
"\n".to_string(),
|
||||||
|
@ -1427,7 +1437,7 @@ fn numpy_section(checker: &mut Checker, definition: &Definition, context: &Secti
|
||||||
CheckKind::NewLineAfterSectionName(context.section_name.to_string()),
|
CheckKind::NewLineAfterSectionName(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Delete the suffix. This requires locating the end of the section name.
|
// Delete the suffix. This requires locating the end of the section name.
|
||||||
if let Some(index) = context.line.find(&context.section_name) {
|
if let Some(index) = context.line.find(&context.section_name) {
|
||||||
// Map from bytes to characters.
|
// Map from bytes to characters.
|
||||||
|
@ -1476,7 +1486,7 @@ fn google_section(checker: &mut Checker, definition: &Definition, context: &Sect
|
||||||
CheckKind::SectionNameEndsInColon(context.section_name.to_string()),
|
CheckKind::SectionNameEndsInColon(context.section_name.to_string()),
|
||||||
Range::from_located(docstring),
|
Range::from_located(docstring),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
// Replace the suffix. This requires locating the end of the section name.
|
// Replace the suffix. This requires locating the end of the section name.
|
||||||
if let Some(index) = context.line.find(&context.section_name) {
|
if let Some(index) = context.line.find(&context.section_name) {
|
||||||
// Map from bytes to characters.
|
// Map from bytes to characters.
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::autofix::{helpers, Fix};
|
||||||
|
|
||||||
/// Generate a Fix to remove any unused imports from an `import` statement.
|
/// Generate a Fix to remove any unused imports from an `import` statement.
|
||||||
pub fn remove_unused_imports(
|
pub fn remove_unused_imports(
|
||||||
locator: &mut SourceCodeLocator,
|
locator: &SourceCodeLocator,
|
||||||
full_names: &[&str],
|
full_names: &[&str],
|
||||||
stmt: &Stmt,
|
stmt: &Stmt,
|
||||||
parent: Option<&Stmt>,
|
parent: Option<&Stmt>,
|
||||||
|
@ -74,7 +74,7 @@ pub fn remove_unused_imports(
|
||||||
|
|
||||||
/// Generate a Fix to remove any unused imports from an `import from` statement.
|
/// Generate a Fix to remove any unused imports from an `import from` statement.
|
||||||
pub fn remove_unused_import_froms(
|
pub fn remove_unused_import_froms(
|
||||||
locator: &mut SourceCodeLocator,
|
locator: &SourceCodeLocator,
|
||||||
full_names: &[&str],
|
full_names: &[&str],
|
||||||
stmt: &Stmt,
|
stmt: &Stmt,
|
||||||
parent: Option<&Stmt>,
|
parent: Option<&Stmt>,
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::autofix::Fix;
|
||||||
|
|
||||||
/// Generate a fix to remove a base from a ClassDef statement.
|
/// Generate a fix to remove a base from a ClassDef statement.
|
||||||
pub fn remove_class_def_base(
|
pub fn remove_class_def_base(
|
||||||
locator: &mut SourceCodeLocator,
|
locator: &SourceCodeLocator,
|
||||||
stmt_at: &Location,
|
stmt_at: &Location,
|
||||||
expr_at: Location,
|
expr_at: Location,
|
||||||
bases: &[Expr],
|
bases: &[Expr],
|
||||||
|
@ -101,7 +101,7 @@ pub fn remove_class_def_base(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_super_arguments(locator: &mut SourceCodeLocator, expr: &Expr) -> Option<Fix> {
|
pub fn remove_super_arguments(locator: &SourceCodeLocator, expr: &Expr) -> Option<Fix> {
|
||||||
let range = Range::from_located(expr);
|
let range = Range::from_located(expr);
|
||||||
let contents = locator.slice_source_code_range(&range);
|
let contents = locator.slice_source_code_range(&range);
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ pub fn deprecated_unittest_alias(checker: &mut Checker, expr: &Expr) {
|
||||||
CheckKind::DeprecatedUnittestAlias(attr.to_string(), target.to_string()),
|
CheckKind::DeprecatedUnittestAlias(attr.to_string(), target.to_string()),
|
||||||
Range::from_located(expr),
|
Range::from_located(expr),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
format!("self.{}", target),
|
format!("self.{}", target),
|
||||||
expr.location,
|
expr.location,
|
||||||
|
|
|
@ -16,9 +16,9 @@ pub fn super_call_with_parameters(checker: &mut Checker, expr: &Expr, func: &Exp
|
||||||
.map(|index| checker.parents[*index])
|
.map(|index| checker.parents[*index])
|
||||||
.collect();
|
.collect();
|
||||||
if let Some(mut check) = checks::super_args(scope, &parents, expr, func, args) {
|
if let Some(mut check) = checks::super_args(scope, &parents, expr, func, args) {
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
if let Some(fix) =
|
if let Some(fix) =
|
||||||
pyupgrade::fixes::remove_super_arguments(&mut checker.locator, expr)
|
pyupgrade::fixes::remove_super_arguments(checker.get_locator(), expr)
|
||||||
{
|
{
|
||||||
check.amend(fix);
|
check.amend(fix);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr, args:
|
||||||
if let Some(mut check) =
|
if let Some(mut check) =
|
||||||
checks::type_of_primitive(func, args, checker.locate_check(Range::from_located(expr)))
|
checks::type_of_primitive(func, args, checker.locate_check(Range::from_located(expr)))
|
||||||
{
|
{
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
if let CheckKind::TypeOfPrimitive(primitive) = &check.kind {
|
if let CheckKind::TypeOfPrimitive(primitive) = &check.kind {
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
primitive.builtin(),
|
primitive.builtin(),
|
||||||
|
|
|
@ -9,7 +9,7 @@ pub fn unnecessary_abspath(checker: &mut Checker, expr: &Expr, func: &Expr, args
|
||||||
if let Some(mut check) =
|
if let Some(mut check) =
|
||||||
checks::unnecessary_abspath(func, args, checker.locate_check(Range::from_located(expr)))
|
checks::unnecessary_abspath(func, args, checker.locate_check(Range::from_located(expr)))
|
||||||
{
|
{
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
"__file__".to_string(),
|
"__file__".to_string(),
|
||||||
expr.location,
|
expr.location,
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub fn use_pep585_annotation(checker: &mut Checker, expr: &Expr, id: &str) {
|
||||||
CheckKind::UsePEP585Annotation(id.to_string()),
|
CheckKind::UsePEP585Annotation(id.to_string()),
|
||||||
Range::from_located(expr),
|
Range::from_located(expr),
|
||||||
);
|
);
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
check.amend(Fix::replacement(
|
check.amend(Fix::replacement(
|
||||||
id.to_lowercase(),
|
id.to_lowercase(),
|
||||||
expr.location,
|
expr.location,
|
||||||
|
|
|
@ -45,7 +45,7 @@ fn union(elts: &[Expr]) -> Expr {
|
||||||
pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, slice: &Expr) {
|
pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, slice: &Expr) {
|
||||||
if match_name_or_attr(value, "Optional") {
|
if match_name_or_attr(value, "Optional") {
|
||||||
let mut check = Check::new(CheckKind::UsePEP604Annotation, Range::from_located(expr));
|
let mut check = Check::new(CheckKind::UsePEP604Annotation, Range::from_located(expr));
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
let mut generator = SourceGenerator::new();
|
let mut generator = SourceGenerator::new();
|
||||||
if let Ok(()) = generator.unparse_expr(&optional(slice), 0) {
|
if let Ok(()) = generator.unparse_expr(&optional(slice), 0) {
|
||||||
if let Ok(content) = generator.generate() {
|
if let Ok(content) = generator.generate() {
|
||||||
|
@ -60,7 +60,7 @@ pub fn use_pep604_annotation(checker: &mut Checker, expr: &Expr, value: &Expr, s
|
||||||
checker.add_check(check);
|
checker.add_check(check);
|
||||||
} else if match_name_or_attr(value, "Union") {
|
} else if match_name_or_attr(value, "Union") {
|
||||||
let mut check = Check::new(CheckKind::UsePEP604Annotation, Range::from_located(expr));
|
let mut check = Check::new(CheckKind::UsePEP604Annotation, Range::from_located(expr));
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
match &slice.node {
|
match &slice.node {
|
||||||
ExprKind::Slice { .. } => {
|
ExprKind::Slice { .. } => {
|
||||||
// Invalid type annotation.
|
// Invalid type annotation.
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub fn useless_metaclass_type(checker: &mut Checker, stmt: &Stmt, value: &Expr,
|
||||||
value,
|
value,
|
||||||
checker.locate_check(Range::from_located(stmt)),
|
checker.locate_check(Range::from_located(stmt)),
|
||||||
) {
|
) {
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
let context = checker.binding_context();
|
let context = checker.binding_context();
|
||||||
let deleted: Vec<&Stmt> = checker
|
let deleted: Vec<&Stmt> = checker
|
||||||
.deletions
|
.deletions
|
||||||
|
|
|
@ -13,9 +13,9 @@ pub fn useless_object_inheritance(
|
||||||
) {
|
) {
|
||||||
let scope = checker.current_scope();
|
let scope = checker.current_scope();
|
||||||
if let Some(mut check) = checks::useless_object_inheritance(name, bases, scope) {
|
if let Some(mut check) = checks::useless_object_inheritance(name, bases, scope) {
|
||||||
if checker.autofix.enabled() {
|
if checker.patch() {
|
||||||
if let Some(fix) = pyupgrade::fixes::remove_class_def_base(
|
if let Some(fix) = pyupgrade::fixes::remove_class_def_base(
|
||||||
&mut checker.locator,
|
checker.get_locator(),
|
||||||
&stmt.location,
|
&stmt.location,
|
||||||
check.location,
|
check.location,
|
||||||
bases,
|
bases,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue