mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-10 13:48:35 +00:00
Rename semantic_model
and model
usages to semantic
(#5097)
## Summary As discussed in Discord, and similar to oxc, we're going to refer to this as `.semantic()` everywhere. While I was auditing usages of `model: &SemanticModel`, I also changed as many function signatures as I could find to consistently take the model as the _last_ argument, rather than the first.
This commit is contained in:
parent
65dbfd2556
commit
bae183b823
209 changed files with 1058 additions and 1167 deletions
|
@ -19,10 +19,10 @@ pub enum FunctionType {
|
|||
|
||||
/// Classify a function based on its scope, name, and decorators.
|
||||
pub fn classify(
|
||||
model: &SemanticModel,
|
||||
scope: &Scope,
|
||||
name: &str,
|
||||
decorator_list: &[Decorator],
|
||||
scope: &Scope,
|
||||
semantic: &SemanticModel,
|
||||
classmethod_decorators: &[String],
|
||||
staticmethod_decorators: &[String],
|
||||
) -> FunctionType {
|
||||
|
@ -32,7 +32,7 @@ pub fn classify(
|
|||
if decorator_list.iter().any(|decorator| {
|
||||
// The method is decorated with a static method decorator (like
|
||||
// `@staticmethod`).
|
||||
model
|
||||
semantic
|
||||
.resolve_call_path(map_callable(&decorator.expression))
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["", "staticmethod"]
|
||||
|
@ -46,7 +46,7 @@ pub fn classify(
|
|||
// Special-case class method, like `__new__`.
|
||||
|| scope.bases.iter().any(|expr| {
|
||||
// The class itself extends a known metaclass, so all methods are class methods.
|
||||
model.resolve_call_path(map_callable(expr)).map_or(false, |call_path| {
|
||||
semantic.resolve_call_path(map_callable(expr)).map_or(false, |call_path| {
|
||||
METACLASS_BASES
|
||||
.iter()
|
||||
.any(|(module, member)| call_path.as_slice() == [*module, *member])
|
||||
|
@ -54,7 +54,7 @@ pub fn classify(
|
|||
})
|
||||
|| decorator_list.iter().any(|decorator| {
|
||||
// The method is decorated with a class method decorator (like `@classmethod`).
|
||||
model.resolve_call_path(map_callable(&decorator.expression)).map_or(false, |call_path| {
|
||||
semantic.resolve_call_path(map_callable(&decorator.expression)).map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["", "classmethod"] ||
|
||||
classmethod_decorators
|
||||
.iter()
|
||||
|
|
|
@ -17,9 +17,9 @@ use crate::model::SemanticModel;
|
|||
/// # This is detected to be a logger candidate
|
||||
/// bar.error()
|
||||
/// ```
|
||||
pub fn is_logger_candidate(func: &Expr, model: &SemanticModel) -> bool {
|
||||
pub fn is_logger_candidate(func: &Expr, semantic: &SemanticModel) -> bool {
|
||||
if let Expr::Attribute(ast::ExprAttribute { value, .. }) = func {
|
||||
let Some(call_path) = (if let Some(call_path) = model.resolve_call_path(value) {
|
||||
let Some(call_path) = (if let Some(call_path) = semantic.resolve_call_path(value) {
|
||||
if call_path.first().map_or(false, |module| *module == "logging") || call_path.as_slice() == ["flask", "current_app", "logger"] {
|
||||
Some(call_path)
|
||||
} else {
|
||||
|
@ -41,7 +41,7 @@ pub fn is_logger_candidate(func: &Expr, model: &SemanticModel) -> bool {
|
|||
|
||||
/// If the keywords to a logging call contain `exc_info=True` or `exc_info=sys.exc_info()`,
|
||||
/// return the `Keyword` for `exc_info`.
|
||||
pub fn exc_info<'a>(keywords: &'a [Keyword], model: &SemanticModel) -> Option<&'a Keyword> {
|
||||
pub fn exc_info<'a>(keywords: &'a [Keyword], semantic: &SemanticModel) -> Option<&'a Keyword> {
|
||||
let exc_info = find_keyword(keywords, "exc_info")?;
|
||||
|
||||
// Ex) `logging.error("...", exc_info=True)`
|
||||
|
@ -57,7 +57,7 @@ pub fn exc_info<'a>(keywords: &'a [Keyword], model: &SemanticModel) -> Option<&'
|
|||
|
||||
// Ex) `logging.error("...", exc_info=sys.exc_info())`
|
||||
if let Expr::Call(ast::ExprCall { func, .. }) = &exc_info.value {
|
||||
if model.resolve_call_path(func).map_or(false, |call_path| {
|
||||
if semantic.resolve_call_path(func).map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["sys", "exc_info"]
|
||||
}) {
|
||||
return Some(exc_info);
|
||||
|
|
|
@ -29,7 +29,7 @@ pub enum SubscriptKind {
|
|||
|
||||
pub fn match_annotated_subscript<'a>(
|
||||
expr: &Expr,
|
||||
semantic_model: &SemanticModel,
|
||||
semantic: &SemanticModel,
|
||||
typing_modules: impl Iterator<Item = &'a str>,
|
||||
extend_generics: &[String],
|
||||
) -> Option<SubscriptKind> {
|
||||
|
@ -37,39 +37,37 @@ pub fn match_annotated_subscript<'a>(
|
|||
return None;
|
||||
}
|
||||
|
||||
semantic_model
|
||||
.resolve_call_path(expr)
|
||||
.and_then(|call_path| {
|
||||
if SUBSCRIPTS.contains(&call_path.as_slice())
|
||||
|| extend_generics
|
||||
.iter()
|
||||
.map(|target| from_qualified_name(target))
|
||||
.any(|target| call_path == target)
|
||||
{
|
||||
return Some(SubscriptKind::AnnotatedSubscript);
|
||||
}
|
||||
if PEP_593_SUBSCRIPTS.contains(&call_path.as_slice()) {
|
||||
return Some(SubscriptKind::PEP593AnnotatedSubscript);
|
||||
}
|
||||
semantic.resolve_call_path(expr).and_then(|call_path| {
|
||||
if SUBSCRIPTS.contains(&call_path.as_slice())
|
||||
|| extend_generics
|
||||
.iter()
|
||||
.map(|target| from_qualified_name(target))
|
||||
.any(|target| call_path == target)
|
||||
{
|
||||
return Some(SubscriptKind::AnnotatedSubscript);
|
||||
}
|
||||
if PEP_593_SUBSCRIPTS.contains(&call_path.as_slice()) {
|
||||
return Some(SubscriptKind::PEP593AnnotatedSubscript);
|
||||
}
|
||||
|
||||
for module in typing_modules {
|
||||
let module_call_path: CallPath = from_unqualified_name(module);
|
||||
if call_path.starts_with(&module_call_path) {
|
||||
for subscript in SUBSCRIPTS.iter() {
|
||||
if call_path.last() == subscript.last() {
|
||||
return Some(SubscriptKind::AnnotatedSubscript);
|
||||
}
|
||||
for module in typing_modules {
|
||||
let module_call_path: CallPath = from_unqualified_name(module);
|
||||
if call_path.starts_with(&module_call_path) {
|
||||
for subscript in SUBSCRIPTS.iter() {
|
||||
if call_path.last() == subscript.last() {
|
||||
return Some(SubscriptKind::AnnotatedSubscript);
|
||||
}
|
||||
for subscript in PEP_593_SUBSCRIPTS.iter() {
|
||||
if call_path.last() == subscript.last() {
|
||||
return Some(SubscriptKind::PEP593AnnotatedSubscript);
|
||||
}
|
||||
}
|
||||
for subscript in PEP_593_SUBSCRIPTS.iter() {
|
||||
if call_path.last() == subscript.last() {
|
||||
return Some(SubscriptKind::PEP593AnnotatedSubscript);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
})
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -91,32 +89,30 @@ impl std::fmt::Display for ModuleMember {
|
|||
|
||||
/// Returns the PEP 585 standard library generic variant for a `typing` module reference, if such
|
||||
/// a variant exists.
|
||||
pub fn to_pep585_generic(expr: &Expr, semantic_model: &SemanticModel) -> Option<ModuleMember> {
|
||||
semantic_model
|
||||
.resolve_call_path(expr)
|
||||
.and_then(|call_path| {
|
||||
let [module, name] = call_path.as_slice() else {
|
||||
pub fn to_pep585_generic(expr: &Expr, semantic: &SemanticModel) -> Option<ModuleMember> {
|
||||
semantic.resolve_call_path(expr).and_then(|call_path| {
|
||||
let [module, name] = call_path.as_slice() else {
|
||||
return None;
|
||||
};
|
||||
PEP_585_GENERICS.iter().find_map(
|
||||
|((from_module, from_member), (to_module, to_member))| {
|
||||
if module == from_module && name == from_member {
|
||||
if to_module.is_empty() {
|
||||
Some(ModuleMember::BuiltIn(to_member))
|
||||
} else {
|
||||
Some(ModuleMember::Member(to_module, to_member))
|
||||
}
|
||||
PEP_585_GENERICS
|
||||
.iter()
|
||||
.find_map(|((from_module, from_member), (to_module, to_member))| {
|
||||
if module == from_module && name == from_member {
|
||||
if to_module.is_empty() {
|
||||
Some(ModuleMember::BuiltIn(to_member))
|
||||
} else {
|
||||
None
|
||||
Some(ModuleMember::Member(to_module, to_member))
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Return whether a given expression uses a PEP 585 standard library generic.
|
||||
pub fn is_pep585_generic(expr: &Expr, model: &SemanticModel) -> bool {
|
||||
if let Some(call_path) = model.resolve_call_path(expr) {
|
||||
pub fn is_pep585_generic(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
if let Some(call_path) = semantic.resolve_call_path(expr) {
|
||||
let [module, name] = call_path.as_slice() else {
|
||||
return false;
|
||||
};
|
||||
|
@ -141,7 +137,7 @@ pub enum Pep604Operator {
|
|||
pub fn to_pep604_operator(
|
||||
value: &Expr,
|
||||
slice: &Expr,
|
||||
semantic_model: &SemanticModel,
|
||||
semantic: &SemanticModel,
|
||||
) -> Option<Pep604Operator> {
|
||||
/// Returns `true` if any argument in the slice is a string.
|
||||
fn any_arg_is_str(slice: &Expr) -> bool {
|
||||
|
@ -161,13 +157,13 @@ pub fn to_pep604_operator(
|
|||
return None;
|
||||
}
|
||||
|
||||
semantic_model
|
||||
semantic
|
||||
.resolve_call_path(value)
|
||||
.as_ref()
|
||||
.and_then(|call_path| {
|
||||
if semantic_model.match_typing_call_path(call_path, "Optional") {
|
||||
if semantic.match_typing_call_path(call_path, "Optional") {
|
||||
Some(Pep604Operator::Optional)
|
||||
} else if semantic_model.match_typing_call_path(call_path, "Union") {
|
||||
} else if semantic.match_typing_call_path(call_path, "Union") {
|
||||
Some(Pep604Operator::Union)
|
||||
} else {
|
||||
None
|
||||
|
@ -177,19 +173,17 @@ pub fn to_pep604_operator(
|
|||
|
||||
/// Return `true` if `Expr` represents a reference to a type annotation that resolves to an
|
||||
/// immutable type.
|
||||
pub fn is_immutable_annotation(semantic_model: &SemanticModel, expr: &Expr) -> bool {
|
||||
pub fn is_immutable_annotation(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
match expr {
|
||||
Expr::Name(_) | Expr::Attribute(_) => {
|
||||
semantic_model
|
||||
.resolve_call_path(expr)
|
||||
.map_or(false, |call_path| {
|
||||
IMMUTABLE_TYPES
|
||||
.iter()
|
||||
.chain(IMMUTABLE_GENERIC_TYPES)
|
||||
.any(|target| call_path.as_slice() == *target)
|
||||
})
|
||||
semantic.resolve_call_path(expr).map_or(false, |call_path| {
|
||||
IMMUTABLE_TYPES
|
||||
.iter()
|
||||
.chain(IMMUTABLE_GENERIC_TYPES)
|
||||
.any(|target| call_path.as_slice() == *target)
|
||||
})
|
||||
}
|
||||
Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => semantic_model
|
||||
Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => semantic
|
||||
.resolve_call_path(value)
|
||||
.map_or(false, |call_path| {
|
||||
if IMMUTABLE_GENERIC_TYPES
|
||||
|
@ -200,16 +194,16 @@ pub fn is_immutable_annotation(semantic_model: &SemanticModel, expr: &Expr) -> b
|
|||
} else if call_path.as_slice() == ["typing", "Union"] {
|
||||
if let Expr::Tuple(ast::ExprTuple { elts, .. }) = slice.as_ref() {
|
||||
elts.iter()
|
||||
.all(|elt| is_immutable_annotation(semantic_model, elt))
|
||||
.all(|elt| is_immutable_annotation(elt, semantic))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else if call_path.as_slice() == ["typing", "Optional"] {
|
||||
is_immutable_annotation(semantic_model, slice)
|
||||
is_immutable_annotation(slice, semantic)
|
||||
} else if call_path.as_slice() == ["typing", "Annotated"] {
|
||||
if let Expr::Tuple(ast::ExprTuple { elts, .. }) = slice.as_ref() {
|
||||
elts.first()
|
||||
.map_or(false, |elt| is_immutable_annotation(semantic_model, elt))
|
||||
.map_or(false, |elt| is_immutable_annotation(elt, semantic))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -222,10 +216,7 @@ pub fn is_immutable_annotation(semantic_model: &SemanticModel, expr: &Expr) -> b
|
|||
op: Operator::BitOr,
|
||||
right,
|
||||
range: _range,
|
||||
}) => {
|
||||
is_immutable_annotation(semantic_model, left)
|
||||
&& is_immutable_annotation(semantic_model, right)
|
||||
}
|
||||
}) => is_immutable_annotation(left, semantic) && is_immutable_annotation(right, semantic),
|
||||
Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::None,
|
||||
..
|
||||
|
@ -257,24 +248,22 @@ const IMMUTABLE_FUNCS: &[&[&str]] = &[
|
|||
|
||||
/// Return `true` if `func` is a function that returns an immutable object.
|
||||
pub fn is_immutable_func(
|
||||
semantic_model: &SemanticModel,
|
||||
func: &Expr,
|
||||
semantic: &SemanticModel,
|
||||
extend_immutable_calls: &[CallPath],
|
||||
) -> bool {
|
||||
semantic_model
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
IMMUTABLE_FUNCS
|
||||
semantic.resolve_call_path(func).map_or(false, |call_path| {
|
||||
IMMUTABLE_FUNCS
|
||||
.iter()
|
||||
.any(|target| call_path.as_slice() == *target)
|
||||
|| extend_immutable_calls
|
||||
.iter()
|
||||
.any(|target| call_path.as_slice() == *target)
|
||||
|| extend_immutable_calls
|
||||
.iter()
|
||||
.any(|target| call_path == *target)
|
||||
})
|
||||
.any(|target| call_path == *target)
|
||||
})
|
||||
}
|
||||
|
||||
/// Return `true` if [`Expr`] is a guard for a type-checking block.
|
||||
pub fn is_type_checking_block(stmt: &ast::StmtIf, semantic_model: &SemanticModel) -> bool {
|
||||
pub fn is_type_checking_block(stmt: &ast::StmtIf, semantic: &SemanticModel) -> bool {
|
||||
let ast::StmtIf { test, .. } = stmt;
|
||||
|
||||
// Ex) `if False:`
|
||||
|
@ -300,12 +289,9 @@ pub fn is_type_checking_block(stmt: &ast::StmtIf, semantic_model: &SemanticModel
|
|||
}
|
||||
|
||||
// Ex) `if typing.TYPE_CHECKING:`
|
||||
if semantic_model
|
||||
.resolve_call_path(test)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["typing", "TYPE_CHECKING"]
|
||||
})
|
||||
{
|
||||
if semantic.resolve_call_path(test).map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["typing", "TYPE_CHECKING"]
|
||||
}) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,9 @@ pub enum Visibility {
|
|||
}
|
||||
|
||||
/// Returns `true` if a function is a "static method".
|
||||
pub fn is_staticmethod(model: &SemanticModel, decorator_list: &[Decorator]) -> bool {
|
||||
pub fn is_staticmethod(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
|
||||
decorator_list.iter().any(|decorator| {
|
||||
model
|
||||
semantic
|
||||
.resolve_call_path(map_callable(&decorator.expression))
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["", "staticmethod"]
|
||||
|
@ -25,9 +25,9 @@ pub fn is_staticmethod(model: &SemanticModel, decorator_list: &[Decorator]) -> b
|
|||
}
|
||||
|
||||
/// Returns `true` if a function is a "class method".
|
||||
pub fn is_classmethod(model: &SemanticModel, decorator_list: &[Decorator]) -> bool {
|
||||
pub fn is_classmethod(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
|
||||
decorator_list.iter().any(|decorator| {
|
||||
model
|
||||
semantic
|
||||
.resolve_call_path(map_callable(&decorator.expression))
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["", "classmethod"]
|
||||
|
@ -36,23 +36,23 @@ pub fn is_classmethod(model: &SemanticModel, decorator_list: &[Decorator]) -> bo
|
|||
}
|
||||
|
||||
/// Returns `true` if a function definition is an `@overload`.
|
||||
pub fn is_overload(model: &SemanticModel, decorator_list: &[Decorator]) -> bool {
|
||||
decorator_list
|
||||
.iter()
|
||||
.any(|decorator| model.match_typing_expr(map_callable(&decorator.expression), "overload"))
|
||||
pub fn is_overload(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
|
||||
decorator_list.iter().any(|decorator| {
|
||||
semantic.match_typing_expr(map_callable(&decorator.expression), "overload")
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `true` if a function definition is an `@override` (PEP 698).
|
||||
pub fn is_override(model: &SemanticModel, decorator_list: &[Decorator]) -> bool {
|
||||
decorator_list
|
||||
.iter()
|
||||
.any(|decorator| model.match_typing_expr(map_callable(&decorator.expression), "override"))
|
||||
pub fn is_override(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
|
||||
decorator_list.iter().any(|decorator| {
|
||||
semantic.match_typing_expr(map_callable(&decorator.expression), "override")
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `true` if a function definition is an abstract method based on its decorators.
|
||||
pub fn is_abstract(model: &SemanticModel, decorator_list: &[Decorator]) -> bool {
|
||||
pub fn is_abstract(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
|
||||
decorator_list.iter().any(|decorator| {
|
||||
model
|
||||
semantic
|
||||
.resolve_call_path(map_callable(&decorator.expression))
|
||||
.map_or(false, |call_path| {
|
||||
matches!(
|
||||
|
@ -73,12 +73,12 @@ pub fn is_abstract(model: &SemanticModel, decorator_list: &[Decorator]) -> bool
|
|||
/// `extra_properties` can be used to check additional non-standard
|
||||
/// `@property`-like decorators.
|
||||
pub fn is_property(
|
||||
model: &SemanticModel,
|
||||
decorator_list: &[Decorator],
|
||||
extra_properties: &[CallPath],
|
||||
semantic: &SemanticModel,
|
||||
) -> bool {
|
||||
decorator_list.iter().any(|decorator| {
|
||||
model
|
||||
semantic
|
||||
.resolve_call_path(map_callable(&decorator.expression))
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["", "property"]
|
||||
|
@ -91,10 +91,10 @@ pub fn is_property(
|
|||
}
|
||||
|
||||
/// Returns `true` if a class is an `final`.
|
||||
pub fn is_final(model: &SemanticModel, decorator_list: &[Decorator]) -> bool {
|
||||
pub fn is_final(decorator_list: &[Decorator], semantic: &SemanticModel) -> bool {
|
||||
decorator_list
|
||||
.iter()
|
||||
.any(|decorator| model.match_typing_expr(map_callable(&decorator.expression), "final"))
|
||||
.any(|decorator| semantic.match_typing_expr(map_callable(&decorator.expression), "final"))
|
||||
}
|
||||
|
||||
/// Returns `true` if a function is a "magic method".
|
||||
|
|
|
@ -142,11 +142,11 @@ impl<'a> Binding<'a> {
|
|||
}
|
||||
|
||||
/// Returns the appropriate visual range for highlighting this binding.
|
||||
pub fn trimmed_range(&self, semantic_model: &SemanticModel, locator: &Locator) -> TextRange {
|
||||
pub fn trimmed_range(&self, semantic: &SemanticModel, locator: &Locator) -> TextRange {
|
||||
match self.kind {
|
||||
BindingKind::ClassDefinition | BindingKind::FunctionDefinition => {
|
||||
self.source.map_or(self.range, |source| {
|
||||
helpers::identifier_range(semantic_model.stmts[source], locator)
|
||||
helpers::identifier_range(semantic.stmts[source], locator)
|
||||
})
|
||||
}
|
||||
_ => self.range,
|
||||
|
@ -154,9 +154,9 @@ impl<'a> Binding<'a> {
|
|||
}
|
||||
|
||||
/// Returns the range of the binding's parent.
|
||||
pub fn parent_range(&self, semantic_model: &SemanticModel) -> Option<TextRange> {
|
||||
pub fn parent_range(&self, semantic: &SemanticModel) -> Option<TextRange> {
|
||||
self.source
|
||||
.map(|node_id| semantic_model.stmts[node_id])
|
||||
.map(|node_id| semantic.stmts[node_id])
|
||||
.and_then(|parent| {
|
||||
if parent.is_import_from_stmt() {
|
||||
Some(parent.range())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue