Return a slice in `StmtClassDef#bases` (#6311)

Slices are strictly more flexible, since you can always convert to an
iterator, etc., but not the other way around. Suggested in
https://github.com/astral-sh/ruff/pull/6259#discussion_r1282730994.
This commit is contained in:
Charlie Marsh 2023-08-03 12:21:55 -04:00 committed by GitHub
parent 718e3945e3
commit 2fa508793f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 16 additions and 15 deletions

View File

@ -79,6 +79,7 @@ pub(crate) fn builtin_attribute_shadowing(
// subscripting and not through attribute access. // subscripting and not through attribute access.
if class_def if class_def
.bases() .bases()
.iter()
.any(|base| checker.semantic().match_typing_expr(base, "TypedDict")) .any(|base| checker.semantic().match_typing_expr(base, "TypedDict"))
{ {
return; return;

View File

@ -58,7 +58,7 @@ pub(crate) fn non_unique_enums(checker: &mut Checker, parent: &Stmt, body: &[Stm
return; return;
}; };
if !parent.bases().any(|expr| { if !parent.bases().iter().any(|expr| {
checker checker
.semantic() .semantic()
.resolve_call_path(expr) .resolve_call_path(expr)

View File

@ -223,6 +223,7 @@ pub(crate) fn unused_private_protocol(
if !class_def if !class_def
.bases() .bases()
.iter()
.any(|base| checker.semantic().match_typing_expr(base, "Protocol")) .any(|base| checker.semantic().match_typing_expr(base, "Protocol"))
{ {
continue; continue;
@ -309,6 +310,7 @@ pub(crate) fn unused_private_typed_dict(
if !class_def if !class_def
.bases() .bases()
.iter()
.any(|base| checker.semantic().match_typing_expr(base, "TypedDict")) .any(|base| checker.semantic().match_typing_expr(base, "TypedDict"))
{ {
continue; continue;

View File

@ -39,7 +39,7 @@ fn runtime_evaluated_base_class(base_classes: &[String], semantic: &SemanticMode
return false; return false;
}; };
class_def.bases().any(|base| { class_def.bases().iter().any(|base| {
semantic.resolve_call_path(base).is_some_and(|call_path| { semantic.resolve_call_path(base).is_some_and(|call_path| {
base_classes base_classes
.iter() .iter()

View File

@ -167,21 +167,19 @@ pub struct StmtClassDef {
impl StmtClassDef { impl StmtClassDef {
/// Return an iterator over the bases of the class. /// Return an iterator over the bases of the class.
pub fn bases(&self) -> impl Iterator<Item = &Expr> { pub fn bases(&self) -> &[Expr] {
self.arguments match &self.arguments {
.as_ref() Some(arguments) => &arguments.args,
.map(|arguments| &arguments.args) None => &[],
.into_iter() }
.flatten()
} }
/// Return an iterator over the metaclass keywords of the class. /// Return an iterator over the metaclass keywords of the class.
pub fn keywords(&self) -> impl Iterator<Item = &Keyword> { pub fn keywords(&self) -> &[Keyword] {
self.arguments match &self.arguments {
.as_ref() Some(arguments) => &arguments.keywords,
.map(|arguments| &arguments.keywords) None => &[],
.into_iter() }
.flatten()
} }
} }

View File

@ -42,7 +42,7 @@ pub fn classify(
FunctionType::StaticMethod FunctionType::StaticMethod
} else if matches!(name, "__new__" | "__init_subclass__" | "__class_getitem__") } else if matches!(name, "__new__" | "__init_subclass__" | "__class_getitem__")
// Special-case class method, like `__new__`. // Special-case class method, like `__new__`.
|| class_def.bases().any(|expr| { || class_def.bases().iter().any(|expr| {
// The class itself extends a known metaclass, so all methods are class methods. // The class itself extends a known metaclass, so all methods are class methods.
semantic semantic
.resolve_call_path(map_callable(expr)) .resolve_call_path(map_callable(expr))