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}`.
///
/// 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())
.skip(
// 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
@ -283,10 +283,10 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
}
// ANN101, ANN102
if !visibility::is_staticmethod(stmt) {
if !visibility::is_staticmethod(checker, stmt) {
if let Some(arg) = args.args.first() {
if arg.node.annotation.is_none() {
if visibility::is_classmethod(stmt) {
if visibility::is_classmethod(checker, stmt) {
if checker.settings.enabled.contains(&CheckCode::ANN102) {
checker.add_check(Check::new(
CheckKind::MissingTypeCls(arg.node.arg.to_string()),
@ -319,14 +319,14 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
return;
}
if visibility::is_classmethod(stmt) {
if visibility::is_classmethod(checker, stmt) {
if checker.settings.enabled.contains(&CheckCode::ANN206) {
checker.add_check(Check::new(
CheckKind::MissingReturnTypeClassMethod(name.to_string()),
Range::from_located(stmt),
));
}
} else if visibility::is_staticmethod(stmt) {
} else if visibility::is_staticmethod(checker, stmt) {
if checker.settings.enabled.contains(&CheckCode::ANN205) {
checker.add_check(Check::new(
CheckKind::MissingReturnTypeStaticMethod(name.to_string()),

View file

@ -1,6 +1,6 @@
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::check_ast::Checker;
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 args.len() == 1
&& item.optional_vars.is_none()
&& match_name_or_attr(func, "assertRaises")
&& match_name_or_attr(args.first().unwrap(), "Exception")
&& matches!(&func.node, ExprKind::Attribute { attr, .. } if attr == "assertRaises")
&& match_module_member(
args.first().unwrap(),
"",
"Exception",
&checker.from_imports,
&checker.import_aliases,
)
{
checker.add_check(Check::new(
CheckKind::NoAssertRaisesException,

View file

@ -76,7 +76,7 @@ pub fn not_missing(
false
}
DefinitionKind::Function(stmt) | DefinitionKind::NestedFunction(stmt) => {
if is_overload(stmt) {
if is_overload(checker, stmt) {
true
} else {
if checker.settings.enabled.contains(&CheckCode::D103) {
@ -89,7 +89,7 @@ pub fn not_missing(
}
}
DefinitionKind::Method(stmt) => {
if is_overload(stmt) || is_override(stmt) {
if is_overload(checker, stmt) || is_override(checker, stmt) {
true
} else if is_magic(stmt) {
if checker.settings.enabled.contains(&CheckCode::D105) {
@ -835,7 +835,7 @@ pub fn if_needed(checker: &mut Checker, definition: &Definition) {
| DefinitionKind::NestedFunction(stmt)
| DefinitionKind::Method(stmt) = definition.kind
{
if is_overload(stmt) {
if is_overload(checker, stmt) {
checker.add_check(Check::new(
CheckKind::SkipDocstring,
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`.
usize::from(
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",
"is_typeddict",
"overload",
"override",
"reveal_type",
"runtime_checkable",
])

View file

@ -6,7 +6,7 @@ use rustpython_ast::{Constant, Expr, ExprKind, Keyword, KeywordData, Location};
use rustpython_parser::lexer;
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::autofix::Fix;
use crate::check_ast::Checker;
@ -64,7 +64,7 @@ fn match_open(expr: &Expr) -> (Option<&Expr>, Vec<Keyword>) {
keywords,
} = &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 (args.get(1), keywords.clone());
}

View file

@ -5,7 +5,8 @@ use std::path::Path;
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;
#[derive(Debug, Clone)]
@ -28,45 +29,57 @@ pub struct VisibleScope {
}
/// 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 {
StmtKind::FunctionDef { decorator_list, .. }
| StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list
.iter()
.any(|expr| match_name_or_attr(expr, "staticmethod")),
| StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list.iter().any(|expr| {
match_module_member(
expr,
"",
"staticmethod",
&checker.from_imports,
&checker.import_aliases,
)
}),
_ => panic!("Found non-FunctionDef in is_staticmethod"),
}
}
/// 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 {
StmtKind::FunctionDef { decorator_list, .. }
| StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list
.iter()
.any(|expr| match_name_or_attr(expr, "classmethod")),
| StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list.iter().any(|expr| {
match_module_member(
expr,
"",
"classmethod",
&checker.from_imports,
&checker.import_aliases,
)
}),
_ => panic!("Found non-FunctionDef in is_classmethod"),
}
}
/// 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 {
StmtKind::FunctionDef { decorator_list, .. }
| StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list
.iter()
.any(|expr| match_name_or_attr(expr, "overload")),
.any(|expr| checker.match_typing_expr(expr, "overload")),
_ => panic!("Found non-FunctionDef in is_overload"),
}
}
/// 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 {
StmtKind::FunctionDef { decorator_list, .. }
| StmtKind::AsyncFunctionDef { decorator_list, .. } => decorator_list
.iter()
.any(|expr| match_name_or_attr(expr, "override")),
.any(|expr| checker.match_typing_expr(expr, "override")),
_ => panic!("Found non-FunctionDef in is_override"),
}
}