mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 13:51:37 +00:00
red_knot_python_semantic: move parameter span helper method
I wanted to use this method in other places, so I moved it to what appears to be a God-type. I also made it slightly more versatile: callers can ask for the entire parameter list by omitting a specific parameter index.
This commit is contained in:
parent
43bd043755
commit
a45a0a92bd
2 changed files with 56 additions and 44 deletions
|
@ -4903,6 +4903,60 @@ impl<'db> Type<'db> {
|
||||||
| Self::AlwaysFalsy => None,
|
| Self::AlwaysFalsy => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a tuple of two spans. The first is
|
||||||
|
/// the span for the identifier of the function
|
||||||
|
/// definition for `self`. The second is
|
||||||
|
/// the span for the parameter in the function
|
||||||
|
/// definition for `self`.
|
||||||
|
///
|
||||||
|
/// If there are no meaningful spans, then this
|
||||||
|
/// returns `None`. For example, when this type
|
||||||
|
/// isn't callable.
|
||||||
|
///
|
||||||
|
/// When `parameter_index` is `None`, then the
|
||||||
|
/// second span returned covers the entire parameter
|
||||||
|
/// list.
|
||||||
|
///
|
||||||
|
/// # Performance
|
||||||
|
///
|
||||||
|
/// Note that this may introduce cross-module
|
||||||
|
/// dependencies. This can have an impact on
|
||||||
|
/// the effectiveness of incremental caching
|
||||||
|
/// and should therefore be used judiciously.
|
||||||
|
///
|
||||||
|
/// An example of a good use case is to improve
|
||||||
|
/// a diagnostic.
|
||||||
|
fn parameter_span(
|
||||||
|
&self,
|
||||||
|
db: &'db dyn Db,
|
||||||
|
parameter_index: Option<usize>,
|
||||||
|
) -> Option<(Span, Span)> {
|
||||||
|
match *self {
|
||||||
|
Type::FunctionLiteral(function) => {
|
||||||
|
let function_scope = function.body_scope(db);
|
||||||
|
let span = Span::from(function_scope.file(db));
|
||||||
|
let node = function_scope.node(db);
|
||||||
|
let func_def = node.as_function()?;
|
||||||
|
let range = parameter_index
|
||||||
|
.and_then(|parameter_index| {
|
||||||
|
func_def
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.nth(parameter_index)
|
||||||
|
.map(|param| param.range())
|
||||||
|
})
|
||||||
|
.unwrap_or(func_def.parameters.range);
|
||||||
|
let name_span = span.clone().with_range(func_def.name.range);
|
||||||
|
let parameter_span = span.with_range(range);
|
||||||
|
Some((name_span, parameter_span))
|
||||||
|
}
|
||||||
|
Type::BoundMethod(bound_method) => {
|
||||||
|
Type::FunctionLiteral(bound_method.function(db)).parameter_span(db, parameter_index)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'db> From<&Type<'db>> for Type<'db> {
|
impl<'db> From<&Type<'db>> for Type<'db> {
|
||||||
|
|
|
@ -23,9 +23,8 @@ use crate::types::{
|
||||||
KnownFunction, KnownInstanceType, MethodWrapperKind, PropertyInstanceType, TupleType,
|
KnownFunction, KnownInstanceType, MethodWrapperKind, PropertyInstanceType, TupleType,
|
||||||
UnionType, WrapperDescriptorKind,
|
UnionType, WrapperDescriptorKind,
|
||||||
};
|
};
|
||||||
use ruff_db::diagnostic::{Annotation, Severity, Span, SubDiagnostic};
|
use ruff_db::diagnostic::{Annotation, Severity, SubDiagnostic};
|
||||||
use ruff_python_ast as ast;
|
use ruff_python_ast as ast;
|
||||||
use ruff_text_size::Ranged;
|
|
||||||
|
|
||||||
/// Binding information for a possible union of callables. At a call site, the arguments must be
|
/// Binding information for a possible union of callables. At a call site, the arguments must be
|
||||||
/// compatible with _all_ of the types in the union for the call to be valid.
|
/// compatible with _all_ of the types in the union for the call to be valid.
|
||||||
|
@ -1386,47 +1385,6 @@ pub(crate) enum BindingError<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'db> BindingError<'db> {
|
impl<'db> BindingError<'db> {
|
||||||
/// Returns a tuple of two spans. The first is
|
|
||||||
/// the span for the identifier of the function
|
|
||||||
/// definition for `callable_ty`. The second is
|
|
||||||
/// the span for the parameter in the function
|
|
||||||
/// definition for `callable_ty`.
|
|
||||||
///
|
|
||||||
/// If there are no meaningful spans, then this
|
|
||||||
/// returns `None`.
|
|
||||||
fn parameter_span_from_index(
|
|
||||||
db: &'db dyn Db,
|
|
||||||
callable_ty: Type<'db>,
|
|
||||||
parameter_index: usize,
|
|
||||||
) -> Option<(Span, Span)> {
|
|
||||||
match callable_ty {
|
|
||||||
Type::FunctionLiteral(function) => {
|
|
||||||
let function_scope = function.body_scope(db);
|
|
||||||
let span = Span::from(function_scope.file(db));
|
|
||||||
let node = function_scope.node(db);
|
|
||||||
if let Some(func_def) = node.as_function() {
|
|
||||||
let range = func_def
|
|
||||||
.parameters
|
|
||||||
.iter()
|
|
||||||
.nth(parameter_index)
|
|
||||||
.map(|param| param.range())
|
|
||||||
.unwrap_or(func_def.parameters.range);
|
|
||||||
let name_span = span.clone().with_range(func_def.name.range);
|
|
||||||
let parameter_span = span.with_range(range);
|
|
||||||
Some((name_span, parameter_span))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Type::BoundMethod(bound_method) => Self::parameter_span_from_index(
|
|
||||||
db,
|
|
||||||
Type::FunctionLiteral(bound_method.function(db)),
|
|
||||||
parameter_index,
|
|
||||||
),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn report_diagnostic(
|
pub(super) fn report_diagnostic(
|
||||||
&self,
|
&self,
|
||||||
context: &InferContext<'db>,
|
context: &InferContext<'db>,
|
||||||
|
@ -1454,7 +1412,7 @@ impl<'db> BindingError<'db> {
|
||||||
"Expected `{expected_ty_display}`, found `{provided_ty_display}`"
|
"Expected `{expected_ty_display}`, found `{provided_ty_display}`"
|
||||||
));
|
));
|
||||||
if let Some((name_span, parameter_span)) =
|
if let Some((name_span, parameter_span)) =
|
||||||
Self::parameter_span_from_index(context.db(), callable_ty, parameter.index)
|
callable_ty.parameter_span(context.db(), Some(parameter.index))
|
||||||
{
|
{
|
||||||
let mut sub = SubDiagnostic::new(Severity::Info, "Function defined here");
|
let mut sub = SubDiagnostic::new(Severity::Info, "Function defined here");
|
||||||
sub.annotate(Annotation::primary(name_span));
|
sub.annotate(Annotation::primary(name_span));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue