mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 06:11:21 +00:00
Avoid lexer usage in PLE1300
and PLE1307
(#11406)
## Summary This PR updates `PLE1300` and `PLE1307` to avoid using the lexer. This is part of #11401 ## Test Plan `cargo test`
This commit is contained in:
parent
af60d539ab
commit
10b85a0f07
3 changed files with 34 additions and 59 deletions
|
@ -1065,13 +1065,17 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
pyflakes::rules::invalid_print_syntax(checker, left);
|
||||
}
|
||||
}
|
||||
Expr::BinOp(ast::ExprBinOp {
|
||||
left,
|
||||
op: Operator::Mod,
|
||||
right,
|
||||
range: _,
|
||||
}) => {
|
||||
if let Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) = left.as_ref() {
|
||||
Expr::BinOp(
|
||||
bin_op @ ast::ExprBinOp {
|
||||
left,
|
||||
op: Operator::Mod,
|
||||
right,
|
||||
range: _,
|
||||
},
|
||||
) => {
|
||||
if let Expr::StringLiteral(format_string @ ast::ExprStringLiteral { value, .. }) =
|
||||
left.as_ref()
|
||||
{
|
||||
if checker.any_enabled(&[
|
||||
Rule::PercentFormatInvalidFormat,
|
||||
Rule::PercentFormatExpectedMapping,
|
||||
|
@ -1151,10 +1155,14 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
pyupgrade::rules::printf_string_formatting(checker, expr, right);
|
||||
}
|
||||
if checker.enabled(Rule::BadStringFormatCharacter) {
|
||||
pylint::rules::bad_string_format_character::percent(checker, expr);
|
||||
pylint::rules::bad_string_format_character::percent(
|
||||
checker,
|
||||
expr,
|
||||
format_string,
|
||||
);
|
||||
}
|
||||
if checker.enabled(Rule::BadStringFormatType) {
|
||||
pylint::rules::bad_string_format_type(checker, expr, right);
|
||||
pylint::rules::bad_string_format_type(checker, bin_op, format_string);
|
||||
}
|
||||
if checker.enabled(Rule::HardcodedSQLExpression) {
|
||||
flake8_bandit::rules::hardcoded_sql_expression(checker, expr);
|
||||
|
|
|
@ -2,14 +2,13 @@ use std::str::FromStr;
|
|||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::{AnyStringFlags, Expr};
|
||||
use ruff_python_ast::{AnyStringFlags, Expr, ExprStringLiteral};
|
||||
use ruff_python_literal::{
|
||||
cformat::{CFormatErrorType, CFormatString},
|
||||
format::FormatPart,
|
||||
format::FromTemplate,
|
||||
format::{FormatSpec, FormatSpecError, FormatString},
|
||||
};
|
||||
use ruff_python_parser::{lexer, Mode, Tok};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
@ -90,27 +89,10 @@ pub(crate) fn call(checker: &mut Checker, string: &str, range: TextRange) {
|
|||
|
||||
/// PLE1300
|
||||
/// Ex) `"%z" % "1"`
|
||||
pub(crate) fn percent(checker: &mut Checker, expr: &Expr) {
|
||||
// Grab each string segment (in case there's an implicit concatenation).
|
||||
let mut strings: Vec<(TextRange, AnyStringFlags)> = vec![];
|
||||
for (tok, range) in
|
||||
lexer::lex_starts_at(checker.locator().slice(expr), Mode::Module, expr.start()).flatten()
|
||||
{
|
||||
match tok {
|
||||
Tok::String { flags, .. } => strings.push((range, flags)),
|
||||
// Break as soon as we find the modulo symbol.
|
||||
Tok::Percent => break,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no string segments, abort.
|
||||
if strings.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
for (range, flags) in &strings {
|
||||
let string = checker.locator().slice(*range);
|
||||
pub(crate) fn percent(checker: &mut Checker, expr: &Expr, format_string: &ExprStringLiteral) {
|
||||
for string_literal in &format_string.value {
|
||||
let string = checker.locator().slice(string_literal);
|
||||
let flags = AnyStringFlags::from(string_literal.flags);
|
||||
let string = &string
|
||||
[usize::from(flags.opener_len())..(string.len() - usize::from(flags.closer_len()))];
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@ use std::str::FromStr;
|
|||
|
||||
use ruff_python_ast::{self as ast, AnyStringFlags, Expr};
|
||||
use ruff_python_literal::cformat::{CFormatPart, CFormatSpec, CFormatStrOrBytes, CFormatString};
|
||||
use ruff_python_parser::{lexer, AsMode, Tok};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
use ruff_text_size::Ranged;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
|
@ -211,30 +210,16 @@ fn is_valid_dict(formats: &[CFormatStrOrBytes<String>], items: &[ast::DictItem])
|
|||
}
|
||||
|
||||
/// PLE1307
|
||||
pub(crate) fn bad_string_format_type(checker: &mut Checker, expr: &Expr, right: &Expr) {
|
||||
// Grab each string segment (in case there's an implicit concatenation).
|
||||
let content = checker.locator().slice(expr);
|
||||
let mut strings: Vec<(TextRange, AnyStringFlags)> = vec![];
|
||||
for (tok, range) in
|
||||
lexer::lex_starts_at(content, checker.source_type.as_mode(), expr.start()).flatten()
|
||||
{
|
||||
match tok {
|
||||
Tok::String { flags, .. } => strings.push((range, flags)),
|
||||
// Break as soon as we find the modulo symbol.
|
||||
Tok::Percent => break,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no string segments, abort.
|
||||
if strings.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
pub(crate) fn bad_string_format_type(
|
||||
checker: &mut Checker,
|
||||
bin_op: &ast::ExprBinOp,
|
||||
format_string: &ast::ExprStringLiteral,
|
||||
) {
|
||||
// Parse each string segment.
|
||||
let mut format_strings = vec![];
|
||||
for (range, flags) in &strings {
|
||||
let string = checker.locator().slice(*range);
|
||||
for string_literal in &format_string.value {
|
||||
let string = checker.locator().slice(string_literal);
|
||||
let flags = AnyStringFlags::from(string_literal.flags);
|
||||
let quote_len = usize::from(flags.quote_len());
|
||||
let string =
|
||||
&string[(usize::from(flags.prefix_len()) + quote_len)..(string.len() - quote_len)];
|
||||
|
@ -246,14 +231,14 @@ pub(crate) fn bad_string_format_type(checker: &mut Checker, expr: &Expr, right:
|
|||
}
|
||||
|
||||
// Parse the parameters.
|
||||
let is_valid = match right {
|
||||
let is_valid = match &*bin_op.right {
|
||||
Expr::Tuple(ast::ExprTuple { elts, .. }) => is_valid_tuple(&format_strings, elts),
|
||||
Expr::Dict(ast::ExprDict { items, range: _ }) => is_valid_dict(&format_strings, items),
|
||||
_ => is_valid_constant(&format_strings, right),
|
||||
_ => is_valid_constant(&format_strings, &bin_op.right),
|
||||
};
|
||||
if !is_valid {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(BadStringFormatType, expr.range()));
|
||||
.push(Diagnostic::new(BadStringFormatType, bin_op.range()));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue