diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/adt.rs | 55 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 67 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_dot.rs | 14 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/completion_item.rs | 19 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 1 |
6 files changed, 99 insertions, 59 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 602e7db74..d30390f25 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -4,7 +4,7 @@ use ra_db::Cancelable; | |||
4 | use ra_syntax::ast::{self, NameOwner, StructFlavor, AstNode}; | 4 | use ra_syntax::ast::{self, NameOwner, StructFlavor, AstNode}; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | DefId, Name, AsName, Struct, Enum, VariantData, StructField, HirDatabase, DefKind, | 7 | DefId, Name, AsName, Struct, Enum, HirDatabase, DefKind, |
8 | type_ref::TypeRef, | 8 | type_ref::TypeRef, |
9 | }; | 9 | }; |
10 | 10 | ||
@@ -12,6 +12,10 @@ impl Struct { | |||
12 | pub(crate) fn new(def_id: DefId) -> Self { | 12 | pub(crate) fn new(def_id: DefId) -> Self { |
13 | Struct { def_id } | 13 | Struct { def_id } |
14 | } | 14 | } |
15 | |||
16 | pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> { | ||
17 | Ok(db.struct_data(self.def_id)?.variant_data.clone()) | ||
18 | } | ||
15 | } | 19 | } |
16 | 20 | ||
17 | #[derive(Debug, Clone, PartialEq, Eq)] | 21 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -83,6 +87,51 @@ impl EnumData { | |||
83 | } | 87 | } |
84 | } | 88 | } |
85 | 89 | ||
90 | /// A single field of an enum variant or struct | ||
91 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
92 | pub struct StructField { | ||
93 | pub(crate) name: Name, | ||
94 | pub(crate) type_ref: TypeRef, | ||
95 | } | ||
96 | |||
97 | /// Fields of an enum variant or struct | ||
98 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
99 | pub enum VariantData { | ||
100 | Struct(Vec<StructField>), | ||
101 | Tuple(Vec<StructField>), | ||
102 | Unit, | ||
103 | } | ||
104 | |||
105 | impl VariantData { | ||
106 | pub fn fields(&self) -> &[StructField] { | ||
107 | match self { | ||
108 | VariantData::Struct(fields) | VariantData::Tuple(fields) => fields, | ||
109 | _ => &[], | ||
110 | } | ||
111 | } | ||
112 | |||
113 | pub fn is_struct(&self) -> bool { | ||
114 | match self { | ||
115 | VariantData::Struct(..) => true, | ||
116 | _ => false, | ||
117 | } | ||
118 | } | ||
119 | |||
120 | pub fn is_tuple(&self) -> bool { | ||
121 | match self { | ||
122 | VariantData::Tuple(..) => true, | ||
123 | _ => false, | ||
124 | } | ||
125 | } | ||
126 | |||
127 | pub fn is_unit(&self) -> bool { | ||
128 | match self { | ||
129 | VariantData::Unit => true, | ||
130 | _ => false, | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | |||
86 | impl VariantData { | 135 | impl VariantData { |
87 | fn new(flavor: StructFlavor) -> Self { | 136 | fn new(flavor: StructFlavor) -> Self { |
88 | match flavor { | 137 | match flavor { |
@@ -114,7 +163,7 @@ impl VariantData { | |||
114 | pub(crate) fn get_field_type_ref(&self, field_name: &Name) -> Option<&TypeRef> { | 163 | pub(crate) fn get_field_type_ref(&self, field_name: &Name) -> Option<&TypeRef> { |
115 | self.fields() | 164 | self.fields() |
116 | .iter() | 165 | .iter() |
117 | .find(|f| f.name() == field_name) | 166 | .find(|f| f.name == *field_name) |
118 | .map(|f| f.type_ref()) | 167 | .map(|f| &f.type_ref) |
119 | } | 168 | } |
120 | } | 169 | } |
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 66c016180..fa3e4baa7 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -5,12 +5,13 @@ use ra_db::{CrateId, Cancelable, FileId}; | |||
5 | use ra_syntax::{ast, TreePtr, SyntaxNode}; | 5 | use ra_syntax::{ast, TreePtr, SyntaxNode}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, | 8 | Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, |
9 | type_ref::TypeRef, | 9 | type_ref::TypeRef, |
10 | nameres::ModuleScope, | 10 | nameres::ModuleScope, |
11 | db::HirDatabase, | 11 | db::HirDatabase, |
12 | expr::BodySyntaxMapping, | 12 | expr::BodySyntaxMapping, |
13 | ty::InferenceResult, | 13 | ty::InferenceResult, |
14 | adt::VariantData, | ||
14 | }; | 15 | }; |
15 | 16 | ||
16 | /// hir::Crate describes a single crate. It's the main interface with which | 17 | /// hir::Crate describes a single crate. It's the main interface with which |
@@ -137,58 +138,18 @@ impl Module { | |||
137 | } | 138 | } |
138 | } | 139 | } |
139 | 140 | ||
140 | /// A single field of an enum variant or struct | 141 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
141 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
142 | pub struct StructField { | 142 | pub struct StructField { |
143 | pub(crate) name: Name, | 143 | struct_: Struct, |
144 | pub(crate) type_ref: TypeRef, | 144 | name: Name, |
145 | } | 145 | } |
146 | 146 | ||
147 | impl StructField { | 147 | impl StructField { |
148 | pub fn name(&self) -> &Name { | 148 | pub fn name(&self) -> &Name { |
149 | &self.name | 149 | &self.name |
150 | } | 150 | } |
151 | 151 | pub fn ty(&self, db: &impl HirDatabase) -> Cancelable<Option<Ty>> { | |
152 | pub fn type_ref(&self) -> &TypeRef { | 152 | db.type_for_field(self.struct_.def_id, self.name.clone()) |
153 | &self.type_ref | ||
154 | } | ||
155 | } | ||
156 | |||
157 | /// Fields of an enum variant or struct | ||
158 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
159 | pub enum VariantData { | ||
160 | Struct(Vec<StructField>), | ||
161 | Tuple(Vec<StructField>), | ||
162 | Unit, | ||
163 | } | ||
164 | |||
165 | impl VariantData { | ||
166 | pub fn fields(&self) -> &[StructField] { | ||
167 | match self { | ||
168 | VariantData::Struct(fields) | VariantData::Tuple(fields) => fields, | ||
169 | _ => &[], | ||
170 | } | ||
171 | } | ||
172 | |||
173 | pub fn is_struct(&self) -> bool { | ||
174 | match self { | ||
175 | VariantData::Struct(..) => true, | ||
176 | _ => false, | ||
177 | } | ||
178 | } | ||
179 | |||
180 | pub fn is_tuple(&self) -> bool { | ||
181 | match self { | ||
182 | VariantData::Tuple(..) => true, | ||
183 | _ => false, | ||
184 | } | ||
185 | } | ||
186 | |||
187 | pub fn is_unit(&self) -> bool { | ||
188 | match self { | ||
189 | VariantData::Unit => true, | ||
190 | _ => false, | ||
191 | } | ||
192 | } | 153 | } |
193 | } | 154 | } |
194 | 155 | ||
@@ -206,8 +167,18 @@ impl Struct { | |||
206 | Ok(db.struct_data(self.def_id)?.name.clone()) | 167 | Ok(db.struct_data(self.def_id)?.name.clone()) |
207 | } | 168 | } |
208 | 169 | ||
209 | pub fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> { | 170 | pub fn fields(&self, db: &impl HirDatabase) -> Cancelable<Vec<StructField>> { |
210 | Ok(db.struct_data(self.def_id)?.variant_data.clone()) | 171 | let res = db |
172 | .struct_data(self.def_id)? | ||
173 | .variant_data | ||
174 | .fields() | ||
175 | .iter() | ||
176 | .map(|it| StructField { | ||
177 | struct_: self.clone(), | ||
178 | name: it.name.clone(), | ||
179 | }) | ||
180 | .collect(); | ||
181 | Ok(res) | ||
211 | } | 182 | } |
212 | } | 183 | } |
213 | 184 | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index ca7f395a8..1b6b72c98 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -56,6 +56,6 @@ pub use self::code_model_api::{ | |||
56 | Crate, CrateDependency, | 56 | Crate, CrateDependency, |
57 | Def, | 57 | Def, |
58 | Module, ModuleSource, Problem, | 58 | Module, ModuleSource, Problem, |
59 | Struct, Enum, VariantData, StructField, | 59 | Struct, Enum, |
60 | Function, FnSignature, | 60 | Function, FnSignature, |
61 | }; | 61 | }; |
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 5d4e60dc5..65bba6dc7 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -28,13 +28,13 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) | |||
28 | Ty::Adt { def_id, .. } => { | 28 | Ty::Adt { def_id, .. } => { |
29 | match def_id.resolve(ctx.db)? { | 29 | match def_id.resolve(ctx.db)? { |
30 | Def::Struct(s) => { | 30 | Def::Struct(s) => { |
31 | let variant_data = s.variant_data(ctx.db)?; | 31 | for field in s.fields(ctx.db)? { |
32 | for field in variant_data.fields() { | ||
33 | CompletionItem::new( | 32 | CompletionItem::new( |
34 | CompletionKind::Reference, | 33 | CompletionKind::Reference, |
35 | field.name().to_string(), | 34 | field.name().to_string(), |
36 | ) | 35 | ) |
37 | .kind(CompletionItemKind::Field) | 36 | .kind(CompletionItemKind::Field) |
37 | .set_detail(field.ty(ctx.db)?.map(|ty| ty.to_string())) | ||
38 | .add_to(acc); | 38 | .add_to(acc); |
39 | } | 39 | } |
40 | } | 40 | } |
@@ -72,7 +72,7 @@ mod tests { | |||
72 | a.<|> | 72 | a.<|> |
73 | } | 73 | } |
74 | ", | 74 | ", |
75 | r#"the_field"#, | 75 | r#"the_field "u32""#, |
76 | ); | 76 | ); |
77 | } | 77 | } |
78 | 78 | ||
@@ -80,14 +80,14 @@ mod tests { | |||
80 | fn test_struct_field_completion_self() { | 80 | fn test_struct_field_completion_self() { |
81 | check_ref_completion( | 81 | check_ref_completion( |
82 | r" | 82 | r" |
83 | struct A { the_field: u32 } | 83 | struct A { the_field: (u32,) } |
84 | impl A { | 84 | impl A { |
85 | fn foo(self) { | 85 | fn foo(self) { |
86 | self.<|> | 86 | self.<|> |
87 | } | 87 | } |
88 | } | 88 | } |
89 | ", | 89 | ", |
90 | r#"the_field"#, | 90 | r#"the_field "(u32,)""#, |
91 | ); | 91 | ); |
92 | } | 92 | } |
93 | 93 | ||
@@ -95,14 +95,14 @@ mod tests { | |||
95 | fn test_struct_field_completion_autoderef() { | 95 | fn test_struct_field_completion_autoderef() { |
96 | check_ref_completion( | 96 | check_ref_completion( |
97 | r" | 97 | r" |
98 | struct A { the_field: u32 } | 98 | struct A { the_field: (u32, i32) } |
99 | impl A { | 99 | impl A { |
100 | fn foo(&self) { | 100 | fn foo(&self) { |
101 | self.<|> | 101 | self.<|> |
102 | } | 102 | } |
103 | } | 103 | } |
104 | ", | 104 | ", |
105 | r#"the_field"#, | 105 | r#"the_field "(u32, i32)""#, |
106 | ); | 106 | ); |
107 | } | 107 | } |
108 | 108 | ||
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index a25b87bee..334449fae 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs | |||
@@ -11,6 +11,7 @@ pub struct CompletionItem { | |||
11 | /// completion. | 11 | /// completion. |
12 | completion_kind: CompletionKind, | 12 | completion_kind: CompletionKind, |
13 | label: String, | 13 | label: String, |
14 | detail: Option<String>, | ||
14 | lookup: Option<String>, | 15 | lookup: Option<String>, |
15 | snippet: Option<String>, | 16 | snippet: Option<String>, |
16 | kind: Option<CompletionItemKind>, | 17 | kind: Option<CompletionItemKind>, |
@@ -51,6 +52,7 @@ impl CompletionItem { | |||
51 | Builder { | 52 | Builder { |
52 | completion_kind, | 53 | completion_kind, |
53 | label, | 54 | label, |
55 | detail: None, | ||
54 | lookup: None, | 56 | lookup: None, |
55 | snippet: None, | 57 | snippet: None, |
56 | kind: None, | 58 | kind: None, |
@@ -60,6 +62,10 @@ impl CompletionItem { | |||
60 | pub fn label(&self) -> &str { | 62 | pub fn label(&self) -> &str { |
61 | &self.label | 63 | &self.label |
62 | } | 64 | } |
65 | /// Short one-line additional information, like a type | ||
66 | pub fn detail(&self) -> Option<&str> { | ||
67 | self.detail.as_ref().map(|it| it.as_str()) | ||
68 | } | ||
63 | /// What string is used for filtering. | 69 | /// What string is used for filtering. |
64 | pub fn lookup(&self) -> &str { | 70 | pub fn lookup(&self) -> &str { |
65 | self.lookup | 71 | self.lookup |
@@ -87,6 +93,7 @@ impl CompletionItem { | |||
87 | pub(crate) struct Builder { | 93 | pub(crate) struct Builder { |
88 | completion_kind: CompletionKind, | 94 | completion_kind: CompletionKind, |
89 | label: String, | 95 | label: String, |
96 | detail: Option<String>, | ||
90 | lookup: Option<String>, | 97 | lookup: Option<String>, |
91 | snippet: Option<String>, | 98 | snippet: Option<String>, |
92 | kind: Option<CompletionItemKind>, | 99 | kind: Option<CompletionItemKind>, |
@@ -100,6 +107,7 @@ impl Builder { | |||
100 | pub(crate) fn build(self) -> CompletionItem { | 107 | pub(crate) fn build(self) -> CompletionItem { |
101 | CompletionItem { | 108 | CompletionItem { |
102 | label: self.label, | 109 | label: self.label, |
110 | detail: self.detail, | ||
103 | lookup: self.lookup, | 111 | lookup: self.lookup, |
104 | snippet: self.snippet, | 112 | snippet: self.snippet, |
105 | kind: self.kind, | 113 | kind: self.kind, |
@@ -118,6 +126,14 @@ impl Builder { | |||
118 | self.kind = Some(kind); | 126 | self.kind = Some(kind); |
119 | self | 127 | self |
120 | } | 128 | } |
129 | #[allow(unused)] | ||
130 | pub(crate) fn detail(self, detail: impl Into<String>) -> Builder { | ||
131 | self.set_detail(Some(detail)) | ||
132 | } | ||
133 | pub(crate) fn set_detail(mut self, detail: Option<impl Into<String>>) -> Builder { | ||
134 | self.detail = detail.map(Into::into); | ||
135 | self | ||
136 | } | ||
121 | pub(super) fn from_resolution( | 137 | pub(super) fn from_resolution( |
122 | mut self, | 138 | mut self, |
123 | ctx: &CompletionContext, | 139 | ctx: &CompletionContext, |
@@ -227,6 +243,9 @@ impl Completions { | |||
227 | } else { | 243 | } else { |
228 | res.push_str(&c.label); | 244 | res.push_str(&c.label); |
229 | } | 245 | } |
246 | if let Some(detail) = &c.detail { | ||
247 | res.push_str(&format!(" {:?}", detail)); | ||
248 | } | ||
230 | if let Some(snippet) = &c.snippet { | 249 | if let Some(snippet) = &c.snippet { |
231 | res.push_str(&format!(" {:?}", snippet)); | 250 | res.push_str(&format!(" {:?}", snippet)); |
232 | } | 251 | } |
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 5c8b3c194..35c679a4a 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -75,6 +75,7 @@ impl Conv for CompletionItem { | |||
75 | fn conv(self) -> <Self as Conv>::Output { | 75 | fn conv(self) -> <Self as Conv>::Output { |
76 | let mut res = ::languageserver_types::CompletionItem { | 76 | let mut res = ::languageserver_types::CompletionItem { |
77 | label: self.label().to_string(), | 77 | label: self.label().to_string(), |
78 | detail: self.detail().map(|it| it.to_string()), | ||
78 | filter_text: Some(self.lookup().to_string()), | 79 | filter_text: Some(self.lookup().to_string()), |
79 | kind: self.kind().map(|it| it.conv()), | 80 | kind: self.kind().map(|it| it.conv()), |
80 | ..Default::default() | 81 | ..Default::default() |