aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-02-12 11:07:21 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-02-12 11:07:21 +0000
commit19718ea109eae2f933ce3464c73879c09f9bdbe2 (patch)
treee7bddef556f430d31903a54fced0df760673a0e8 /crates
parent37148000dcd43e5ccba4737a3e379f1ae6861893 (diff)
parent7e8527f74831b37c5757ea6b25e40bcbb61bb6d4 (diff)
Merge #801
801: Implement completion for associated items r=matklad a=lnicola Fixes #747. r? @matklad Co-authored-by: LaurenČ›iu Nicola <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs20
-rw-r--r--crates/ra_ide_api/src/completion.rs22
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs104
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs34
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_const.snap28
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_method.snap30
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_type.snap28
7 files changed, 265 insertions, 1 deletions
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index b8e911b88..e81bd3e06 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -174,4 +174,24 @@ impl Ty {
174 } 174 }
175 None 175 None
176 } 176 }
177
178 // This would be nicer if it just returned an iterator, but that runs into
179 // lifetime problems, because we need to borrow temp `CrateImplBlocks`.
180 pub fn iterate_impl_items<T>(
181 self,
182 db: &impl HirDatabase,
183 mut callback: impl FnMut(ImplItem) -> Option<T>,
184 ) -> Option<T> {
185 let krate = def_crate(db, &self)?;
186 let impls = db.impls_in_crate(krate);
187
188 for (_, impl_block) in impls.lookup_impl_blocks(db, &self) {
189 for item in impl_block.items() {
190 if let Some(result) = callback(*item) {
191 return Some(result);
192 }
193 }
194 }
195 None
196 }
177} 197}
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs
index 722d94f3a..83c243944 100644
--- a/crates/ra_ide_api/src/completion.rs
+++ b/crates/ra_ide_api/src/completion.rs
@@ -80,3 +80,25 @@ pub fn function_label(node: &ast::FnDef) -> Option<String> {
80 80
81 Some(label.trim().to_owned()) 81 Some(label.trim().to_owned())
82} 82}
83
84pub fn const_label(node: &ast::ConstDef) -> String {
85 let label: String = node
86 .syntax()
87 .children()
88 .filter(|child| ast::Comment::cast(child).is_none())
89 .map(|node| node.text().to_string())
90 .collect();
91
92 label.trim().to_owned()
93}
94
95pub fn type_label(node: &ast::TypeDef) -> String {
96 let label: String = node
97 .syntax()
98 .children()
99 .filter(|child| ast::Comment::cast(child).is_none())
100 .map(|node| node.text().to_string())
101 .collect();
102
103 label.trim().to_owned()
104}
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index 91ca7525e..d337fe970 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -1,6 +1,6 @@
1use join_to_string::join; 1use join_to_string::join;
2use hir::{Docs, Resolution}; 2use hir::{Docs, Resolution};
3use ra_syntax::AstNode; 3use ra_syntax::{AstNode, ast::NameOwner};
4use test_utils::tested_by; 4use test_utils::tested_by;
5 5
6use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}; 6use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext};
@@ -58,6 +58,51 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
58 } 58 }
59 }); 59 });
60 } 60 }
61 hir::ModuleDef::Struct(s) => {
62 let ty = s.ty(ctx.db);
63 ty.iterate_impl_items(ctx.db, |item| match item {
64 hir::ImplItem::Method(func) => {
65 let sig = func.signature(ctx.db);
66 if !sig.has_self_param() {
67 CompletionItem::new(
68 CompletionKind::Reference,
69 ctx.source_range(),
70 sig.name().to_string(),
71 )
72 .from_function(ctx, func)
73 .kind(CompletionItemKind::Method)
74 .add_to(acc);
75 }
76 None::<()>
77 }
78 hir::ImplItem::Const(ct) => {
79 let source = ct.source(ctx.db);
80 if let Some(name) = source.1.name() {
81 CompletionItem::new(
82 CompletionKind::Reference,
83 ctx.source_range(),
84 name.text().to_string(),
85 )
86 .from_const(ctx, ct)
87 .add_to(acc);
88 }
89 None::<()>
90 }
91 hir::ImplItem::Type(ty) => {
92 let source = ty.source(ctx.db);
93 if let Some(name) = source.1.name() {
94 CompletionItem::new(
95 CompletionKind::Reference,
96 ctx.source_range(),
97 name.text().to_string(),
98 )
99 .from_type(ctx, ty)
100 .add_to(acc);
101 }
102 None::<()>
103 }
104 });
105 }
61 _ => return, 106 _ => return,
62 }; 107 };
63} 108}
@@ -198,6 +243,63 @@ mod tests {
198 } 243 }
199 244
200 #[test] 245 #[test]
246 fn completes_struct_associated_method() {
247 check_reference_completion(
248 "struct_associated_method",
249 "
250 //- /lib.rs
251 /// A Struct
252 struct S;
253
254 impl S {
255 /// An associated method
256 fn m() { }
257 }
258
259 fn foo() { let _ = S::<|> }
260 ",
261 );
262 }
263
264 #[test]
265 fn completes_struct_associated_const() {
266 check_reference_completion(
267 "struct_associated_const",
268 "
269 //- /lib.rs
270 /// A Struct
271 struct S;
272
273 impl S {
274 /// An associated const
275 const C: i32 = 42;
276 }
277
278 fn foo() { let _ = S::<|> }
279 ",
280 );
281 }
282
283 #[test]
284 fn completes_struct_associated_type() {
285 check_reference_completion(
286 "struct_associated_type",
287 "
288 //- /lib.rs
289 /// A Struct
290 struct S;
291
292 impl S {
293 /// An associated type
294 type T = i32;
295 }
296
297 fn foo() { let _ = S::<|> }
298 ",
299 );
300 }
301
302 #[test]
201 fn completes_use_paths_across_crates() { 303 fn completes_use_paths_across_crates() {
202 check_reference_completion( 304 check_reference_completion(
203 "completes_use_paths_across_crates", 305 "completes_use_paths_across_crates",
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index 22ff08a23..6003e1d89 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -8,6 +8,8 @@ use test_utils::tested_by;
8use crate::completion::{ 8use crate::completion::{
9 completion_context::CompletionContext, 9 completion_context::CompletionContext,
10 function_label, 10 function_label,
11 const_label,
12 type_label
11}; 13};
12 14
13/// `CompletionItem` describes a single completion variant in the editor pop-up. 15/// `CompletionItem` describes a single completion variant in the editor pop-up.
@@ -267,6 +269,28 @@ impl Builder {
267 self.kind = Some(CompletionItemKind::Function); 269 self.kind = Some(CompletionItemKind::Function);
268 self 270 self
269 } 271 }
272
273 pub(super) fn from_const(mut self, ctx: &CompletionContext, ct: hir::Const) -> Builder {
274 if let Some(docs) = ct.docs(ctx.db) {
275 self.documentation = Some(docs);
276 }
277
278 self.detail = Some(const_item_label(ctx, ct));
279 self.kind = Some(CompletionItemKind::Const);
280
281 self
282 }
283
284 pub(super) fn from_type(mut self, ctx: &CompletionContext, ty: hir::Type) -> Builder {
285 if let Some(docs) = ty.docs(ctx.db) {
286 self.documentation = Some(docs);
287 }
288
289 self.detail = Some(type_item_label(ctx, ty));
290 self.kind = Some(CompletionItemKind::TypeAlias);
291
292 self
293 }
270} 294}
271 295
272impl<'a> Into<CompletionItem> for Builder { 296impl<'a> Into<CompletionItem> for Builder {
@@ -305,6 +329,16 @@ fn function_item_label(ctx: &CompletionContext, function: hir::Function) -> Opti
305 function_label(&node) 329 function_label(&node)
306} 330}
307 331
332fn const_item_label(ctx: &CompletionContext, ct: hir::Const) -> String {
333 let node = ct.source(ctx.db).1;
334 const_label(&node)
335}
336
337fn type_item_label(ctx: &CompletionContext, ty: hir::Type) -> String {
338 let node = ty.source(ctx.db).1;
339 type_label(&node)
340}
341
308#[cfg(test)] 342#[cfg(test)]
309pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { 343pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
310 use crate::mock_analysis::{single_file_with_position, analysis_and_position}; 344 use crate::mock_analysis::{single_file_with_position, analysis_and_position};
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_const.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_const.snap
new file mode 100644
index 000000000..ff1eef5f5
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_const.snap
@@ -0,0 +1,28 @@
1---
2created: "2019-02-12T09:57:51.107816726Z"
3creator: [email protected]
4source: crates/ra_ide_api/src/completion/completion_item.rs
5expression: kind_completions
6---
7[
8 CompletionItem {
9 completion_kind: Reference,
10 label: "C",
11 kind: Some(
12 Const
13 ),
14 detail: Some(
15 "const C: i32 = 42;"
16 ),
17 documentation: Some(
18 Documentation(
19 "An associated const"
20 )
21 ),
22 lookup: None,
23 insert_text: None,
24 insert_text_format: PlainText,
25 source_range: [107; 107),
26 text_edit: None
27 }
28]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_method.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_method.snap
new file mode 100644
index 000000000..c53c61d0e
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_method.snap
@@ -0,0 +1,30 @@
1---
2created: "2019-02-12T09:57:51.106389138Z"
3creator: [email protected]
4source: crates/ra_ide_api/src/completion/completion_item.rs
5expression: kind_completions
6---
7[
8 CompletionItem {
9 completion_kind: Reference,
10 label: "m",
11 kind: Some(
12 Method
13 ),
14 detail: Some(
15 "fn m()"
16 ),
17 documentation: Some(
18 Documentation(
19 "An associated method"
20 )
21 ),
22 lookup: None,
23 insert_text: Some(
24 "m()$0"
25 ),
26 insert_text_format: Snippet,
27 source_range: [100; 100),
28 text_edit: None
29 }
30]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_type.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_type.snap
new file mode 100644
index 000000000..e993fb1b0
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__struct_associated_type.snap
@@ -0,0 +1,28 @@
1---
2created: "2019-02-12T09:33:54.719956203Z"
3creator: [email protected]
4source: crates/ra_ide_api/src/completion/completion_item.rs
5expression: kind_completions
6---
7[
8 CompletionItem {
9 completion_kind: Reference,
10 label: "T",
11 kind: Some(
12 TypeAlias
13 ),
14 detail: Some(
15 "type T = i32;"
16 ),
17 documentation: Some(
18 Documentation(
19 "An associated type"
20 )
21 ),
22 lookup: None,
23 insert_text: None,
24 insert_text_format: PlainText,
25 source_range: [101; 101),
26 text_edit: None
27 }
28]