aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/completion/complete_path.rs39
-rw-r--r--crates/ra_analysis/src/completion/completion_item.rs1
-rw-r--r--crates/ra_analysis/src/extend_selection.rs44
-rw-r--r--crates/ra_analysis/src/macros.rs11
-rw-r--r--crates/ra_analysis/src/mock_analysis.rs17
-rw-r--r--crates/ra_hir/src/adt.rs45
-rw-r--r--crates/ra_hir/src/db.rs9
-rw-r--r--crates/ra_hir/src/module.rs13
-rw-r--r--crates/ra_hir/src/name.rs16
-rw-r--r--crates/ra_hir/src/query_definitions.rs8
-rw-r--r--crates/ra_hir/src/ty.rs24
-rw-r--r--crates/ra_lsp_server/src/conv.rs1
12 files changed, 150 insertions, 78 deletions
diff --git a/crates/ra_analysis/src/completion/complete_path.rs b/crates/ra_analysis/src/completion/complete_path.rs
index aaa2c7cee..c73a083a4 100644
--- a/crates/ra_analysis/src/completion/complete_path.rs
+++ b/crates/ra_analysis/src/completion/complete_path.rs
@@ -1,6 +1,6 @@
1use crate::{ 1use crate::{
2 Cancelable, 2 Cancelable,
3 completion::{CompletionItem, Completions, CompletionKind, CompletionContext}, 3 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext},
4}; 4};
5 5
6pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> { 6pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> {
@@ -12,16 +12,25 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> C
12 Some(it) => it, 12 Some(it) => it,
13 None => return Ok(()), 13 None => return Ok(()),
14 }; 14 };
15 let target_module = match def_id.resolve(ctx.db)? { 15 match def_id.resolve(ctx.db)? {
16 hir::Def::Module(it) => it, 16 hir::Def::Module(module) => {
17 let module_scope = module.scope(ctx.db)?;
18 module_scope.entries().for_each(|(name, res)| {
19 CompletionItem::new(CompletionKind::Reference, name.to_string())
20 .from_resolution(ctx.db, res)
21 .add_to(acc)
22 });
23 }
24 hir::Def::Enum(e) => e
25 .variants(ctx.db)?
26 .into_iter()
27 .for_each(|(name, _variant)| {
28 CompletionItem::new(CompletionKind::Reference, name.to_string())
29 .kind(CompletionItemKind::EnumVariant)
30 .add_to(acc)
31 }),
17 _ => return Ok(()), 32 _ => return Ok(()),
18 }; 33 };
19 let module_scope = target_module.scope(ctx.db)?;
20 module_scope.entries().for_each(|(name, res)| {
21 CompletionItem::new(CompletionKind::Reference, name.to_string())
22 .from_resolution(ctx.db, res)
23 .add_to(acc)
24 });
25 Ok(()) 34 Ok(())
26} 35}
27 36
@@ -92,4 +101,16 @@ mod tests {
92 "Spam", 101 "Spam",
93 ); 102 );
94 } 103 }
104
105 #[test]
106 fn completes_enum_variant() {
107 check_reference_completion(
108 "
109 //- /lib.rs
110 enum E { Foo, Bar(i32) }
111 fn foo() { let _ = E::<|> }
112 ",
113 "Foo;Bar",
114 );
115 }
95} 116}
diff --git a/crates/ra_analysis/src/completion/completion_item.rs b/crates/ra_analysis/src/completion/completion_item.rs
index c9f9f495d..1d294c553 100644
--- a/crates/ra_analysis/src/completion/completion_item.rs
+++ b/crates/ra_analysis/src/completion/completion_item.rs
@@ -29,6 +29,7 @@ pub enum CompletionItemKind {
29 Function, 29 Function,
30 Struct, 30 Struct,
31 Enum, 31 Enum,
32 EnumVariant,
32 Binding, 33 Binding,
33 Field, 34 Field,
34} 35}
diff --git a/crates/ra_analysis/src/extend_selection.rs b/crates/ra_analysis/src/extend_selection.rs
index 5e1fbee18..cde6ee101 100644
--- a/crates/ra_analysis/src/extend_selection.rs
+++ b/crates/ra_analysis/src/extend_selection.rs
@@ -1,4 +1,8 @@
1use ra_db::SyntaxDatabase; 1use ra_db::SyntaxDatabase;
2use ra_syntax::{
3 SyntaxNodeRef, AstNode,
4 ast, algo::find_covering_node,
5};
2 6
3use crate::{ 7use crate::{
4 TextRange, FileRange, 8 TextRange, FileRange,
@@ -6,6 +10,42 @@ use crate::{
6}; 10};
7 11
8pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRange { 12pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRange {
9 let file = db.source_file(frange.file_id); 13 let source_file = db.source_file(frange.file_id);
10 ra_editor::extend_selection(&file, frange.range).unwrap_or(frange.range) 14 if let Some(macro_call) = find_macro_call(source_file.syntax(), frange.range) {
15 if let Some(exp) = crate::macros::expand(db, frange.file_id, macro_call) {
16 if let Some(dst_range) = exp.map_range_forward(frange.range) {
17 if let Some(dst_range) = ra_editor::extend_selection(exp.source_file(), dst_range) {
18 if let Some(src_range) = exp.map_range_back(dst_range) {
19 return src_range;
20 }
21 }
22 }
23 }
24 }
25 ra_editor::extend_selection(&source_file, frange.range).unwrap_or(frange.range)
26}
27
28fn find_macro_call(node: SyntaxNodeRef, range: TextRange) -> Option<ast::MacroCall> {
29 find_covering_node(node, range)
30 .ancestors()
31 .find_map(ast::MacroCall::cast)
32}
33
34#[cfg(test)]
35mod tests {
36 use crate::mock_analysis::single_file_with_range;
37 use test_utils::assert_eq_dbg;
38
39 #[test]
40 fn extend_selection_inside_macros() {
41 let (analysis, frange) = single_file_with_range(
42 "
43 fn main() {
44 ctry!(foo(|x| <|>x<|>));
45 }
46 ",
47 );
48 let r = analysis.extend_selection(frange);
49 assert_eq_dbg("[51; 56)", &r);
50 }
11} 51}
diff --git a/crates/ra_analysis/src/macros.rs b/crates/ra_analysis/src/macros.rs
index c0dd49dc8..b9feb7fad 100644
--- a/crates/ra_analysis/src/macros.rs
+++ b/crates/ra_analysis/src/macros.rs
@@ -61,4 +61,15 @@ impl MacroExpansion {
61 } 61 }
62 None 62 None
63 } 63 }
64 pub(crate) fn map_range_forward(&self, src_range: TextRange) -> Option<TextRange> {
65 for (s_range, t_range) in self.ranges_map.iter() {
66 if src_range.is_subrange(&s_range) {
67 let src_at_zero_range = src_range - src_range.start();
68 let src_range_offset = src_range.start() - s_range.start();
69 let src_range = src_at_zero_range + src_range_offset + t_range.start();
70 return Some(src_range);
71 }
72 }
73 None
74 }
64} 75}
diff --git a/crates/ra_analysis/src/mock_analysis.rs b/crates/ra_analysis/src/mock_analysis.rs
index 5ce2aa2b4..960529404 100644
--- a/crates/ra_analysis/src/mock_analysis.rs
+++ b/crates/ra_analysis/src/mock_analysis.rs
@@ -1,10 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use relative_path::RelativePathBuf; 3use relative_path::RelativePathBuf;
4use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; 4use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER};
5use ra_db::mock::FileMap; 5use ra_db::mock::FileMap;
6 6
7use crate::{Analysis, AnalysisChange, AnalysisHost, FileId, FilePosition, SourceRootId}; 7use crate::{Analysis, AnalysisChange, AnalysisHost, FileId, FilePosition, FileRange, SourceRootId};
8 8
9/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis 9/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis
10/// from a set of in-memory files. 10/// from a set of in-memory files.
@@ -66,6 +66,12 @@ impl MockAnalysis {
66 self.files.push((path.to_string(), text.to_string())); 66 self.files.push((path.to_string(), text.to_string()));
67 FilePosition { file_id, offset } 67 FilePosition { file_id, offset }
68 } 68 }
69 pub fn add_file_with_range(&mut self, path: &str, text: &str) -> FileRange {
70 let (range, text) = extract_range(text);
71 let file_id = FileId((self.files.len() + 1) as u32);
72 self.files.push((path.to_string(), text.to_string()));
73 FileRange { file_id, range }
74 }
69 pub fn id_of(&self, path: &str) -> FileId { 75 pub fn id_of(&self, path: &str) -> FileId {
70 let (idx, _) = self 76 let (idx, _) = self
71 .files 77 .files
@@ -115,3 +121,10 @@ pub fn single_file_with_position(code: &str) -> (Analysis, FilePosition) {
115 let pos = mock.add_file_with_position("/main.rs", code); 121 let pos = mock.add_file_with_position("/main.rs", code);
116 (mock.analysis(), pos) 122 (mock.analysis(), pos)
117} 123}
124
125/// Creates analysis for a single file, returns range marked with a pair of <|>.
126pub fn single_file_with_range(code: &str) -> (Analysis, FileRange) {
127 let mut mock = MockAnalysis::new();
128 let pos = mock.add_file_with_range("/main.rs", code);
129 (mock.analysis(), pos)
130}
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 65c461148..e839a5a90 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -1,10 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{SmolStr, ast::{self, NameOwner, StructFlavor}}; 3use ra_syntax::ast::{self, NameOwner, StructFlavor};
4 4
5use crate::{ 5use crate::{
6 DefId, Cancelable, 6 DefId, Cancelable, Name, AsName,
7 db::{HirDatabase}, 7 db::HirDatabase,
8 type_ref::TypeRef, 8 type_ref::TypeRef,
9}; 9};
10 10
@@ -29,26 +29,26 @@ impl Struct {
29 Ok(db.struct_data(self.def_id)?) 29 Ok(db.struct_data(self.def_id)?)
30 } 30 }
31 31
32 pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<SmolStr>> { 32 pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> {
33 Ok(db.struct_data(self.def_id)?.name.clone()) 33 Ok(db.struct_data(self.def_id)?.name.clone())
34 } 34 }
35} 35}
36 36
37#[derive(Debug, Clone, PartialEq, Eq)] 37#[derive(Debug, Clone, PartialEq, Eq)]
38pub struct StructData { 38pub struct StructData {
39 name: Option<SmolStr>, 39 name: Option<Name>,
40 variant_data: Arc<VariantData>, 40 variant_data: Arc<VariantData>,
41} 41}
42 42
43impl StructData { 43impl StructData {
44 pub(crate) fn new(struct_def: ast::StructDef) -> StructData { 44 pub(crate) fn new(struct_def: ast::StructDef) -> StructData {
45 let name = struct_def.name().map(|n| n.text()); 45 let name = struct_def.name().map(|n| n.as_name());
46 let variant_data = VariantData::new(struct_def.flavor()); 46 let variant_data = VariantData::new(struct_def.flavor());
47 let variant_data = Arc::new(variant_data); 47 let variant_data = Arc::new(variant_data);
48 StructData { name, variant_data } 48 StructData { name, variant_data }
49 } 49 }
50 50
51 pub fn name(&self) -> Option<&SmolStr> { 51 pub fn name(&self) -> Option<&Name> {
52 self.name.as_ref() 52 self.name.as_ref()
53 } 53 }
54 54
@@ -70,27 +70,29 @@ impl Enum {
70 self.def_id 70 self.def_id
71 } 71 }
72 72
73 pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<SmolStr>> { 73 pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> {
74 Ok(db.enum_data(self.def_id)?.name.clone()) 74 Ok(db.enum_data(self.def_id)?.name.clone())
75 } 75 }
76
77 pub fn variants(&self, db: &impl HirDatabase) -> Cancelable<Vec<(Name, Arc<VariantData>)>> {
78 Ok(db.enum_data(self.def_id)?.variants.clone())
79 }
76} 80}
77 81
78#[derive(Debug, Clone, PartialEq, Eq)] 82#[derive(Debug, Clone, PartialEq, Eq)]
79pub struct EnumData { 83pub struct EnumData {
80 name: Option<SmolStr>, 84 name: Option<Name>,
81 variants: Vec<(SmolStr, Arc<VariantData>)>, 85 variants: Vec<(Name, Arc<VariantData>)>,
82} 86}
83 87
84impl EnumData { 88impl EnumData {
85 pub(crate) fn new(enum_def: ast::EnumDef) -> Self { 89 pub(crate) fn new(enum_def: ast::EnumDef) -> Self {
86 let name = enum_def.name().map(|n| n.text()); 90 let name = enum_def.name().map(|n| n.as_name());
87 let variants = if let Some(evl) = enum_def.variant_list() { 91 let variants = if let Some(evl) = enum_def.variant_list() {
88 evl.variants() 92 evl.variants()
89 .map(|v| { 93 .map(|v| {
90 ( 94 (
91 v.name() 95 v.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
92 .map(|n| n.text())
93 .unwrap_or_else(|| SmolStr::new("[error]")),
94 Arc::new(VariantData::new(v.flavor())), 96 Arc::new(VariantData::new(v.flavor())),
95 ) 97 )
96 }) 98 })
@@ -105,12 +107,12 @@ impl EnumData {
105/// A single field of an enum variant or struct 107/// A single field of an enum variant or struct
106#[derive(Debug, Clone, PartialEq, Eq)] 108#[derive(Debug, Clone, PartialEq, Eq)]
107pub struct StructField { 109pub struct StructField {
108 name: SmolStr, 110 name: Name,
109 type_ref: TypeRef, 111 type_ref: TypeRef,
110} 112}
111 113
112impl StructField { 114impl StructField {
113 pub fn name(&self) -> SmolStr { 115 pub fn name(&self) -> Name {
114 self.name.clone() 116 self.name.clone()
115 } 117 }
116 pub fn type_ref(&self) -> &TypeRef { 118 pub fn type_ref(&self) -> &TypeRef {
@@ -134,7 +136,7 @@ impl VariantData {
134 .fields() 136 .fields()
135 .enumerate() 137 .enumerate()
136 .map(|(i, fd)| StructField { 138 .map(|(i, fd)| StructField {
137 name: SmolStr::new(i.to_string()), 139 name: Name::tuple_field_name(i),
138 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 140 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
139 }) 141 })
140 .collect(); 142 .collect();
@@ -144,10 +146,7 @@ impl VariantData {
144 let fields = fl 146 let fields = fl
145 .fields() 147 .fields()
146 .map(|fd| StructField { 148 .map(|fd| StructField {
147 name: fd 149 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
148 .name()
149 .map(|n| n.text())
150 .unwrap_or_else(|| SmolStr::new("[error]")),
151 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 150 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
152 }) 151 })
153 .collect(); 152 .collect();
@@ -157,10 +156,10 @@ impl VariantData {
157 } 156 }
158 } 157 }
159 158
160 pub(crate) fn get_field_type_ref(&self, field_name: &str) -> Option<&TypeRef> { 159 pub(crate) fn get_field_type_ref(&self, field_name: &Name) -> Option<&TypeRef> {
161 self.fields() 160 self.fields()
162 .iter() 161 .iter()
163 .find(|f| f.name == field_name) 162 .find(|f| f.name == *field_name)
164 .map(|f| &f.type_ref) 163 .map(|f| &f.type_ref)
165 } 164 }
166 165
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index ba43a4502..b41a7429a 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,13 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::SyntaxNode;
4 SmolStr,
5 SyntaxNode,
6};
7use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable}; 4use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, FileId, Cancelable};
8 5
9use crate::{ 6use crate::{
10 DefLoc, DefId, 7 DefLoc, DefId, Name,
11 SourceFileItems, SourceItemId, 8 SourceFileItems, SourceItemId,
12 query_definitions, 9 query_definitions,
13 FnScopes, 10 FnScopes,
@@ -47,7 +44,7 @@ pub trait HirDatabase: SyntaxDatabase
47 use fn query_definitions::type_for_def; 44 use fn query_definitions::type_for_def;
48 } 45 }
49 46
50 fn type_for_field(def_id: DefId, field: SmolStr) -> Cancelable<Ty> { 47 fn type_for_field(def_id: DefId, field: Name) -> Cancelable<Ty> {
51 type TypeForFieldQuery; 48 type TypeForFieldQuery;
52 use fn query_definitions::type_for_field; 49 use fn query_definitions::type_for_field;
53 } 50 }
diff --git a/crates/ra_hir/src/module.rs b/crates/ra_hir/src/module.rs
index 43413acb8..24c346984 100644
--- a/crates/ra_hir/src/module.rs
+++ b/crates/ra_hir/src/module.rs
@@ -13,8 +13,8 @@ use ra_db::{SourceRootId, FileId, Cancelable};
13use relative_path::RelativePathBuf; 13use relative_path::RelativePathBuf;
14 14
15use crate::{ 15use crate::{
16 DefKind, DefLoc, DefId, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId, Crate, 16 Def, DefKind, DefLoc, DefId,
17 Name, 17 Name, Path, PathKind, HirDatabase, SourceItemId, SourceFileItemId, Crate,
18 arena::{Arena, Id}, 18 arena::{Arena, Id},
19}; 19};
20 20
@@ -139,13 +139,8 @@ impl Module {
139 } else { 139 } else {
140 return Ok(PerNs::none()); 140 return Ok(PerNs::none());
141 }; 141 };
142 let module = match curr.loc(db) { 142 let module = match curr.resolve(db)? {
143 DefLoc { 143 Def::Module(it) => it,
144 kind: DefKind::Module,
145 source_root_id,
146 module_id,
147 ..
148 } => Module::new(db, source_root_id, module_id)?,
149 // TODO here would be the place to handle enum variants... 144 // TODO here would be the place to handle enum variants...
150 _ => return Ok(PerNs::none()), 145 _ => return Ok(PerNs::none()),
151 }; 146 };
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index e4fc141a6..51e8b3da8 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -23,6 +23,18 @@ impl fmt::Debug for Name {
23} 23}
24 24
25impl Name { 25impl Name {
26 fn new(text: SmolStr) -> Name {
27 Name { text }
28 }
29
30 pub(crate) fn missing() -> Name {
31 Name::new("[missing name]".into())
32 }
33
34 pub(crate) fn tuple_field_name(idx: usize) -> Name {
35 Name::new(idx.to_string().into())
36 }
37
26 pub(crate) fn as_known_name(&self) -> Option<KnownName> { 38 pub(crate) fn as_known_name(&self) -> Option<KnownName> {
27 let name = match self.text.as_str() { 39 let name = match self.text.as_str() {
28 "isize" => KnownName::Isize, 40 "isize" => KnownName::Isize,
@@ -43,10 +55,6 @@ impl Name {
43 }; 55 };
44 Some(name) 56 Some(name)
45 } 57 }
46
47 fn new(text: SmolStr) -> Name {
48 Name { text }
49 }
50} 58}
51 59
52pub(crate) trait AsName { 60pub(crate) trait AsName {
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index 56e3f7e9d..016d86ee6 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -5,7 +5,7 @@ use std::{
5 5
6use rustc_hash::FxHashMap; 6use rustc_hash::FxHashMap;
7use ra_syntax::{ 7use ra_syntax::{
8 AstNode, SyntaxNode, SmolStr, 8 AstNode, SyntaxNode,
9 ast::{self, NameOwner, ModuleItemOwner} 9 ast::{self, NameOwner, ModuleItemOwner}
10}; 10};
11use ra_db::{SourceRootId, FileId, Cancelable,}; 11use ra_db::{SourceRootId, FileId, Cancelable,};
@@ -39,11 +39,7 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<T
39 ty::type_for_def(db, def_id) 39 ty::type_for_def(db, def_id)
40} 40}
41 41
42pub(super) fn type_for_field( 42pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Cancelable<Ty> {
43 db: &impl HirDatabase,
44 def_id: DefId,
45 field: SmolStr,
46) -> Cancelable<Ty> {
47 ty::type_for_field(db, def_id, field) 43 ty::type_for_field(db, def_id, field)
48} 44}
49 45
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index ad097d1f1..38720b7b5 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -10,13 +10,12 @@ use rustc_hash::{FxHashMap};
10 10
11use ra_db::{LocalSyntaxPtr, Cancelable}; 11use ra_db::{LocalSyntaxPtr, Cancelable};
12use ra_syntax::{ 12use ra_syntax::{
13 SmolStr,
14 ast::{self, AstNode, LoopBodyOwner, ArgListOwner, PrefixOp}, 13 ast::{self, AstNode, LoopBodyOwner, ArgListOwner, PrefixOp},
15 SyntaxNodeRef 14 SyntaxNodeRef
16}; 15};
17 16
18use crate::{ 17use crate::{
19 Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, 18 Def, DefId, FnScopes, Module, Function, Struct, Enum, Path, Name, AsName,
20 db::HirDatabase, 19 db::HirDatabase,
21 adt::VariantData, 20 adt::VariantData,
22 type_ref::{TypeRef, Mutability}, 21 type_ref::{TypeRef, Mutability},
@@ -45,7 +44,7 @@ pub enum Ty {
45 /// The DefId of the struct/enum. 44 /// The DefId of the struct/enum.
46 def_id: DefId, 45 def_id: DefId,
47 /// The name, for displaying. 46 /// The name, for displaying.
48 name: SmolStr, 47 name: Name,
49 // later we'll need generic substitutions here 48 // later we'll need generic substitutions here
50 }, 49 },
51 50
@@ -276,18 +275,14 @@ pub fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> {
276pub fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Cancelable<Ty> { 275pub fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Cancelable<Ty> {
277 Ok(Ty::Adt { 276 Ok(Ty::Adt {
278 def_id: s.def_id(), 277 def_id: s.def_id(),
279 name: s 278 name: s.name(db)?.unwrap_or_else(Name::missing),
280 .name(db)?
281 .unwrap_or_else(|| SmolStr::new("[unnamed struct]")),
282 }) 279 })
283} 280}
284 281
285pub fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Cancelable<Ty> { 282pub fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Cancelable<Ty> {
286 Ok(Ty::Adt { 283 Ok(Ty::Adt {
287 def_id: s.def_id(), 284 def_id: s.def_id(),
288 name: s 285 name: s.name(db)?.unwrap_or_else(Name::missing),
289 .name(db)?
290 .unwrap_or_else(|| SmolStr::new("[unnamed enum]")),
291 }) 286 })
292} 287}
293 288
@@ -308,11 +303,7 @@ pub fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> {
308 } 303 }
309} 304}
310 305
311pub(super) fn type_for_field( 306pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Cancelable<Ty> {
312 db: &impl HirDatabase,
313 def_id: DefId,
314 field: SmolStr,
315) -> Cancelable<Ty> {
316 let def = def_id.resolve(db)?; 307 let def = def_id.resolve(db)?;
317 let variant_data = match def { 308 let variant_data = match def {
318 Def::Struct(s) => { 309 Def::Struct(s) => {
@@ -559,14 +550,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
559 ast::Expr::FieldExpr(e) => { 550 ast::Expr::FieldExpr(e) => {
560 let receiver_ty = self.infer_expr_opt(e.expr())?; 551 let receiver_ty = self.infer_expr_opt(e.expr())?;
561 if let Some(nr) = e.name_ref() { 552 if let Some(nr) = e.name_ref() {
562 let text = nr.text();
563 match receiver_ty { 553 match receiver_ty {
564 Ty::Tuple(fields) => { 554 Ty::Tuple(fields) => {
565 let i = text.parse::<usize>().ok(); 555 let i = nr.text().parse::<usize>().ok();
566 i.and_then(|i| fields.get(i).cloned()) 556 i.and_then(|i| fields.get(i).cloned())
567 .unwrap_or(Ty::Unknown) 557 .unwrap_or(Ty::Unknown)
568 } 558 }
569 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, text)?, 559 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, nr.as_name())?,
570 _ => Ty::Unknown, 560 _ => Ty::Unknown,
571 } 561 }
572 } else { 562 } else {
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 3d56ccd97..0d6e62727 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -57,6 +57,7 @@ impl Conv for CompletionItemKind {
57 CompletionItemKind::Function => Function, 57 CompletionItemKind::Function => Function,
58 CompletionItemKind::Struct => Struct, 58 CompletionItemKind::Struct => Struct,
59 CompletionItemKind::Enum => Enum, 59 CompletionItemKind::Enum => Enum,
60 CompletionItemKind::EnumVariant => EnumMember,
60 CompletionItemKind::Binding => Variable, 61 CompletionItemKind::Binding => Variable,
61 CompletionItemKind::Field => Field, 62 CompletionItemKind::Field => Field,
62 } 63 }