aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/completion
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/completion')
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs29
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs90
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs5
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs40
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap40
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap36
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap18
7 files changed, 178 insertions, 80 deletions
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index b33ddcde5..0b9948d4b 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -1,21 +1,21 @@
1use join_to_string::join; 1use join_to_string::join;
2 2
3use hir::{Docs, Resolution};
4
3use crate::{ 5use crate::{
4 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, 6 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext},
5}; 7};
6 8
7use hir::Docs;
8
9pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { 9pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
10 let (path, module) = match (&ctx.path_prefix, &ctx.module) { 10 let path = match &ctx.path_prefix {
11 (Some(path), Some(module)) => (path.clone(), module), 11 Some(path) => path.clone(),
12 _ => return, 12 _ => return,
13 }; 13 };
14 let def_id = match module.resolve_path(ctx.db, &path).take_types() { 14 let def = match ctx.resolver.resolve_path(ctx.db, &path).take_types() {
15 Some(it) => it, 15 Some(Resolution::Def(def)) => def,
16 None => return, 16 _ => return,
17 }; 17 };
18 match def_id { 18 match def {
19 hir::ModuleDef::Module(module) => { 19 hir::ModuleDef::Module(module) => {
20 let module_scope = module.scope(ctx.db); 20 let module_scope = module.scope(ctx.db);
21 for (name, res) in module_scope.entries() { 21 for (name, res) in module_scope.entries() {
@@ -24,7 +24,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
24 ctx.source_range(), 24 ctx.source_range(),
25 name.to_string(), 25 name.to_string(),
26 ) 26 )
27 .from_resolution(ctx, res) 27 .from_resolution(ctx, &res.def.map(hir::Resolution::Def))
28 .add_to(acc); 28 .add_to(acc);
29 } 29 }
30 } 30 }
@@ -66,6 +66,17 @@ mod tests {
66 } 66 }
67 67
68 #[test] 68 #[test]
69 #[ignore] // should not complete foo, which currently doesn't work
70 fn dont_complete_current_use() {
71 check_reference_completion(
72 "dont_complete_current_use",
73 r"
74 use self::foo<|>;
75 ",
76 );
77 }
78
79 #[test]
69 fn completes_mod_with_docs() { 80 fn completes_mod_with_docs() {
70 check_reference_completion( 81 check_reference_completion(
71 "mod_with_docs", 82 "mod_with_docs",
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index f837bb1db..44514ab2b 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -1,63 +1,20 @@
1use rustc_hash::FxHashSet; 1use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionContext};
2use ra_syntax::ast::AstNode;
3use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext};
4 2
5pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { 3pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
6 if !ctx.is_trivial_path { 4 if !ctx.is_trivial_path {
7 return; 5 return;
8 } 6 }
9 let module = match &ctx.module { 7 let names = ctx.resolver.all_names();
10 Some(it) => it,
11 None => return,
12 };
13 if let Some(function) = &ctx.function {
14 let scopes = function.scopes(ctx.db);
15 complete_fn(acc, &scopes, ctx);
16 }
17
18 let module_scope = module.scope(ctx.db);
19 module_scope
20 .entries()
21 .filter(|(_name, res)| {
22 // For cases like `use self::foo<|>` don't suggest foo itself.
23 match res.import {
24 None => true,
25 Some(import) => {
26 let source = module.import_source(ctx.db, import);
27 !source.syntax().range().is_subrange(&ctx.leaf.range())
28 }
29 }
30 })
31 .for_each(|(name, res)| {
32 CompletionItem::new(
33 CompletionKind::Reference,
34 ctx.source_range(),
35 name.to_string(),
36 )
37 .from_resolution(ctx, res)
38 .add_to(acc)
39 });
40}
41 8
42fn complete_fn( 9 names.into_iter().for_each(|(name, res)| {
43 acc: &mut Completions, 10 CompletionItem::new(
44 scopes: &hir::ScopesWithSyntaxMapping, 11 CompletionKind::Reference,
45 ctx: &CompletionContext, 12 ctx.source_range(),
46) { 13 name.to_string(),
47 let mut shadowed = FxHashSet::default(); 14 )
48 scopes 15 .from_resolution(ctx, &res)
49 .scope_chain_for_offset(ctx.offset) 16 .add_to(acc)
50 .flat_map(|scope| scopes.scopes.entries(scope).iter()) 17 });
51 .filter(|entry| shadowed.insert(entry.name()))
52 .for_each(|entry| {
53 CompletionItem::new(
54 CompletionKind::Reference,
55 ctx.source_range(),
56 entry.name().to_string(),
57 )
58 .kind(CompletionItemKind::Binding)
59 .add_to(acc)
60 });
61} 18}
62 19
63#[cfg(test)] 20#[cfg(test)]
@@ -116,6 +73,30 @@ mod tests {
116 } 73 }
117 74
118 #[test] 75 #[test]
76 fn completes_generic_params() {
77 check_reference_completion(
78 "generic_params",
79 r"
80 fn quux<T>() {
81 <|>
82 }
83 ",
84 );
85 }
86
87 #[test]
88 fn completes_generic_params_in_struct() {
89 check_reference_completion(
90 "generic_params_in_struct",
91 r"
92 struct X<T> {
93 x: <|>
94 }
95 ",
96 );
97 }
98
99 #[test]
119 fn completes_module_items() { 100 fn completes_module_items() {
120 check_reference_completion( 101 check_reference_completion(
121 "module_items", 102 "module_items",
@@ -174,5 +155,4 @@ mod tests {
174 fn completes_self_in_methods() { 155 fn completes_self_in_methods() {
175 check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }") 156 check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }")
176 } 157 }
177
178} 158}
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index 578af6e5b..5d1851da6 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -5,7 +5,7 @@ use ra_syntax::{
5 algo::{find_leaf_at_offset, find_covering_node, find_node_at_offset}, 5 algo::{find_leaf_at_offset, find_covering_node, find_node_at_offset},
6 SyntaxKind::*, 6 SyntaxKind::*,
7}; 7};
8use hir::source_binder; 8use hir::{source_binder, Resolver};
9 9
10use crate::{db, FilePosition}; 10use crate::{db, FilePosition};
11 11
@@ -16,6 +16,7 @@ pub(crate) struct CompletionContext<'a> {
16 pub(super) db: &'a db::RootDatabase, 16 pub(super) db: &'a db::RootDatabase,
17 pub(super) offset: TextUnit, 17 pub(super) offset: TextUnit,
18 pub(super) leaf: &'a SyntaxNode, 18 pub(super) leaf: &'a SyntaxNode,
19 pub(super) resolver: Resolver,
19 pub(super) module: Option<hir::Module>, 20 pub(super) module: Option<hir::Module>,
20 pub(super) function: Option<hir::Function>, 21 pub(super) function: Option<hir::Function>,
21 pub(super) function_syntax: Option<&'a ast::FnDef>, 22 pub(super) function_syntax: Option<&'a ast::FnDef>,
@@ -42,12 +43,14 @@ impl<'a> CompletionContext<'a> {
42 original_file: &'a SourceFile, 43 original_file: &'a SourceFile,
43 position: FilePosition, 44 position: FilePosition,
44 ) -> Option<CompletionContext<'a>> { 45 ) -> Option<CompletionContext<'a>> {
46 let resolver = source_binder::resolver_for_position(db, position);
45 let module = source_binder::module_from_position(db, position); 47 let module = source_binder::module_from_position(db, position);
46 let leaf = find_leaf_at_offset(original_file.syntax(), position.offset).left_biased()?; 48 let leaf = find_leaf_at_offset(original_file.syntax(), position.offset).left_biased()?;
47 let mut ctx = CompletionContext { 49 let mut ctx = CompletionContext {
48 db, 50 db,
49 leaf, 51 leaf,
50 offset: position.offset, 52 offset: position.offset,
53 resolver,
51 module, 54 module,
52 function: None, 55 function: None,
53 function_syntax: None, 56 function_syntax: None,
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index d3bc14894..bada6a33b 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -1,5 +1,7 @@
1use hir::{Docs, Documentation}; 1use hir::{Docs, Documentation, PerNs, Resolution};
2use ra_syntax::TextRange; 2use ra_syntax::{
3 TextRange,
4};
3use ra_text_edit::TextEdit; 5use ra_text_edit::TextEdit;
4use test_utils::tested_by; 6use test_utils::tested_by;
5 7
@@ -48,6 +50,7 @@ pub enum CompletionItemKind {
48 Trait, 50 Trait,
49 TypeAlias, 51 TypeAlias,
50 Method, 52 Method,
53 TypeParam,
51} 54}
52 55
53#[derive(Debug, PartialEq, Eq, Copy, Clone)] 56#[derive(Debug, PartialEq, Eq, Copy, Clone)]
@@ -207,23 +210,34 @@ impl Builder {
207 pub(super) fn from_resolution( 210 pub(super) fn from_resolution(
208 mut self, 211 mut self,
209 ctx: &CompletionContext, 212 ctx: &CompletionContext,
210 resolution: &hir::Resolution, 213 resolution: &PerNs<Resolution>,
211 ) -> Builder { 214 ) -> Builder {
212 let def = resolution.def.take_types().or(resolution.def.take_values()); 215 use hir::ModuleDef::*;
216
217 let def = resolution
218 .as_ref()
219 .take_types()
220 .or(resolution.as_ref().take_values());
213 let def = match def { 221 let def = match def {
214 None => return self, 222 None => return self,
215 Some(it) => it, 223 Some(it) => it,
216 }; 224 };
217 let (kind, docs) = match def { 225 let (kind, docs) = match def {
218 hir::ModuleDef::Module(it) => (CompletionItemKind::Module, it.docs(ctx.db)), 226 Resolution::Def(Module(it)) => (CompletionItemKind::Module, it.docs(ctx.db)),
219 hir::ModuleDef::Function(func) => return self.from_function(ctx, func), 227 Resolution::Def(Function(func)) => return self.from_function(ctx, *func),
220 hir::ModuleDef::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), 228 Resolution::Def(Struct(it)) => (CompletionItemKind::Struct, it.docs(ctx.db)),
221 hir::ModuleDef::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), 229 Resolution::Def(Enum(it)) => (CompletionItemKind::Enum, it.docs(ctx.db)),
222 hir::ModuleDef::EnumVariant(it) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), 230 Resolution::Def(EnumVariant(it)) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)),
223 hir::ModuleDef::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), 231 Resolution::Def(Const(it)) => (CompletionItemKind::Const, it.docs(ctx.db)),
224 hir::ModuleDef::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), 232 Resolution::Def(Static(it)) => (CompletionItemKind::Static, it.docs(ctx.db)),
225 hir::ModuleDef::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), 233 Resolution::Def(Trait(it)) => (CompletionItemKind::Trait, it.docs(ctx.db)),
226 hir::ModuleDef::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), 234 Resolution::Def(Type(it)) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)),
235 Resolution::GenericParam(..) => (CompletionItemKind::TypeParam, None),
236 Resolution::LocalBinding(..) => (CompletionItemKind::Binding, None),
237 Resolution::SelfType(..) => (
238 CompletionItemKind::TypeParam, // (does this need its own kind?)
239 None,
240 ),
227 }; 241 };
228 self.kind = Some(kind); 242 self.kind = Some(kind);
229 self.documentation = docs; 243 self.documentation = docs;
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap
new file mode 100644
index 000000000..71cb55a5b
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap
@@ -0,0 +1,40 @@
1---
2created: "2019-02-01T22:20:40.580128393+00:00"
3creator: [email protected]
4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs
6---
7[
8 CompletionItem {
9 completion_kind: Reference,
10 label: "T",
11 kind: Some(
12 TypeParam
13 ),
14 detail: None,
15 documentation: None,
16 lookup: None,
17 insert_text: None,
18 insert_text_format: PlainText,
19 source_range: [44; 44),
20 text_edit: None
21 },
22 CompletionItem {
23 completion_kind: Reference,
24 label: "quux",
25 kind: Some(
26 Function
27 ),
28 detail: Some(
29 "fn quux<T>()"
30 ),
31 documentation: None,
32 lookup: None,
33 insert_text: Some(
34 "quux()$0"
35 ),
36 insert_text_format: Snippet,
37 source_range: [44; 44),
38 text_edit: None
39 }
40]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap
new file mode 100644
index 000000000..a35c0cd13
--- /dev/null
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap
@@ -0,0 +1,36 @@
1---
2created: "2019-02-01T22:23:21.508620224+00:00"
3creator: [email protected]
4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs
6---
7[
8 CompletionItem {
9 completion_kind: Reference,
10 label: "T",
11 kind: Some(
12 TypeParam
13 ),
14 detail: None,
15 documentation: None,
16 lookup: None,
17 insert_text: None,
18 insert_text_format: PlainText,
19 source_range: [46; 46),
20 text_edit: None
21 },
22 CompletionItem {
23 completion_kind: Reference,
24 label: "X",
25 kind: Some(
26 Struct
27 ),
28 detail: None,
29 documentation: None,
30 lookup: None,
31 insert_text: None,
32 insert_text_format: PlainText,
33 source_range: [46; 46),
34 text_edit: None
35 }
36]
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap
index 6a49e325c..ba1d4abbd 100644
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap
+++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap
@@ -1,12 +1,26 @@
1--- 1---
2created: "2019-01-23T05:27:32.422259+00:00" 2created: "2019-01-27T20:17:10.051725945+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: crates/ra_ide_api/src/completion/completion_item.rs
6--- 6---
7[ 7[
8 CompletionItem { 8 CompletionItem {
9 completion_kind: Reference, 9 completion_kind: Reference,
10 label: "Self",
11 kind: Some(
12 TypeParam
13 ),
14 detail: None,
15 documentation: None,
16 lookup: None,
17 insert_text: None,
18 insert_text_format: PlainText,
19 source_range: [25; 25),
20 text_edit: None
21 },
22 CompletionItem {
23 completion_kind: Reference,
10 label: "self", 24 label: "self",
11 kind: Some( 25 kind: Some(
12 Binding 26 Binding