aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/expr.rs18
-rw-r--r--crates/ra_hir/src/expr/scope.rs38
-rw-r--r--crates/ra_hir/src/nameres.rs9
-rw-r--r--crates/ra_hir/src/resolve.rs57
-rw-r--r--crates/ra_hir/src/source_binder.rs31
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs12
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs63
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs5
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs44
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap18
-rw-r--r--crates/ra_lsp_server/src/conv.rs1
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)] 75pub fn resolver_for_expr(
76pub 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
84pub 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
153impl ScopesWithSyntaxMapping { 139impl 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
84impl<T> Default for PerNs<T> {
85 fn default() -> Self {
86 PerNs {
87 types: None,
88 values: None,
89 }
90 }
91}
92
84impl<T> PerNs<T> { 93impl<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};
9use ra_syntax::{ 9use 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
15use crate::{ 15use 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)] 206pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver<'static> {
206pub 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::{
7use hir::Docs; 7use hir::Docs;
8 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_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 @@
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 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
42fn 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};
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<'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 @@
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,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---
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
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}