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);
|
pyflakes::rules::invalid_print_syntax(checker, left);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::BinOp(ast::ExprBinOp {
|
Expr::BinOp(
|
||||||
left,
|
bin_op @ ast::ExprBinOp {
|
||||||
op: Operator::Mod,
|
left,
|
||||||
right,
|
op: Operator::Mod,
|
||||||
range: _,
|
right,
|
||||||
}) => {
|
range: _,
|
||||||
if let Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) = left.as_ref() {
|
},
|
||||||
|
) => {
|
||||||
|
if let Expr::StringLiteral(format_string @ ast::ExprStringLiteral { value, .. }) =
|
||||||
|
left.as_ref()
|
||||||
|
{
|
||||||
if checker.any_enabled(&[
|
if checker.any_enabled(&[
|
||||||
Rule::PercentFormatInvalidFormat,
|
Rule::PercentFormatInvalidFormat,
|
||||||
Rule::PercentFormatExpectedMapping,
|
Rule::PercentFormatExpectedMapping,
|
||||||
|
@ -1151,10 +1155,14 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||||
pyupgrade::rules::printf_string_formatting(checker, expr, right);
|
pyupgrade::rules::printf_string_formatting(checker, expr, right);
|
||||||
}
|
}
|
||||||
if checker.enabled(Rule::BadStringFormatCharacter) {
|
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) {
|
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) {
|
if checker.enabled(Rule::HardcodedSQLExpression) {
|
||||||
flake8_bandit::rules::hardcoded_sql_expression(checker, expr);
|
flake8_bandit::rules::hardcoded_sql_expression(checker, expr);
|
||||||
|
|
|
@ -2,14 +2,13 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, 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::{
|
use ruff_python_literal::{
|
||||||
cformat::{CFormatErrorType, CFormatString},
|
cformat::{CFormatErrorType, CFormatString},
|
||||||
format::FormatPart,
|
format::FormatPart,
|
||||||
format::FromTemplate,
|
format::FromTemplate,
|
||||||
format::{FormatSpec, FormatSpecError, FormatString},
|
format::{FormatSpec, FormatSpecError, FormatString},
|
||||||
};
|
};
|
||||||
use ruff_python_parser::{lexer, Mode, Tok};
|
|
||||||
use ruff_text_size::{Ranged, TextRange};
|
use ruff_text_size::{Ranged, TextRange};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
@ -90,27 +89,10 @@ pub(crate) fn call(checker: &mut Checker, string: &str, range: TextRange) {
|
||||||
|
|
||||||
/// PLE1300
|
/// PLE1300
|
||||||
/// Ex) `"%z" % "1"`
|
/// Ex) `"%z" % "1"`
|
||||||
pub(crate) fn percent(checker: &mut Checker, expr: &Expr) {
|
pub(crate) fn percent(checker: &mut Checker, expr: &Expr, format_string: &ExprStringLiteral) {
|
||||||
// Grab each string segment (in case there's an implicit concatenation).
|
for string_literal in &format_string.value {
|
||||||
let mut strings: Vec<(TextRange, AnyStringFlags)> = vec![];
|
let string = checker.locator().slice(string_literal);
|
||||||
for (tok, range) in
|
let flags = AnyStringFlags::from(string_literal.flags);
|
||||||
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);
|
|
||||||
let string = &string
|
let string = &string
|
||||||
[usize::from(flags.opener_len())..(string.len() - usize::from(flags.closer_len()))];
|
[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_ast::{self as ast, AnyStringFlags, Expr};
|
||||||
use ruff_python_literal::cformat::{CFormatPart, CFormatSpec, CFormatStrOrBytes, CFormatString};
|
use ruff_python_literal::cformat::{CFormatPart, CFormatSpec, CFormatStrOrBytes, CFormatString};
|
||||||
use ruff_python_parser::{lexer, AsMode, Tok};
|
use ruff_text_size::Ranged;
|
||||||
use ruff_text_size::{Ranged, TextRange};
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
|
@ -211,30 +210,16 @@ fn is_valid_dict(formats: &[CFormatStrOrBytes<String>], items: &[ast::DictItem])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PLE1307
|
/// PLE1307
|
||||||
pub(crate) fn bad_string_format_type(checker: &mut Checker, expr: &Expr, right: &Expr) {
|
pub(crate) fn bad_string_format_type(
|
||||||
// Grab each string segment (in case there's an implicit concatenation).
|
checker: &mut Checker,
|
||||||
let content = checker.locator().slice(expr);
|
bin_op: &ast::ExprBinOp,
|
||||||
let mut strings: Vec<(TextRange, AnyStringFlags)> = vec![];
|
format_string: &ast::ExprStringLiteral,
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse each string segment.
|
// Parse each string segment.
|
||||||
let mut format_strings = vec![];
|
let mut format_strings = vec![];
|
||||||
for (range, flags) in &strings {
|
for string_literal in &format_string.value {
|
||||||
let string = checker.locator().slice(*range);
|
let string = checker.locator().slice(string_literal);
|
||||||
|
let flags = AnyStringFlags::from(string_literal.flags);
|
||||||
let quote_len = usize::from(flags.quote_len());
|
let quote_len = usize::from(flags.quote_len());
|
||||||
let string =
|
let string =
|
||||||
&string[(usize::from(flags.prefix_len()) + quote_len)..(string.len() - quote_len)];
|
&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.
|
// 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::Tuple(ast::ExprTuple { elts, .. }) => is_valid_tuple(&format_strings, elts),
|
||||||
Expr::Dict(ast::ExprDict { items, range: _ }) => is_valid_dict(&format_strings, items),
|
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 {
|
if !is_valid {
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.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