improve rendering of signatures in hovers

This commit is contained in:
Aria Desires 2025-12-16 09:42:42 -05:00
parent d755f3b522
commit 53ac09c920
2 changed files with 57 additions and 30 deletions

View File

@ -1183,13 +1183,13 @@ def ab(a: str): ...
.build();
assert_snapshot!(test.hover(), @r"
(a: int) -> Unknown
def ab(a: int) -> Unknown
---------------------------------------------
the int overload
---------------------------------------------
```python
(a: int) -> Unknown
def ab(a: int) -> Unknown
```
---
the int overload
@ -1243,13 +1243,13 @@ def ab(a: str):
.build();
assert_snapshot!(test.hover(), @r#"
(a: str) -> Unknown
def ab(a: str) -> Unknown
---------------------------------------------
the int overload
---------------------------------------------
```python
(a: str) -> Unknown
def ab(a: str) -> Unknown
```
---
the int overload
@ -1303,7 +1303,7 @@ def ab(a: int):
.build();
assert_snapshot!(test.hover(), @r"
(
def ab(
a: int,
b: int
) -> Unknown
@ -1312,7 +1312,7 @@ def ab(a: int):
---------------------------------------------
```python
(
def ab(
a: int,
b: int
) -> Unknown
@ -1369,13 +1369,13 @@ def ab(a: int):
.build();
assert_snapshot!(test.hover(), @r"
(a: int) -> Unknown
def ab(a: int) -> Unknown
---------------------------------------------
the two arg overload
---------------------------------------------
```python
(a: int) -> Unknown
def ab(a: int) -> Unknown
```
---
the two arg overload
@ -1433,7 +1433,7 @@ def ab(a: int, *, c: int):
.build();
assert_snapshot!(test.hover(), @r"
(
def ab(
a: int,
*,
b: int
@ -1443,7 +1443,7 @@ def ab(a: int, *, c: int):
---------------------------------------------
```python
(
def ab(
a: int,
*,
b: int
@ -1505,7 +1505,7 @@ def ab(a: int, *, c: int):
.build();
assert_snapshot!(test.hover(), @r"
(
def ab(
a: int,
*,
c: int
@ -1515,7 +1515,7 @@ def ab(a: int, *, c: int):
---------------------------------------------
```python
(
def ab(
a: int,
*,
c: int
@ -1564,11 +1564,11 @@ def ab(a: int, *, c: int):
);
assert_snapshot!(test.hover(), @r#"
(
def foo(
a: int,
b
) -> Unknown
(
def foo(
a: str,
b
) -> Unknown
@ -1577,11 +1577,11 @@ def ab(a: int, *, c: int):
---------------------------------------------
```python
(
def foo(
a: int,
b
) -> Unknown
(
def foo(
a: str,
b
) -> Unknown
@ -1628,15 +1628,15 @@ def ab(a: int, *, c: int):
);
assert_snapshot!(test.hover(), @r#"
(a: int) -> Unknown
(a: str) -> Unknown
def foo(a: int) -> Unknown
def foo(a: str) -> Unknown
---------------------------------------------
The first overload
---------------------------------------------
```python
(a: int) -> Unknown
(a: str) -> Unknown
def foo(a: int) -> Unknown
def foo(a: str) -> Unknown
```
---
The first overload
@ -2151,10 +2151,10 @@ def function():
// TODO: This should just be `**AB@Alias2 (<variance>)`
// https://github.com/astral-sh/ty/issues/1581
assert_snapshot!(test.hover(), @r"
(**AB@Alias2) -> tuple[AB@Alias2]
def _(**AB@Alias2) -> tuple[AB@Alias2]
---------------------------------------------
```python
(**AB@Alias2) -> tuple[AB@Alias2]
def _(**AB@Alias2) -> tuple[AB@Alias2]
```
---------------------------------------------
info[hover]: Hovered content is
@ -3233,12 +3233,12 @@ def function():
// TODO: We should only show the matching overload here.
// https://github.com/astral-sh/ty/issues/73
assert_snapshot!(test.hover(), @r"
(other: Test, /) -> Test
(other: Other, /) -> Test
def __add__(other: Test, /) -> Test
def __add__(other: Other, /) -> Test
---------------------------------------------
```python
(other: Test, /) -> Test
(other: Other, /) -> Test
def __add__(other: Test, /) -> Test
def __add__(other: Other, /) -> Test
```
---------------------------------------------
info[hover]: Hovered content is

View File

@ -15,6 +15,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
use crate::Db;
use crate::place::Place;
use crate::semantic_index::definition::Definition;
use crate::types::class::{ClassLiteral, ClassType, GenericAlias};
use crate::types::function::{FunctionType, OverloadLiteral};
use crate::types::generics::{GenericContext, Specialization};
@ -40,6 +41,9 @@ pub struct DisplaySettings<'db> {
pub qualified: Rc<FxHashMap<&'db str, QualificationLevel>>,
/// Whether long unions and literals are displayed in full
pub preserve_full_unions: bool,
/// Disallow Signature printing to introduce a name
/// (presumably because we rendered one already)
pub disallow_signature_name: bool,
}
impl<'db> DisplaySettings<'db> {
@ -75,6 +79,14 @@ impl<'db> DisplaySettings<'db> {
}
}
#[must_use]
pub fn disallow_signature_name(&self) -> Self {
Self {
disallow_signature_name: true,
..self.clone()
}
}
#[must_use]
pub fn from_possibly_ambiguous_types(
db: &'db dyn Db,
@ -742,7 +754,7 @@ impl<'db> FmtDetailed<'db> for DisplayRepresentation<'db> {
type_parameters.fmt_detailed(f)?;
signature
.bind_self(self.db, Some(typing_self_ty))
.display_with(self.db, self.settings.clone())
.display_with(self.db, self.settings.disallow_signature_name())
.fmt_detailed(f)
}
signatures => {
@ -1158,7 +1170,7 @@ impl<'db> FmtDetailed<'db> for DisplayOverloadLiteral<'db> {
write!(f, "{}", self.literal.name(self.db))?;
type_parameters.fmt_detailed(f)?;
signature
.display_with(self.db, self.settings.clone())
.display_with(self.db, self.settings.disallow_signature_name())
.fmt_detailed(f)
}
}
@ -1205,7 +1217,7 @@ impl<'db> FmtDetailed<'db> for DisplayFunctionType<'db> {
write!(f, "{}", self.ty.name(self.db))?;
type_parameters.fmt_detailed(f)?;
signature
.display_with(self.db, self.settings.clone())
.display_with(self.db, self.settings.disallow_signature_name())
.fmt_detailed(f)
}
signatures => {
@ -1624,6 +1636,7 @@ impl<'db> Signature<'db> {
settings: DisplaySettings<'db>,
) -> DisplaySignature<'a, 'db> {
DisplaySignature {
definition: self.definition(),
parameters: self.parameters(),
return_ty: self.return_ty,
db,
@ -1633,6 +1646,7 @@ impl<'db> Signature<'db> {
}
pub(crate) struct DisplaySignature<'a, 'db> {
definition: Option<Definition<'db>>,
parameters: &'a Parameters<'db>,
return_ty: Option<Type<'db>>,
db: &'db dyn Db,
@ -1660,6 +1674,19 @@ impl<'db> FmtDetailed<'db> for DisplaySignature<'_, 'db> {
// When we exit this function, write a marker signaling we're ending a signature
let mut f = f.with_detail(TypeDetail::SignatureEnd);
// If we're multiline printing and a name hasn't been emitted, try to
// make one up to make things more pretty
if self.settings.multiline && !self.settings.disallow_signature_name {
f.write_str("def ")?;
if let Some(definition) = self.definition
&& let Some(name) = definition.name(self.db)
{
f.write_str(&name)?;
} else {
f.write_str("_")?;
}
}
// Parameters
self.parameters
.display_with(self.db, self.settings.clone())
@ -2694,7 +2721,7 @@ mod tests {
let db = setup_db();
// Empty parameters with no return type.
assert_snapshot!(display_signature_multiline(&db, [], None), @"() -> Unknown");
assert_snapshot!(display_signature_multiline(&db, [], None), @"def _() -> Unknown");
// Empty parameters with a return type.
assert_snapshot!(