diff options
-rw-r--r-- | crates/ra_hir/src/expr.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/expr/scope.rs | 38 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 57 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 31 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_path.rs | 12 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_scope.rs | 63 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/completion_context.rs | 5 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/completion_item.rs | 44 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap | 18 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 1 |
11 files changed, 190 insertions, 106 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 503a09f25..6c294bf10 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -72,11 +72,23 @@ impl Body { | |||
72 | } | 72 | } |
73 | 73 | ||
74 | // needs arbitrary_self_types to be a method... or maybe move to the def? | 74 | // needs arbitrary_self_types to be a method... or maybe move to the def? |
75 | #[allow(dead_code)] | 75 | pub fn resolver_for_expr( |
76 | pub fn resolver_for_expr(body: Arc<Body>, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { | 76 | body: Arc<Body>, |
77 | db: &impl HirDatabase, | ||
78 | expr_id: ExprId, | ||
79 | ) -> Resolver<'static> { | ||
80 | let scopes = db.expr_scopes(body.owner); | ||
81 | resolver_for_scope(body, db, scopes.scope_for(expr_id)) | ||
82 | } | ||
83 | |||
84 | pub fn resolver_for_scope( | ||
85 | body: Arc<Body>, | ||
86 | db: &impl HirDatabase, | ||
87 | scope_id: Option<scope::ScopeId>, | ||
88 | ) -> Resolver<'static> { | ||
77 | let mut r = body.owner.resolver(db); | 89 | let mut r = body.owner.resolver(db); |
78 | let scopes = db.expr_scopes(body.owner); | 90 | let scopes = db.expr_scopes(body.owner); |
79 | let scope_chain = scopes.scope_chain_for(expr_id).collect::<Vec<_>>(); | 91 | let scope_chain = scopes.scope_chain_for(scope_id).collect::<Vec<_>>(); |
80 | for scope in scope_chain.into_iter().rev() { | 92 | for scope in scope_chain.into_iter().rev() { |
81 | r = r.push_expr_scope(Arc::clone(&scopes), scope); | 93 | r = r.push_expr_scope(Arc::clone(&scopes), scope); |
82 | } | 94 | } |
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 887ad8dd8..23f1c5e7f 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs | |||
@@ -62,25 +62,11 @@ impl ExprScopes { | |||
62 | &self.scopes[scope].entries | 62 | &self.scopes[scope].entries |
63 | } | 63 | } |
64 | 64 | ||
65 | pub fn scope_chain_for<'a>(&'a self, expr: ExprId) -> impl Iterator<Item = ScopeId> + 'a { | 65 | pub fn scope_chain_for<'a>( |
66 | generate(self.scope_for(expr), move |&scope| { | ||
67 | self.scopes[scope].parent | ||
68 | }) | ||
69 | } | ||
70 | |||
71 | pub fn resolve_local_name<'a>( | ||
72 | &'a self, | 66 | &'a self, |
73 | context_expr: ExprId, | 67 | scope: Option<ScopeId>, |
74 | name: Name, | 68 | ) -> impl Iterator<Item = ScopeId> + 'a { |
75 | ) -> Option<&'a ScopeEntry> { | 69 | generate(scope, move |&scope| self.scopes[scope].parent) |
76 | // TODO replace by Resolver::resolve_name | ||
77 | let mut shadowed = FxHashSet::default(); | ||
78 | let ret = self | ||
79 | .scope_chain_for(context_expr) | ||
80 | .flat_map(|scope| self.entries(scope).iter()) | ||
81 | .filter(|entry| shadowed.insert(entry.name())) | ||
82 | .find(|entry| entry.name() == &name); | ||
83 | ret | ||
84 | } | 70 | } |
85 | 71 | ||
86 | fn root_scope(&mut self) -> ScopeId { | 72 | fn root_scope(&mut self) -> ScopeId { |
@@ -123,7 +109,7 @@ impl ExprScopes { | |||
123 | self.scope_for.insert(node, scope); | 109 | self.scope_for.insert(node, scope); |
124 | } | 110 | } |
125 | 111 | ||
126 | fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { | 112 | pub fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { |
127 | self.scope_for.get(&expr).map(|&scope| scope) | 113 | self.scope_for.get(&expr).map(|&scope| scope) |
128 | } | 114 | } |
129 | } | 115 | } |
@@ -151,18 +137,14 @@ impl ScopeEntryWithSyntax { | |||
151 | } | 137 | } |
152 | 138 | ||
153 | impl ScopesWithSyntaxMapping { | 139 | impl ScopesWithSyntaxMapping { |
154 | pub fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a { | 140 | fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a { |
155 | generate(self.scope_for(node), move |&scope| { | 141 | generate(self.scope_for(node), move |&scope| { |
156 | self.scopes.scopes[scope].parent | 142 | self.scopes.scopes[scope].parent |
157 | }) | 143 | }) |
158 | } | 144 | } |
159 | 145 | ||
160 | pub fn scope_chain_for_offset<'a>( | 146 | pub fn scope_for_offset<'a>(&'a self, offset: TextUnit) -> Option<ScopeId> { |
161 | &'a self, | 147 | self.scopes |
162 | offset: TextUnit, | ||
163 | ) -> impl Iterator<Item = ScopeId> + 'a { | ||
164 | let scope = self | ||
165 | .scopes | ||
166 | .scope_for | 148 | .scope_for |
167 | .iter() | 149 | .iter() |
168 | .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope))) | 150 | .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope))) |
@@ -173,9 +155,7 @@ impl ScopesWithSyntaxMapping { | |||
173 | ptr.range().len(), | 155 | ptr.range().len(), |
174 | ) | 156 | ) |
175 | }) | 157 | }) |
176 | .map(|(ptr, scope)| self.adjust(ptr, *scope, offset)); | 158 | .map(|(ptr, scope)| self.adjust(ptr, *scope, offset)) |
177 | |||
178 | generate(scope, move |&scope| self.scopes.scopes[scope].parent) | ||
179 | } | 159 | } |
180 | 160 | ||
181 | // XXX: during completion, cursor might be outside of any particular | 161 | // XXX: during completion, cursor might be outside of any particular |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 193c6a977..9b020db81 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -81,6 +81,15 @@ pub struct PerNs<T> { | |||
81 | pub values: Option<T>, | 81 | pub values: Option<T>, |
82 | } | 82 | } |
83 | 83 | ||
84 | impl<T> Default for PerNs<T> { | ||
85 | fn default() -> Self { | ||
86 | PerNs { | ||
87 | types: None, | ||
88 | values: None, | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
84 | impl<T> PerNs<T> { | 93 | impl<T> PerNs<T> { |
85 | pub fn none() -> PerNs<T> { | 94 | pub fn none() -> PerNs<T> { |
86 | PerNs { | 95 | PerNs { |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 36daed65b..30cf9c69e 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -89,8 +89,20 @@ impl Resolver { | |||
89 | } | 89 | } |
90 | } | 90 | } |
91 | 91 | ||
92 | pub fn all_names(&self) -> FxHashMap<Name, Resolution> { | 92 | pub fn all_names(&self) -> FxHashMap<Name, PerNs<Resolution>> { |
93 | unimplemented!() | 93 | let mut names = FxHashMap::default(); |
94 | for scope in &self.scopes { | ||
95 | scope.collect_names(&mut |name, res| { | ||
96 | let current: &mut PerNs<Resolution> = names.entry(name).or_default(); | ||
97 | if current.types.is_none() { | ||
98 | current.types = res.types; | ||
99 | } | ||
100 | if current.values.is_none() { | ||
101 | current.values = res.values; | ||
102 | } | ||
103 | }); | ||
104 | } | ||
105 | names | ||
94 | } | 106 | } |
95 | 107 | ||
96 | fn module(&self) -> Option<(&ItemMap, Module)> { | 108 | fn module(&self) -> Option<(&ItemMap, Module)> { |
@@ -175,4 +187,45 @@ impl Scope { | |||
175 | } | 187 | } |
176 | } | 188 | } |
177 | } | 189 | } |
190 | |||
191 | fn collect_names(&self, f: &mut FnMut(Name, PerNs<Resolution>)) { | ||
192 | match self { | ||
193 | Scope::ModuleScope(m) => { | ||
194 | m.item_map[m.module.module_id] | ||
195 | .entries() | ||
196 | .for_each(|(name, res)| { | ||
197 | f(name.clone(), res.def.map(|def| Resolution::Def { def })); | ||
198 | }) | ||
199 | } | ||
200 | Scope::ModuleScopeRef(m) => { | ||
201 | m.item_map[m.module.module_id] | ||
202 | .entries() | ||
203 | .for_each(|(name, res)| { | ||
204 | f(name.clone(), res.def.map(|def| Resolution::Def { def })); | ||
205 | }) | ||
206 | } | ||
207 | Scope::GenericParams(gp) => { | ||
208 | for param in &gp.params { | ||
209 | f( | ||
210 | param.name.clone(), | ||
211 | PerNs::types(Resolution::GenericParam { idx: param.idx }), | ||
212 | ) | ||
213 | } | ||
214 | } | ||
215 | Scope::ImplBlockScope(i) => { | ||
216 | f( | ||
217 | Name::self_type(), | ||
218 | PerNs::types(Resolution::SelfType(i.clone())), | ||
219 | ); | ||
220 | } | ||
221 | Scope::ExprScope(e) => { | ||
222 | e.expr_scopes.entries(e.scope_id).iter().for_each(|e| { | ||
223 | f( | ||
224 | e.name().clone(), | ||
225 | PerNs::values(Resolution::LocalBinding { pat: e.pat() }), | ||
226 | ); | ||
227 | }); | ||
228 | } | ||
229 | } | ||
230 | } | ||
178 | } | 231 | } |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 1fdd7d087..998158b3e 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -9,13 +9,14 @@ use ra_db::{FileId, FilePosition}; | |||
9 | use ra_syntax::{ | 9 | use ra_syntax::{ |
10 | SmolStr, TextRange, SyntaxNode, | 10 | SmolStr, TextRange, SyntaxNode, |
11 | ast::{self, AstNode, NameOwner}, | 11 | ast::{self, AstNode, NameOwner}, |
12 | algo::find_node_at_offset, | 12 | algo::{find_node_at_offset, find_leaf_at_offset}, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | HirDatabase, Function, ModuleDef, Struct, Enum, | 16 | HirDatabase, Function, ModuleDef, Struct, Enum, |
17 | AsName, Module, HirFileId, Crate, Trait, Resolver, | 17 | AsName, Module, HirFileId, Crate, Trait, Resolver, |
18 | ids::{LocationCtx, SourceFileItemId}, | 18 | ids::{LocationCtx, SourceFileItemId}, |
19 | expr | ||
19 | }; | 20 | }; |
20 | 21 | ||
21 | /// Locates the module by `FileId`. Picks topmost module in the file. | 22 | /// Locates the module by `FileId`. Picks topmost module in the file. |
@@ -202,7 +203,29 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te | |||
202 | res | 203 | res |
203 | } | 204 | } |
204 | 205 | ||
205 | #[allow(unused_variables)] | 206 | pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver<'static> { |
206 | pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver { | 207 | let file = db.parse(position.file_id); |
207 | unimplemented!() | 208 | find_leaf_at_offset(file.syntax(), position.offset) |
209 | .find_map(|node| { | ||
210 | node.ancestors().find_map(|node| { | ||
211 | if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { | ||
212 | if let Some(func) = function_from_child_node(db, position.file_id, node) { | ||
213 | let scopes = func.scopes(db); | ||
214 | let scope = scopes.scope_for_offset(position.offset); | ||
215 | Some(expr::resolver_for_scope(func.body(db), db, scope)) | ||
216 | } else { | ||
217 | // TODO const/static/array length | ||
218 | None | ||
219 | } | ||
220 | } else if let Some(module) = ast::Module::cast(node) { | ||
221 | Some(module_from_declaration(db, position.file_id, module)?.resolver(db)) | ||
222 | } else if let Some(_) = ast::SourceFile::cast(node) { | ||
223 | Some(module_from_source(db, position.file_id.into(), None)?.resolver(db)) | ||
224 | } else { | ||
225 | // TODO add missing cases | ||
226 | None | ||
227 | } | ||
228 | }) | ||
229 | }) | ||
230 | .unwrap_or_default() | ||
208 | } | 231 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index b33ddcde5..9e61c0212 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -7,13 +7,13 @@ use crate::{ | |||
7 | use hir::Docs; | 7 | use hir::Docs; |
8 | 8 | ||
9 | pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | 9 | pub(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_id { |
19 | hir::ModuleDef::Module(module) => { | 19 | hir::ModuleDef::Module(module) => { |
@@ -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(|def| hir::Resolution::Def { def })) |
28 | .add_to(acc); | 28 | .add_to(acc); |
29 | } | 29 | } |
30 | } | 30 | } |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index f837bb1db..3488d6480 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -1,61 +1,32 @@ | |||
1 | use rustc_hash::FxHashSet; | 1 | use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionContext}; |
2 | use ra_syntax::ast::AstNode; | ||
3 | use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}; | ||
4 | 2 | ||
5 | pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { | 3 | pub(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 | 8 | ||
18 | let module_scope = module.scope(ctx.db); | 9 | // let module_scope = module.scope(ctx.db); |
19 | module_scope | 10 | names |
20 | .entries() | 11 | .into_iter() |
21 | .filter(|(_name, res)| { | 12 | // FIXME check tests |
22 | // For cases like `use self::foo<|>` don't suggest foo itself. | 13 | // .filter(|(_name, res)| { |
23 | match res.import { | 14 | // // For cases like `use self::foo<|>` don't suggest foo itself. |
24 | None => true, | 15 | // match res.import { |
25 | Some(import) => { | 16 | // None => true, |
26 | let source = module.import_source(ctx.db, import); | 17 | // Some(import) => { |
27 | !source.syntax().range().is_subrange(&ctx.leaf.range()) | 18 | // let source = module.import_source(ctx.db, import); |
28 | } | 19 | // !source.syntax().range().is_subrange(&ctx.leaf.range()) |
29 | } | 20 | // } |
30 | }) | 21 | // } |
22 | // }) | ||
31 | .for_each(|(name, res)| { | 23 | .for_each(|(name, res)| { |
32 | CompletionItem::new( | 24 | CompletionItem::new( |
33 | CompletionKind::Reference, | 25 | CompletionKind::Reference, |
34 | ctx.source_range(), | 26 | ctx.source_range(), |
35 | name.to_string(), | 27 | name.to_string(), |
36 | ) | 28 | ) |
37 | .from_resolution(ctx, res) | 29 | .from_resolution(ctx, &res) |
38 | .add_to(acc) | ||
39 | }); | ||
40 | } | ||
41 | |||
42 | fn complete_fn( | ||
43 | acc: &mut Completions, | ||
44 | scopes: &hir::ScopesWithSyntaxMapping, | ||
45 | ctx: &CompletionContext, | ||
46 | ) { | ||
47 | let mut shadowed = FxHashSet::default(); | ||
48 | scopes | ||
49 | .scope_chain_for_offset(ctx.offset) | ||
50 | .flat_map(|scope| scopes.scopes.entries(scope).iter()) | ||
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) | 30 | .add_to(acc) |
60 | }); | 31 | }); |
61 | } | 32 | } |
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index 578af6e5b..aea32fce3 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 | }; |
8 | use hir::source_binder; | 8 | use hir::{source_binder, Resolver}; |
9 | 9 | ||
10 | use crate::{db, FilePosition}; | 10 | use 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<'static>, | ||
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..4101ce88a 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 @@ | |||
1 | use hir::{Docs, Documentation}; | 1 | use hir::{Docs, Documentation, PerNs, Resolution}; |
2 | use ra_syntax::TextRange; | 2 | use ra_syntax::{ |
3 | TextRange, | ||
4 | }; | ||
3 | use ra_text_edit::TextEdit; | 5 | use ra_text_edit::TextEdit; |
4 | use test_utils::tested_by; | 6 | use 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,38 @@ 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 { def: Module(it) } => (CompletionItemKind::Module, it.docs(ctx.db)), |
219 | hir::ModuleDef::Function(func) => return self.from_function(ctx, func), | 227 | Resolution::Def { |
220 | hir::ModuleDef::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), | 228 | def: Function(func), |
221 | hir::ModuleDef::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), | 229 | } => return self.from_function(ctx, *func), |
222 | hir::ModuleDef::EnumVariant(it) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), | 230 | Resolution::Def { def: Struct(it) } => (CompletionItemKind::Struct, it.docs(ctx.db)), |
223 | hir::ModuleDef::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), | 231 | Resolution::Def { def: Enum(it) } => (CompletionItemKind::Enum, it.docs(ctx.db)), |
224 | hir::ModuleDef::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), | 232 | Resolution::Def { |
225 | hir::ModuleDef::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), | 233 | def: EnumVariant(it), |
226 | hir::ModuleDef::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), | 234 | } => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), |
235 | Resolution::Def { def: Const(it) } => (CompletionItemKind::Const, it.docs(ctx.db)), | ||
236 | Resolution::Def { def: Static(it) } => (CompletionItemKind::Static, it.docs(ctx.db)), | ||
237 | Resolution::Def { def: Trait(it) } => (CompletionItemKind::Trait, it.docs(ctx.db)), | ||
238 | Resolution::Def { def: Type(it) } => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), | ||
239 | Resolution::GenericParam { .. } => (CompletionItemKind::TypeParam, None), | ||
240 | Resolution::LocalBinding { .. } => (CompletionItemKind::Binding, None), | ||
241 | Resolution::SelfType { .. } => ( | ||
242 | CompletionItemKind::TypeParam, // (does this need its own kind?) | ||
243 | None, | ||
244 | ), | ||
227 | }; | 245 | }; |
228 | self.kind = Some(kind); | 246 | self.kind = Some(kind); |
229 | self.documentation = docs; | 247 | self.documentation = docs; |
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 | --- |
2 | created: "2019-01-23T05:27:32.422259+00:00" | 2 | created: "2019-01-27T20:17:10.051725945+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: kind_completions | 4 | expression: kind_completions |
5 | source: crates/ra_ide_api/src/completion/completion_item.rs | 5 | source: 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 |
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index c033ecdea..17fa07340 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -70,6 +70,7 @@ impl Conv for CompletionItemKind { | |||
70 | CompletionItemKind::Const => Constant, | 70 | CompletionItemKind::Const => Constant, |
71 | CompletionItemKind::Static => Value, | 71 | CompletionItemKind::Static => Value, |
72 | CompletionItemKind::Method => Method, | 72 | CompletionItemKind::Method => Method, |
73 | CompletionItemKind::TypeParam => TypeParameter, | ||
73 | } | 74 | } |
74 | } | 75 | } |
75 | } | 76 | } |