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:
Anders Kaseorg 2023-07-02 19:13:35 -07:00 committed by GitHub
parent c8b9a46e2b
commit df13e69c3c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
105 changed files with 782 additions and 362 deletions

View file

@ -4435,7 +4435,7 @@ impl<'a> Checker<'a> {
}
fn handle_node_delete(&mut self, expr: &'a Expr) {
let Expr::Name(ast::ExprName { id, .. } )= expr else {
let Expr::Name(ast::ExprName { id, .. }) = expr else {
return;
};

View file

@ -268,11 +268,12 @@ impl Notebook {
.markers()
.iter()
.rev()
.find(|m| m.source <= *offset) else {
// There are no markers above the current offset, so we can
// stop here.
break;
};
.find(|m| m.source <= *offset)
else {
// There are no markers above the current offset, so we can
// stop here.
break;
};
last_marker = Some(marker);
marker
}

View file

@ -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![];
};

View file

@ -67,7 +67,7 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
return None;
};
// Only evaluate the full BinOp, not the nested components.
let Expr::BinOp(_ )= parent else {
let Expr::BinOp(_) = parent else {
if any_over_expr(expr, &has_string_literal) {
return Some(checker.generator().expr(expr));
}

View file

@ -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 {
decorator_list,
body,
name: method_name,
..
})
) = stmt else {
let (Stmt::FunctionDef(ast::StmtFunctionDef {
decorator_list,
body,
name: method_name,
..
})
| Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
decorator_list,
body,
name: method_name,
..
})) = stmt
else {
continue;
};

View file

@ -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() {
["", "Exception"] => Some(ExceptionKind::Exception),
["", "BaseException"] => Some(ExceptionKind::BaseException),
_ => None,
}
}) else { return; };
.and_then(|call_path| match call_path.as_slice() {
["", "Exception"] => Some(ExceptionKind::Exception),
["", "BaseException"] => Some(ExceptionKind::BaseException),
_ => None,
})
else {
return;
};
let assertion = if matches!(func.as_ref(), Expr::Attribute(ast::ExprAttribute { attr, .. }) if attr == "assertRaises")
{

View file

@ -59,7 +59,7 @@ pub(crate) fn assignment_to_os_environ(checker: &mut Checker, targets: &[Expr])
if attr != "environ" {
return;
}
let Expr::Name(ast::ExprName { id, .. } )= value.as_ref() else {
let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() else {
return;
};
if id != "os" {

View file

@ -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() {

View file

@ -47,7 +47,7 @@ impl Violation for ExceptWithNonExceptionClasses {
/// This should leave any unstarred iterables alone (subsequently raising a
/// warning for B029).
fn flatten_starred_iterables(expr: &Expr) -> Vec<&Expr> {
let Expr::Tuple(ast::ExprTuple { elts, .. } )= expr else {
let Expr::Tuple(ast::ExprTuple { elts, .. }) = expr else {
return vec![expr];
};
let mut flattened_exprs: Vec<&Expr> = Vec::with_capacity(elts.len());

View file

@ -64,7 +64,7 @@ pub(crate) fn getattr_with_constant(
func: &Expr,
args: &[Expr],
) {
let Expr::Name(ast::ExprName { id, .. } )= func else {
let Expr::Name(ast::ExprName { id, .. }) = func else {
return;
};
if id != "getattr" {
@ -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) {

View file

@ -69,7 +69,7 @@ pub(crate) fn mutable_argument_default(checker: &mut Checker, arguments: &Argume
.chain(&arguments.args)
.chain(&arguments.kwonlyargs)
{
let Some(default)= default else {
let Some(default) = default else {
continue;
};

View file

@ -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 {

View file

@ -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) {

View file

@ -64,7 +64,7 @@ pub(crate) fn star_arg_unpacking_after_keyword_arg(
return;
};
for arg in args {
let Expr::Starred (_) = arg else {
let Expr::Starred(_) = arg else {
continue;
};
if arg.start() <= keyword.start() {

View file

@ -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;
};

View file

@ -45,9 +45,9 @@ pub(crate) fn unary_prefix_increment(
if !matches!(op, UnaryOp::UAdd) {
return;
}
let Expr::UnaryOp(ast::ExprUnaryOp { op, .. })= operand else {
return;
};
let Expr::UnaryOp(ast::ExprUnaryOp { op, .. }) = operand else {
return;
};
if !matches!(op, UnaryOp::UAdd) {
return;
}

View file

@ -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__" {

View file

@ -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;
};

View file

@ -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![];

View file

@ -66,11 +66,13 @@ pub(crate) fn unnecessary_comprehension_any_all(
if !keywords.is_empty() {
return;
}
let Expr::Name(ast::ExprName { id, .. } )= func else {
let Expr::Name(ast::ExprName { id, .. }) = func else {
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) {

View file

@ -84,7 +84,7 @@ pub(crate) fn unnecessary_double_cast_or_process(
let Some(arg) = args.first() else {
return;
};
let Expr::Call(ast::ExprCall { func, ..} )= arg else {
let Expr::Call(ast::ExprCall { func, .. }) = arg else {
return;
};
let Some(inner) = helpers::expr_name(func) else {

View file

@ -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 {

View file

@ -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") {

View file

@ -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") {

View file

@ -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") {

View file

@ -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") {

View file

@ -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") {

View file

@ -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") {

View file

@ -83,7 +83,7 @@ pub(crate) fn unnecessary_map(
)
}
let Some(id) = helpers::expr_name(func) else {
let Some(id) = helpers::expr_name(func) else {
return;
};
match id {
@ -127,9 +127,11 @@ pub(crate) fn unnecessary_map(
if args.len() != 2 {
return;
}
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
return;
};
let Some(argument) =
helpers::first_argument_with_matching_function("map", func, args)
else {
return;
};
if let Expr::Lambda(_) = argument {
let mut diagnostic = create_diagnostic(id, expr.range());
if checker.patch(diagnostic.kind.rule()) {
@ -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 {

View file

@ -64,9 +64,15 @@ 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 {
return;
};
let Expr::Slice(ast::ExprSlice {
lower,
upper,
step,
range: _,
}) = slice.as_ref()
else {
return;
};
if lower.is_some() || upper.is_some() {
return;
}
@ -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) {

View file

@ -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;
};

View file

@ -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"])

View file

@ -96,18 +96,18 @@ fn is_non_abstract_model(bases: &[Expr], body: &[Stmt], semantic: &SemanticModel
/// Check if class is abstract, in terms of Django model inheritance.
fn is_model_abstract(body: &[Stmt]) -> bool {
for element in body.iter() {
let Stmt::ClassDef(ast::StmtClassDef {name, body, ..}) = element else {
continue
let Stmt::ClassDef(ast::StmtClassDef { name, body, .. }) = element else {
continue;
};
if name != "Meta" {
continue;
}
for element in body.iter() {
let Stmt::Assign(ast::StmtAssign {targets, value, ..}) = element else {
let Stmt::Assign(ast::StmtAssign { targets, value, .. }) = element else {
continue;
};
for target in targets.iter() {
let Expr::Name(ast::ExprName {id , ..}) = target else {
let Expr::Name(ast::ExprName { id, .. }) = target else {
continue;
};
if id != "abstract" {

View file

@ -64,8 +64,8 @@ const NOT_NULL_TRUE_FIELDS: [&str; 6] = [
pub(crate) fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> Vec<Diagnostic> {
let mut errors = Vec::new();
for statement in body.iter() {
let Stmt::Assign(ast::StmtAssign {value, ..}) = statement else {
continue
let Stmt::Assign(ast::StmtAssign { value, .. }) = statement else {
continue;
};
if let Some(field_name) = is_nullable_field(checker, value) {
errors.push(Diagnostic::new(
@ -80,7 +80,7 @@ pub(crate) fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> V
}
fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a str> {
let Expr::Call(ast::ExprCall {func, keywords, ..}) = value else {
let Expr::Call(ast::ExprCall { func, keywords, .. }) = value else {
return None;
};
@ -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;

View file

@ -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,24 +75,25 @@ 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()) {
continue;
}
let Expr::Attribute(ast::ExprAttribute { value, attr, .. } )= func.as_ref() else {
continue
let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func.as_ref() else {
continue;
};
if attr != "startswith" && attr != "endswith" {
continue;
}
let Expr::Name(ast::ExprName { id: arg_name, .. } )= value.as_ref() else {
continue
let Expr::Name(ast::ExprName { id: arg_name, .. }) = value.as_ref() else {
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"))

View file

@ -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;
};

View file

@ -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") {
Some(VarKind::ParamSpec)
} 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") {
Some(VarKind::TypeVarTuple)
} else {
None
}
}) else {
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")
{
Some(VarKind::TypeVar)
} else if checker
.semantic()
.match_typing_call_path(&call_path, "TypeVarTuple")
{
Some(VarKind::TypeVarTuple)
} else {
None
}
})
else {
return;
};
checker

View file

@ -270,7 +270,7 @@ fn is_valid_default_value_without_annotation(default: &Expr) -> bool {
/// Returns `true` if an [`Expr`] appears to be `TypeVar`, `TypeVarTuple`, `NewType`, or `ParamSpec`
/// call.
fn is_type_var_like_call(expr: &Expr, semantic: &SemanticModel) -> bool {
let Expr::Call(ast::ExprCall { func, .. } )= expr else {
let Expr::Call(ast::ExprCall { func, .. }) = expr else {
return false;
};
semantic.resolve_call_path(func).map_or(false, |call_path| {

View file

@ -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 {

View file

@ -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")
};

View file

@ -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;
};

View file

@ -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 {

View file

@ -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,13 +198,19 @@ 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() {
return;
}
let Expr::Attribute(ast::ExprAttribute { value, attr, .. } )= func.as_ref() else {
let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func.as_ref() else {
return;
};
if !value.is_dict_expr() {

View file

@ -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,25 +532,41 @@ 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 {
return;
}
let Expr::Name(ast::ExprName { id: body_id, .. } )= &body_targets[0] else {
let Expr::Name(ast::ExprName { id: body_id, .. }) = &body_targets[0] else {
return;
};
let Expr::Name(ast::ExprName { id: orelse_id, .. } )= &orelse_targets[0] else {
let Expr::Name(ast::ExprName { id: orelse_id, .. }) = &orelse_targets[0] else {
return;
};
if body_id != orelse_id {
@ -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: _ }) = &current else {
let Stmt::If(ast::StmtIf {
test,
body,
orelse,
range: _,
}) = &current
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,10 +865,13 @@ 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 {
let Stmt::Return(ast::StmtReturn { value, range: _ }) = &body[0] else {
return;
};
if value.as_ref().map_or(false, |value| {
@ -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;
};

View file

@ -141,13 +141,13 @@ pub(crate) fn explicit_true_false_in_ifexpr(
body: &Expr,
orelse: &Expr,
) {
let Expr::Constant(ast::ExprConstant { value, .. } )= &body else {
let Expr::Constant(ast::ExprConstant { value, .. }) = &body else {
return;
};
if !matches!(value, Constant::Bool(true)) {
return;
}
let Expr::Constant(ast::ExprConstant { value, .. } )= &orelse else {
let Expr::Constant(ast::ExprConstant { value, .. }) = &orelse else {
return;
};
if !matches!(value, Constant::Bool(false)) {
@ -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() {
@ -245,10 +250,10 @@ pub(crate) fn twisted_arms_in_ifexpr(
}
// Check if the test operand and else branch use the same variable.
let Expr::Name(ast::ExprName { id: test_id, .. } )= test_operand.as_ref() else {
let Expr::Name(ast::ExprName { id: test_id, .. }) = test_operand.as_ref() else {
return;
};
let Expr::Name(ast::ExprName {id: orelse_id, ..}) = orelse else {
let Expr::Name(ast::ExprName { id: orelse_id, .. }) = orelse else {
return;
};
if !test_id.eq(orelse_id) {

View file

@ -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) {

View file

@ -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")
};

View file

@ -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");
};

View file

@ -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()) {

View file

@ -49,9 +49,9 @@ fn match_async_exit_stack(semantic: &SemanticModel) -> bool {
let Expr::Await(ast::ExprAwait { value, range: _ }) = expr else {
return false;
};
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
return false;
};
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
return false;
};
let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() else {
return false;
};
@ -80,9 +80,9 @@ fn match_exit_stack(semantic: &SemanticModel) -> bool {
let Some(expr) = semantic.expr_parent() else {
return false;
};
let Expr::Call(ast::ExprCall { func, .. }) = expr else {
return false;
};
let Expr::Call(ast::ExprCall { func, .. }) = expr else {
return false;
};
let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() else {
return false;
};

View file

@ -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;
};

View file

@ -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);

View file

@ -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| {
@ -71,8 +68,9 @@ fn includes_import(stmt: &Stmt, target: &AnyImport) -> bool {
module,
names,
level,
range: _,
}) = &stmt else {
range: _,
}) = &stmt
else {
return false;
};
module.as_deref() == target.module

View file

@ -62,7 +62,7 @@ impl Violation for PandasUseOfDotStack {
pub(crate) fn call(checker: &mut Checker, func: &Expr) {
let rules = &checker.settings.rules;
let Expr::Attribute(ast::ExprAttribute { value, attr, .. } )= func else {
let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func else {
return;
};
let violation: DiagnosticKind = match attr.as_str() {

View file

@ -26,7 +26,7 @@ pub(super) fn is_named_tuple_assignment(stmt: &Stmt, semantic: &SemanticModel) -
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
return false;
};
let Expr::Call(ast::ExprCall {func, ..}) = value.as_ref() else {
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
return false;
};
semantic.resolve_call_path(func).map_or(false, |call_path| {
@ -41,7 +41,7 @@ pub(super) fn is_typed_dict_assignment(stmt: &Stmt, semantic: &SemanticModel) ->
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
return false;
};
let Expr::Call(ast::ExprCall {func, ..}) = value.as_ref() else {
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
return false;
};
semantic.resolve_call_path(func).map_or(false, |call_path| {
@ -53,7 +53,7 @@ pub(super) fn is_type_var_assignment(stmt: &Stmt, semantic: &SemanticModel) -> b
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
return false;
};
let Expr::Call(ast::ExprCall {func, ..}) = value.as_ref() else {
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
return false;
};
semantic.resolve_call_path(func).map_or(false, |call_path| {

View file

@ -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;
@ -72,7 +68,7 @@ pub(crate) fn incorrect_dict_iterator(checker: &mut Checker, target: &Expr, iter
if !args.is_empty() {
return;
}
let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func.as_ref() else {
let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func.as_ref() else {
return;
};
if attr != "items" {

View file

@ -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;
};
@ -56,7 +62,7 @@ pub(crate) fn unnecessary_list_cast(checker: &mut Checker, iter: &Expr) {
return;
}
let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() else{
let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() else {
return;
};

View file

@ -161,10 +161,11 @@ impl AlwaysAutofixableViolation for BlankLineBeforeClass {
/// D203, D204, D211
pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
let Definition::Member(Member {
kind: MemberKind::Class | MemberKind::NestedClass ,
kind: MemberKind::Class | MemberKind::NestedClass,
stmt,
..
}) = docstring.definition else {
}) = docstring.definition
else {
return;
};

View file

@ -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;
};

View file

@ -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.

View file

@ -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()) {

View file

@ -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;
};

View file

@ -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 {

View file

@ -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 {
args: arguments, ..
})
| Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
args: arguments, ..
})
) = stmt else {
let (Stmt::FunctionDef(ast::StmtFunctionDef {
args: arguments, ..
})
| Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
args: arguments, ..
})) = stmt
else {
return;
};

View file

@ -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;

View file

@ -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 {

View file

@ -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)?;

View file

@ -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,
let (ScopeKind::Function(ast::StmtFunctionDef {
name,
decorator_list,
..
}) |
ScopeKind::AsyncFunction(ast::StmtAsyncFunctionDef {
name,
decorator_list,
..
})
) = scope.kind else {
})
| ScopeKind::AsyncFunction(ast::StmtAsyncFunctionDef {
name,
decorator_list,
..
})) = scope.kind
else {
return false;
};
if name != "__init__" {

View file

@ -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;
};

View file

@ -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;

View file

@ -143,7 +143,7 @@ pub(crate) fn nested_min_max(
}
if args.iter().any(|arg| {
let Expr::Call(ast::ExprCall { func, keywords, ..} )= arg else {
let Expr::Call(ast::ExprCall { func, keywords, .. }) = arg else {
return false;
};
MinMax::try_from_call(func.as_ref(), keywords.as_ref(), checker.semantic()) == Some(min_max)

View file

@ -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;
};

View file

@ -85,7 +85,7 @@ pub(crate) fn useless_return<'a>(
}
// Verify that the last statement is a return statement.
let Stmt::Return(ast::StmtReturn { value, range: _}) = &last_stmt else {
let Stmt::Return(ast::StmtReturn { value, range: _ }) = &last_stmt else {
return;
};

View file

@ -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,10 +137,12 @@ 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 {
let Expr::List(ast::ExprList { elts, .. }) = &fields else {
bail!("Expected argument to be `Expr::List`");
};
if elts.is_empty() {
@ -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;
};

View file

@ -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;
};

View file

@ -471,7 +471,7 @@ impl<'a> ImportReplacer<'a> {
// line, we can't add a statement after it. For example, if we have
// `if True: import foo`, we can't add a statement to the next line.
let Some(indentation) = indentation else {
let operation = WithoutRename {
let operation = WithoutRename {
target: target.to_string(),
members: matched_names
.iter()

View file

@ -106,7 +106,7 @@ fn match_extraneous_parentheses(tokens: &[LexResult], mut i: usize) -> Option<(u
if i >= tokens.len() {
return None;
}
let Ok(( tok, _)) = &tokens[i] else {
let Ok((tok, _)) = &tokens[i] else {
return None;
};
match tok {
@ -122,7 +122,7 @@ fn match_extraneous_parentheses(tokens: &[LexResult], mut i: usize) -> Option<(u
if i >= tokens.len() {
return None;
}
let Ok(( tok, _)) = &tokens[i] else {
let Ok((tok, _)) = &tokens[i] else {
return None;
};
if matches!(tok, Tok::Rpar) {

View file

@ -197,7 +197,7 @@ fn try_convert_to_f_string(expr: &Expr, locator: &Locator) -> Option<String> {
return None;
};
let Some(mut summary) = FormatSummaryValues::try_from_expr( expr, locator) else {
let Some(mut summary) = FormatSummaryValues::try_from_expr(expr, locator) else {
return None;
};
@ -325,7 +325,7 @@ pub(crate) fn f_strings(checker: &mut Checker, summary: &FormatSummary, expr: &E
// Currently, the only issue we know of is in LibCST:
// https://github.com/Instagram/LibCST/issues/846
let Some(mut contents) = try_convert_to_f_string( expr, checker.locator) else {
let Some(mut contents) = try_convert_to_f_string(expr, checker.locator) else {
return;
};

View file

@ -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;
};

View file

@ -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;
};

View file

@ -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" {
LiteralType::Str
} else {
LiteralType::Bytes
}}, expr.range());
let mut diagnostic = Diagnostic::new(
NativeLiterals {
literal_type: if id == "str" {
LiteralType::Str
} else {
LiteralType::Bytes
},
},
expr.range(),
);
if checker.patch(diagnostic.kind.rule()) {
let constant = if id == "bytes" {
Constant::Bytes(vec![])

View file

@ -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;
};

View file

@ -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;
};

View file

@ -66,7 +66,7 @@ pub(crate) fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr,
{
return;
}
let Expr::Constant(ast::ExprConstant { value, .. } )= &args[0] else {
let Expr::Constant(ast::ExprConstant { value, .. }) = &args[0] else {
return;
};
let Some(primitive) = Primitive::from_constant(value) else {

View file

@ -61,7 +61,8 @@ fn match_encoded_variable(func: &Expr) -> Option<&Expr> {
value: variable,
attr,
..
}) = func else {
}) = func
else {
return None;
};
if attr != "encode" {

View file

@ -56,7 +56,8 @@ pub(crate) fn unpacked_list_comprehension(checker: &mut Checker, targets: &[Expr
elt,
generators,
range: _,
}) = value else {
}) = value
else {
return;
};

View file

@ -52,13 +52,13 @@ pub(crate) fn useless_metaclass_type(
return;
}
let Expr::Name(ast::ExprName { id, .. }) = targets.first().unwrap() else {
return ;
return;
};
if id != "__metaclass__" {
return;
}
let Expr::Name(ast::ExprName { id, .. }) = value else {
return ;
return;
};
if id != "type" {
return;

View file

@ -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_ {

View file

@ -82,7 +82,8 @@ pub(crate) fn explicit_f_string_type_conversion(
args,
keywords,
..
}) = value.as_ref() else {
}) = value.as_ref()
else {
continue;
};

View file

@ -191,7 +191,7 @@ impl<'a> TypingTarget<'a> {
if semantic.match_typing_expr(value, "Optional") {
return Some(TypingTarget::Optional);
}
let Expr::Tuple(ast::ExprTuple { elts: elements, .. }) = slice.as_ref() else{
let Expr::Tuple(ast::ExprTuple { elts: elements, .. }) = slice.as_ref() else {
return None;
};
if semantic.match_typing_expr(value, "Literal") {
@ -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();

View file

@ -67,7 +67,7 @@ fn match_slice_info(expr: &Expr) -> Option<SliceInfo> {
return None;
};
let Expr::Slice(ast::ExprSlice { lower, step, .. }) = slice.as_ref() else {
let Expr::Slice(ast::ExprSlice { lower, step, .. }) = slice.as_ref() else {
return None;
};

View file

@ -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 {

View file

@ -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();

View file

@ -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");
}

View file

@ -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(())

View file

@ -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.,

View file

@ -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()))

View file

@ -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)) {

View file

@ -187,8 +187,9 @@ pub fn except(handler: &ExceptHandler, locator: &Locator) -> TextRange {
/// Return the [`TextRange`] of the `else` token in a `For`, `AsyncFor`, or `While` statement.
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::AsyncFor(ast::StmtAsyncFor { body, orelse, .. })
| Stmt::While(ast::StmtWhile { body, orelse, .. })) = stmt
else {
return None;
};

View file

@ -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,10 +175,10 @@ 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
{
return CommentPlacement::Default(comment);
};
whitespace::indentation(locator, preceding_except_handler).map(str::len)
else {
return CommentPlacement::Default(comment);
};
if comment_indentation > except_indentation {
// Delegate to `handle_trailing_body_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.

Some files were not shown because too many files have changed in this diff Show more