Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions crates/ty_python_semantic/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6655,11 +6655,13 @@ impl<'db> Type<'db> {
db: &'db dyn Db,
parameter_index: Option<usize>,
) -> Option<(Span, Span)> {
match *self {
Type::FunctionLiteral(function) => function.parameter_span(db, parameter_index),
Type::BoundMethod(bound_method) => bound_method
.function(db)
.parameter_span(db, parameter_index),
match self {
Type::FunctionLiteral(function) => Some(function.parameter_span(db, parameter_index)),
Type::BoundMethod(bound_method) => Some(
bound_method
.function(db)
.parameter_span(db, parameter_index),
),
_ => None,
}
}
Expand All @@ -6682,9 +6684,9 @@ impl<'db> Type<'db> {
/// An example of a good use case is to improve
/// a diagnostic.
fn function_spans(&self, db: &'db dyn Db) -> Option<FunctionSpans> {
match *self {
Type::FunctionLiteral(function) => function.spans(db),
Type::BoundMethod(bound_method) => bound_method.function(db).spans(db),
match self {
Type::FunctionLiteral(function) => Some(function.spans(db)),
Type::BoundMethod(bound_method) => Some(bound_method.function(db).spans(db)),
_ => None,
}
}
Expand Down
23 changes: 9 additions & 14 deletions crates/ty_python_semantic/src/types/call/bind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2502,15 +2502,12 @@ impl<'db> CallableBinding<'db> {
let (overloads, implementation) =
function.overloads_and_implementation(context.db());

if let Some(spans) = overloads
.first()
.and_then(|overload| overload.spans(context.db()))
{
if let Some(overload) = overloads.first() {
let mut sub = SubDiagnostic::new(
SubDiagnosticSeverity::Info,
"First overload defined here",
);
sub.annotate(Annotation::primary(spans.signature));
sub.annotate(Annotation::primary(overload.spans(context.db()).signature));
diag.sub(sub);
}

Expand All @@ -2532,14 +2529,14 @@ impl<'db> CallableBinding<'db> {
));
}

if let Some(spans) =
implementation.and_then(|function| function.spans(context.db()))
{
if let Some(implementation) = implementation {
let mut sub = SubDiagnostic::new(
SubDiagnosticSeverity::Info,
"Overload implementation defined here",
);
sub.annotate(Annotation::primary(spans.signature));
sub.annotate(Annotation::primary(
implementation.spans(context.db()).signature,
));
diag.sub(sub);
}
}
Expand Down Expand Up @@ -4421,15 +4418,13 @@ impl<'db> BindingError<'db> {
}

if let Some(matching_overload) = matching_overload {
if let Some((name_span, parameter_span)) =
matching_overload.get(context.db()).and_then(|overload| {
overload.parameter_span(context.db(), Some(parameter.index))
})
{
if let Some(overload_literal) = matching_overload.get(context.db()) {
let mut sub = SubDiagnostic::new(
SubDiagnosticSeverity::Info,
"Matching overload defined here",
);
let (name_span, parameter_span) =
overload_literal.parameter_span(context.db(), Some(parameter.index));
sub.annotate(Annotation::primary(name_span));
sub.annotate(
Annotation::secondary(parameter_span)
Expand Down
34 changes: 12 additions & 22 deletions crates/ty_python_semantic/src/types/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4239,15 +4239,13 @@ pub(crate) fn report_rebound_typevar<'db>(
return;
};
let span = match binding_type(db, other_definition) {
Type::ClassLiteral(class) => Some(class.header_span(db)),
Type::FunctionLiteral(function) => function.spans(db).map(|spans| spans.signature),
Type::ClassLiteral(class) => class.header_span(db),
Type::FunctionLiteral(function) => function.spans(db).signature,
_ => return,
};
if let Some(span) = span {
diagnostic.annotate(Annotation::secondary(span).message(format_args!(
"Type variable `{typevar_name}` is bound in this enclosing scope",
)));
}
diagnostic.annotate(Annotation::secondary(span).message(format_args!(
"Type variable `{typevar_name}` is bound in this enclosing scope",
)));
}

// I tried refactoring this function to placate Clippy,
Expand All @@ -4265,13 +4263,8 @@ pub(super) fn report_invalid_method_override<'db>(
) {
let db = context.db();

let signature_span = |function: FunctionType<'db>| {
function
.literal(db)
.last_definition(db)
.spans(db)
.map(|spans| spans.signature)
};
let signature_span =
|function: FunctionType<'db>| function.literal(db).last_definition(db).spans(db).signature;

let subclass_definition_kind = subclass_definition.kind(db);
let subclass_definition_signature_span = signature_span(subclass_function);
Expand All @@ -4280,8 +4273,7 @@ pub(super) fn report_invalid_method_override<'db>(
// in the body of the class here, we cannot use the range associated with the `FunctionType`
let diagnostic_range = if subclass_definition_kind.is_function_def() {
subclass_definition_signature_span
.as_ref()
.and_then(Span::range)
.range()
.unwrap_or_else(|| {
subclass_function
.node(db, context.file(), context.module())
Expand Down Expand Up @@ -4340,11 +4332,9 @@ pub(super) fn report_invalid_method_override<'db>(

diagnostic.info("This violates the Liskov Substitution Principle");

if !subclass_definition_kind.is_function_def()
&& let Some(span) = subclass_definition_signature_span
{
if !subclass_definition_kind.is_function_def() {
diagnostic.annotate(
Annotation::secondary(span)
Annotation::secondary(subclass_definition_signature_span)
.message(format_args!("Signature of `{class_name}.{member}`")),
);
}
Expand All @@ -4368,8 +4358,8 @@ pub(super) fn report_invalid_method_override<'db>(
);

let superclass_function_span = match superclass_type {
Type::FunctionLiteral(function) => signature_span(function),
Type::BoundMethod(method) => signature_span(method.function(db)),
Type::FunctionLiteral(function) => Some(signature_span(function)),
Type::BoundMethod(method) => Some(signature_span(method.function(db))),
_ => None,
};

Expand Down
38 changes: 16 additions & 22 deletions crates/ty_python_semantic/src/types/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,12 +599,11 @@ impl<'db> OverloadLiteral<'db> {
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 module = parsed_module(db, self.file(db)).load(db);
let func_def = node.as_function()?.node(&module);
) -> (Span, Span) {
let file = self.file(db);
let span = Span::from(file);
let module = parsed_module(db, file).load(db);
let func_def = self.node(db, file, &module);
let range = parameter_index
.and_then(|parameter_index| {
func_def
Expand All @@ -616,26 +615,25 @@ impl<'db> OverloadLiteral<'db> {
.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))
(name_span, parameter_span)
}

pub(crate) fn spans(self, db: &'db dyn Db) -> Option<FunctionSpans> {
let function_scope = self.body_scope(db);
let span = Span::from(function_scope.file(db));
let node = function_scope.node(db);
pub(crate) fn spans(self, db: &'db dyn Db) -> FunctionSpans {
let file = self.file(db);
let span = Span::from(file);
let module = parsed_module(db, self.file(db)).load(db);
let func_def = node.as_function()?.node(&module);
let func_def = self.node(db, file, &module);
let return_type_range = func_def.returns.as_ref().map(|returns| returns.range());
let mut signature = func_def.name.range.cover(func_def.parameters.range);
if let Some(return_type_range) = return_type_range {
signature = signature.cover(return_type_range);
}
Some(FunctionSpans {
FunctionSpans {
signature: span.clone().with_range(signature),
name: span.clone().with_range(func_def.name.range),
parameters: span.clone().with_range(func_def.parameters.range),
return_type: return_type_range.map(|range| span.clone().with_range(range)),
})
}
}
}

Expand Down Expand Up @@ -686,15 +684,11 @@ impl<'db> FunctionLiteral<'db> {
self.last_definition(db).definition(db)
}

fn parameter_span(
self,
db: &'db dyn Db,
parameter_index: Option<usize>,
) -> Option<(Span, Span)> {
fn parameter_span(self, db: &'db dyn Db, parameter_index: Option<usize>) -> (Span, Span) {
self.last_definition(db).parameter_span(db, parameter_index)
}

fn spans(self, db: &'db dyn Db) -> Option<FunctionSpans> {
fn spans(self, db: &'db dyn Db) -> FunctionSpans {
self.last_definition(db).spans(db)
}

Expand Down Expand Up @@ -992,7 +986,7 @@ impl<'db> FunctionType<'db> {
self,
db: &'db dyn Db,
parameter_index: Option<usize>,
) -> Option<(Span, Span)> {
) -> (Span, Span) {
self.literal(db).parameter_span(db, parameter_index)
}

Expand All @@ -1009,7 +1003,7 @@ impl<'db> FunctionType<'db> {
///
/// An example of a good use case is to improve
/// a diagnostic.
pub(crate) fn spans(self, db: &'db dyn Db) -> Option<FunctionSpans> {
pub(crate) fn spans(self, db: &'db dyn Db) -> FunctionSpans {
self.literal(db).spans(db)
}

Expand Down