mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 07:04:49 +00:00
Compute data layout of types
This commit is contained in:
parent
957b4bb216
commit
86b5b609f1
16 changed files with 2822 additions and 157 deletions
|
@ -2,7 +2,10 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use either::Either;
|
||||
use hir::{AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay, Semantics, TypeInfo};
|
||||
use hir::{
|
||||
db::HirDatabase, Adt, AsAssocItem, AttributeTemplate, HasAttrs, HasSource, HirDisplay,
|
||||
Semantics, TypeInfo,
|
||||
};
|
||||
use ide_db::{
|
||||
base_db::SourceDatabase,
|
||||
defs::Definition,
|
||||
|
@ -388,10 +391,30 @@ pub(super) fn definition(
|
|||
let mod_path = definition_mod_path(db, &def);
|
||||
let (label, docs) = match def {
|
||||
Definition::Macro(it) => label_and_docs(db, it),
|
||||
Definition::Field(it) => label_and_docs(db, it),
|
||||
Definition::Field(it) => label_and_layout_info_and_docs(db, it, |&it| {
|
||||
let var_def = it.parent_def(db);
|
||||
let id = it.index();
|
||||
let layout = it.layout(db).ok()?;
|
||||
let offset = match var_def {
|
||||
hir::VariantDef::Struct(s) => {
|
||||
let layout = Adt::from(s).layout(db).ok()?;
|
||||
layout.fields.offset(id, &db.current_target_data_layout())
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
Some(format!(
|
||||
"size = {}, align = {}, offset = {}",
|
||||
layout.size.bytes(),
|
||||
layout.align.abi.bytes(),
|
||||
offset.bytes()
|
||||
))
|
||||
}),
|
||||
Definition::Module(it) => label_and_docs(db, it),
|
||||
Definition::Function(it) => label_and_docs(db, it),
|
||||
Definition::Adt(it) => label_and_docs(db, it),
|
||||
Definition::Adt(it) => label_and_layout_info_and_docs(db, it, |&it| {
|
||||
let layout = it.layout(db).ok()?;
|
||||
Some(format!("size = {}, align = {}", layout.size.bytes(), layout.align.abi.bytes()))
|
||||
}),
|
||||
Definition::Variant(it) => label_value_and_docs(db, it, |&it| {
|
||||
if !it.parent_enum(db).is_data_carrying(db) {
|
||||
match it.eval(db) {
|
||||
|
@ -489,6 +512,25 @@ where
|
|||
(label, docs)
|
||||
}
|
||||
|
||||
fn label_and_layout_info_and_docs<D, E, V>(
|
||||
db: &RootDatabase,
|
||||
def: D,
|
||||
value_extractor: E,
|
||||
) -> (String, Option<hir::Documentation>)
|
||||
where
|
||||
D: HasAttrs + HirDisplay,
|
||||
E: Fn(&D) -> Option<V>,
|
||||
V: Display,
|
||||
{
|
||||
let label = if let Some(value) = value_extractor(&def) {
|
||||
format!("{} // {}", def.display(db), value)
|
||||
} else {
|
||||
def.display(db).to_string()
|
||||
};
|
||||
let docs = def.attrs(db).docs();
|
||||
(label, docs)
|
||||
}
|
||||
|
||||
fn label_value_and_docs<D, E, V>(
|
||||
db: &RootDatabase,
|
||||
def: D,
|
||||
|
|
|
@ -522,6 +522,27 @@ fn main() { }
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hover_field_offset() {
|
||||
// Hovering over the field when instantiating
|
||||
check(
|
||||
r#"
|
||||
struct Foo { fiel$0d_a: u8, field_b: i32, field_c: i16 }
|
||||
"#,
|
||||
expect![[r#"
|
||||
*field_a*
|
||||
|
||||
```rust
|
||||
test::Foo
|
||||
```
|
||||
|
||||
```rust
|
||||
field_a: u8 // size = 1, align = 1, offset = 6
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hover_shows_struct_field_info() {
|
||||
// Hovering over the field when instantiating
|
||||
|
@ -534,16 +555,16 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*field_a*
|
||||
*field_a*
|
||||
|
||||
```rust
|
||||
test::Foo
|
||||
```
|
||||
```rust
|
||||
test::Foo
|
||||
```
|
||||
|
||||
```rust
|
||||
field_a: u32
|
||||
```
|
||||
"#]],
|
||||
```rust
|
||||
field_a: u32 // size = 4, align = 4, offset = 0
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
|
||||
// Hovering over the field in the definition
|
||||
|
@ -556,16 +577,16 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*field_a*
|
||||
*field_a*
|
||||
|
||||
```rust
|
||||
test::Foo
|
||||
```
|
||||
```rust
|
||||
test::Foo
|
||||
```
|
||||
|
||||
```rust
|
||||
field_a: u32
|
||||
```
|
||||
"#]],
|
||||
```rust
|
||||
field_a: u32 // size = 4, align = 4, offset = 0
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1508,30 +1529,30 @@ struct Bar;
|
|||
|
||||
fn foo() { let bar = Ba$0r; }
|
||||
"#,
|
||||
expect![[r##"
|
||||
*Bar*
|
||||
expect![[r#"
|
||||
*Bar*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
struct Bar
|
||||
```
|
||||
```rust
|
||||
struct Bar // size = 0, align = 1
|
||||
```
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
This is an example
|
||||
multiline doc
|
||||
This is an example
|
||||
multiline doc
|
||||
|
||||
# Example
|
||||
# Example
|
||||
|
||||
```
|
||||
let five = 5;
|
||||
```
|
||||
let five = 5;
|
||||
|
||||
assert_eq!(6, my_crate::add_one(5));
|
||||
```
|
||||
"##]],
|
||||
assert_eq!(6, my_crate::add_one(5));
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1545,20 +1566,20 @@ struct Bar;
|
|||
fn foo() { let bar = Ba$0r; }
|
||||
"#,
|
||||
expect![[r#"
|
||||
*Bar*
|
||||
*Bar*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
struct Bar
|
||||
```
|
||||
```rust
|
||||
struct Bar // size = 0, align = 1
|
||||
```
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
bar docs
|
||||
"#]],
|
||||
bar docs
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1574,22 +1595,22 @@ struct Bar;
|
|||
fn foo() { let bar = Ba$0r; }
|
||||
"#,
|
||||
expect![[r#"
|
||||
*Bar*
|
||||
*Bar*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
struct Bar
|
||||
```
|
||||
```rust
|
||||
struct Bar // size = 0, align = 1
|
||||
```
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
bar docs 0
|
||||
bar docs 1
|
||||
bar docs 2
|
||||
"#]],
|
||||
bar docs 0
|
||||
bar docs 1
|
||||
bar docs 2
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1602,20 +1623,20 @@ pub struct Foo;
|
|||
pub struct B$0ar
|
||||
"#,
|
||||
expect
|
||||
"#]],
|
||||
[external](https://www.google.com)
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1629,20 +1650,20 @@ pub struct Foo;
|
|||
pub struct B$0ar
|
||||
"#,
|
||||
expect
|
||||
"#]],
|
||||
[baz](Baz)
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2960,7 +2981,7 @@ fn main() {
|
|||
```
|
||||
|
||||
```rust
|
||||
f: i32
|
||||
f: i32 // size = 4, align = 4, offset = 0
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
|
@ -4203,20 +4224,20 @@ pub fn gimme() -> theitem::TheItem {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*[`TheItem`]*
|
||||
*[`TheItem`]*
|
||||
|
||||
```rust
|
||||
test::theitem
|
||||
```
|
||||
```rust
|
||||
test::theitem
|
||||
```
|
||||
|
||||
```rust
|
||||
pub struct TheItem
|
||||
```
|
||||
```rust
|
||||
pub struct TheItem // size = 0, align = 1
|
||||
```
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
This is the item. Cool!
|
||||
"#]],
|
||||
This is the item. Cool!
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4351,20 +4372,20 @@ mod string {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
*String*
|
||||
*String*
|
||||
|
||||
```rust
|
||||
main
|
||||
```
|
||||
```rust
|
||||
main
|
||||
```
|
||||
|
||||
```rust
|
||||
struct String
|
||||
```
|
||||
```rust
|
||||
struct String // size = 0, align = 1
|
||||
```
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
Custom `String` type.
|
||||
"#]],
|
||||
Custom `String` type.
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -5025,7 +5046,7 @@ foo_macro!(
|
|||
```
|
||||
|
||||
```rust
|
||||
pub struct Foo
|
||||
pub struct Foo // size = 0, align = 1
|
||||
```
|
||||
|
||||
---
|
||||
|
@ -5040,7 +5061,7 @@ fn hover_intra_in_attr() {
|
|||
check(
|
||||
r#"
|
||||
#[doc = "Doc comment for [`Foo$0`]"]
|
||||
pub struct Foo;
|
||||
pub struct Foo(i32);
|
||||
"#,
|
||||
expect![[r#"
|
||||
*[`Foo`]*
|
||||
|
@ -5050,7 +5071,7 @@ pub struct Foo;
|
|||
```
|
||||
|
||||
```rust
|
||||
pub struct Foo
|
||||
pub struct Foo // size = 4, align = 4
|
||||
```
|
||||
|
||||
---
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue