ty_python_semantic: move some routines to FunctionType

These are, after all, specific to function types. The methods on `Type`
are more like conveniences that return something when the type *happens*
to be a function. But defining them on `FunctionType` itself makes it
easy to call them when you have a `FunctionType` instead of a `Type`.
This commit is contained in:
Andrew Gallant 2025-05-13 12:37:19 -04:00 committed by Andrew Gallant
parent bd5b7f415f
commit 451c5db7a3

View file

@ -5372,16 +5372,7 @@ impl<'db> Type<'db> {
/// a diagnostic.
fn return_type_span(&self, db: &'db dyn Db) -> 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 return_type_range = func_def.returns.as_ref()?.range();
let name_span = span.clone().with_range(func_def.name.range);
let return_type_span = span.with_range(return_type_range);
Some((name_span, return_type_span))
}
Type::FunctionLiteral(function) => function.return_type_span(db),
Type::BoundMethod(bound_method) => {
Type::FunctionLiteral(bound_method.function(db)).return_type_span(db)
}
@ -5418,24 +5409,7 @@ impl<'db> Type<'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::FunctionLiteral(function) => function.parameter_span(db, parameter_index),
Type::BoundMethod(bound_method) => {
Type::FunctionLiteral(bound_method.function(db)).parameter_span(db, parameter_index)
}
@ -6919,6 +6893,83 @@ impl<'db> FunctionType<'db> {
})
}
}
/// 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 return type in the function
/// definition for `self`.
///
/// If there are no meaningful spans, then this
/// returns `None`. For example, when this type
/// isn't callable or if the function has no
/// declared return type.
///
/// # 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 return_type_span(&self, db: &'db dyn Db) -> Option<(Span, Span)> {
let function_scope = self.body_scope(db);
let span = Span::from(function_scope.file(db));
let node = function_scope.node(db);
let func_def = node.as_function()?;
let return_type_range = func_def.returns.as_ref()?.range();
let name_span = span.clone().with_range(func_def.name.range);
let return_type_span = span.with_range(return_type_range);
Some((name_span, return_type_span))
}
/// 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)> {
let function_scope = self.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))
}
}
fn signature_cycle_recover<'db>(