Remove sloppy match_name_or_attr helper (#1027)

This commit is contained in:
Anders Kaseorg 2022-12-04 06:12:03 -08:00 committed by GitHub
parent 4b0c3e3bc9
commit dbb1a6e44b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 47 additions and 36 deletions

View file

@ -61,15 +61,6 @@ pub fn dealias_call_path<'a>(
} }
} }
/// Return `true` if the `Expr` is a name or attribute reference to `${target}`.
pub fn match_name_or_attr(expr: &Expr, target: &str) -> bool {
match &expr.node {
ExprKind::Attribute { attr, .. } => target == attr,
ExprKind::Name { id, .. } => target == id,
_ => false,
}
}
/// Return `true` if the `Expr` is a reference to `${module}.${target}`. /// Return `true` if the `Expr` is a reference to `${module}.${target}`.
/// ///
/// Useful for, e.g., ensuring that a `Union` reference represents /// Useful for, e.g., ensuring that a `Union` reference represents

View file

@ -211,7 +211,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
.chain(args.kwonlyargs.iter()) .chain(args.kwonlyargs.iter())
.skip( .skip(
// If this is a non-static method, skip `cls` or `self`. // If this is a non-static method, skip `cls` or `self`.
usize::from(!visibility::is_staticmethod(stmt)), usize::from(!visibility::is_staticmethod(checker, stmt)),
) )
{ {
// ANN401 for dynamically typed arguments // ANN401 for dynamically typed arguments
@ -283,10 +283,10 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
} }
// ANN101, ANN102 // ANN101, ANN102
if !visibility::is_staticmethod(stmt) { if !visibility::is_staticmethod(checker, stmt) {
if let Some(arg) = args.args.first() { if let Some(arg) = args.args.first() {
if arg.node.annotation.is_none() { if arg.node.annotation.is_none() {
if visibility::is_classmethod(stmt) { if visibility::is_classmethod(checker, stmt) {
if checker.settings.enabled.contains(&CheckCode::ANN102) { if checker.settings.enabled.contains(&CheckCode::ANN102) {
checker.add_check(Check::new( checker.add_check(Check::new(
CheckKind::MissingTypeCls(arg.node.arg.to_string()), CheckKind::MissingTypeCls(arg.node.arg.to_string()),
@ -319,14 +319,14 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
return; return;
} }
if visibility::is_classmethod(stmt) { if visibility::is_classmethod(checker, stmt) {
if checker.settings.enabled.contains(&CheckCode::ANN206) { if checker.settings.enabled.contains(&CheckCode::ANN206) {
checker.add_check(Check::new( checker.add_check(Check::new(
CheckKind::MissingReturnTypeClassMethod(name.to_string()), CheckKind::MissingReturnTypeClassMethod(name.to_string()),
Range::from_located(stmt), Range::from_located(stmt),
)); ));
} }
} else if visibility::is_staticmethod(stmt) { } else if visibility::is_staticmethod(checker, stmt) {
if checker.settings.enabled.contains(&CheckCode::ANN205) { if checker.settings.enabled.contains(&CheckCode::ANN205) {
checker.add_check(Check::new( checker.add_check(Check::new(
CheckKind::MissingReturnTypeStaticMethod(name.to_string()), CheckKind::MissingReturnTypeStaticMethod(name.to_string()),

View file

@ -1,6 +1,6 @@
use rustpython_ast::{ExprKind, Stmt, Withitem}; use rustpython_ast::{ExprKind, Stmt, Withitem};
use crate::ast::helpers::match_name_or_attr; use crate::ast::helpers::match_module_member;
use crate::ast::types::Range; use crate::ast::types::Range;
use crate::check_ast::Checker; use crate::check_ast::Checker;
use crate::checks::{Check, CheckKind}; use crate::checks::{Check, CheckKind};
@ -12,8 +12,14 @@ pub fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: &[With
if let ExprKind::Call { func, args, .. } = &item_context.node { if let ExprKind::Call { func, args, .. } = &item_context.node {
if args.len() == 1 if args.len() == 1
&& item.optional_vars.is_none() && item.optional_vars.is_none()
&& match_name_or_attr(func, "assertRaises") && matches!(&func.node, ExprKind::Attribute { attr, .. } if attr == "assertRaises")
&& match_name_or_attr(args.first().unwrap(), "Exception") && match_module_member(
args.first().unwrap(),
"",
"Exception",
&checker.from_imports,
&checker.import_aliases,
)
{ {
checker.add_check(Check::new( checker.add_check(Check::new(
CheckKind::NoAssertRaisesException, CheckKind::NoAssertRaisesException,

View file

@ -76,7 +76,7 @@ pub fn not_missing(
false false
} }
DefinitionKind::Function(stmt) | DefinitionKind::NestedFunction(stmt) => { DefinitionKind::Function(stmt) | DefinitionKind::NestedFunction(stmt) => {
if is_overload(stmt) { if is_overload(checker, stmt) {
true true
} else { } else {
if checker.settings.enabled.contains(&CheckCode::D103) { if checker.settings.enabled.contains(&CheckCode::D103) {
@ -89,7 +89,7 @@ pub fn not_missing(
} }
} }
DefinitionKind::Method(stmt) => { DefinitionKind::Method(stmt) => {
if is_overload(stmt) || is_override(stmt) { if is_overload(checker, stmt) || is_override(checker, stmt) {
true true
} else if is_magic(stmt) { } else if is_magic(stmt) {
if checker.settings.enabled.contains(&CheckCode::D105) { if checker.settings.enabled.contains(&CheckCode::D105) {
@ -835,7 +835,7 @@ pub fn if_needed(checker: &mut Checker, definition: &Definition) {
| DefinitionKind::NestedFunction(stmt) | DefinitionKind::NestedFunction(stmt)
| DefinitionKind::Method(stmt) = definition.kind | DefinitionKind::Method(stmt) = definition.kind
{ {
if is_overload(stmt) { if is_overload(checker, stmt) {
checker.add_check(Check::new( checker.add_check(Check::new(
CheckKind::SkipDocstring, CheckKind::SkipDocstring,
Range::from_located(stmt), Range::from_located(stmt),
@ -1319,7 +1319,7 @@ fn missing_args(checker: &mut Checker, definition: &Definition, docstrings_args:
// If this is a non-static method, skip `cls` or `self`. // If this is a non-static method, skip `cls` or `self`.
usize::from( usize::from(
matches!(definition.kind, DefinitionKind::Method(_)) matches!(definition.kind, DefinitionKind::Method(_))
&& !is_staticmethod(parent), && !is_staticmethod(checker, parent),
), ),
) )
{ {

View file

@ -55,6 +55,7 @@ static TYPING_EXTENSIONS: Lazy<FxHashSet<&'static str>> = Lazy::new(|| {
"get_overloads", "get_overloads",
"is_typeddict", "is_typeddict",
"overload", "overload",
"override",
"reveal_type", "reveal_type",
"runtime_checkable", "runtime_checkable",
]) ])

View file

@ -6,7 +6,7 @@ use rustpython_ast::{Constant, Expr, ExprKind, Keyword, KeywordData, Location};
use rustpython_parser::lexer; use rustpython_parser::lexer;
use rustpython_parser::token::Tok; use rustpython_parser::token::Tok;
use crate::ast::helpers::{self, match_name_or_attr}; use crate::ast::helpers;
use crate::ast::types::Range; use crate::ast::types::Range;
use crate::autofix::Fix; use crate::autofix::Fix;
use crate::check_ast::Checker; use crate::check_ast::Checker;
@ -64,7 +64,7 @@ fn match_open(expr: &Expr) -> (Option<&Expr>, Vec<Keyword>) {
keywords, keywords,
} = &expr.node } = &expr.node
{ {
if match_name_or_attr(func, OPEN_FUNC_NAME) { if matches!(&func.node, ExprKind::Name {id, ..} if id == OPEN_FUNC_NAME) {
// Return the "open mode" parameter and keywords. // Return the "open mode" parameter and keywords.
return (args.get(1), keywords.clone()); return (args.get(1), keywords.clone());
} }

View file

@ -5,7 +5,8 @@ use std::path::Path;
use rustpython_ast::{Stmt, StmtKind}; use rustpython_ast::{Stmt, StmtKind};
use crate::ast::helpers::match_name_or_attr; use crate::ast::helpers::match_module_member;
use crate::check_ast::Checker;
use crate::docstrings::definition::Documentable; use crate::docstrings::definition::Documentable;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -28,45 +29,57 @@ pub struct VisibleScope {
} }
/// Returns `true` if a function is a "static method". /// Returns `true` if a function is a "static method".
pub fn is_staticmethod(stmt: &Stmt) -> bool { pub fn is_staticmethod(checker: &Checker, stmt: &Stmt) -> bool {
match &stmt.node { match &stmt.node {
StmtKind::FunctionDef { decorator_list, .. } StmtKind::FunctionDef { decorator_list, .. }
| StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list | StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list.iter().any(|expr| {
.iter() match_module_member(
.any(|expr| match_name_or_attr(expr, "staticmethod")), expr,
"",
"staticmethod",
&checker.from_imports,
&checker.import_aliases,
)
}),
_ => panic!("Found non-FunctionDef in is_staticmethod"), _ => panic!("Found non-FunctionDef in is_staticmethod"),
} }
} }
/// Returns `true` if a function is a "class method". /// Returns `true` if a function is a "class method".
pub fn is_classmethod(stmt: &Stmt) -> bool { pub fn is_classmethod(checker: &Checker, stmt: &Stmt) -> bool {
match &stmt.node { match &stmt.node {
StmtKind::FunctionDef { decorator_list, .. } StmtKind::FunctionDef { decorator_list, .. }
| StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list | StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list.iter().any(|expr| {
.iter() match_module_member(
.any(|expr| match_name_or_attr(expr, "classmethod")), expr,
"",
"classmethod",
&checker.from_imports,
&checker.import_aliases,
)
}),
_ => panic!("Found non-FunctionDef in is_classmethod"), _ => panic!("Found non-FunctionDef in is_classmethod"),
} }
} }
/// Returns `true` if a function definition is an `@overload`. /// Returns `true` if a function definition is an `@overload`.
pub fn is_overload(stmt: &Stmt) -> bool { pub fn is_overload(checker: &Checker, stmt: &Stmt) -> bool {
match &stmt.node { match &stmt.node {
StmtKind::FunctionDef { decorator_list, .. } StmtKind::FunctionDef { decorator_list, .. }
| StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list | StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list
.iter() .iter()
.any(|expr| match_name_or_attr(expr, "overload")), .any(|expr| checker.match_typing_expr(expr, "overload")),
_ => panic!("Found non-FunctionDef in is_overload"), _ => panic!("Found non-FunctionDef in is_overload"),
} }
} }
/// Returns `true` if a function definition is an `@override` (PEP 698). /// Returns `true` if a function definition is an `@override` (PEP 698).
pub fn is_override(stmt: &Stmt) -> bool { pub fn is_override(checker: &Checker, stmt: &Stmt) -> bool {
match &stmt.node { match &stmt.node {
StmtKind::FunctionDef { decorator_list, .. } StmtKind::FunctionDef { decorator_list, .. }
| StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list | StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list
.iter() .iter()
.any(|expr| match_name_or_attr(expr, "override")), .any(|expr| checker.match_typing_expr(expr, "override")),
_ => panic!("Found non-FunctionDef in is_override"), _ => panic!("Found non-FunctionDef in is_override"),
} }
} }