Move super-args and unnecessary-coding-comment into their own modules (#2432)

This commit is contained in:
Charlie Marsh 2023-01-31 22:26:56 -05:00 committed by GitHub
parent c15595325c
commit 841d176289
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 112 additions and 106 deletions

View file

@ -9,24 +9,22 @@ pub(crate) use functools_cache::functools_cache;
pub(crate) use import_replacements::{import_replacements, ImportReplacements};
pub(crate) use lru_cache_without_parameters::lru_cache_without_parameters;
pub(crate) use native_literals::native_literals;
use once_cell::sync::Lazy;
pub(crate) use open_alias::open_alias;
pub(crate) use os_error_alias::os_error_alias;
pub(crate) use printf_string_formatting::printf_string_formatting;
pub(crate) use redundant_open_modes::redundant_open_modes;
use regex::Regex;
pub(crate) use replace_stdout_stderr::replace_stdout_stderr;
pub(crate) use replace_universal_newlines::replace_universal_newlines;
pub(crate) use rewrite_c_element_tree::replace_c_element_tree;
pub(crate) use rewrite_mock_import::{rewrite_mock_attribute, rewrite_mock_import};
pub(crate) use rewrite_unicode_literal::rewrite_unicode_literal;
pub(crate) use rewrite_yield_from::rewrite_yield_from;
use rustpython_ast::Location;
use rustpython_parser::ast::{ArgData, Expr, ExprKind, Stmt, StmtKind};
pub(crate) use super_args::super_args;
pub(crate) use super_call_with_parameters::super_call_with_parameters;
pub(crate) use type_of_primitive::type_of_primitive;
pub(crate) use typing_text_str_alias::typing_text_str_alias;
pub(crate) use unnecessary_builtin_import::unnecessary_builtin_import;
pub(crate) use unnecessary_coding_comment::unnecessary_coding_comment;
pub(crate) use unnecessary_encode_utf8::unnecessary_encode_utf8;
pub(crate) use unnecessary_future_import::unnecessary_future_import;
pub(crate) use unpack_list_comprehension::unpack_list_comprehension;
@ -35,12 +33,6 @@ pub(crate) use use_pep604_annotation::use_pep604_annotation;
pub(crate) use useless_metaclass_type::useless_metaclass_type;
pub(crate) use useless_object_inheritance::useless_object_inheritance;
use crate::ast::helpers;
use crate::ast::types::{Range, Scope, ScopeKind};
use crate::fix::Fix;
use crate::registry::Diagnostic;
use crate::violations;
mod convert_named_tuple_functional_to_class;
mod convert_typed_dict_functional_to_class;
mod datetime_utc_alias;
@ -62,10 +54,12 @@ mod rewrite_c_element_tree;
mod rewrite_mock_import;
mod rewrite_unicode_literal;
mod rewrite_yield_from;
mod super_args;
mod super_call_with_parameters;
mod type_of_primitive;
mod typing_text_str_alias;
mod unnecessary_builtin_import;
mod unnecessary_coding_comment;
mod unnecessary_encode_utf8;
mod unnecessary_future_import;
mod unpack_list_comprehension;
@ -73,99 +67,3 @@ mod use_pep585_annotation;
mod use_pep604_annotation;
mod useless_metaclass_type;
mod useless_object_inheritance;
/// UP008
pub fn super_args(
scope: &Scope,
parents: &[&Stmt],
expr: &Expr,
func: &Expr,
args: &[Expr],
) -> Option<Diagnostic> {
if !helpers::is_super_call_with_arguments(func, args) {
return None;
}
// Check: are we in a Function scope?
if !matches!(scope.kind, ScopeKind::Function { .. }) {
return None;
}
let mut parents = parents.iter().rev();
// For a `super` invocation to be unnecessary, the first argument needs to match
// the enclosing class, and the second argument needs to match the first
// argument to the enclosing function.
let [first_arg, second_arg] = args else {
return None;
};
// Find the enclosing function definition (if any).
let Some(StmtKind::FunctionDef {
args: parent_args, ..
}) = parents
.find(|stmt| matches!(stmt.node, StmtKind::FunctionDef { .. }))
.map(|stmt| &stmt.node) else {
return None;
};
// Extract the name of the first argument to the enclosing function.
let Some(ArgData {
arg: parent_arg, ..
}) = parent_args.args.first().map(|expr| &expr.node) else {
return None;
};
// Find the enclosing class definition (if any).
let Some(StmtKind::ClassDef {
name: parent_name, ..
}) = parents
.find(|stmt| matches!(stmt.node, StmtKind::ClassDef { .. }))
.map(|stmt| &stmt.node) else {
return None;
};
let (
ExprKind::Name {
id: first_arg_id, ..
},
ExprKind::Name {
id: second_arg_id, ..
},
) = (&first_arg.node, &second_arg.node) else {
return None;
};
if first_arg_id == parent_name && second_arg_id == parent_arg {
return Some(Diagnostic::new(
violations::SuperCallWithParameters,
Range::from_located(expr),
));
}
None
}
// Regex from PEP263.
static CODING_COMMENT_REGEX: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^[ \t\f]*#.*?coding[:=][ \t]*utf-?8").unwrap());
/// UP009
pub fn unnecessary_coding_comment(lineno: usize, line: &str, autofix: bool) -> Option<Diagnostic> {
// PEP3120 makes utf-8 the default encoding.
if CODING_COMMENT_REGEX.is_match(line) {
let mut diagnostic = Diagnostic::new(
violations::PEP3120UnnecessaryCodingComment,
Range::new(Location::new(lineno + 1, 0), Location::new(lineno + 2, 0)),
);
if autofix {
diagnostic.amend(Fix::deletion(
Location::new(lineno + 1, 0),
Location::new(lineno + 2, 0),
));
}
Some(diagnostic)
} else {
None
}
}

View file

@ -0,0 +1,77 @@
use crate::ast::helpers;
use crate::ast::types::{Range, Scope, ScopeKind};
use crate::registry::Diagnostic;
use crate::violations;
use rustpython_ast::{ArgData, Expr, ExprKind, Stmt, StmtKind};
/// UP008
pub fn super_args(
scope: &Scope,
parents: &[&Stmt],
expr: &Expr,
func: &Expr,
args: &[Expr],
) -> Option<Diagnostic> {
if !helpers::is_super_call_with_arguments(func, args) {
return None;
}
// Check: are we in a Function scope?
if !matches!(scope.kind, ScopeKind::Function { .. }) {
return None;
}
let mut parents = parents.iter().rev();
// For a `super` invocation to be unnecessary, the first argument needs to match
// the enclosing class, and the second argument needs to match the first
// argument to the enclosing function.
let [first_arg, second_arg] = args else {
return None;
};
// Find the enclosing function definition (if any).
let Some(StmtKind::FunctionDef {
args: parent_args, ..
}) = parents
.find(|stmt| matches!(stmt.node, StmtKind::FunctionDef { .. }))
.map(|stmt| &stmt.node) else {
return None;
};
// Extract the name of the first argument to the enclosing function.
let Some(ArgData {
arg: parent_arg, ..
}) = parent_args.args.first().map(|expr| &expr.node) else {
return None;
};
// Find the enclosing class definition (if any).
let Some(StmtKind::ClassDef {
name: parent_name, ..
}) = parents
.find(|stmt| matches!(stmt.node, StmtKind::ClassDef { .. }))
.map(|stmt| &stmt.node) else {
return None;
};
let (
ExprKind::Name {
id: first_arg_id, ..
},
ExprKind::Name {
id: second_arg_id, ..
},
) = (&first_arg.node, &second_arg.node) else {
return None;
};
if first_arg_id == parent_name && second_arg_id == parent_arg {
return Some(Diagnostic::new(
violations::SuperCallWithParameters,
Range::from_located(expr),
));
}
None
}

View file

@ -0,0 +1,31 @@
use crate::ast::types::Range;
use crate::fix::Fix;
use crate::registry::Diagnostic;
use crate::violations;
use once_cell::sync::Lazy;
use regex::Regex;
use rustpython_ast::Location;
// Regex from PEP263.
static CODING_COMMENT_REGEX: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^[ \t\f]*#.*?coding[:=][ \t]*utf-?8").unwrap());
/// UP009
pub fn unnecessary_coding_comment(lineno: usize, line: &str, autofix: bool) -> Option<Diagnostic> {
// PEP3120 makes utf-8 the default encoding.
if CODING_COMMENT_REGEX.is_match(line) {
let mut diagnostic = Diagnostic::new(
violations::PEP3120UnnecessaryCodingComment,
Range::new(Location::new(lineno + 1, 0), Location::new(lineno + 2, 0)),
);
if autofix {
diagnostic.amend(Fix::deletion(
Location::new(lineno + 1, 0),
Location::new(lineno + 2, 0),
));
}
Some(diagnostic)
} else {
None
}
}