mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 13:33:50 +00:00
Format let-else with rustfmt nightly (#5461)
Support for `let…else` formatting was just merged to nightly (rust-lang/rust#113225). Rerun `cargo fmt` with Rust nightly 2023-07-02 to pick this up. Followup to #939. Signed-off-by: Anders Kaseorg <andersk@mit.edu>
This commit is contained in:
parent
c8b9a46e2b
commit
df13e69c3c
105 changed files with 782 additions and 362 deletions
|
@ -268,7 +268,8 @@ impl Notebook {
|
|||
.markers()
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|m| m.source <= *offset) else {
|
||||
.find(|m| m.source <= *offset)
|
||||
else {
|
||||
// There are no markers above the current offset, so we can
|
||||
// stop here.
|
||||
break;
|
||||
|
|
|
@ -457,11 +457,7 @@ pub(crate) fn definition(
|
|||
// TODO(charlie): Consider using the AST directly here rather than `Definition`.
|
||||
// We could adhere more closely to `flake8-annotations` by defining public
|
||||
// vs. secret vs. protected.
|
||||
let Definition::Member(Member {
|
||||
kind,
|
||||
stmt,
|
||||
..
|
||||
}) = definition else {
|
||||
let Definition::Member(Member { kind, stmt, .. }) = definition else {
|
||||
return vec![];
|
||||
};
|
||||
|
||||
|
|
|
@ -161,19 +161,19 @@ pub(crate) fn abstract_base_class(
|
|||
continue;
|
||||
}
|
||||
|
||||
let (
|
||||
Stmt::FunctionDef(ast::StmtFunctionDef {
|
||||
decorator_list,
|
||||
body,
|
||||
name: method_name,
|
||||
..
|
||||
}) | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
|
||||
let (Stmt::FunctionDef(ast::StmtFunctionDef {
|
||||
decorator_list,
|
||||
body,
|
||||
name: method_name,
|
||||
..
|
||||
})
|
||||
) = stmt else {
|
||||
| Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
|
||||
decorator_list,
|
||||
body,
|
||||
name: method_name,
|
||||
..
|
||||
})) = stmt
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
|
@ -78,7 +78,13 @@ impl fmt::Display for ExceptionKind {
|
|||
/// B017
|
||||
pub(crate) fn assert_raises_exception(checker: &mut Checker, items: &[WithItem]) {
|
||||
for item in items {
|
||||
let Expr::Call(ast::ExprCall { func, args, keywords, range: _ }) = &item.context_expr else {
|
||||
let Expr::Call(ast::ExprCall {
|
||||
func,
|
||||
args,
|
||||
keywords,
|
||||
range: _,
|
||||
}) = &item.context_expr
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if args.len() != 1 {
|
||||
|
@ -91,13 +97,14 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, items: &[WithItem])
|
|||
let Some(exception) = checker
|
||||
.semantic()
|
||||
.resolve_call_path(args.first().unwrap())
|
||||
.and_then(|call_path| {
|
||||
match call_path.as_slice() {
|
||||
.and_then(|call_path| match call_path.as_slice() {
|
||||
["", "Exception"] => Some(ExceptionKind::Exception),
|
||||
["", "BaseException"] => Some(ExceptionKind::BaseException),
|
||||
_ => None,
|
||||
}
|
||||
}) else { return; };
|
||||
})
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let assertion = if matches!(func.as_ref(), Expr::Attribute(ast::ExprAttribute { attr, .. }) if attr == "assertRaises")
|
||||
{
|
||||
|
|
|
@ -166,7 +166,11 @@ pub(crate) fn duplicate_exceptions(checker: &mut Checker, handlers: &[ExceptHand
|
|||
let mut seen: FxHashSet<CallPath> = FxHashSet::default();
|
||||
let mut duplicates: FxHashMap<CallPath, Vec<&Expr>> = FxHashMap::default();
|
||||
for handler in handlers {
|
||||
let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_: Some(type_), .. }) = handler else {
|
||||
let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
|
||||
type_: Some(type_),
|
||||
..
|
||||
}) = handler
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
match type_.as_ref() {
|
||||
|
|
|
@ -76,7 +76,8 @@ pub(crate) fn getattr_with_constant(
|
|||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Str(value),
|
||||
..
|
||||
} )= arg else {
|
||||
}) = arg
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !is_identifier(value) {
|
||||
|
|
|
@ -59,7 +59,11 @@ pub(crate) fn redundant_tuple_in_exception_handler(
|
|||
handlers: &[ExceptHandler],
|
||||
) {
|
||||
for handler in handlers {
|
||||
let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_: Some(type_), .. }) = handler else {
|
||||
let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
|
||||
type_: Some(type_),
|
||||
..
|
||||
}) = handler
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let Expr::Tuple(ast::ExprTuple { elts, .. }) = type_.as_ref() else {
|
||||
|
|
|
@ -82,7 +82,8 @@ pub(crate) fn setattr_with_constant(
|
|||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Str(name),
|
||||
..
|
||||
} )= name else {
|
||||
}) = name
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !is_identifier(name) {
|
||||
|
|
|
@ -62,7 +62,8 @@ pub(crate) fn strip_with_multi_characters(
|
|||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Str(value),
|
||||
..
|
||||
} )= &args[0] else {
|
||||
}) = &args[0]
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -63,8 +63,8 @@ pub(crate) fn unreliable_callable_check(
|
|||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Str(s),
|
||||
..
|
||||
}) = &args[1] else
|
||||
{
|
||||
}) = &args[1]
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if s != "__call__" {
|
||||
|
|
|
@ -68,7 +68,13 @@ pub(crate) fn zip_without_explicit_strict(
|
|||
/// Return `true` if the [`Expr`] appears to be an infinite iterator (e.g., a call to
|
||||
/// `itertools.cycle` or similar).
|
||||
fn is_infinite_iterator(arg: &Expr, semantic: &SemanticModel) -> bool {
|
||||
let Expr::Call(ast::ExprCall { func, args, keywords, .. }) = &arg else {
|
||||
let Expr::Call(ast::ExprCall {
|
||||
func,
|
||||
args,
|
||||
keywords,
|
||||
..
|
||||
}) = &arg
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
|
|
@ -109,7 +109,8 @@ pub(crate) fn fix_unnecessary_generator_dict(
|
|||
// Extract the (k, v) from `(k, v) for ...`.
|
||||
let generator_exp = match_generator_exp(&arg.value)?;
|
||||
let tuple = match_tuple(&generator_exp.elt)?;
|
||||
let [Element::Simple { value: key, .. }, Element::Simple { value, .. }] = &tuple.elements[..] else {
|
||||
let [Element::Simple { value: key, .. }, Element::Simple { value, .. }] = &tuple.elements[..]
|
||||
else {
|
||||
bail!("Expected tuple to contain two elements");
|
||||
};
|
||||
|
||||
|
@ -188,9 +189,10 @@ pub(crate) fn fix_unnecessary_list_comprehension_dict(
|
|||
|
||||
let tuple = match_tuple(&list_comp.elt)?;
|
||||
|
||||
let [Element::Simple {
|
||||
value: key, ..
|
||||
}, Element::Simple { value, .. }] = &tuple.elements[..] else { bail!("Expected tuple with two elements"); };
|
||||
let [Element::Simple { value: key, .. }, Element::Simple { value, .. }] = &tuple.elements[..]
|
||||
else {
|
||||
bail!("Expected tuple with two elements");
|
||||
};
|
||||
|
||||
tree = Expression::DictComp(Box::new(DictComp {
|
||||
key: Box::new(key.clone()),
|
||||
|
@ -982,14 +984,10 @@ pub(crate) fn fix_unnecessary_map(
|
|||
}
|
||||
|
||||
let Some(Element::Simple { value: key, .. }) = &tuple.elements.get(0) else {
|
||||
bail!(
|
||||
"Expected tuple to contain a key as the first element"
|
||||
);
|
||||
bail!("Expected tuple to contain a key as the first element");
|
||||
};
|
||||
let Some(Element::Simple { value, .. }) = &tuple.elements.get(1) else {
|
||||
bail!(
|
||||
"Expected tuple to contain a key as the second element"
|
||||
);
|
||||
bail!("Expected tuple to contain a key as the second element");
|
||||
};
|
||||
|
||||
(key, value)
|
||||
|
@ -1063,9 +1061,7 @@ pub(crate) fn fix_unnecessary_comprehension_any_all(
|
|||
let call = match_call_mut(&mut tree)?;
|
||||
|
||||
let Expression::ListComp(list_comp) = &call.args[0].value else {
|
||||
bail!(
|
||||
"Expected Expression::ListComp"
|
||||
);
|
||||
bail!("Expected Expression::ListComp");
|
||||
};
|
||||
|
||||
let mut new_empty_lines = vec![];
|
||||
|
|
|
@ -70,7 +70,9 @@ pub(crate) fn unnecessary_comprehension_any_all(
|
|||
return;
|
||||
};
|
||||
if (matches!(id.as_str(), "all" | "any")) && args.len() == 1 {
|
||||
let (Expr::ListComp(ast::ExprListComp { elt, .. } )| Expr::SetComp(ast::ExprSetComp { elt, .. })) = &args[0] else {
|
||||
let (Expr::ListComp(ast::ExprListComp { elt, .. })
|
||||
| Expr::SetComp(ast::ExprSetComp { elt, .. })) = &args[0]
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if contains_await(elt) {
|
||||
|
|
|
@ -49,7 +49,9 @@ pub(crate) fn unnecessary_generator_dict(
|
|||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
||||
let Some(argument) =
|
||||
helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if let Expr::GeneratorExp(ast::ExprGeneratorExp { elt, .. }) = argument {
|
||||
|
|
|
@ -49,7 +49,9 @@ pub(crate) fn unnecessary_generator_list(
|
|||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("list", func, args, keywords) else {
|
||||
let Some(argument) =
|
||||
helpers::exactly_one_argument_with_matching_function("list", func, args, keywords)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic().is_builtin("list") {
|
||||
|
|
|
@ -49,7 +49,9 @@ pub(crate) fn unnecessary_generator_set(
|
|||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
||||
let Some(argument) =
|
||||
helpers::exactly_one_argument_with_matching_function("set", func, args, keywords)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic().is_builtin("set") {
|
||||
|
|
|
@ -47,7 +47,9 @@ pub(crate) fn unnecessary_list_comprehension_dict(
|
|||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
||||
let Some(argument) =
|
||||
helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic().is_builtin("dict") {
|
||||
|
|
|
@ -47,7 +47,9 @@ pub(crate) fn unnecessary_list_comprehension_set(
|
|||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
||||
let Some(argument) =
|
||||
helpers::exactly_one_argument_with_matching_function("set", func, args, keywords)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic().is_builtin("set") {
|
||||
|
|
|
@ -54,7 +54,9 @@ pub(crate) fn unnecessary_literal_dict(
|
|||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
||||
let Some(argument) =
|
||||
helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic().is_builtin("dict") {
|
||||
|
|
|
@ -55,7 +55,9 @@ pub(crate) fn unnecessary_literal_set(
|
|||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
||||
let Some(argument) =
|
||||
helpers::exactly_one_argument_with_matching_function("set", func, args, keywords)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic().is_builtin("set") {
|
||||
|
|
|
@ -127,7 +127,9 @@ pub(crate) fn unnecessary_map(
|
|||
if args.len() != 2 {
|
||||
return;
|
||||
}
|
||||
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
|
||||
let Some(argument) =
|
||||
helpers::first_argument_with_matching_function("map", func, args)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if let Expr::Lambda(_) = argument {
|
||||
|
@ -155,7 +157,9 @@ pub(crate) fn unnecessary_map(
|
|||
|
||||
if args.len() == 1 {
|
||||
if let Expr::Call(ast::ExprCall { func, args, .. }) = &args[0] {
|
||||
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
|
||||
let Some(argument) =
|
||||
helpers::first_argument_with_matching_function("map", func, args)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if let Expr::Lambda(ast::ExprLambda { body, .. }) = argument {
|
||||
|
|
|
@ -64,7 +64,13 @@ pub(crate) fn unnecessary_subscript_reversal(
|
|||
let Expr::Subscript(ast::ExprSubscript { slice, .. }) = first_arg else {
|
||||
return;
|
||||
};
|
||||
let Expr::Slice(ast::ExprSlice { lower, upper, step, range: _ }) = slice.as_ref() else {
|
||||
let Expr::Slice(ast::ExprSlice {
|
||||
lower,
|
||||
upper,
|
||||
step,
|
||||
range: _,
|
||||
}) = slice.as_ref()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if lower.is_some() || upper.is_some() {
|
||||
|
@ -77,13 +83,15 @@ pub(crate) fn unnecessary_subscript_reversal(
|
|||
op: UnaryOp::USub,
|
||||
operand,
|
||||
range: _,
|
||||
}) = step.as_ref() else {
|
||||
}) = step.as_ref()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Int(val),
|
||||
..
|
||||
}) = operand.as_ref() else {
|
||||
}) = operand.as_ref()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if *val != BigInt::from(1) {
|
||||
|
|
|
@ -49,11 +49,13 @@ pub(crate) fn call_datetime_strptime_without_zone(
|
|||
}
|
||||
};
|
||||
|
||||
let (Some(grandparent), Some(parent)) = (checker.semantic().expr_grandparent(), checker.semantic().expr_parent()) else {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
CallDatetimeStrptimeWithoutZone,
|
||||
location,
|
||||
));
|
||||
let (Some(grandparent), Some(parent)) = (
|
||||
checker.semantic().expr_grandparent(),
|
||||
checker.semantic().expr_parent(),
|
||||
) else {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(CallDatetimeStrptimeWithoutZone, location));
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ pub(crate) fn locals_in_render_function(
|
|||
|
||||
fn is_locals_call(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
let Expr::Call(ast::ExprCall { func, .. }) = expr else {
|
||||
return false
|
||||
return false;
|
||||
};
|
||||
semantic.resolve_call_path(func).map_or(false, |call_path| {
|
||||
matches!(call_path.as_slice(), ["", "locals"])
|
||||
|
|
|
@ -97,7 +97,7 @@ fn is_non_abstract_model(bases: &[Expr], body: &[Stmt], semantic: &SemanticModel
|
|||
fn is_model_abstract(body: &[Stmt]) -> bool {
|
||||
for element in body.iter() {
|
||||
let Stmt::ClassDef(ast::StmtClassDef { name, body, .. }) = element else {
|
||||
continue
|
||||
continue;
|
||||
};
|
||||
if name != "Meta" {
|
||||
continue;
|
||||
|
|
|
@ -65,7 +65,7 @@ pub(crate) fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> V
|
|||
let mut errors = Vec::new();
|
||||
for statement in body.iter() {
|
||||
let Stmt::Assign(ast::StmtAssign { value, .. }) = statement else {
|
||||
continue
|
||||
continue;
|
||||
};
|
||||
if let Some(field_name) = is_nullable_field(checker, value) {
|
||||
errors.push(Diagnostic::new(
|
||||
|
@ -97,7 +97,7 @@ fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a st
|
|||
let mut unique_key = false;
|
||||
for keyword in keywords.iter() {
|
||||
let Some(argument) = &keyword.arg else {
|
||||
continue
|
||||
continue;
|
||||
};
|
||||
if !is_const_true(&keyword.value) {
|
||||
continue;
|
||||
|
|
|
@ -60,7 +60,12 @@ impl AlwaysAutofixableViolation for MultipleStartsEndsWith {
|
|||
|
||||
/// PIE810
|
||||
pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
||||
let Expr::BoolOp(ast::ExprBoolOp { op: BoolOp::Or, values, range: _ }) = expr else {
|
||||
let Expr::BoolOp(ast::ExprBoolOp {
|
||||
op: BoolOp::Or,
|
||||
values,
|
||||
range: _,
|
||||
}) = expr
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -70,9 +75,10 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
|||
func,
|
||||
args,
|
||||
keywords,
|
||||
range: _
|
||||
}) = &call else {
|
||||
continue
|
||||
range: _,
|
||||
}) = &call
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if !(args.len() == 1 && keywords.is_empty()) {
|
||||
|
@ -80,14 +86,14 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
|||
}
|
||||
|
||||
let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func.as_ref() else {
|
||||
continue
|
||||
continue;
|
||||
};
|
||||
if attr != "startswith" && attr != "endswith" {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Expr::Name(ast::ExprName { id: arg_name, .. }) = value.as_ref() else {
|
||||
continue
|
||||
continue;
|
||||
};
|
||||
|
||||
duplicates
|
||||
|
@ -110,8 +116,17 @@ pub(crate) fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
|||
.iter()
|
||||
.map(|index| &values[*index])
|
||||
.map(|expr| {
|
||||
let Expr::Call(ast::ExprCall { func: _, args, keywords: _, range: _}) = expr else {
|
||||
unreachable!("{}", format!("Indices should only contain `{attr_name}` calls"))
|
||||
let Expr::Call(ast::ExprCall {
|
||||
func: _,
|
||||
args,
|
||||
keywords: _,
|
||||
range: _,
|
||||
}) = expr
|
||||
else {
|
||||
unreachable!(
|
||||
"{}",
|
||||
format!("Indices should only contain `{attr_name}` calls")
|
||||
)
|
||||
};
|
||||
args.get(0)
|
||||
.unwrap_or_else(|| panic!("`{attr_name}` should have one argument"))
|
||||
|
|
|
@ -70,15 +70,12 @@ pub(crate) fn iter_method_return_iterable(checker: &mut Checker, definition: &De
|
|||
kind: MemberKind::Method,
|
||||
stmt,
|
||||
..
|
||||
}) = definition else {
|
||||
}) = definition
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Stmt::FunctionDef(ast::StmtFunctionDef {
|
||||
name,
|
||||
returns,
|
||||
..
|
||||
}) = stmt else {
|
||||
let Stmt::FunctionDef(ast::StmtFunctionDef { name, returns, .. }) = stmt else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -70,17 +70,30 @@ pub(crate) fn prefix_type_params(checker: &mut Checker, value: &Expr, targets: &
|
|||
};
|
||||
|
||||
if let Expr::Call(ast::ExprCall { func, .. }) = value {
|
||||
let Some(kind) = checker.semantic().resolve_call_path(func).and_then(|call_path| {
|
||||
if checker.semantic().match_typing_call_path(&call_path, "ParamSpec") {
|
||||
let Some(kind) = checker
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.and_then(|call_path| {
|
||||
if checker
|
||||
.semantic()
|
||||
.match_typing_call_path(&call_path, "ParamSpec")
|
||||
{
|
||||
Some(VarKind::ParamSpec)
|
||||
} else if checker.semantic().match_typing_call_path(&call_path, "TypeVar") {
|
||||
} else if checker
|
||||
.semantic()
|
||||
.match_typing_call_path(&call_path, "TypeVar")
|
||||
{
|
||||
Some(VarKind::TypeVar)
|
||||
} else if checker.semantic().match_typing_call_path(&call_path, "TypeVarTuple") {
|
||||
} else if checker
|
||||
.semantic()
|
||||
.match_typing_call_path(&call_path, "TypeVarTuple")
|
||||
{
|
||||
Some(VarKind::TypeVarTuple)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) else {
|
||||
})
|
||||
else {
|
||||
return;
|
||||
};
|
||||
checker
|
||||
|
|
|
@ -50,8 +50,9 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) {
|
|||
returns,
|
||||
args,
|
||||
..
|
||||
}) = stmt else {
|
||||
return
|
||||
}) = stmt
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(returns) = returns else {
|
||||
|
|
|
@ -392,7 +392,8 @@ fn fix_composite_condition(stmt: &Stmt, locator: &Locator, stylist: &Stylist) ->
|
|||
let statements = if outer_indent.is_empty() {
|
||||
&mut tree.body
|
||||
} else {
|
||||
let [Statement::Compound(CompoundStatement::FunctionDef(embedding))] = &mut *tree.body else {
|
||||
let [Statement::Compound(CompoundStatement::FunctionDef(embedding))] = &mut *tree.body
|
||||
else {
|
||||
bail!("Expected statement to be embedded in a function definition")
|
||||
};
|
||||
|
||||
|
|
|
@ -481,7 +481,10 @@ fn unnecessary_assign(checker: &mut Checker, stack: &Stack) {
|
|||
continue;
|
||||
};
|
||||
|
||||
let Expr::Name(ast::ExprName { id: returned_id, .. }) = value.as_ref() else {
|
||||
let Expr::Name(ast::ExprName {
|
||||
id: returned_id, ..
|
||||
}) = value.as_ref()
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
@ -494,7 +497,10 @@ fn unnecessary_assign(checker: &mut Checker, stack: &Stack) {
|
|||
continue;
|
||||
};
|
||||
|
||||
let Expr::Name(ast::ExprName { id: assigned_id, .. }) = target else {
|
||||
let Expr::Name(ast::ExprName {
|
||||
id: assigned_id, ..
|
||||
}) = target
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
|
@ -299,7 +299,12 @@ fn is_same_expr<'a>(a: &'a Expr, b: &'a Expr) -> Option<&'a str> {
|
|||
|
||||
/// SIM101
|
||||
pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
|
||||
let Expr::BoolOp(ast::ExprBoolOp { op: BoolOp::Or, values, range: _ } )= expr else {
|
||||
let Expr::BoolOp(ast::ExprBoolOp {
|
||||
op: BoolOp::Or,
|
||||
values,
|
||||
range: _,
|
||||
}) = expr
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -308,7 +313,13 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
|
|||
let mut duplicates: FxHashMap<ComparableExpr, Vec<usize>> = FxHashMap::default();
|
||||
for (index, call) in values.iter().enumerate() {
|
||||
// Verify that this is an `isinstance` call.
|
||||
let Expr::Call(ast::ExprCall { func, args, keywords, range: _ }) = &call else {
|
||||
let Expr::Call(ast::ExprCall {
|
||||
func,
|
||||
args,
|
||||
keywords,
|
||||
range: _,
|
||||
}) = &call
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
if args.len() != 2 {
|
||||
|
@ -430,7 +441,13 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
|
|||
}
|
||||
|
||||
fn match_eq_target(expr: &Expr) -> Option<(&str, &Expr)> {
|
||||
let Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _ } )= expr else {
|
||||
let Expr::Compare(ast::ExprCompare {
|
||||
left,
|
||||
ops,
|
||||
comparators,
|
||||
range: _,
|
||||
}) = expr
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if ops.len() != 1 || comparators.len() != 1 {
|
||||
|
@ -451,7 +468,12 @@ fn match_eq_target(expr: &Expr) -> Option<(&str, &Expr)> {
|
|||
|
||||
/// SIM109
|
||||
pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
|
||||
let Expr::BoolOp(ast::ExprBoolOp { op: BoolOp::Or, values, range: _ }) = expr else {
|
||||
let Expr::BoolOp(ast::ExprBoolOp {
|
||||
op: BoolOp::Or,
|
||||
values,
|
||||
range: _,
|
||||
}) = expr
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -540,7 +562,12 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
|
|||
|
||||
/// SIM220
|
||||
pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) {
|
||||
let Expr::BoolOp(ast::ExprBoolOp { op: BoolOp::And, values, range: _, }) = expr else {
|
||||
let Expr::BoolOp(ast::ExprBoolOp {
|
||||
op: BoolOp::And,
|
||||
values,
|
||||
range: _,
|
||||
}) = expr
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if values.len() < 2 {
|
||||
|
@ -594,7 +621,12 @@ pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) {
|
|||
|
||||
/// SIM221
|
||||
pub(crate) fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) {
|
||||
let Expr::BoolOp(ast::ExprBoolOp { op: BoolOp::Or, values, range: _, }) = expr else {
|
||||
let Expr::BoolOp(ast::ExprBoolOp {
|
||||
op: BoolOp::Or,
|
||||
values,
|
||||
range: _,
|
||||
}) = expr
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if values.len() < 2 {
|
||||
|
@ -672,7 +704,12 @@ fn is_short_circuit(
|
|||
expected_op: BoolOp,
|
||||
checker: &Checker,
|
||||
) -> Option<(Edit, ContentAround)> {
|
||||
let Expr::BoolOp(ast::ExprBoolOp { op, values, range: _, }) = expr else {
|
||||
let Expr::BoolOp(ast::ExprBoolOp {
|
||||
op,
|
||||
values,
|
||||
range: _,
|
||||
}) = expr
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if *op != expected_op {
|
||||
|
|
|
@ -109,7 +109,11 @@ pub(crate) fn use_capital_environment_variables(checker: &mut Checker, expr: &Ex
|
|||
let Some(arg) = args.get(0) else {
|
||||
return;
|
||||
};
|
||||
let Expr::Constant(ast::ExprConstant { value: Constant::Str(env_var), .. }) = arg else {
|
||||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Str(env_var),
|
||||
..
|
||||
}) = arg
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !checker
|
||||
|
@ -143,7 +147,12 @@ fn check_os_environ_subscript(checker: &mut Checker, expr: &Expr) {
|
|||
let Expr::Subscript(ast::ExprSubscript { value, slice, .. }) = expr else {
|
||||
return;
|
||||
};
|
||||
let Expr::Attribute(ast::ExprAttribute { value: attr_value, attr, .. }) = value.as_ref() else {
|
||||
let Expr::Attribute(ast::ExprAttribute {
|
||||
value: attr_value,
|
||||
attr,
|
||||
..
|
||||
}) = value.as_ref()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Expr::Name(ast::ExprName { id, .. }) = attr_value.as_ref() else {
|
||||
|
@ -152,7 +161,12 @@ fn check_os_environ_subscript(checker: &mut Checker, expr: &Expr) {
|
|||
if id != "os" || attr != "environ" {
|
||||
return;
|
||||
}
|
||||
let Expr::Constant(ast::ExprConstant { value: Constant::Str(env_var), kind, range: _ }) = slice.as_ref() else {
|
||||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Str(env_var),
|
||||
kind,
|
||||
range: _,
|
||||
}) = slice.as_ref()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let capital_env_var = env_var.to_ascii_uppercase();
|
||||
|
@ -184,7 +198,13 @@ fn check_os_environ_subscript(checker: &mut Checker, expr: &Expr) {
|
|||
|
||||
/// SIM910
|
||||
pub(crate) fn dict_get_with_none_default(checker: &mut Checker, expr: &Expr) {
|
||||
let Expr::Call(ast::ExprCall { func, args, keywords, range: _ }) = expr else {
|
||||
let Expr::Call(ast::ExprCall {
|
||||
func,
|
||||
args,
|
||||
keywords,
|
||||
range: _,
|
||||
}) = expr
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !keywords.is_empty() {
|
||||
|
|
|
@ -300,7 +300,15 @@ fn is_main_check(expr: &Expr) -> bool {
|
|||
/// ...
|
||||
/// ```
|
||||
fn find_last_nested_if(body: &[Stmt]) -> Option<(&Expr, &Stmt)> {
|
||||
let [Stmt::If(ast::StmtIf { test, body: inner_body, orelse, .. })] = body else { return None };
|
||||
let [Stmt::If(ast::StmtIf {
|
||||
test,
|
||||
body: inner_body,
|
||||
orelse,
|
||||
..
|
||||
})] = body
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if !orelse.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
@ -429,10 +437,19 @@ fn is_one_line_return_bool(stmts: &[Stmt]) -> Option<Bool> {
|
|||
|
||||
/// SIM103
|
||||
pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) {
|
||||
let Stmt::If(ast::StmtIf { test, body, orelse, range: _ }) = stmt else {
|
||||
let Stmt::If(ast::StmtIf {
|
||||
test,
|
||||
body,
|
||||
orelse,
|
||||
range: _,
|
||||
}) = stmt
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let (Some(if_return), Some(else_return)) = (is_one_line_return_bool(body), is_one_line_return_bool(orelse)) else {
|
||||
let (Some(if_return), Some(else_return)) = (
|
||||
is_one_line_return_bool(body),
|
||||
is_one_line_return_bool(orelse),
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -515,16 +532,32 @@ fn contains_call_path(expr: &Expr, target: &[&str], semantic: &SemanticModel) ->
|
|||
|
||||
/// SIM108
|
||||
pub(crate) fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: Option<&Stmt>) {
|
||||
let Stmt::If(ast::StmtIf { test, body, orelse, range: _ } )= stmt else {
|
||||
let Stmt::If(ast::StmtIf {
|
||||
test,
|
||||
body,
|
||||
orelse,
|
||||
range: _,
|
||||
}) = stmt
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if body.len() != 1 || orelse.len() != 1 {
|
||||
return;
|
||||
}
|
||||
let Stmt::Assign(ast::StmtAssign { targets: body_targets, value: body_value, .. } )= &body[0] else {
|
||||
let Stmt::Assign(ast::StmtAssign {
|
||||
targets: body_targets,
|
||||
value: body_value,
|
||||
..
|
||||
}) = &body[0]
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Stmt::Assign(ast::StmtAssign { targets: orelse_targets, value: orelse_value, .. } )= &orelse[0] else {
|
||||
let Stmt::Assign(ast::StmtAssign {
|
||||
targets: orelse_targets,
|
||||
value: orelse_value,
|
||||
..
|
||||
}) = &orelse[0]
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if body_targets.len() != 1 || orelse_targets.len() != 1 {
|
||||
|
@ -638,7 +671,13 @@ fn get_if_body_pairs<'a>(
|
|||
if orelse.len() != 1 {
|
||||
break;
|
||||
}
|
||||
let Stmt::If(ast::StmtIf { test, body, orelse: orelse_orelse, range: _ }) = &orelse[0] else {
|
||||
let Stmt::If(ast::StmtIf {
|
||||
test,
|
||||
body,
|
||||
orelse: orelse_orelse,
|
||||
range: _,
|
||||
}) = &orelse[0]
|
||||
else {
|
||||
break;
|
||||
};
|
||||
pairs.push((test, body));
|
||||
|
@ -649,7 +688,13 @@ fn get_if_body_pairs<'a>(
|
|||
|
||||
/// SIM114
|
||||
pub(crate) fn if_with_same_arms(checker: &mut Checker, stmt: &Stmt, parent: Option<&Stmt>) {
|
||||
let Stmt::If(ast::StmtIf { test, body, orelse, range: _ }) = stmt else {
|
||||
let Stmt::If(ast::StmtIf {
|
||||
test,
|
||||
body,
|
||||
orelse,
|
||||
range: _,
|
||||
}) = stmt
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -718,7 +763,8 @@ pub(crate) fn manual_dict_lookup(
|
|||
ops,
|
||||
comparators,
|
||||
range: _,
|
||||
})= &test else {
|
||||
}) = &test
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Expr::Name(ast::ExprName { id: target, .. }) = left.as_ref() else {
|
||||
|
@ -736,7 +782,10 @@ pub(crate) fn manual_dict_lookup(
|
|||
if comparators.len() != 1 {
|
||||
return;
|
||||
}
|
||||
let Expr::Constant(ast::ExprConstant { value: constant, .. }) = &comparators[0] else {
|
||||
let Expr::Constant(ast::ExprConstant {
|
||||
value: constant, ..
|
||||
}) = &comparators[0]
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Stmt::Return(ast::StmtReturn { value, range: _ }) = &body[0] else {
|
||||
|
@ -783,7 +832,13 @@ pub(crate) fn manual_dict_lookup(
|
|||
|
||||
let mut child: Option<&Stmt> = orelse.get(0);
|
||||
while let Some(current) = child.take() {
|
||||
let Stmt::If(ast::StmtIf { test, body, orelse, range: _ }) = ¤t else {
|
||||
let Stmt::If(ast::StmtIf {
|
||||
test,
|
||||
body,
|
||||
orelse,
|
||||
range: _,
|
||||
}) = ¤t
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if body.len() != 1 {
|
||||
|
@ -796,8 +851,9 @@ pub(crate) fn manual_dict_lookup(
|
|||
left,
|
||||
ops,
|
||||
comparators,
|
||||
range: _
|
||||
} )= test.as_ref() else {
|
||||
range: _,
|
||||
}) = test.as_ref()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() else {
|
||||
|
@ -809,7 +865,10 @@ pub(crate) fn manual_dict_lookup(
|
|||
if comparators.len() != 1 {
|
||||
return;
|
||||
}
|
||||
let Expr::Constant(ast::ExprConstant { value: constant, .. } )= &comparators[0] else {
|
||||
let Expr::Constant(ast::ExprConstant {
|
||||
value: constant, ..
|
||||
}) = &comparators[0]
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Stmt::Return(ast::StmtReturn { value, range: _ }) = &body[0] else {
|
||||
|
@ -859,19 +918,35 @@ pub(crate) fn use_dict_get_with_default(
|
|||
if body.len() != 1 || orelse.len() != 1 {
|
||||
return;
|
||||
}
|
||||
let Stmt::Assign(ast::StmtAssign { targets: body_var, value: body_value, ..}) = &body[0] else {
|
||||
let Stmt::Assign(ast::StmtAssign {
|
||||
targets: body_var,
|
||||
value: body_value,
|
||||
..
|
||||
}) = &body[0]
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if body_var.len() != 1 {
|
||||
return;
|
||||
};
|
||||
let Stmt::Assign(ast::StmtAssign { targets: orelse_var, value: orelse_value, .. }) = &orelse[0] else {
|
||||
let Stmt::Assign(ast::StmtAssign {
|
||||
targets: orelse_var,
|
||||
value: orelse_value,
|
||||
..
|
||||
}) = &orelse[0]
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if orelse_var.len() != 1 {
|
||||
return;
|
||||
};
|
||||
let Expr::Compare(ast::ExprCompare { left: test_key, ops , comparators: test_dict, range: _ }) = &test else {
|
||||
let Expr::Compare(ast::ExprCompare {
|
||||
left: test_key,
|
||||
ops,
|
||||
comparators: test_dict,
|
||||
range: _,
|
||||
}) = &test
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if test_dict.len() != 1 {
|
||||
|
@ -885,7 +960,12 @@ pub(crate) fn use_dict_get_with_default(
|
|||
}
|
||||
};
|
||||
let test_dict = &test_dict[0];
|
||||
let Expr::Subscript(ast::ExprSubscript { value: expected_subscript, slice: expected_slice, .. } ) = expected_value.as_ref() else {
|
||||
let Expr::Subscript(ast::ExprSubscript {
|
||||
value: expected_subscript,
|
||||
slice: expected_slice,
|
||||
..
|
||||
}) = expected_value.as_ref()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -237,7 +237,12 @@ pub(crate) fn twisted_arms_in_ifexpr(
|
|||
body: &Expr,
|
||||
orelse: &Expr,
|
||||
) {
|
||||
let Expr::UnaryOp(ast::ExprUnaryOp { op, operand: test_operand, range: _ } )= &test else {
|
||||
let Expr::UnaryOp(ast::ExprUnaryOp {
|
||||
op,
|
||||
operand: test_operand,
|
||||
range: _,
|
||||
}) = &test
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !op.is_not() {
|
||||
|
|
|
@ -127,7 +127,13 @@ fn is_dunder_method(name: &str) -> bool {
|
|||
}
|
||||
|
||||
fn is_exception_check(stmt: &Stmt) -> bool {
|
||||
let Stmt::If(ast::StmtIf {test: _, body, orelse: _, range: _ })= stmt else {
|
||||
let Stmt::If(ast::StmtIf {
|
||||
test: _,
|
||||
body,
|
||||
orelse: _,
|
||||
range: _,
|
||||
}) = stmt
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
if body.len() != 1 {
|
||||
|
@ -149,7 +155,13 @@ pub(crate) fn negation_with_equal_op(
|
|||
if !matches!(op, UnaryOp::Not) {
|
||||
return;
|
||||
}
|
||||
let Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _}) = operand else {
|
||||
let Expr::Compare(ast::ExprCompare {
|
||||
left,
|
||||
ops,
|
||||
comparators,
|
||||
range: _,
|
||||
}) = operand
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !matches!(&ops[..], [CmpOp::Eq]) {
|
||||
|
@ -201,7 +213,13 @@ pub(crate) fn negation_with_not_equal_op(
|
|||
if !matches!(op, UnaryOp::Not) {
|
||||
return;
|
||||
}
|
||||
let Expr::Compare(ast::ExprCompare { left, ops, comparators, range: _}) = operand else {
|
||||
let Expr::Compare(ast::ExprCompare {
|
||||
left,
|
||||
ops,
|
||||
comparators,
|
||||
range: _,
|
||||
}) = operand
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !matches!(&ops[..], [CmpOp::NotEq]) {
|
||||
|
@ -248,7 +266,12 @@ pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: UnaryOp, o
|
|||
if !matches!(op, UnaryOp::Not) {
|
||||
return;
|
||||
}
|
||||
let Expr::UnaryOp(ast::ExprUnaryOp { op: operand_op, operand, range: _ }) = operand else {
|
||||
let Expr::UnaryOp(ast::ExprUnaryOp {
|
||||
op: operand_op,
|
||||
operand,
|
||||
range: _,
|
||||
}) = operand
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !matches!(operand_op, UnaryOp::Not) {
|
||||
|
|
|
@ -90,7 +90,8 @@ pub(crate) fn fix_nested_if_statements(
|
|||
body: Suite::IndentedBlock(ref mut outer_body),
|
||||
orelse: None,
|
||||
..
|
||||
} = outer_if else {
|
||||
} = outer_if
|
||||
else {
|
||||
bail!("Expected outer if to have indented body and no else")
|
||||
};
|
||||
|
||||
|
|
|
@ -54,13 +54,12 @@ pub(crate) fn fix_multiple_with_statements(
|
|||
let With {
|
||||
body: Suite::IndentedBlock(ref mut outer_body),
|
||||
..
|
||||
} = outer_with else {
|
||||
} = outer_with
|
||||
else {
|
||||
bail!("Expected outer with to have indented body")
|
||||
};
|
||||
|
||||
let [Statement::Compound(CompoundStatement::With(inner_with))] =
|
||||
&mut *outer_body.body
|
||||
else {
|
||||
let [Statement::Compound(CompoundStatement::With(inner_with))] = &mut *outer_body.body else {
|
||||
bail!("Expected one inner with statement");
|
||||
};
|
||||
|
||||
|
|
|
@ -71,8 +71,9 @@ fn key_in_dict(checker: &mut Checker, left: &Expr, right: &Expr, range: TextRang
|
|||
func,
|
||||
args,
|
||||
keywords,
|
||||
range: _
|
||||
}) = &right else {
|
||||
range: _,
|
||||
}) = &right
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !(args.is_empty() && keywords.is_empty()) {
|
||||
|
|
|
@ -221,7 +221,8 @@ fn return_values_for_else(stmt: &Stmt) -> Option<Loop> {
|
|||
iter,
|
||||
orelse,
|
||||
..
|
||||
}) = stmt else {
|
||||
}) = stmt
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
@ -236,8 +237,10 @@ fn return_values_for_else(stmt: &Stmt) -> Option<Loop> {
|
|||
let Stmt::If(ast::StmtIf {
|
||||
body: nested_body,
|
||||
test: nested_test,
|
||||
orelse: nested_orelse, range: _,
|
||||
}) = &body[0] else {
|
||||
orelse: nested_orelse,
|
||||
range: _,
|
||||
}) = &body[0]
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if nested_body.len() != 1 {
|
||||
|
@ -252,18 +255,30 @@ fn return_values_for_else(stmt: &Stmt) -> Option<Loop> {
|
|||
let Some(value) = value else {
|
||||
return None;
|
||||
};
|
||||
let Expr::Constant(ast::ExprConstant { value: Constant::Bool(value), .. }) = value.as_ref() else {
|
||||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Bool(value),
|
||||
..
|
||||
}) = value.as_ref()
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
// The `else` block has to contain a single `return True` or `return False`.
|
||||
let Stmt::Return(ast::StmtReturn { value: next_value, range: _ }) = &orelse[0] else {
|
||||
let Stmt::Return(ast::StmtReturn {
|
||||
value: next_value,
|
||||
range: _,
|
||||
}) = &orelse[0]
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
let Some(next_value) = next_value else {
|
||||
return None;
|
||||
};
|
||||
let Expr::Constant(ast::ExprConstant { value: Constant::Bool(next_value), .. }) = next_value.as_ref() else {
|
||||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Bool(next_value),
|
||||
..
|
||||
}) = next_value.as_ref()
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
@ -286,7 +301,8 @@ fn return_values_for_siblings<'a>(stmt: &'a Stmt, sibling: &'a Stmt) -> Option<L
|
|||
iter,
|
||||
orelse,
|
||||
..
|
||||
}) = stmt else {
|
||||
}) = stmt
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
@ -301,8 +317,10 @@ fn return_values_for_siblings<'a>(stmt: &'a Stmt, sibling: &'a Stmt) -> Option<L
|
|||
let Stmt::If(ast::StmtIf {
|
||||
body: nested_body,
|
||||
test: nested_test,
|
||||
orelse: nested_orelse, range: _,
|
||||
}) = &body[0] else {
|
||||
orelse: nested_orelse,
|
||||
range: _,
|
||||
}) = &body[0]
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if nested_body.len() != 1 {
|
||||
|
@ -317,18 +335,30 @@ fn return_values_for_siblings<'a>(stmt: &'a Stmt, sibling: &'a Stmt) -> Option<L
|
|||
let Some(value) = value else {
|
||||
return None;
|
||||
};
|
||||
let Expr::Constant(ast::ExprConstant { value: Constant::Bool(value), .. }) = value.as_ref() else {
|
||||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Bool(value),
|
||||
..
|
||||
}) = value.as_ref()
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
// The next statement has to be a `return True` or `return False`.
|
||||
let Stmt::Return(ast::StmtReturn { value: next_value, range: _ }) = &sibling else {
|
||||
let Stmt::Return(ast::StmtReturn {
|
||||
value: next_value,
|
||||
range: _,
|
||||
}) = &sibling
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
let Some(next_value) = next_value else {
|
||||
return None;
|
||||
};
|
||||
let Expr::Constant(ast::ExprConstant { value: Constant::Bool(next_value), .. }) = next_value.as_ref() else {
|
||||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Bool(next_value),
|
||||
..
|
||||
}) = next_value.as_ref()
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
|
|
@ -88,11 +88,7 @@ fn build_fstring(joiner: &str, joinees: &[Expr]) -> Option<Expr> {
|
|||
}
|
||||
|
||||
pub(crate) fn static_join_to_fstring(checker: &mut Checker, expr: &Expr, joiner: &str) {
|
||||
let Expr::Call(ast::ExprCall {
|
||||
args,
|
||||
keywords,
|
||||
..
|
||||
}) = expr else {
|
||||
let Expr::Call(ast::ExprCall { args, keywords, .. }) = expr else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -111,7 +107,9 @@ pub(crate) fn static_join_to_fstring(checker: &mut Checker, expr: &Expr, joiner:
|
|||
|
||||
// Try to build the fstring (internally checks whether e.g. the elements are
|
||||
// convertible to f-string parts).
|
||||
let Some(new_expr) = build_fstring(joiner, joinees) else { return };
|
||||
let Some(new_expr) = build_fstring(joiner, joinees) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker.generator().expr(&new_expr);
|
||||
|
||||
|
|
|
@ -56,10 +56,7 @@ impl AlwaysAutofixableViolation for MissingRequiredImport {
|
|||
fn includes_import(stmt: &Stmt, target: &AnyImport) -> bool {
|
||||
match target {
|
||||
AnyImport::Import(target) => {
|
||||
let Stmt::Import(ast::StmtImport {
|
||||
names,
|
||||
range: _,
|
||||
}) = &stmt else {
|
||||
let Stmt::Import(ast::StmtImport { names, range: _ }) = &stmt else {
|
||||
return false;
|
||||
};
|
||||
names.iter().any(|alias| {
|
||||
|
@ -72,7 +69,8 @@ fn includes_import(stmt: &Stmt, target: &AnyImport) -> bool {
|
|||
names,
|
||||
level,
|
||||
range: _,
|
||||
}) = &stmt else {
|
||||
}) = &stmt
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
module.as_deref() == target.module
|
||||
|
|
|
@ -56,12 +56,8 @@ impl AlwaysAutofixableViolation for IncorrectDictIterator {
|
|||
|
||||
/// PERF102
|
||||
pub(crate) fn incorrect_dict_iterator(checker: &mut Checker, target: &Expr, iter: &Expr) {
|
||||
let Expr::Tuple(ast::ExprTuple {
|
||||
elts,
|
||||
..
|
||||
}) = target
|
||||
else {
|
||||
return
|
||||
let Expr::Tuple(ast::ExprTuple { elts, .. }) = target else {
|
||||
return;
|
||||
};
|
||||
if elts.len() != 2 {
|
||||
return;
|
||||
|
|
|
@ -48,7 +48,13 @@ impl AlwaysAutofixableViolation for UnnecessaryListCast {
|
|||
|
||||
/// PERF101
|
||||
pub(crate) fn unnecessary_list_cast(checker: &mut Checker, iter: &Expr) {
|
||||
let Expr::Call(ast::ExprCall{ func, args, range: list_range, ..}) = iter else {
|
||||
let Expr::Call(ast::ExprCall {
|
||||
func,
|
||||
args,
|
||||
range: list_range,
|
||||
..
|
||||
}) = iter
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -164,7 +164,8 @@ pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstr
|
|||
kind: MemberKind::Class | MemberKind::NestedClass,
|
||||
stmt,
|
||||
..
|
||||
}) = docstring.definition else {
|
||||
}) = docstring.definition
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -107,7 +107,8 @@ pub(crate) fn blank_before_after_function(checker: &mut Checker, docstring: &Doc
|
|||
kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method,
|
||||
stmt,
|
||||
..
|
||||
}) = docstring.definition else {
|
||||
}) = docstring.definition
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ pub(crate) fn capitalized(checker: &mut Checker, docstring: &Docstring) {
|
|||
|
||||
let body = docstring.body();
|
||||
let Some(first_word) = body.split(' ').next() else {
|
||||
return
|
||||
return;
|
||||
};
|
||||
|
||||
// Like pydocstyle, we only support ASCII for now.
|
||||
|
|
|
@ -84,7 +84,8 @@ pub(crate) fn if_needed(checker: &mut Checker, docstring: &Docstring) {
|
|||
kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method,
|
||||
stmt,
|
||||
..
|
||||
}) = docstring.definition else {
|
||||
}) = docstring.definition
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !is_overload(cast::decorator_list(stmt), checker.semantic()) {
|
||||
|
|
|
@ -132,10 +132,7 @@ pub(crate) fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstr
|
|||
};
|
||||
let mut content_lines = UniversalNewlineIterator::with_offset(contents, docstring.start());
|
||||
|
||||
let Some(first_line) = content_lines
|
||||
.next()
|
||||
else
|
||||
{
|
||||
let Some(first_line) = content_lines.next() else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -58,7 +58,8 @@ pub(crate) fn no_signature(checker: &mut Checker, docstring: &Docstring) {
|
|||
kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method,
|
||||
stmt,
|
||||
..
|
||||
}) = docstring.definition else {
|
||||
}) = docstring.definition
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let Stmt::FunctionDef(ast::StmtFunctionDef { name, .. }) = stmt else {
|
||||
|
|
|
@ -1715,18 +1715,18 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: &
|
|||
kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method,
|
||||
stmt,
|
||||
..
|
||||
}) = docstring.definition else {
|
||||
}) = docstring.definition
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let (
|
||||
Stmt::FunctionDef(ast::StmtFunctionDef {
|
||||
let (Stmt::FunctionDef(ast::StmtFunctionDef {
|
||||
args: arguments, ..
|
||||
})
|
||||
| Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
|
||||
args: arguments, ..
|
||||
})
|
||||
) = stmt else {
|
||||
})) = stmt
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ pub(crate) fn starts_with_this(checker: &mut Checker, docstring: &Docstring) {
|
|||
}
|
||||
|
||||
let Some(first_word) = trimmed.split(' ').next() else {
|
||||
return
|
||||
return;
|
||||
};
|
||||
if normalize_word(first_word) != "this" {
|
||||
return;
|
||||
|
|
|
@ -25,8 +25,8 @@ impl From<&CFormatString> for CFormatSummary {
|
|||
ref min_field_width,
|
||||
ref precision,
|
||||
..
|
||||
}) = format_part.1 else
|
||||
{
|
||||
}) = format_part.1
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
match mapping_key {
|
||||
|
|
|
@ -44,7 +44,8 @@ impl TryFrom<&str> for FormatSummary {
|
|||
field_name,
|
||||
format_spec,
|
||||
..
|
||||
} = format_part else {
|
||||
} = format_part
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let parsed = FieldName::parse(field_name)?;
|
||||
|
|
|
@ -10,18 +10,17 @@ use crate::settings::Settings;
|
|||
|
||||
pub(super) fn in_dunder_init(semantic: &SemanticModel, settings: &Settings) -> bool {
|
||||
let scope = semantic.scope();
|
||||
let (
|
||||
ScopeKind::Function(ast::StmtFunctionDef {
|
||||
name,
|
||||
decorator_list,
|
||||
..
|
||||
}) |
|
||||
ScopeKind::AsyncFunction(ast::StmtAsyncFunctionDef {
|
||||
let (ScopeKind::Function(ast::StmtFunctionDef {
|
||||
name,
|
||||
decorator_list,
|
||||
..
|
||||
})
|
||||
) = scope.kind else {
|
||||
| ScopeKind::AsyncFunction(ast::StmtAsyncFunctionDef {
|
||||
name,
|
||||
decorator_list,
|
||||
..
|
||||
})) = scope.kind
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
if name != "__init__" {
|
||||
|
|
|
@ -60,7 +60,8 @@ pub(crate) fn import_from_self(
|
|||
let Some(module_path) = module_path else {
|
||||
return None;
|
||||
};
|
||||
let Some(imported_module_path) = resolve_imported_module_path(level, module, Some(module_path)) else {
|
||||
let Some(imported_module_path) = resolve_imported_module_path(level, module, Some(module_path))
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
|
|
@ -94,7 +94,12 @@ pub(crate) fn invalid_envvar_default(
|
|||
let Some(expr) = args.get(1).or_else(|| {
|
||||
keywords
|
||||
.iter()
|
||||
.find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg .as_str()== "default"))
|
||||
.find(|keyword| {
|
||||
keyword
|
||||
.arg
|
||||
.as_ref()
|
||||
.map_or(false, |arg| arg.as_str() == "default")
|
||||
})
|
||||
.map(|keyword| &keyword.value)
|
||||
}) else {
|
||||
return;
|
||||
|
|
|
@ -160,7 +160,9 @@ pub(crate) fn unexpected_special_method_signature(
|
|||
let actual_params = args.args.len();
|
||||
let mandatory_params = args.args.iter().filter(|arg| arg.default.is_none()).count();
|
||||
|
||||
let Some(expected_params) = ExpectedParams::from_method(name, is_staticmethod(decorator_list, checker.semantic())) else {
|
||||
let Some(expected_params) =
|
||||
ExpectedParams::from_method(name, is_staticmethod(decorator_list, checker.semantic()))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -81,7 +81,8 @@ fn match_named_tuple_assign<'a>(
|
|||
args,
|
||||
keywords,
|
||||
range: _,
|
||||
}) = value else {
|
||||
}) = value
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if !semantic.match_typing_expr(func, "NamedTuple") {
|
||||
|
@ -136,7 +137,9 @@ fn match_defaults(keywords: &[Keyword]) -> Result<&[Expr]> {
|
|||
/// Create a list of property assignments from the `NamedTuple` arguments.
|
||||
fn create_properties_from_args(args: &[Expr], defaults: &[Expr]) -> Result<Vec<Stmt>> {
|
||||
let Some(fields) = args.get(1) else {
|
||||
let node = Stmt::Pass(ast::StmtPass { range: TextRange::default()});
|
||||
let node = Stmt::Pass(ast::StmtPass {
|
||||
range: TextRange::default(),
|
||||
});
|
||||
return Ok(vec![node]);
|
||||
};
|
||||
let Expr::List(ast::ExprList { elts, .. }) = &fields else {
|
||||
|
@ -167,7 +170,8 @@ fn create_properties_from_args(args: &[Expr], defaults: &[Expr]) -> Result<Vec<S
|
|||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Str(property),
|
||||
..
|
||||
}) = &field_name else {
|
||||
}) = &field_name
|
||||
else {
|
||||
bail!("Expected `field_name` to be `Constant::Str`")
|
||||
};
|
||||
if !is_identifier(property) {
|
||||
|
@ -219,8 +223,8 @@ pub(crate) fn convert_named_tuple_functional_to_class(
|
|||
value: &Expr,
|
||||
) {
|
||||
let Some((typename, args, keywords, base_class)) =
|
||||
match_named_tuple_assign(targets, value, checker.semantic()) else
|
||||
{
|
||||
match_named_tuple_assign(targets, value, checker.semantic())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -79,8 +79,9 @@ fn match_typed_dict_assign<'a>(
|
|||
func,
|
||||
args,
|
||||
keywords,
|
||||
range: _
|
||||
}) = value else {
|
||||
range: _,
|
||||
}) = value
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if !semantic.match_typing_expr(func, "TypedDict") {
|
||||
|
@ -205,7 +206,7 @@ fn properties_from_keywords(keywords: &[Keyword]) -> Result<Vec<Stmt>> {
|
|||
fn match_total_from_only_keyword(keywords: &[Keyword]) -> Option<&Keyword> {
|
||||
keywords.iter().find(|keyword| {
|
||||
let Some(arg) = &keyword.arg else {
|
||||
return false
|
||||
return false;
|
||||
};
|
||||
arg.as_str() == "total"
|
||||
})
|
||||
|
@ -271,8 +272,8 @@ pub(crate) fn convert_typed_dict_functional_to_class(
|
|||
value: &Expr,
|
||||
) {
|
||||
let Some((class_name, args, keywords, base_class)) =
|
||||
match_typed_dict_assign(targets, value, checker.semantic()) else
|
||||
{
|
||||
match_typed_dict_assign(targets, value, checker.semantic())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -64,7 +64,8 @@ pub(crate) fn lru_cache_with_maxsize_none(checker: &mut Checker, decorator_list:
|
|||
args,
|
||||
keywords,
|
||||
range: _,
|
||||
}) = &decorator.expression else {
|
||||
}) = &decorator.expression
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
|
@ -62,7 +62,8 @@ pub(crate) fn lru_cache_without_parameters(checker: &mut Checker, decorator_list
|
|||
args,
|
||||
keywords,
|
||||
range: _,
|
||||
}) = &decorator.expression else {
|
||||
}) = &decorator.expression
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
|
@ -88,11 +88,16 @@ pub(crate) fn native_literals(
|
|||
|
||||
if (id == "str" || id == "bytes") && checker.semantic().is_builtin(id) {
|
||||
let Some(arg) = args.get(0) else {
|
||||
let mut diagnostic = Diagnostic::new(NativeLiterals{literal_type:if id == "str" {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
NativeLiterals {
|
||||
literal_type: if id == "str" {
|
||||
LiteralType::Str
|
||||
} else {
|
||||
LiteralType::Bytes
|
||||
}}, expr.range());
|
||||
},
|
||||
},
|
||||
expr.range(),
|
||||
);
|
||||
if checker.patch(diagnostic.kind.rule()) {
|
||||
let constant = if id == "bytes" {
|
||||
Constant::Bytes(vec![])
|
||||
|
|
|
@ -223,7 +223,11 @@ fn fix_py2_block(
|
|||
let parent = checker.semantic().stmt_parent();
|
||||
let edit = delete_stmt(
|
||||
stmt,
|
||||
if matches!(block.leading_token.tok, StartTok::If) { parent } else { None },
|
||||
if matches!(block.leading_token.tok, StartTok::If) {
|
||||
parent
|
||||
} else {
|
||||
None
|
||||
},
|
||||
checker.locator,
|
||||
checker.indexer,
|
||||
);
|
||||
|
@ -348,7 +352,8 @@ pub(crate) fn outdated_version_block(
|
|||
ops,
|
||||
comparators,
|
||||
range: _,
|
||||
}) = &test else {
|
||||
}) = &test
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -99,22 +99,27 @@ pub(crate) fn super_call_with_parameters(
|
|||
// Find the enclosing function definition (if any).
|
||||
let Some(Stmt::FunctionDef(ast::StmtFunctionDef {
|
||||
args: parent_args, ..
|
||||
})) = parents.find(|stmt| stmt.is_function_def_stmt()) else {
|
||||
})) = parents.find(|stmt| stmt.is_function_def_stmt())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Extract the name of the first argument to the enclosing function.
|
||||
let Some(ArgWithDefault {
|
||||
def: Arg { arg: parent_arg, .. },
|
||||
def: Arg {
|
||||
arg: parent_arg, ..
|
||||
},
|
||||
..
|
||||
}) = parent_args.args.first() else {
|
||||
}) = parent_args.args.first()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Find the enclosing class definition (if any).
|
||||
let Some(Stmt::ClassDef(ast::StmtClassDef {
|
||||
name: parent_name, ..
|
||||
})) = parents.find(|stmt| stmt.is_class_def_stmt()) else {
|
||||
})) = parents.find(|stmt| stmt.is_class_def_stmt())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -125,7 +130,8 @@ pub(crate) fn super_call_with_parameters(
|
|||
Expr::Name(ast::ExprName {
|
||||
id: second_arg_id, ..
|
||||
}),
|
||||
) = (first_arg, second_arg) else {
|
||||
) = (first_arg, second_arg)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@ fn match_encoded_variable(func: &Expr) -> Option<&Expr> {
|
|||
value: variable,
|
||||
attr,
|
||||
..
|
||||
}) = func else {
|
||||
}) = func
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if attr != "encode" {
|
||||
|
|
|
@ -56,7 +56,8 @@ pub(crate) fn unpacked_list_comprehension(checker: &mut Checker, targets: &[Expr
|
|||
elt,
|
||||
generators,
|
||||
range: _,
|
||||
}) = value else {
|
||||
}) = value
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -86,7 +86,13 @@ enum Type {
|
|||
|
||||
/// Recursively merge all the tuples and lists in the expression.
|
||||
fn concatenate_expressions(expr: &Expr) -> Option<(Expr, Type)> {
|
||||
let Expr::BinOp(ast::ExprBinOp { left, op: Operator::Add, right, range: _ }) = expr else {
|
||||
let Expr::BinOp(ast::ExprBinOp {
|
||||
left,
|
||||
op: Operator::Add,
|
||||
right,
|
||||
range: _,
|
||||
}) = expr
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
@ -171,7 +177,7 @@ pub(crate) fn collection_literal_concatenation(checker: &mut Checker, expr: &Exp
|
|||
}
|
||||
|
||||
let Some((new_expr, type_)) = concatenate_expressions(expr) else {
|
||||
return
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = match type_ {
|
||||
|
|
|
@ -82,7 +82,8 @@ pub(crate) fn explicit_f_string_type_conversion(
|
|||
args,
|
||||
keywords,
|
||||
..
|
||||
}) = value.as_ref() else {
|
||||
}) = value.as_ref()
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
|
|
|
@ -266,31 +266,41 @@ impl<'a> TypingTarget<'a> {
|
|||
| TypingTarget::Any
|
||||
| TypingTarget::Object => true,
|
||||
TypingTarget::Literal(elements) => elements.iter().any(|element| {
|
||||
let Some(new_target) = TypingTarget::try_from_expr(element, semantic, locator, target_version) else {
|
||||
let Some(new_target) =
|
||||
TypingTarget::try_from_expr(element, semantic, locator, target_version)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
// Literal can only contain `None`, a literal value, other `Literal`
|
||||
// or an enum value.
|
||||
match new_target {
|
||||
TypingTarget::None => true,
|
||||
TypingTarget::Literal(_) => new_target.contains_none(semantic, locator, target_version),
|
||||
TypingTarget::Literal(_) => {
|
||||
new_target.contains_none(semantic, locator, target_version)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}),
|
||||
TypingTarget::Union(elements) => elements.iter().any(|element| {
|
||||
let Some(new_target) = TypingTarget::try_from_expr(element, semantic, locator, target_version) else {
|
||||
let Some(new_target) =
|
||||
TypingTarget::try_from_expr(element, semantic, locator, target_version)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
new_target.contains_none(semantic, locator, target_version)
|
||||
}),
|
||||
TypingTarget::Annotated(element) => {
|
||||
let Some(new_target) = TypingTarget::try_from_expr(element, semantic, locator, target_version) else {
|
||||
let Some(new_target) =
|
||||
TypingTarget::try_from_expr(element, semantic, locator, target_version)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
new_target.contains_none(semantic, locator, target_version)
|
||||
}
|
||||
TypingTarget::ForwardReference(expr) => {
|
||||
let Some(new_target) = TypingTarget::try_from_expr(expr, semantic, locator, target_version) else {
|
||||
let Some(new_target) =
|
||||
TypingTarget::try_from_expr(expr, semantic, locator, target_version)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
new_target.contains_none(semantic, locator, target_version)
|
||||
|
@ -312,7 +322,8 @@ fn type_hint_explicitly_allows_none<'a>(
|
|||
locator: &Locator,
|
||||
target_version: PythonVersion,
|
||||
) -> Option<&'a Expr> {
|
||||
let Some(target) = TypingTarget::try_from_expr(annotation, semantic, locator, target_version) else {
|
||||
let Some(target) = TypingTarget::try_from_expr(annotation, semantic, locator, target_version)
|
||||
else {
|
||||
return Some(annotation);
|
||||
};
|
||||
match target {
|
||||
|
@ -392,14 +403,12 @@ pub(crate) fn implicit_optional(checker: &mut Checker, arguments: &Arguments) {
|
|||
.chain(&arguments.args)
|
||||
.chain(&arguments.kwonlyargs)
|
||||
{
|
||||
let Some(default) = default else {
|
||||
continue
|
||||
};
|
||||
let Some(default) = default else { continue };
|
||||
if !is_const_none(default) {
|
||||
continue;
|
||||
}
|
||||
let Some(annotation) = &def.annotation else {
|
||||
continue
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Expr::Constant(ast::ExprConstant {
|
||||
|
@ -410,7 +419,12 @@ pub(crate) fn implicit_optional(checker: &mut Checker, arguments: &Arguments) {
|
|||
{
|
||||
// Quoted annotation.
|
||||
if let Ok((annotation, kind)) = parse_type_annotation(string, *range, checker.locator) {
|
||||
let Some(expr) = type_hint_explicitly_allows_none(&annotation, checker.semantic(), checker.locator, checker.settings.target_version) else {
|
||||
let Some(expr) = type_hint_explicitly_allows_none(
|
||||
&annotation,
|
||||
checker.semantic(),
|
||||
checker.locator,
|
||||
checker.settings.target_version,
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
let conversion_type = checker.settings.target_version.into();
|
||||
|
@ -426,7 +440,12 @@ pub(crate) fn implicit_optional(checker: &mut Checker, arguments: &Arguments) {
|
|||
}
|
||||
} else {
|
||||
// Unquoted annotation.
|
||||
let Some(expr) = type_hint_explicitly_allows_none(annotation, checker.semantic(), checker.locator, checker.settings.target_version) else {
|
||||
let Some(expr) = type_hint_explicitly_allows_none(
|
||||
annotation,
|
||||
checker.semantic(),
|
||||
checker.locator,
|
||||
checker.settings.target_version,
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
let conversion_type = checker.settings.target_version.into();
|
||||
|
|
|
@ -44,7 +44,10 @@ pub(crate) fn useless_try_except(checker: &mut Checker, handlers: &[ExceptHandle
|
|||
.map(|handler| {
|
||||
let ExceptHandler::ExceptHandler(ExceptHandlerExceptHandler { name, body, .. }) =
|
||||
handler;
|
||||
let Some(Stmt::Raise(ast::StmtRaise { exc, cause: None, .. })) = &body.first() else {
|
||||
let Some(Stmt::Raise(ast::StmtRaise {
|
||||
exc, cause: None, ..
|
||||
})) = &body.first()
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
if let Some(expr) = exc {
|
||||
|
|
|
@ -23,7 +23,9 @@ pub(crate) fn show_settings(
|
|||
let Some(entry) = paths
|
||||
.iter()
|
||||
.flatten()
|
||||
.sorted_by(|a, b| a.path().cmp(b.path())).next() else {
|
||||
.sorted_by(|a, b| a.path().cmp(b.path()))
|
||||
.next()
|
||||
else {
|
||||
bail!("No files found under the given path");
|
||||
};
|
||||
let path = entry.path();
|
||||
|
|
|
@ -46,18 +46,24 @@ pub(crate) fn generate() -> String {
|
|||
|
||||
// Generate all the top-level fields.
|
||||
for (name, entry) in &sorted_options {
|
||||
let OptionEntry::Field(field) = entry else { continue; };
|
||||
let OptionEntry::Field(field) = entry else {
|
||||
continue;
|
||||
};
|
||||
emit_field(&mut output, name, field, None);
|
||||
output.push_str("---\n\n");
|
||||
}
|
||||
|
||||
// Generate all the sub-groups.
|
||||
for (group_name, entry) in &sorted_options {
|
||||
let OptionEntry::Group(fields) = entry else { continue; };
|
||||
let OptionEntry::Group(fields) = entry else {
|
||||
continue;
|
||||
};
|
||||
output.push_str(&format!("### `{group_name}`\n"));
|
||||
output.push('\n');
|
||||
for (name, entry) in fields.iter().sorted_by_key(|(name, _)| name) {
|
||||
let OptionEntry::Field(field) = entry else { continue; };
|
||||
let OptionEntry::Field(field) = entry else {
|
||||
continue;
|
||||
};
|
||||
emit_field(&mut output, name, field, Some(group_name));
|
||||
output.push_str("---\n\n");
|
||||
}
|
||||
|
|
|
@ -19,7 +19,9 @@ pub(crate) fn derive_message_formats(func: &ItemFn) -> TokenStream {
|
|||
}
|
||||
|
||||
fn parse_block(block: &Block, strings: &mut TokenStream) -> Result<(), TokenStream> {
|
||||
let Some(Stmt::Expr(last, _)) = block.stmts.last() else {panic!("expected last statement in block to be an expression")};
|
||||
let Some(Stmt::Expr(last, _)) = block.stmts.last() else {
|
||||
panic!("expected last statement in block to be an expression")
|
||||
};
|
||||
parse_expr(last, strings)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -28,7 +30,9 @@ fn parse_expr(expr: &Expr, strings: &mut TokenStream) -> Result<(), TokenStream>
|
|||
match expr {
|
||||
Expr::Macro(mac) if mac.mac.path.is_ident("format") => {
|
||||
let Some(first_token) = mac.mac.tokens.to_token_stream().into_iter().next() else {
|
||||
return Err(quote_spanned!(expr.span() => compile_error!("expected format! to have an argument")))
|
||||
return Err(
|
||||
quote_spanned!(expr.span() => compile_error!("expected format! to have an argument")),
|
||||
);
|
||||
};
|
||||
strings.extend(quote! {#first_token,});
|
||||
Ok(())
|
||||
|
|
|
@ -31,14 +31,30 @@ struct Rule {
|
|||
|
||||
pub(crate) fn map_codes(func: &ItemFn) -> syn::Result<TokenStream> {
|
||||
let Some(last_stmt) = func.block.stmts.last() else {
|
||||
return Err(Error::new(func.block.span(), "expected body to end in an expression"));
|
||||
return Err(Error::new(
|
||||
func.block.span(),
|
||||
"expected body to end in an expression",
|
||||
));
|
||||
};
|
||||
let Stmt::Expr(Expr::Call(ExprCall { args: some_args, .. }), _) = last_stmt else {
|
||||
return Err(Error::new(last_stmt.span(), "expected last expression to be `Some(match (..) { .. })`"));
|
||||
let Stmt::Expr(
|
||||
Expr::Call(ExprCall {
|
||||
args: some_args, ..
|
||||
}),
|
||||
_,
|
||||
) = last_stmt
|
||||
else {
|
||||
return Err(Error::new(
|
||||
last_stmt.span(),
|
||||
"expected last expression to be `Some(match (..) { .. })`",
|
||||
));
|
||||
};
|
||||
let mut some_args = some_args.into_iter();
|
||||
let (Some(Expr::Match(ExprMatch { arms, .. })), None) = (some_args.next(), some_args.next()) else {
|
||||
return Err(Error::new(last_stmt.span(), "expected last expression to be `Some(match (..) { .. })`"));
|
||||
let (Some(Expr::Match(ExprMatch { arms, .. })), None) = (some_args.next(), some_args.next())
|
||||
else {
|
||||
return Err(Error::new(
|
||||
last_stmt.span(),
|
||||
"expected last expression to be `Some(match (..) { .. })`",
|
||||
));
|
||||
};
|
||||
|
||||
// Map from: linter (e.g., `Flake8Bugbear`) to rule code (e.g.,`"002"`) to rule data (e.g.,
|
||||
|
|
|
@ -6,10 +6,16 @@ use syn::spanned::Spanned;
|
|||
use syn::{Attribute, Data, DataEnum, DeriveInput, Error, ExprLit, Lit, Meta, MetaNameValue};
|
||||
|
||||
pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
|
||||
let DeriveInput { ident, data: Data::Enum(DataEnum {
|
||||
variants, ..
|
||||
}), .. } = input else {
|
||||
return Err(Error::new(input.ident.span(), "only named fields are supported"));
|
||||
let DeriveInput {
|
||||
ident,
|
||||
data: Data::Enum(DataEnum { variants, .. }),
|
||||
..
|
||||
} = input
|
||||
else {
|
||||
return Err(Error::new(
|
||||
input.ident.span(),
|
||||
"only named fields are supported",
|
||||
));
|
||||
};
|
||||
|
||||
let mut parsed = Vec::new();
|
||||
|
@ -53,8 +59,12 @@ pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result<proc_macro2::TokenS
|
|||
));
|
||||
}
|
||||
|
||||
let Some(doc_attr) = variant.attrs.iter().find(|attr| attr.path().is_ident("doc")) else {
|
||||
return Err(Error::new(variant.span(), r#"expected a doc comment"#))
|
||||
let Some(doc_attr) = variant
|
||||
.attrs
|
||||
.iter()
|
||||
.find(|attr| attr.path().is_ident("doc"))
|
||||
else {
|
||||
return Err(Error::new(variant.span(), r#"expected a doc comment"#));
|
||||
};
|
||||
|
||||
let variant_ident = variant.ident;
|
||||
|
@ -125,8 +135,19 @@ pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result<proc_macro2::TokenS
|
|||
/// Parses an attribute in the form of `#[doc = " [name](https://example.com/)"]`
|
||||
/// into a tuple of link label and URL.
|
||||
fn parse_doc_attr(doc_attr: &Attribute) -> syn::Result<(String, String)> {
|
||||
let Meta::NameValue(MetaNameValue{value: syn::Expr::Lit(ExprLit { lit: Lit::Str(doc_lit), ..}), ..}) = &doc_attr.meta else {
|
||||
return Err(Error::new(doc_attr.span(), r#"expected doc attribute to be in the form of #[doc = "..."]"#))
|
||||
let Meta::NameValue(MetaNameValue {
|
||||
value:
|
||||
syn::Expr::Lit(ExprLit {
|
||||
lit: Lit::Str(doc_lit),
|
||||
..
|
||||
}),
|
||||
..
|
||||
}) = &doc_attr.meta
|
||||
else {
|
||||
return Err(Error::new(
|
||||
doc_attr.span(),
|
||||
r#"expected doc attribute to be in the form of #[doc = "..."]"#,
|
||||
));
|
||||
};
|
||||
parse_markdown_link(doc_lit.value().trim())
|
||||
.map(|(name, url)| (name.to_string(), url.to_string()))
|
||||
|
|
|
@ -1411,11 +1411,18 @@ impl Truthiness {
|
|||
Constant::Ellipsis => Some(true),
|
||||
Constant::Tuple(elts) => Some(!elts.is_empty()),
|
||||
},
|
||||
Expr::JoinedStr(ast::ExprJoinedStr { values, range: _range }) => {
|
||||
Expr::JoinedStr(ast::ExprJoinedStr {
|
||||
values,
|
||||
range: _range,
|
||||
}) => {
|
||||
if values.is_empty() {
|
||||
Some(false)
|
||||
} else if values.iter().any(|value| {
|
||||
let Expr::Constant(ast::ExprConstant { value: Constant::Str(string), .. } )= &value else {
|
||||
let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
}) = &value
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
!string.is_empty()
|
||||
|
@ -1425,14 +1432,30 @@ impl Truthiness {
|
|||
None
|
||||
}
|
||||
}
|
||||
Expr::List(ast::ExprList { elts, range: _range, .. })
|
||||
| Expr::Set(ast::ExprSet { elts, range: _range })
|
||||
| Expr::Tuple(ast::ExprTuple { elts, range: _range,.. }) => Some(!elts.is_empty()),
|
||||
Expr::Dict(ast::ExprDict { keys, range: _range, .. }) => Some(!keys.is_empty()),
|
||||
Expr::List(ast::ExprList {
|
||||
elts,
|
||||
range: _range,
|
||||
..
|
||||
})
|
||||
| Expr::Set(ast::ExprSet {
|
||||
elts,
|
||||
range: _range,
|
||||
})
|
||||
| Expr::Tuple(ast::ExprTuple {
|
||||
elts,
|
||||
range: _range,
|
||||
..
|
||||
}) => Some(!elts.is_empty()),
|
||||
Expr::Dict(ast::ExprDict {
|
||||
keys,
|
||||
range: _range,
|
||||
..
|
||||
}) => Some(!keys.is_empty()),
|
||||
Expr::Call(ast::ExprCall {
|
||||
func,
|
||||
args,
|
||||
keywords, range: _range,
|
||||
keywords,
|
||||
range: _range,
|
||||
}) => {
|
||||
if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() {
|
||||
if is_iterable_initializer(id.as_str(), |id| is_builtin(id)) {
|
||||
|
|
|
@ -188,7 +188,8 @@ pub fn except(handler: &ExceptHandler, locator: &Locator) -> TextRange {
|
|||
pub fn else_(stmt: &Stmt, locator: &Locator) -> Option<TextRange> {
|
||||
let (Stmt::For(ast::StmtFor { body, orelse, .. })
|
||||
| Stmt::AsyncFor(ast::StmtAsyncFor { body, orelse, .. })
|
||||
| Stmt::While(ast::StmtWhile { body, orelse, .. })) = stmt else {
|
||||
| Stmt::While(ast::StmtWhile { body, orelse, .. })) = stmt
|
||||
else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
|
|
@ -67,14 +67,12 @@ fn handle_match_comment<'a>(
|
|||
|
||||
// Get the enclosing match case
|
||||
let Some(match_case) = comment.enclosing_node().match_case() else {
|
||||
return CommentPlacement::Default(comment)
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
|
||||
// And its parent match statement.
|
||||
let Some(match_stmt) = comment
|
||||
.enclosing_parent()
|
||||
.and_then(AnyNodeRef::stmt_match) else {
|
||||
return CommentPlacement::Default(comment)
|
||||
let Some(match_stmt) = comment.enclosing_parent().and_then(AnyNodeRef::stmt_match) else {
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
|
||||
// Get the next sibling (sibling traversal would be really nice)
|
||||
|
@ -163,7 +161,9 @@ fn handle_in_between_except_handlers_or_except_handler_and_else_or_finally_comme
|
|||
return CommentPlacement::Default(comment);
|
||||
}
|
||||
|
||||
let (Some(AnyNodeRef::ExceptHandlerExceptHandler(preceding_except_handler)), Some(following)) = (comment.preceding_node(), comment.following_node()) else {
|
||||
let (Some(AnyNodeRef::ExceptHandlerExceptHandler(preceding_except_handler)), Some(following)) =
|
||||
(comment.preceding_node(), comment.following_node())
|
||||
else {
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
|
||||
|
@ -175,8 +175,8 @@ fn handle_in_between_except_handlers_or_except_handler_and_else_or_finally_comme
|
|||
.unwrap_or_default();
|
||||
|
||||
let Some(except_indentation) =
|
||||
whitespace::indentation(locator, preceding_except_handler).map(str::len) else
|
||||
{
|
||||
whitespace::indentation(locator, preceding_except_handler).map(str::len)
|
||||
else {
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
|
||||
|
@ -447,7 +447,9 @@ fn handle_trailing_body_comment<'a>(
|
|||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
|
||||
let Some(comment_indentation) = whitespace::indentation_at_offset(locator, comment.slice().range().start()) else {
|
||||
let Some(comment_indentation) =
|
||||
whitespace::indentation_at_offset(locator, comment.slice().range().start())
|
||||
else {
|
||||
// The comment can't be a comment for the previous block if it isn't indented..
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
|
@ -465,7 +467,9 @@ fn handle_trailing_body_comment<'a>(
|
|||
// # Trailing if comment
|
||||
// ```
|
||||
// Here we keep the comment a trailing comment of the `if`
|
||||
let Some(preceding_node_indentation) = whitespace::indentation_at_offset(locator, preceding_node.start()) else {
|
||||
let Some(preceding_node_indentation) =
|
||||
whitespace::indentation_at_offset(locator, preceding_node.start())
|
||||
else {
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
if comment_indentation_len == preceding_node_indentation.len() {
|
||||
|
@ -593,7 +597,8 @@ fn handle_trailing_end_of_line_condition_comment<'a>(
|
|||
}
|
||||
|
||||
// Must be between the condition expression and the first body element
|
||||
let (Some(preceding), Some(following)) = (comment.preceding_node(), comment.following_node()) else {
|
||||
let (Some(preceding), Some(following)) = (comment.preceding_node(), comment.following_node())
|
||||
else {
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
|
||||
|
@ -881,8 +886,9 @@ fn handle_module_level_own_line_comment_before_class_or_function_comment<'a>(
|
|||
}
|
||||
|
||||
// ... for comments with a preceding and following node,
|
||||
let (Some(preceding), Some(following)) = (comment.preceding_node(), comment.following_node()) else {
|
||||
return CommentPlacement::Default(comment)
|
||||
let (Some(preceding), Some(following)) = (comment.preceding_node(), comment.following_node())
|
||||
else {
|
||||
return CommentPlacement::Default(comment);
|
||||
};
|
||||
|
||||
// ... where the following is a function or class statement.
|
||||
|
|
|
@ -49,7 +49,7 @@ impl<'ast> FormatBinaryLike<'ast> for ExprBoolOp {
|
|||
let comments = f.context().comments().clone();
|
||||
|
||||
let Some(first) = values.next() else {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
write!(f, [group(&first.format())])?;
|
||||
|
|
|
@ -52,7 +52,7 @@ impl FormatRule<Suite, PyFormatContext<'_>> for FormatSuite {
|
|||
|
||||
let mut iter = statements.iter();
|
||||
let Some(first) = iter.next() else {
|
||||
return Ok(())
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
// First entry has never any separator, doesn't matter which one we take;
|
||||
|
|
|
@ -245,7 +245,7 @@ impl<'a> SimpleTokenizer<'a> {
|
|||
return Token {
|
||||
kind: TokenKind::EndOfFile,
|
||||
range: TextRange::empty(self.offset),
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
if self.bogus {
|
||||
|
@ -310,7 +310,7 @@ impl<'a> SimpleTokenizer<'a> {
|
|||
return Token {
|
||||
kind: TokenKind::EndOfFile,
|
||||
range: TextRange::empty(self.back_offset),
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
if self.bogus {
|
||||
|
|
|
@ -20,7 +20,11 @@ use crate::model::SemanticModel;
|
|||
pub fn is_logger_candidate(func: &Expr, semantic: &SemanticModel) -> bool {
|
||||
if let Expr::Attribute(ast::ExprAttribute { value, .. }) = func {
|
||||
let Some(call_path) = (if let Some(call_path) = semantic.resolve_call_path(value) {
|
||||
if call_path.first().map_or(false, |module| *module == "logging") || call_path.as_slice() == ["flask", "current_app", "logger"] {
|
||||
if call_path
|
||||
.first()
|
||||
.map_or(false, |module| *module == "logging")
|
||||
|| call_path.as_slice() == ["flask", "current_app", "logger"]
|
||||
{
|
||||
Some(call_path)
|
||||
} else {
|
||||
None
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue