mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
fix: Fix wrong where clause rendering on hover
This commit is contained in:
parent
0dd89d7ee7
commit
d69a81fddb
2 changed files with 211 additions and 109 deletions
|
@ -159,6 +159,7 @@ impl HirDisplay for Adt {
|
||||||
impl HirDisplay for Struct {
|
impl HirDisplay for Struct {
|
||||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||||
let module_id = self.module(f.db).id;
|
let module_id = self.module(f.db).id;
|
||||||
|
// FIXME: Render repr if its set explicitly?
|
||||||
write_visibility(module_id, self.visibility(f.db), f)?;
|
write_visibility(module_id, self.visibility(f.db), f)?;
|
||||||
f.write_str("struct ")?;
|
f.write_str("struct ")?;
|
||||||
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
|
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
|
||||||
|
@ -166,7 +167,8 @@ impl HirDisplay for Struct {
|
||||||
write_generic_params(def_id, f)?;
|
write_generic_params(def_id, f)?;
|
||||||
|
|
||||||
let variant_data = self.variant_data(f.db);
|
let variant_data = self.variant_data(f.db);
|
||||||
if let StructKind::Tuple = variant_data.kind() {
|
match variant_data.kind() {
|
||||||
|
StructKind::Tuple => {
|
||||||
f.write_char('(')?;
|
f.write_char('(')?;
|
||||||
let mut it = variant_data.fields().iter().peekable();
|
let mut it = variant_data.fields().iter().peekable();
|
||||||
|
|
||||||
|
@ -179,13 +181,13 @@ impl HirDisplay for Struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f.write_str(");")?;
|
f.write_char(')')?;
|
||||||
}
|
|
||||||
|
|
||||||
write_where_clause(def_id, f)?;
|
write_where_clause(def_id, f)?;
|
||||||
|
}
|
||||||
if let StructKind::Record = variant_data.kind() {
|
StructKind::Record => {
|
||||||
|
let has_where_clause = write_where_clause(def_id, f)?;
|
||||||
let fields = self.fields(f.db);
|
let fields = self.fields(f.db);
|
||||||
|
f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
|
||||||
if fields.is_empty() {
|
if fields.is_empty() {
|
||||||
f.write_str("{}")?;
|
f.write_str("{}")?;
|
||||||
} else {
|
} else {
|
||||||
|
@ -198,6 +200,8 @@ impl HirDisplay for Struct {
|
||||||
f.write_str("}")?;
|
f.write_str("}")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
StructKind::Unit => _ = write_where_clause(def_id, f)?,
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -210,10 +214,11 @@ impl HirDisplay for Enum {
|
||||||
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
|
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
|
||||||
let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
|
let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
|
||||||
write_generic_params(def_id, f)?;
|
write_generic_params(def_id, f)?;
|
||||||
write_where_clause(def_id, f)?;
|
let has_where_clause = write_where_clause(def_id, f)?;
|
||||||
|
|
||||||
let variants = self.variants(f.db);
|
let variants = self.variants(f.db);
|
||||||
if !variants.is_empty() {
|
if !variants.is_empty() {
|
||||||
|
f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
|
||||||
f.write_str("{\n")?;
|
f.write_str("{\n")?;
|
||||||
for variant in variants {
|
for variant in variants {
|
||||||
f.write_str(" ")?;
|
f.write_str(" ")?;
|
||||||
|
@ -234,10 +239,11 @@ impl HirDisplay for Union {
|
||||||
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
|
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
|
||||||
let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
|
let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
|
||||||
write_generic_params(def_id, f)?;
|
write_generic_params(def_id, f)?;
|
||||||
write_where_clause(def_id, f)?;
|
let has_where_clause = write_where_clause(def_id, f)?;
|
||||||
|
|
||||||
let fields = self.fields(f.db);
|
let fields = self.fields(f.db);
|
||||||
if !fields.is_empty() {
|
if !fields.is_empty() {
|
||||||
|
f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
|
||||||
f.write_str("{\n")?;
|
f.write_str("{\n")?;
|
||||||
for field in self.fields(f.db) {
|
for field in self.fields(f.db) {
|
||||||
f.write_str(" ")?;
|
f.write_str(" ")?;
|
||||||
|
@ -446,7 +452,10 @@ fn write_generic_params(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
fn write_where_clause(
|
||||||
|
def: GenericDefId,
|
||||||
|
f: &mut HirFormatter<'_>,
|
||||||
|
) -> Result<bool, HirDisplayError> {
|
||||||
let params = f.db.generic_params(def);
|
let params = f.db.generic_params(def);
|
||||||
|
|
||||||
// unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
|
// unnamed type targets are displayed inline with the argument itself, e.g. `f: impl Y`.
|
||||||
|
@ -465,7 +474,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(),
|
||||||
});
|
});
|
||||||
|
|
||||||
if !has_displayable_predicate {
|
if !has_displayable_predicate {
|
||||||
return Ok(());
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter<'_>| match target {
|
let write_target = |target: &WherePredicateTypeTarget, f: &mut HirFormatter<'_>| match target {
|
||||||
|
@ -543,7 +552,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(),
|
||||||
// End of final predicate. There must be at least one predicate here.
|
// End of final predicate. There must be at least one predicate here.
|
||||||
f.write_char(',')?;
|
f.write_char(',')?;
|
||||||
|
|
||||||
Ok(())
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HirDisplay for Const {
|
impl HirDisplay for Const {
|
||||||
|
@ -594,11 +603,12 @@ impl HirDisplay for Trait {
|
||||||
write!(f, "trait {}", data.name.display(f.db.upcast()))?;
|
write!(f, "trait {}", data.name.display(f.db.upcast()))?;
|
||||||
let def_id = GenericDefId::TraitId(self.id);
|
let def_id = GenericDefId::TraitId(self.id);
|
||||||
write_generic_params(def_id, f)?;
|
write_generic_params(def_id, f)?;
|
||||||
write_where_clause(def_id, f)?;
|
let has_where_clause = write_where_clause(def_id, f)?;
|
||||||
|
|
||||||
if let Some(limit) = f.entity_limit {
|
if let Some(limit) = f.entity_limit {
|
||||||
let assoc_items = self.items(f.db);
|
let assoc_items = self.items(f.db);
|
||||||
let count = assoc_items.len().min(limit);
|
let count = assoc_items.len().min(limit);
|
||||||
|
f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
if assoc_items.is_empty() {
|
if assoc_items.is_empty() {
|
||||||
f.write_str("{}")?;
|
f.write_str("{}")?;
|
||||||
|
@ -651,7 +661,6 @@ impl HirDisplay for TypeAlias {
|
||||||
write!(f, "type {}", data.name.display(f.db.upcast()))?;
|
write!(f, "type {}", data.name.display(f.db.upcast()))?;
|
||||||
let def_id = GenericDefId::TypeAliasId(self.id);
|
let def_id = GenericDefId::TypeAliasId(self.id);
|
||||||
write_generic_params(def_id, f)?;
|
write_generic_params(def_id, f)?;
|
||||||
write_where_clause(def_id, f)?;
|
|
||||||
if !data.bounds.is_empty() {
|
if !data.bounds.is_empty() {
|
||||||
f.write_str(": ")?;
|
f.write_str(": ")?;
|
||||||
f.write_joined(data.bounds.iter(), " + ")?;
|
f.write_joined(data.bounds.iter(), " + ")?;
|
||||||
|
@ -660,6 +669,7 @@ impl HirDisplay for TypeAlias {
|
||||||
f.write_str(" = ")?;
|
f.write_str(" = ")?;
|
||||||
ty.hir_fmt(f)?;
|
ty.hir_fmt(f)?;
|
||||||
}
|
}
|
||||||
|
write_where_clause(def_id, f)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -819,7 +819,7 @@ fn foo(foo: Foo) {
|
||||||
fn hover_tuple_struct() {
|
fn hover_tuple_struct() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
struct Foo$0(pub u32)
|
struct Foo$0(pub u32) where u32: Copy;
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
*Foo*
|
*Foo*
|
||||||
|
@ -830,7 +830,99 @@ struct Foo$0(pub u32)
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// size = 4, align = 4
|
// size = 4, align = 4
|
||||||
struct Foo(pub u32);
|
struct Foo(pub u32)
|
||||||
|
where
|
||||||
|
u32: Copy,
|
||||||
|
```
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_record_struct() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
struct Foo$0 { field: u32 }
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*Foo*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// size = 4, align = 4
|
||||||
|
struct Foo {
|
||||||
|
field: u32,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
struct Foo$0 where u32: Copy { field: u32 }
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*Foo*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// size = 4, align = 4
|
||||||
|
struct Foo
|
||||||
|
where
|
||||||
|
u32: Copy,
|
||||||
|
{
|
||||||
|
field: u32,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_unit_struct() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
struct Foo$0 where u32: Copy;
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*Foo*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// size = 0, align = 1
|
||||||
|
struct Foo
|
||||||
|
where
|
||||||
|
u32: Copy,
|
||||||
|
```
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hover_type_alias() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
type Fo$0o: Trait = S where T: Trait;
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
*Foo*
|
||||||
|
|
||||||
|
```rust
|
||||||
|
test
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
type Foo: Trait = S
|
||||||
|
where
|
||||||
|
T: Trait,
|
||||||
```
|
```
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
@ -2540,7 +2632,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; }
|
||||||
focus_range: 7..10,
|
focus_range: 7..10,
|
||||||
name: "Arg",
|
name: "Arg",
|
||||||
kind: Struct,
|
kind: Struct,
|
||||||
description: "struct Arg(u32);",
|
description: "struct Arg(u32)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
HoverGotoTypeData {
|
HoverGotoTypeData {
|
||||||
|
@ -2599,7 +2691,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
|
||||||
focus_range: 7..10,
|
focus_range: 7..10,
|
||||||
name: "Arg",
|
name: "Arg",
|
||||||
kind: Struct,
|
kind: Struct,
|
||||||
description: "struct Arg(u32);",
|
description: "struct Arg(u32)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
HoverGotoTypeData {
|
HoverGotoTypeData {
|
||||||
|
@ -2648,7 +2740,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
|
||||||
focus_range: 7..8,
|
focus_range: 7..8,
|
||||||
name: "A",
|
name: "A",
|
||||||
kind: Struct,
|
kind: Struct,
|
||||||
description: "struct A(u32);",
|
description: "struct A(u32)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
HoverGotoTypeData {
|
HoverGotoTypeData {
|
||||||
|
@ -2661,7 +2753,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
|
||||||
focus_range: 22..23,
|
focus_range: 22..23,
|
||||||
name: "B",
|
name: "B",
|
||||||
kind: Struct,
|
kind: Struct,
|
||||||
description: "struct B(u32);",
|
description: "struct B(u32)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
HoverGotoTypeData {
|
HoverGotoTypeData {
|
||||||
|
@ -2675,7 +2767,7 @@ fn main() { let s$0t = (A(1), B(2), M::C(3) ); }
|
||||||
name: "C",
|
name: "C",
|
||||||
kind: Struct,
|
kind: Struct,
|
||||||
container_name: "M",
|
container_name: "M",
|
||||||
description: "pub struct C(u32);",
|
description: "pub struct C(u32)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -3498,7 +3590,7 @@ struct S$0T<const C: usize = 1, T = Foo>(T);
|
||||||
```
|
```
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
struct ST<const C: usize = 1, T = Foo>(T);
|
struct ST<const C: usize = 1, T = Foo>(T)
|
||||||
```
|
```
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
@ -3519,7 +3611,7 @@ struct S$0T<const C: usize = {40 + 2}, T = Foo>(T);
|
||||||
```
|
```
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
struct ST<const C: usize = {const}, T = Foo>(T);
|
struct ST<const C: usize = {const}, T = Foo>(T)
|
||||||
```
|
```
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
@ -3541,7 +3633,7 @@ struct S$0T<const C: usize = VAL, T = Foo>(T);
|
||||||
```
|
```
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
struct ST<const C: usize = VAL, T = Foo>(T);
|
struct ST<const C: usize = VAL, T = Foo>(T)
|
||||||
```
|
```
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
@ -6166,7 +6258,7 @@ pub struct Foo(i32);
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// size = 4, align = 4
|
// size = 4, align = 4
|
||||||
pub struct Foo(i32);
|
pub struct Foo(i32)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -6191,7 +6283,7 @@ pub struct Foo<T>(T);
|
||||||
```
|
```
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
pub struct Foo<T>(T);
|
pub struct Foo<T>(T)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue