Improve handling of builtin symbols in linter rules (#10919)

Add a new method to the semantic model to simplify and improve the correctness of a common pattern
This commit is contained in:
Alex Waygood 2024-04-16 11:37:31 +01:00 committed by GitHub
parent effd5188c9
commit f779babc5f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
93 changed files with 886 additions and 588 deletions

View file

@ -37,7 +37,7 @@ pub fn classify(
semantic
.resolve_qualified_name(map_callable(expr))
.is_some_and( |qualified_name| {
matches!(qualified_name.segments(), ["", "type"] | ["abc", "ABCMeta"])
matches!(qualified_name.segments(), ["" | "builtins", "type"] | ["abc", "ABCMeta"])
})
})
|| decorator_list.iter().any(|decorator| is_class_method(decorator, semantic, classmethod_decorators))
@ -63,7 +63,7 @@ fn is_static_method(
.is_some_and(|qualified_name| {
matches!(
qualified_name.segments(),
["", "staticmethod"] | ["abc", "abstractstaticmethod"]
["" | "builtins", "staticmethod"] | ["abc", "abstractstaticmethod"]
) || staticmethod_decorators
.iter()
.any(|decorator| qualified_name == QualifiedName::from_dotted_name(decorator))
@ -103,7 +103,7 @@ fn is_class_method(
.is_some_and(|qualified_name| {
matches!(
qualified_name.segments(),
["", "classmethod"] | ["abc", "abstractclassmethod"]
["" | "builtins", "classmethod"] | ["abc", "abstractclassmethod"]
) || classmethod_decorators
.iter()
.any(|decorator| qualified_name == QualifiedName::from_dotted_name(decorator))

View file

@ -686,7 +686,7 @@ impl TypeChecker for IoBaseChecker {
.is_some_and(|qualified_name| {
matches!(
qualified_name.segments(),
["io", "open" | "open_code"] | ["os" | "", "open"]
["io", "open" | "open_code"] | ["os" | "" | "builtins", "open"]
)
})
}

View file

@ -15,20 +15,16 @@ pub enum Visibility {
/// Returns `true` if a function is a "static method".
pub fn is_staticmethod(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
decorator_list.iter().any(|decorator| {
semantic
.resolve_qualified_name(map_callable(&decorator.expression))
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["", "staticmethod"]))
})
decorator_list
.iter()
.any(|decorator| semantic.match_builtin_expr(&decorator.expression, "staticmethod"))
}
/// Returns `true` if a function is a "class method".
pub fn is_classmethod(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
decorator_list.iter().any(|decorator| {
semantic
.resolve_qualified_name(map_callable(&decorator.expression))
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["", "classmethod"]))
})
decorator_list
.iter()
.any(|decorator| semantic.match_builtin_expr(&decorator.expression, "classmethod"))
}
/// Returns `true` if a function definition is an `@overload`.
@ -79,7 +75,7 @@ pub fn is_property(
.is_some_and(|qualified_name| {
matches!(
qualified_name.segments(),
["", "property"] | ["functools", "cached_property"]
["" | "builtins", "property"] | ["functools", "cached_property"]
) || extra_properties
.iter()
.any(|extra_property| extra_property.segments() == qualified_name.segments())