mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 02:12:22 +00:00
Rename end_of_statement
to end_of_last_statement
(#3775)
This commit is contained in:
parent
990b378c4d
commit
22d5b0071d
3 changed files with 39 additions and 32 deletions
|
@ -1,4 +1,8 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt};
|
use rustpython_parser::ast::{Constant, Expr, ExprKind, Location, Stmt};
|
||||||
|
|
||||||
|
use ruff_python_ast::helpers::to_absolute;
|
||||||
|
use ruff_python_ast::newlines::StrExt;
|
||||||
|
use ruff_python_ast::source_code::Locator;
|
||||||
|
|
||||||
/// Return `true` if a function's return statement include at least one
|
/// Return `true` if a function's return statement include at least one
|
||||||
/// non-`None` value.
|
/// non-`None` value.
|
||||||
|
@ -16,3 +20,32 @@ pub fn result_exists(returns: &[(&Stmt, Option<&Expr>)]) -> bool {
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given a statement, find its "logical end".
|
||||||
|
///
|
||||||
|
/// For example: the statement could be following by a trailing semicolon, by an end-of-line
|
||||||
|
/// comment, or by any number of continuation lines (and then by a comment, and so on).
|
||||||
|
///
|
||||||
|
/// This method assumes that the statement is the last statement in its body; specifically, that
|
||||||
|
/// the statement isn't followed by a semicolon, followed by a multi-line statement.
|
||||||
|
pub fn end_of_last_statement(stmt: &Stmt, locator: &Locator) -> Location {
|
||||||
|
let contents = locator.skip(stmt.end_location.unwrap());
|
||||||
|
|
||||||
|
// End-of-file, so just return the end of the statement.
|
||||||
|
if contents.is_empty() {
|
||||||
|
return stmt.end_location.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, find the end of the last line that's "part of" the statement.
|
||||||
|
for (lineno, line) in contents.universal_newlines().enumerate() {
|
||||||
|
if line.ends_with('\\') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return to_absolute(
|
||||||
|
Location::new(lineno + 1, line.chars().count()),
|
||||||
|
stmt.end_location.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!("Expected to find end-of-statement")
|
||||||
|
}
|
||||||
|
|
|
@ -4,14 +4,15 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, Location, Stmt, StmtKind}
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
|
||||||
use ruff_diagnostics::{Diagnostic, Edit};
|
use ruff_diagnostics::{Diagnostic, Edit};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
use ruff_python_ast::helpers::elif_else_range;
|
||||||
use ruff_python_ast::helpers::is_const_none;
|
use ruff_python_ast::helpers::is_const_none;
|
||||||
use ruff_python_ast::helpers::{elif_else_range, end_of_statement};
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::visitor::Visitor;
|
use ruff_python_ast::visitor::Visitor;
|
||||||
use ruff_python_ast::whitespace::indentation;
|
use ruff_python_ast::whitespace::indentation;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::{AsRule, Rule};
|
use crate::registry::{AsRule, Rule};
|
||||||
|
use crate::rules::flake8_return::helpers::end_of_last_statement;
|
||||||
|
|
||||||
use super::branch::Branch;
|
use super::branch::Branch;
|
||||||
use super::helpers::result_exists;
|
use super::helpers::result_exists;
|
||||||
|
@ -222,7 +223,7 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) {
|
||||||
content.push_str("return None");
|
content.push_str("return None");
|
||||||
diagnostic.set_fix(Edit::insertion(
|
diagnostic.set_fix(Edit::insertion(
|
||||||
content,
|
content,
|
||||||
end_of_statement(stmt, checker.locator),
|
end_of_last_statement(stmt, checker.locator),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,7 +261,7 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) {
|
||||||
content.push_str("return None");
|
content.push_str("return None");
|
||||||
diagnostic.set_fix(Edit::insertion(
|
diagnostic.set_fix(Edit::insertion(
|
||||||
content,
|
content,
|
||||||
end_of_statement(stmt, checker.locator),
|
end_of_last_statement(stmt, checker.locator),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,7 +300,7 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) {
|
||||||
content.push_str("return None");
|
content.push_str("return None");
|
||||||
diagnostic.set_fix(Edit::insertion(
|
diagnostic.set_fix(Edit::insertion(
|
||||||
content,
|
content,
|
||||||
end_of_statement(stmt, checker.locator),
|
end_of_last_statement(stmt, checker.locator),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ use rustpython_parser::{lexer, Mode, StringKind, Tok};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::newlines::StrExt;
|
|
||||||
use crate::scope::{Binding, BindingKind};
|
use crate::scope::{Binding, BindingKind};
|
||||||
use crate::source_code::{Generator, Indexer, Locator, Stylist};
|
use crate::source_code::{Generator, Indexer, Locator, Stylist};
|
||||||
use crate::types::{CallPath, Range};
|
use crate::types::{CallPath, Range};
|
||||||
|
@ -1139,32 +1138,6 @@ pub fn first_colon_range(range: Range, locator: &Locator) -> Option<Range> {
|
||||||
range
|
range
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a statement, find its "logical end".
|
|
||||||
///
|
|
||||||
/// For example: the statement could be following by a trailing semicolon, by an end-of-line
|
|
||||||
/// comment, or by any number of continuation lines (and then by a comment, and so on).
|
|
||||||
pub fn end_of_statement(stmt: &Stmt, locator: &Locator) -> Location {
|
|
||||||
let contents = locator.skip(stmt.end_location.unwrap());
|
|
||||||
|
|
||||||
// End-of-file, so just return the end of the statement.
|
|
||||||
if contents.is_empty() {
|
|
||||||
return stmt.end_location.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, find the end of the last line that's "part of" the statement.
|
|
||||||
for (lineno, line) in contents.universal_newlines().enumerate() {
|
|
||||||
if line.ends_with('\\') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return to_absolute(
|
|
||||||
Location::new(lineno + 1, line.chars().count()),
|
|
||||||
stmt.end_location.unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
unreachable!("Expected to find end-of-statement")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the `Range` of the first `Elif` or `Else` token in an `If` statement.
|
/// Return the `Range` of the first `Elif` or `Else` token in an `If` statement.
|
||||||
pub fn elif_else_range(stmt: &Stmt, locator: &Locator) -> Option<Range> {
|
pub fn elif_else_range(stmt: &Stmt, locator: &Locator) -> Option<Range> {
|
||||||
let StmtKind::If { body, orelse, .. } = &stmt.node else {
|
let StmtKind::If { body, orelse, .. } = &stmt.node else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue