diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-04-09 09:08:55 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-04-09 09:08:55 +0100 |
commit | 412eda73877c7a897561a70b83f55ee346e18a2c (patch) | |
tree | b30c91efe4050087f1935d477db4612357a2665a /crates/ra_hir_def | |
parent | 01e5bd50f30ae22abab0733468d1e1c6dea7d506 (diff) | |
parent | 585bb83e2aec9c79dae8c2e031e9165f40937003 (diff) |
Merge #3880
3880: Add support for attributes for struct fields r=matklad a=bnjjj
Hello I try to solve this example:
```rust
struct MyStruct {
my_val: usize,
#[cfg(feature = "foo")]
bar: bool,
}
impl MyStruct {
#[cfg(feature = "foo")]
pub(crate) fn new(my_val: usize, bar: bool) -> Self {
Self { my_val, bar }
}
#[cfg(not(feature = "foo"))]
pub(crate) fn new(my_val: usize, _bar: bool) -> Self {
Self { my_val }
}
}
```
Here is a draft PR to try to solve this issue. In fact for now when i have this kind of example, rust-analyzer tells me that my second Self {} miss the bar field. Which is a bug.
I have some difficulties to add this features. Here in my draft I share my work about adding attributes support on struct field data. But I'm stuck when I have to fetch attributes from parent expressions. I don't really know how to do that. For the first iteration I just want to solve my issue without solving on all different expressions. And then after I will try to implement that on different kind of expression. I think I have to fetch my FunctionId and then I will be able to find attributes with myFunction.attrs() But I don't know if it's the right way.
@matklad (or anyone else) if you can help me it would be great :D
Co-authored-by: Benjamin Coenen <[email protected]>
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/src/adt.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 31 |
2 files changed, 27 insertions, 5 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index de07fc952..7fc4cd76e 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -54,6 +54,7 @@ pub struct StructFieldData { | |||
54 | impl StructData { | 54 | impl StructData { |
55 | pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { | 55 | pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> { |
56 | let src = id.lookup(db).source(db); | 56 | let src = id.lookup(db).source(db); |
57 | |||
57 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); | 58 | let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); |
58 | let variant_data = VariantData::new(db, src.map(|s| s.kind())); | 59 | let variant_data = VariantData::new(db, src.map(|s| s.kind())); |
59 | let variant_data = Arc::new(variant_data); | 60 | let variant_data = Arc::new(variant_data); |
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 04bd4a305..606ec48b0 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -3,15 +3,18 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use hir_expand::{ | 5 | use hir_expand::{ |
6 | hygiene::Hygiene, | ||
6 | name::{name, AsName, Name}, | 7 | name::{name, AsName, Name}, |
7 | AstId, InFile, | 8 | AstId, InFile, |
8 | }; | 9 | }; |
10 | use ra_cfg::CfgOptions; | ||
9 | use ra_prof::profile; | 11 | use ra_prof::profile; |
10 | use ra_syntax::ast::{ | 12 | use ra_syntax::ast::{ |
11 | self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner, | 13 | self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner, |
12 | }; | 14 | }; |
13 | 15 | ||
14 | use crate::{ | 16 | use crate::{ |
17 | attr::Attrs, | ||
15 | db::DefDatabase, | 18 | db::DefDatabase, |
16 | path::{path, GenericArgs, Path}, | 19 | path::{path, GenericArgs, Path}, |
17 | src::HasSource, | 20 | src::HasSource, |
@@ -26,6 +29,7 @@ pub struct FunctionData { | |||
26 | pub name: Name, | 29 | pub name: Name, |
27 | pub params: Vec<TypeRef>, | 30 | pub params: Vec<TypeRef>, |
28 | pub ret_type: TypeRef, | 31 | pub ret_type: TypeRef, |
32 | pub attrs: Attrs, | ||
29 | /// True if the first param is `self`. This is relevant to decide whether this | 33 | /// True if the first param is `self`. This is relevant to decide whether this |
30 | /// can be called as a method. | 34 | /// can be called as a method. |
31 | pub has_self_param: bool, | 35 | pub has_self_param: bool, |
@@ -63,6 +67,8 @@ impl FunctionData { | |||
63 | params.push(type_ref); | 67 | params.push(type_ref); |
64 | } | 68 | } |
65 | } | 69 | } |
70 | let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); | ||
71 | |||
66 | let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { | 72 | let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { |
67 | TypeRef::from_ast(type_ref) | 73 | TypeRef::from_ast(type_ref) |
68 | } else { | 74 | } else { |
@@ -81,7 +87,7 @@ impl FunctionData { | |||
81 | let visibility = | 87 | let visibility = |
82 | RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); | 88 | RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); |
83 | 89 | ||
84 | let sig = FunctionData { name, params, ret_type, has_self_param, visibility }; | 90 | let sig = FunctionData { name, params, ret_type, has_self_param, visibility, attrs }; |
85 | Arc::new(sig) | 91 | Arc::new(sig) |
86 | } | 92 | } |
87 | } | 93 | } |
@@ -211,6 +217,7 @@ impl ImplData { | |||
211 | let module_id = impl_loc.container.module(db); | 217 | let module_id = impl_loc.container.module(db); |
212 | 218 | ||
213 | let mut items = Vec::new(); | 219 | let mut items = Vec::new(); |
220 | |||
214 | if let Some(item_list) = src.value.item_list() { | 221 | if let Some(item_list) = src.value.item_list() { |
215 | items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id)); | 222 | items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id)); |
216 | items.extend(collect_impl_items_in_macros( | 223 | items.extend(collect_impl_items_in_macros( |
@@ -311,6 +318,10 @@ fn collect_impl_items_in_macro( | |||
311 | } | 318 | } |
312 | } | 319 | } |
313 | 320 | ||
321 | fn is_cfg_enabled(cfg_options: &CfgOptions, attrs: &Attrs) -> bool { | ||
322 | attrs.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false)) | ||
323 | } | ||
324 | |||
314 | fn collect_impl_items( | 325 | fn collect_impl_items( |
315 | db: &dyn DefDatabase, | 326 | db: &dyn DefDatabase, |
316 | impl_items: impl Iterator<Item = ImplItem>, | 327 | impl_items: impl Iterator<Item = ImplItem>, |
@@ -318,16 +329,26 @@ fn collect_impl_items( | |||
318 | id: ImplId, | 329 | id: ImplId, |
319 | ) -> Vec<AssocItemId> { | 330 | ) -> Vec<AssocItemId> { |
320 | let items = db.ast_id_map(file_id); | 331 | let items = db.ast_id_map(file_id); |
332 | let crate_graph = db.crate_graph(); | ||
333 | let module_id = id.lookup(db).container.module(db); | ||
321 | 334 | ||
322 | impl_items | 335 | impl_items |
323 | .map(|item_node| match item_node { | 336 | .filter_map(|item_node| match item_node { |
324 | ast::ImplItem::FnDef(it) => { | 337 | ast::ImplItem::FnDef(it) => { |
325 | let def = FunctionLoc { | 338 | let def = FunctionLoc { |
326 | container: AssocContainerId::ImplId(id), | 339 | container: AssocContainerId::ImplId(id), |
327 | ast_id: AstId::new(file_id, items.ast_id(&it)), | 340 | ast_id: AstId::new(file_id, items.ast_id(&it)), |
328 | } | 341 | } |
329 | .intern(db); | 342 | .intern(db); |
330 | def.into() | 343 | |
344 | if !is_cfg_enabled( | ||
345 | &crate_graph[module_id.krate].cfg_options, | ||
346 | &db.function_data(def).attrs, | ||
347 | ) { | ||
348 | None | ||
349 | } else { | ||
350 | Some(def.into()) | ||
351 | } | ||
331 | } | 352 | } |
332 | ast::ImplItem::ConstDef(it) => { | 353 | ast::ImplItem::ConstDef(it) => { |
333 | let def = ConstLoc { | 354 | let def = ConstLoc { |
@@ -335,7 +356,7 @@ fn collect_impl_items( | |||
335 | ast_id: AstId::new(file_id, items.ast_id(&it)), | 356 | ast_id: AstId::new(file_id, items.ast_id(&it)), |
336 | } | 357 | } |
337 | .intern(db); | 358 | .intern(db); |
338 | def.into() | 359 | Some(def.into()) |
339 | } | 360 | } |
340 | ast::ImplItem::TypeAliasDef(it) => { | 361 | ast::ImplItem::TypeAliasDef(it) => { |
341 | let def = TypeAliasLoc { | 362 | let def = TypeAliasLoc { |
@@ -343,7 +364,7 @@ fn collect_impl_items( | |||
343 | ast_id: AstId::new(file_id, items.ast_id(&it)), | 364 | ast_id: AstId::new(file_id, items.ast_id(&it)), |
344 | } | 365 | } |
345 | .intern(db); | 366 | .intern(db); |
346 | def.into() | 367 | Some(def.into()) |
347 | } | 368 | } |
348 | }) | 369 | }) |
349 | .collect() | 370 | .collect() |