diff options
-rw-r--r-- | crates/ra_hir/src/adt.rs | 108 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 83 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/function.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_impl/module.rs | 28 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ids.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/mock.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/enum.txt | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_path.rs | 23 | ||||
-rw-r--r-- | crates/ra_ide_api/src/db.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 43 | ||||
-rw-r--r-- | crates/ra_ide_api/src/lib.rs | 64 |
16 files changed, 384 insertions, 62 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index d30390f25..bcb705c24 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -1,10 +1,15 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::Cancelable; | 3 | use ra_db::Cancelable; |
4 | use ra_syntax::ast::{self, NameOwner, StructFlavor, AstNode}; | 4 | use ra_syntax::{ |
5 | SyntaxNode, | ||
6 | ast::{self, NameOwner, StructFlavor, AstNode} | ||
7 | }; | ||
5 | 8 | ||
6 | use crate::{ | 9 | use crate::{ |
7 | DefId, Name, AsName, Struct, Enum, HirDatabase, DefKind, | 10 | DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, |
11 | HirDatabase, DefKind, | ||
12 | SourceItemId, | ||
8 | type_ref::TypeRef, | 13 | type_ref::TypeRef, |
9 | }; | 14 | }; |
10 | 15 | ||
@@ -45,33 +50,37 @@ impl StructData { | |||
45 | } | 50 | } |
46 | } | 51 | } |
47 | 52 | ||
48 | impl Enum { | 53 | fn get_def_id( |
49 | pub(crate) fn new(def_id: DefId) -> Self { | 54 | db: &impl HirDatabase, |
50 | Enum { def_id } | 55 | same_file_loc: &DefLoc, |
51 | } | 56 | node: &SyntaxNode, |
57 | expected_kind: DefKind, | ||
58 | ) -> DefId { | ||
59 | let file_id = same_file_loc.source_item_id.file_id; | ||
60 | let file_items = db.file_items(file_id); | ||
61 | |||
62 | let item_id = file_items.id_of(file_id, node); | ||
63 | let source_item_id = SourceItemId { | ||
64 | item_id: Some(item_id), | ||
65 | ..same_file_loc.source_item_id | ||
66 | }; | ||
67 | let loc = DefLoc { | ||
68 | kind: expected_kind, | ||
69 | source_item_id: source_item_id, | ||
70 | ..*same_file_loc | ||
71 | }; | ||
72 | loc.id(db) | ||
52 | } | 73 | } |
53 | 74 | ||
54 | #[derive(Debug, Clone, PartialEq, Eq)] | 75 | #[derive(Debug, Clone, PartialEq, Eq)] |
55 | pub struct EnumData { | 76 | pub struct EnumData { |
56 | pub(crate) name: Option<Name>, | 77 | pub(crate) name: Option<Name>, |
57 | pub(crate) variants: Vec<(Name, Arc<VariantData>)>, | 78 | pub(crate) variants: Vec<(Name, EnumVariant)>, |
58 | } | 79 | } |
59 | 80 | ||
60 | impl EnumData { | 81 | impl EnumData { |
61 | fn new(enum_def: &ast::EnumDef) -> Self { | 82 | fn new(enum_def: &ast::EnumDef, variants: Vec<(Name, EnumVariant)>) -> Self { |
62 | let name = enum_def.name().map(|n| n.as_name()); | 83 | let name = enum_def.name().map(|n| n.as_name()); |
63 | let variants = if let Some(evl) = enum_def.variant_list() { | ||
64 | evl.variants() | ||
65 | .map(|v| { | ||
66 | ( | ||
67 | v.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), | ||
68 | Arc::new(VariantData::new(v.flavor())), | ||
69 | ) | ||
70 | }) | ||
71 | .collect() | ||
72 | } else { | ||
73 | Vec::new() | ||
74 | }; | ||
75 | EnumData { name, variants } | 84 | EnumData { name, variants } |
76 | } | 85 | } |
77 | 86 | ||
@@ -83,7 +92,64 @@ impl EnumData { | |||
83 | assert!(def_loc.kind == DefKind::Enum); | 92 | assert!(def_loc.kind == DefKind::Enum); |
84 | let syntax = db.file_item(def_loc.source_item_id); | 93 | let syntax = db.file_item(def_loc.source_item_id); |
85 | let enum_def = ast::EnumDef::cast(&syntax).expect("enum def should point to EnumDef node"); | 94 | let enum_def = ast::EnumDef::cast(&syntax).expect("enum def should point to EnumDef node"); |
86 | Ok(Arc::new(EnumData::new(enum_def))) | 95 | let variants = if let Some(vl) = enum_def.variant_list() { |
96 | vl.variants() | ||
97 | .filter_map(|variant_def| { | ||
98 | let name = variant_def.name().map(|n| n.as_name()); | ||
99 | |||
100 | name.map(|n| { | ||
101 | let def_id = | ||
102 | get_def_id(db, &def_loc, variant_def.syntax(), DefKind::EnumVariant); | ||
103 | (n, EnumVariant::new(def_id)) | ||
104 | }) | ||
105 | }) | ||
106 | .collect() | ||
107 | } else { | ||
108 | Vec::new() | ||
109 | }; | ||
110 | Ok(Arc::new(EnumData::new(enum_def, variants))) | ||
111 | } | ||
112 | } | ||
113 | |||
114 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
115 | pub struct EnumVariantData { | ||
116 | pub(crate) name: Option<Name>, | ||
117 | pub(crate) variant_data: Arc<VariantData>, | ||
118 | pub(crate) parent_enum: Enum, | ||
119 | } | ||
120 | |||
121 | impl EnumVariantData { | ||
122 | fn new(variant_def: &ast::EnumVariant, parent_enum: Enum) -> EnumVariantData { | ||
123 | let name = variant_def.name().map(|n| n.as_name()); | ||
124 | let variant_data = VariantData::new(variant_def.flavor()); | ||
125 | let variant_data = Arc::new(variant_data); | ||
126 | EnumVariantData { | ||
127 | name, | ||
128 | variant_data, | ||
129 | parent_enum, | ||
130 | } | ||
131 | } | ||
132 | |||
133 | pub(crate) fn enum_variant_data_query( | ||
134 | db: &impl HirDatabase, | ||
135 | def_id: DefId, | ||
136 | ) -> Cancelable<Arc<EnumVariantData>> { | ||
137 | let def_loc = def_id.loc(db); | ||
138 | assert!(def_loc.kind == DefKind::EnumVariant); | ||
139 | let syntax = db.file_item(def_loc.source_item_id); | ||
140 | let variant_def = ast::EnumVariant::cast(&syntax) | ||
141 | .expect("enum variant def should point to EnumVariant node"); | ||
142 | let enum_node = syntax | ||
143 | .parent() | ||
144 | .expect("enum variant should have enum variant list ancestor") | ||
145 | .parent() | ||
146 | .expect("enum variant list should have enum ancestor"); | ||
147 | let enum_def_id = get_def_id(db, &def_loc, enum_node, DefKind::Enum); | ||
148 | |||
149 | Ok(Arc::new(EnumVariantData::new( | ||
150 | variant_def, | ||
151 | Enum::new(enum_def_id), | ||
152 | ))) | ||
87 | } | 153 | } |
88 | } | 154 | } |
89 | 155 | ||
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index fa3e4baa7..e69f546ff 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -2,10 +2,10 @@ use std::sync::Arc; | |||
2 | 2 | ||
3 | use relative_path::RelativePathBuf; | 3 | use relative_path::RelativePathBuf; |
4 | use ra_db::{CrateId, Cancelable, FileId}; | 4 | use ra_db::{CrateId, Cancelable, FileId}; |
5 | use ra_syntax::{ast, TreePtr, SyntaxNode}; | 5 | use ra_syntax::{ast, TreePtr, SyntaxNode, AstNode}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, | 8 | Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId, |
9 | type_ref::TypeRef, | 9 | type_ref::TypeRef, |
10 | nameres::ModuleScope, | 10 | nameres::ModuleScope, |
11 | db::HirDatabase, | 11 | db::HirDatabase, |
@@ -44,6 +44,7 @@ pub enum Def { | |||
44 | Module(Module), | 44 | Module(Module), |
45 | Struct(Struct), | 45 | Struct(Struct), |
46 | Enum(Enum), | 46 | Enum(Enum), |
47 | EnumVariant(EnumVariant), | ||
47 | Function(Function), | 48 | Function(Function), |
48 | Item, | 49 | Item, |
49 | } | 50 | } |
@@ -180,6 +181,19 @@ impl Struct { | |||
180 | .collect(); | 181 | .collect(); |
181 | Ok(res) | 182 | Ok(res) |
182 | } | 183 | } |
184 | |||
185 | pub fn source( | ||
186 | &self, | ||
187 | db: &impl HirDatabase, | ||
188 | ) -> Cancelable<(HirFileId, TreePtr<ast::StructDef>)> { | ||
189 | let (file_id, syntax) = self.def_id.source(db); | ||
190 | Ok(( | ||
191 | file_id, | ||
192 | ast::StructDef::cast(&syntax) | ||
193 | .expect("struct def should point to StructDef node") | ||
194 | .to_owned(), | ||
195 | )) | ||
196 | } | ||
183 | } | 197 | } |
184 | 198 | ||
185 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 199 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -188,6 +202,10 @@ pub struct Enum { | |||
188 | } | 202 | } |
189 | 203 | ||
190 | impl Enum { | 204 | impl Enum { |
205 | pub(crate) fn new(def_id: DefId) -> Self { | ||
206 | Enum { def_id } | ||
207 | } | ||
208 | |||
191 | pub fn def_id(&self) -> DefId { | 209 | pub fn def_id(&self) -> DefId { |
192 | self.def_id | 210 | self.def_id |
193 | } | 211 | } |
@@ -196,9 +214,59 @@ impl Enum { | |||
196 | Ok(db.enum_data(self.def_id)?.name.clone()) | 214 | Ok(db.enum_data(self.def_id)?.name.clone()) |
197 | } | 215 | } |
198 | 216 | ||
199 | pub fn variants(&self, db: &impl HirDatabase) -> Cancelable<Vec<(Name, Arc<VariantData>)>> { | 217 | pub fn variants(&self, db: &impl HirDatabase) -> Cancelable<Vec<(Name, EnumVariant)>> { |
200 | Ok(db.enum_data(self.def_id)?.variants.clone()) | 218 | Ok(db.enum_data(self.def_id)?.variants.clone()) |
201 | } | 219 | } |
220 | |||
221 | pub fn source(&self, db: &impl HirDatabase) -> Cancelable<(HirFileId, TreePtr<ast::EnumDef>)> { | ||
222 | let (file_id, syntax) = self.def_id.source(db); | ||
223 | Ok(( | ||
224 | file_id, | ||
225 | ast::EnumDef::cast(&syntax) | ||
226 | .expect("enum def should point to EnumDef node") | ||
227 | .to_owned(), | ||
228 | )) | ||
229 | } | ||
230 | } | ||
231 | |||
232 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
233 | pub struct EnumVariant { | ||
234 | pub(crate) def_id: DefId, | ||
235 | } | ||
236 | |||
237 | impl EnumVariant { | ||
238 | pub(crate) fn new(def_id: DefId) -> Self { | ||
239 | EnumVariant { def_id } | ||
240 | } | ||
241 | |||
242 | pub fn def_id(&self) -> DefId { | ||
243 | self.def_id | ||
244 | } | ||
245 | |||
246 | pub fn parent_enum(&self, db: &impl HirDatabase) -> Cancelable<Enum> { | ||
247 | Ok(db.enum_variant_data(self.def_id)?.parent_enum.clone()) | ||
248 | } | ||
249 | |||
250 | pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> { | ||
251 | Ok(db.enum_variant_data(self.def_id)?.name.clone()) | ||
252 | } | ||
253 | |||
254 | pub fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> { | ||
255 | Ok(db.enum_variant_data(self.def_id)?.variant_data.clone()) | ||
256 | } | ||
257 | |||
258 | pub fn source( | ||
259 | &self, | ||
260 | db: &impl HirDatabase, | ||
261 | ) -> Cancelable<(HirFileId, TreePtr<ast::EnumVariant>)> { | ||
262 | let (file_id, syntax) = self.def_id.source(db); | ||
263 | Ok(( | ||
264 | file_id, | ||
265 | ast::EnumVariant::cast(&syntax) | ||
266 | .expect("variant def should point to EnumVariant node") | ||
267 | .to_owned(), | ||
268 | )) | ||
269 | } | ||
202 | } | 270 | } |
203 | 271 | ||
204 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 272 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -209,11 +277,16 @@ pub struct Function { | |||
209 | /// The declared signature of a function. | 277 | /// The declared signature of a function. |
210 | #[derive(Debug, Clone, PartialEq, Eq)] | 278 | #[derive(Debug, Clone, PartialEq, Eq)] |
211 | pub struct FnSignature { | 279 | pub struct FnSignature { |
280 | pub(crate) name: Name, | ||
212 | pub(crate) args: Vec<TypeRef>, | 281 | pub(crate) args: Vec<TypeRef>, |
213 | pub(crate) ret_type: TypeRef, | 282 | pub(crate) ret_type: TypeRef, |
214 | } | 283 | } |
215 | 284 | ||
216 | impl FnSignature { | 285 | impl FnSignature { |
286 | pub fn name(&self) -> &Name { | ||
287 | &self.name | ||
288 | } | ||
289 | |||
217 | pub fn args(&self) -> &[TypeRef] { | 290 | pub fn args(&self) -> &[TypeRef] { |
218 | &self.args | 291 | &self.args |
219 | } | 292 | } |
@@ -228,8 +301,8 @@ impl Function { | |||
228 | self.def_id | 301 | self.def_id |
229 | } | 302 | } |
230 | 303 | ||
231 | pub fn source(&self, db: &impl HirDatabase) -> TreePtr<ast::FnDef> { | 304 | pub fn source(&self, db: &impl HirDatabase) -> Cancelable<(HirFileId, TreePtr<ast::FnDef>)> { |
232 | self.source_impl(db) | 305 | Ok(self.source_impl(db)) |
233 | } | 306 | } |
234 | 307 | ||
235 | pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Cancelable<Arc<BodySyntaxMapping>> { | 308 | pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Cancelable<Arc<BodySyntaxMapping>> { |
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index 13c57ed21..1bd4cc802 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs | |||
@@ -5,11 +5,11 @@ use std::sync::Arc; | |||
5 | use ra_db::Cancelable; | 5 | use ra_db::Cancelable; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
7 | TreePtr, | 7 | TreePtr, |
8 | ast::{self, AstNode}, | 8 | ast::{self, AstNode, NameOwner}, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | DefId, DefKind, HirDatabase, Name, Function, FnSignature, Module, | 12 | DefId, DefKind, HirDatabase, Name, AsName, Function, FnSignature, Module, HirFileId, |
13 | type_ref::{TypeRef, Mutability}, | 13 | type_ref::{TypeRef, Mutability}, |
14 | expr::Body, | 14 | expr::Body, |
15 | impl_block::ImplBlock, | 15 | impl_block::ImplBlock, |
@@ -22,11 +22,14 @@ impl Function { | |||
22 | Function { def_id } | 22 | Function { def_id } |
23 | } | 23 | } |
24 | 24 | ||
25 | pub(crate) fn source_impl(&self, db: &impl HirDatabase) -> TreePtr<ast::FnDef> { | 25 | pub(crate) fn source_impl(&self, db: &impl HirDatabase) -> (HirFileId, TreePtr<ast::FnDef>) { |
26 | let def_loc = self.def_id.loc(db); | 26 | let def_loc = self.def_id.loc(db); |
27 | assert!(def_loc.kind == DefKind::Function); | 27 | assert!(def_loc.kind == DefKind::Function); |
28 | let syntax = db.file_item(def_loc.source_item_id); | 28 | let syntax = db.file_item(def_loc.source_item_id); |
29 | ast::FnDef::cast(&syntax).unwrap().to_owned() | 29 | ( |
30 | def_loc.source_item_id.file_id, | ||
31 | ast::FnDef::cast(&syntax).unwrap().to_owned(), | ||
32 | ) | ||
30 | } | 33 | } |
31 | 34 | ||
32 | pub(crate) fn body(&self, db: &impl HirDatabase) -> Cancelable<Arc<Body>> { | 35 | pub(crate) fn body(&self, db: &impl HirDatabase) -> Cancelable<Arc<Body>> { |
@@ -46,7 +49,11 @@ impl Function { | |||
46 | impl FnSignature { | 49 | impl FnSignature { |
47 | pub(crate) fn fn_signature_query(db: &impl HirDatabase, def_id: DefId) -> Arc<FnSignature> { | 50 | pub(crate) fn fn_signature_query(db: &impl HirDatabase, def_id: DefId) -> Arc<FnSignature> { |
48 | let func = Function::new(def_id); | 51 | let func = Function::new(def_id); |
49 | let node = func.source(db); | 52 | let node = func.source_impl(db).1; // TODO we're using source_impl here to avoid returning Cancelable... this is a bit hacky |
53 | let name = node | ||
54 | .name() | ||
55 | .map(|n| n.as_name()) | ||
56 | .unwrap_or_else(Name::missing); | ||
50 | let mut args = Vec::new(); | 57 | let mut args = Vec::new(); |
51 | if let Some(param_list) = node.param_list() { | 58 | if let Some(param_list) = node.param_list() { |
52 | if let Some(self_param) = param_list.self_param() { | 59 | if let Some(self_param) = param_list.self_param() { |
@@ -76,7 +83,11 @@ impl FnSignature { | |||
76 | } else { | 83 | } else { |
77 | TypeRef::unit() | 84 | TypeRef::unit() |
78 | }; | 85 | }; |
79 | let sig = FnSignature { args, ret_type }; | 86 | let sig = FnSignature { |
87 | name, | ||
88 | args, | ||
89 | ret_type, | ||
90 | }; | ||
80 | Arc::new(sig) | 91 | Arc::new(sig) |
81 | } | 92 | } |
82 | } | 93 | } |
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 1cb408cff..878dc37c8 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -13,6 +13,7 @@ impl Module { | |||
13 | pub(crate) fn new(def_id: DefId) -> Self { | 13 | pub(crate) fn new(def_id: DefId) -> Self { |
14 | crate::code_model_api::Module { def_id } | 14 | crate::code_model_api::Module { def_id } |
15 | } | 15 | } |
16 | |||
16 | pub(crate) fn from_module_id( | 17 | pub(crate) fn from_module_id( |
17 | db: &impl HirDatabase, | 18 | db: &impl HirDatabase, |
18 | source_root_id: SourceRootId, | 19 | source_root_id: SourceRootId, |
@@ -85,6 +86,7 @@ impl Module { | |||
85 | let module_id = loc.module_id.crate_root(&module_tree); | 86 | let module_id = loc.module_id.crate_root(&module_tree); |
86 | Module::from_module_id(db, loc.source_root_id, module_id) | 87 | Module::from_module_id(db, loc.source_root_id, module_id) |
87 | } | 88 | } |
89 | |||
88 | /// Finds a child module with the specified name. | 90 | /// Finds a child module with the specified name. |
89 | pub fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 91 | pub fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { |
90 | let loc = self.def_id.loc(db); | 92 | let loc = self.def_id.loc(db); |
@@ -92,12 +94,14 @@ impl Module { | |||
92 | let child_id = ctry!(loc.module_id.child(&module_tree, name)); | 94 | let child_id = ctry!(loc.module_id.child(&module_tree, name)); |
93 | Module::from_module_id(db, loc.source_root_id, child_id).map(Some) | 95 | Module::from_module_id(db, loc.source_root_id, child_id).map(Some) |
94 | } | 96 | } |
97 | |||
95 | pub fn parent_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { | 98 | pub fn parent_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { |
96 | let loc = self.def_id.loc(db); | 99 | let loc = self.def_id.loc(db); |
97 | let module_tree = db.module_tree(loc.source_root_id)?; | 100 | let module_tree = db.module_tree(loc.source_root_id)?; |
98 | let parent_id = ctry!(loc.module_id.parent(&module_tree)); | 101 | let parent_id = ctry!(loc.module_id.parent(&module_tree)); |
99 | Module::from_module_id(db, loc.source_root_id, parent_id).map(Some) | 102 | Module::from_module_id(db, loc.source_root_id, parent_id).map(Some) |
100 | } | 103 | } |
104 | |||
101 | /// Returns a `ModuleScope`: a set of items, visible in this module. | 105 | /// Returns a `ModuleScope`: a set of items, visible in this module. |
102 | pub fn scope_impl(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { | 106 | pub fn scope_impl(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { |
103 | let loc = self.def_id.loc(db); | 107 | let loc = self.def_id.loc(db); |
@@ -105,6 +109,7 @@ impl Module { | |||
105 | let res = item_map.per_module[&loc.module_id].clone(); | 109 | let res = item_map.per_module[&loc.module_id].clone(); |
106 | Ok(res) | 110 | Ok(res) |
107 | } | 111 | } |
112 | |||
108 | pub fn resolve_path_impl( | 113 | pub fn resolve_path_impl( |
109 | &self, | 114 | &self, |
110 | db: &impl HirDatabase, | 115 | db: &impl HirDatabase, |
@@ -126,7 +131,7 @@ impl Module { | |||
126 | ); | 131 | ); |
127 | 132 | ||
128 | let segments = &path.segments; | 133 | let segments = &path.segments; |
129 | for name in segments.iter() { | 134 | for (idx, name) in segments.iter().enumerate() { |
130 | let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { | 135 | let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { |
131 | r | 136 | r |
132 | } else { | 137 | } else { |
@@ -134,7 +139,25 @@ impl Module { | |||
134 | }; | 139 | }; |
135 | let module = match curr.resolve(db)? { | 140 | let module = match curr.resolve(db)? { |
136 | Def::Module(it) => it, | 141 | Def::Module(it) => it, |
137 | // TODO here would be the place to handle enum variants... | 142 | Def::Enum(e) => { |
143 | if segments.len() == idx + 1 { | ||
144 | // enum variant | ||
145 | let matching_variant = | ||
146 | e.variants(db)?.into_iter().find(|(n, _variant)| n == name); | ||
147 | |||
148 | if let Some((_n, variant)) = matching_variant { | ||
149 | return Ok(PerNs::both(variant.def_id(), e.def_id())); | ||
150 | } else { | ||
151 | return Ok(PerNs::none()); | ||
152 | } | ||
153 | } else if segments.len() == idx { | ||
154 | // enum | ||
155 | return Ok(PerNs::types(e.def_id())); | ||
156 | } else { | ||
157 | // malformed enum? | ||
158 | return Ok(PerNs::none()); | ||
159 | } | ||
160 | } | ||
138 | _ => return Ok(PerNs::none()), | 161 | _ => return Ok(PerNs::none()), |
139 | }; | 162 | }; |
140 | let scope = module.scope(db)?; | 163 | let scope = module.scope(db)?; |
@@ -146,6 +169,7 @@ impl Module { | |||
146 | } | 169 | } |
147 | Ok(curr_per_ns) | 170 | Ok(curr_per_ns) |
148 | } | 171 | } |
172 | |||
149 | pub fn problems_impl( | 173 | pub fn problems_impl( |
150 | &self, | 174 | &self, |
151 | db: &impl HirDatabase, | 175 | db: &impl HirDatabase, |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 7dbe93f2b..9a6ef8083 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -12,7 +12,7 @@ use crate::{ | |||
12 | module_tree::{ModuleId, ModuleTree}, | 12 | module_tree::{ModuleId, ModuleTree}, |
13 | nameres::{ItemMap, InputModuleItems}, | 13 | nameres::{ItemMap, InputModuleItems}, |
14 | ty::{InferenceResult, Ty}, | 14 | ty::{InferenceResult, Ty}, |
15 | adt::{StructData, EnumData}, | 15 | adt::{StructData, EnumData, EnumVariantData}, |
16 | impl_block::ModuleImplBlocks, | 16 | impl_block::ModuleImplBlocks, |
17 | }; | 17 | }; |
18 | 18 | ||
@@ -47,6 +47,11 @@ pub trait HirDatabase: SyntaxDatabase | |||
47 | use fn crate::adt::EnumData::enum_data_query; | 47 | use fn crate::adt::EnumData::enum_data_query; |
48 | } | 48 | } |
49 | 49 | ||
50 | fn enum_variant_data(def_id: DefId) -> Cancelable<Arc<EnumVariantData>> { | ||
51 | type EnumVariantDataQuery; | ||
52 | use fn crate::adt::EnumVariantData::enum_variant_data_query; | ||
53 | } | ||
54 | |||
50 | fn infer(def_id: DefId) -> Cancelable<Arc<InferenceResult>> { | 55 | fn infer(def_id: DefId) -> Cancelable<Arc<InferenceResult>> { |
51 | type InferQuery; | 56 | type InferQuery; |
52 | use fn crate::ty::infer; | 57 | use fn crate::ty::infer; |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index ebb83d084..e5596cbaa 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -762,7 +762,7 @@ pub(crate) fn body_syntax_mapping( | |||
762 | let def = def_id.resolve(db)?; | 762 | let def = def_id.resolve(db)?; |
763 | 763 | ||
764 | let body_syntax_mapping = match def { | 764 | let body_syntax_mapping = match def { |
765 | Def::Function(f) => collect_fn_body_syntax(&f.source(db)), | 765 | Def::Function(f) => collect_fn_body_syntax(&f.source(db)?.1), |
766 | // TODO: consts, etc. | 766 | // TODO: consts, etc. |
767 | _ => panic!("Trying to get body for item type without body"), | 767 | _ => panic!("Trying to get body for item type without body"), |
768 | }; | 768 | }; |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 0aa687a08..c75ef4ae7 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -3,7 +3,7 @@ use ra_syntax::{TreePtr, SyntaxKind, SyntaxNode, SourceFile, AstNode, ast}; | |||
3 | use ra_arena::{Arena, RawId, impl_arena_id}; | 3 | use ra_arena::{Arena, RawId, impl_arena_id}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | HirDatabase, PerNs, Def, Function, Struct, Enum, ImplBlock, Crate, | 6 | HirDatabase, PerNs, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate, |
7 | module_tree::ModuleId, | 7 | module_tree::ModuleId, |
8 | }; | 8 | }; |
9 | 9 | ||
@@ -34,7 +34,7 @@ pub struct HirFileId(HirFileIdRepr); | |||
34 | impl HirFileId { | 34 | impl HirFileId { |
35 | /// For macro-expansion files, returns the file original source file the | 35 | /// For macro-expansion files, returns the file original source file the |
36 | /// expansionoriginated from. | 36 | /// expansionoriginated from. |
37 | pub(crate) fn original_file(self, db: &impl HirDatabase) -> FileId { | 37 | pub fn original_file(self, db: &impl HirDatabase) -> FileId { |
38 | match self.0 { | 38 | match self.0 { |
39 | HirFileIdRepr::File(file_id) => file_id, | 39 | HirFileIdRepr::File(file_id) => file_id, |
40 | HirFileIdRepr::Macro(macro_call_id) => { | 40 | HirFileIdRepr::Macro(macro_call_id) => { |
@@ -145,6 +145,7 @@ pub(crate) enum DefKind { | |||
145 | Function, | 145 | Function, |
146 | Struct, | 146 | Struct, |
147 | Enum, | 147 | Enum, |
148 | EnumVariant, | ||
148 | Item, | 149 | Item, |
149 | 150 | ||
150 | StructCtor, | 151 | StructCtor, |
@@ -170,16 +171,20 @@ impl DefId { | |||
170 | let struct_def = Struct::new(self); | 171 | let struct_def = Struct::new(self); |
171 | Def::Struct(struct_def) | 172 | Def::Struct(struct_def) |
172 | } | 173 | } |
173 | DefKind::Enum => { | 174 | DefKind::Enum => Def::Enum(Enum::new(self)), |
174 | let enum_def = Enum::new(self); | 175 | DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)), |
175 | Def::Enum(enum_def) | ||
176 | } | ||
177 | DefKind::StructCtor => Def::Item, | 176 | DefKind::StructCtor => Def::Item, |
178 | DefKind::Item => Def::Item, | 177 | DefKind::Item => Def::Item, |
179 | }; | 178 | }; |
180 | Ok(res) | 179 | Ok(res) |
181 | } | 180 | } |
182 | 181 | ||
182 | pub(crate) fn source(self, db: &impl HirDatabase) -> (HirFileId, TreePtr<SyntaxNode>) { | ||
183 | let loc = self.loc(db); | ||
184 | let syntax = db.file_item(loc.source_item_id); | ||
185 | (loc.source_item_id.file_id, syntax) | ||
186 | } | ||
187 | |||
183 | /// For a module, returns that module; for any other def, returns the containing module. | 188 | /// For a module, returns that module; for any other def, returns the containing module. |
184 | pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> { | 189 | pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> { |
185 | let loc = self.loc(db); | 190 | let loc = self.loc(db); |
@@ -258,7 +263,9 @@ impl SourceFileItems { | |||
258 | // change parent's id. This means that, say, adding a new function to a | 263 | // change parent's id. This means that, say, adding a new function to a |
259 | // trait does not chage ids of top-level items, which helps caching. | 264 | // trait does not chage ids of top-level items, which helps caching. |
260 | bfs(source_file.syntax(), |it| { | 265 | bfs(source_file.syntax(), |it| { |
261 | if let Some(module_item) = ast::ModuleItem::cast(it) { | 266 | if let Some(enum_variant) = ast::EnumVariant::cast(it) { |
267 | self.alloc(enum_variant.syntax().to_owned()); | ||
268 | } else if let Some(module_item) = ast::ModuleItem::cast(it) { | ||
262 | self.alloc(module_item.syntax().to_owned()); | 269 | self.alloc(module_item.syntax().to_owned()); |
263 | } else if let Some(macro_call) = ast::MacroCall::cast(it) { | 270 | } else if let Some(macro_call) = ast::MacroCall::cast(it) { |
264 | self.alloc(macro_call.syntax().to_owned()); | 271 | self.alloc(macro_call.syntax().to_owned()); |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index b8246a7d1..1aca2f067 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -58,6 +58,6 @@ pub use self::code_model_api::{ | |||
58 | Crate, CrateDependency, | 58 | Crate, CrateDependency, |
59 | Def, | 59 | Def, |
60 | Module, ModuleSource, Problem, | 60 | Module, ModuleSource, Problem, |
61 | Struct, Enum, | 61 | Struct, Enum, EnumVariant, |
62 | Function, FnSignature, | 62 | Function, FnSignature, |
63 | }; | 63 | }; |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 7a0301648..6f93bb59d 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -233,6 +233,7 @@ salsa::database_storage! { | |||
233 | fn type_for_field() for db::TypeForFieldQuery; | 233 | fn type_for_field() for db::TypeForFieldQuery; |
234 | fn struct_data() for db::StructDataQuery; | 234 | fn struct_data() for db::StructDataQuery; |
235 | fn enum_data() for db::EnumDataQuery; | 235 | fn enum_data() for db::EnumDataQuery; |
236 | fn enum_variant_data() for db::EnumVariantDataQuery; | ||
236 | fn impls_in_module() for db::ImplsInModuleQuery; | 237 | fn impls_in_module() for db::ImplsInModuleQuery; |
237 | fn body_hir() for db::BodyHirQuery; | 238 | fn body_hir() for db::BodyHirQuery; |
238 | fn body_syntax_mapping() for db::BodySyntaxMappingQuery; | 239 | fn body_syntax_mapping() for db::BodySyntaxMappingQuery; |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index eb7764f65..18c41a015 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -30,7 +30,7 @@ use join_to_string::join; | |||
30 | use ra_db::Cancelable; | 30 | use ra_db::Cancelable; |
31 | 31 | ||
32 | use crate::{ | 32 | use crate::{ |
33 | Def, DefId, Module, Function, Struct, Enum, Path, Name, ImplBlock, | 33 | Def, DefId, Module, Function, Struct, Enum, EnumVariant, Path, Name, ImplBlock, |
34 | FnSignature, FnScopes, | 34 | FnSignature, FnScopes, |
35 | db::HirDatabase, | 35 | db::HirDatabase, |
36 | type_ref::{TypeRef, Mutability}, | 36 | type_ref::{TypeRef, Mutability}, |
@@ -453,6 +453,12 @@ pub fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Cancelable<Ty> { | |||
453 | }) | 453 | }) |
454 | } | 454 | } |
455 | 455 | ||
456 | pub fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> Cancelable<Ty> { | ||
457 | let enum_parent = ev.parent_enum(db)?; | ||
458 | |||
459 | type_for_enum(db, enum_parent) | ||
460 | } | ||
461 | |||
456 | pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { | 462 | pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { |
457 | let def = def_id.resolve(db)?; | 463 | let def = def_id.resolve(db)?; |
458 | match def { | 464 | match def { |
@@ -463,6 +469,7 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<T | |||
463 | Def::Function(f) => type_for_fn(db, f), | 469 | Def::Function(f) => type_for_fn(db, f), |
464 | Def::Struct(s) => type_for_struct(db, s), | 470 | Def::Struct(s) => type_for_struct(db, s), |
465 | Def::Enum(e) => type_for_enum(db, e), | 471 | Def::Enum(e) => type_for_enum(db, e), |
472 | Def::EnumVariant(ev) => type_for_enum_variant(db, ev), | ||
466 | Def::Item => { | 473 | Def::Item => { |
467 | log::debug!("trying to get type for item of unknown type {:?}", def_id); | 474 | log::debug!("trying to get type for item of unknown type {:?}", def_id); |
468 | Ok(Ty::Unknown) | 475 | Ok(Ty::Unknown) |
@@ -477,12 +484,9 @@ pub(super) fn type_for_field( | |||
477 | ) -> Cancelable<Option<Ty>> { | 484 | ) -> Cancelable<Option<Ty>> { |
478 | let def = def_id.resolve(db)?; | 485 | let def = def_id.resolve(db)?; |
479 | let variant_data = match def { | 486 | let variant_data = match def { |
480 | Def::Struct(s) => { | 487 | Def::Struct(s) => s.variant_data(db)?, |
481 | let variant_data = s.variant_data(db)?; | 488 | Def::EnumVariant(ev) => ev.variant_data(db)?, |
482 | variant_data | ||
483 | } | ||
484 | // TODO: unions | 489 | // TODO: unions |
485 | // TODO: enum variants | ||
486 | _ => panic!( | 490 | _ => panic!( |
487 | "trying to get type for field in non-struct/variant {:?}", | 491 | "trying to get type for field in non-struct/variant {:?}", |
488 | def_id | 492 | def_id |
@@ -788,6 +792,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
788 | let ty = type_for_struct(self.db, s)?; | 792 | let ty = type_for_struct(self.db, s)?; |
789 | (ty, Some(def_id)) | 793 | (ty, Some(def_id)) |
790 | } | 794 | } |
795 | Def::EnumVariant(ev) => { | ||
796 | let ty = type_for_enum_variant(self.db, ev)?; | ||
797 | (ty, Some(def_id)) | ||
798 | } | ||
791 | _ => (Ty::Unknown, None), | 799 | _ => (Ty::Unknown, None), |
792 | }) | 800 | }) |
793 | } | 801 | } |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index ba2a44474..d8c0af326 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -95,6 +95,22 @@ fn test() { | |||
95 | } | 95 | } |
96 | 96 | ||
97 | #[test] | 97 | #[test] |
98 | fn infer_enum() { | ||
99 | check_inference( | ||
100 | r#" | ||
101 | enum E { | ||
102 | V1 { field: u32 }, | ||
103 | V2 | ||
104 | } | ||
105 | fn test() { | ||
106 | E::V1 { field: 1 }; | ||
107 | E::V2; | ||
108 | }"#, | ||
109 | "enum.txt", | ||
110 | ); | ||
111 | } | ||
112 | |||
113 | #[test] | ||
98 | fn infer_refs() { | 114 | fn infer_refs() { |
99 | check_inference( | 115 | check_inference( |
100 | r#" | 116 | r#" |
diff --git a/crates/ra_hir/src/ty/tests/data/enum.txt b/crates/ra_hir/src/ty/tests/data/enum.txt new file mode 100644 index 000000000..481eb0bc7 --- /dev/null +++ b/crates/ra_hir/src/ty/tests/data/enum.txt | |||
@@ -0,0 +1,4 @@ | |||
1 | [48; 82) '{ E:...:V2; }': () | ||
2 | [52; 70) 'E::V1 ...d: 1 }': E | ||
3 | [67; 68) '1': u32 | ||
4 | [74; 79) 'E::V2': E | ||
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 2494d28ed..a25ad3f13 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -15,20 +15,21 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> C | |||
15 | match def_id.resolve(ctx.db)? { | 15 | match def_id.resolve(ctx.db)? { |
16 | hir::Def::Module(module) => { | 16 | hir::Def::Module(module) => { |
17 | let module_scope = module.scope(ctx.db)?; | 17 | let module_scope = module.scope(ctx.db)?; |
18 | module_scope.entries().for_each(|(name, res)| { | 18 | for (name, res) in module_scope.entries() { |
19 | CompletionItem::new(CompletionKind::Reference, name.to_string()) | 19 | CompletionItem::new(CompletionKind::Reference, name.to_string()) |
20 | .from_resolution(ctx, res) | 20 | .from_resolution(ctx, res) |
21 | .add_to(acc) | 21 | .add_to(acc); |
22 | }); | 22 | } |
23 | } | ||
24 | hir::Def::Enum(e) => { | ||
25 | e.variants(ctx.db)? | ||
26 | .into_iter() | ||
27 | .for_each(|(variant_name, _variant)| { | ||
28 | CompletionItem::new(CompletionKind::Reference, variant_name.to_string()) | ||
29 | .kind(CompletionItemKind::EnumVariant) | ||
30 | .add_to(acc) | ||
31 | }); | ||
23 | } | 32 | } |
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 | }), | ||
32 | _ => return Ok(()), | 33 | _ => return Ok(()), |
33 | }; | 34 | }; |
34 | Ok(()) | 35 | Ok(()) |
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs index a2e06f5db..efdf261be 100644 --- a/crates/ra_ide_api/src/db.rs +++ b/crates/ra_ide_api/src/db.rs | |||
@@ -122,6 +122,7 @@ salsa::database_storage! { | |||
122 | fn type_for_field() for hir::db::TypeForFieldQuery; | 122 | fn type_for_field() for hir::db::TypeForFieldQuery; |
123 | fn struct_data() for hir::db::StructDataQuery; | 123 | fn struct_data() for hir::db::StructDataQuery; |
124 | fn enum_data() for hir::db::EnumDataQuery; | 124 | fn enum_data() for hir::db::EnumDataQuery; |
125 | fn enum_variant_data() for hir::db::EnumVariantDataQuery; | ||
125 | fn impls_in_module() for hir::db::ImplsInModuleQuery; | 126 | fn impls_in_module() for hir::db::ImplsInModuleQuery; |
126 | fn body_hir() for hir::db::BodyHirQuery; | 127 | fn body_hir() for hir::db::BodyHirQuery; |
127 | fn body_syntax_mapping() for hir::db::BodySyntaxMappingQuery; | 128 | fn body_syntax_mapping() for hir::db::BodySyntaxMappingQuery; |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 0d524b6f1..eaddd5083 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -42,6 +42,24 @@ pub(crate) fn reference_definition( | |||
42 | return Ok(vec![nav]); | 42 | return Ok(vec![nav]); |
43 | }; | 43 | }; |
44 | } | 44 | } |
45 | // Then try module name resolution | ||
46 | if let Some(module) = | ||
47 | hir::source_binder::module_from_child_node(db, file_id, name_ref.syntax())? | ||
48 | { | ||
49 | if let Some(path) = name_ref | ||
50 | .syntax() | ||
51 | .ancestors() | ||
52 | .find_map(ast::Path::cast) | ||
53 | .and_then(hir::Path::from_ast) | ||
54 | { | ||
55 | let resolved = module.resolve_path(db, &path)?; | ||
56 | if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { | ||
57 | if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)?)? { | ||
58 | return Ok(vec![target]); | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | } | ||
45 | // If that fails try the index based approach. | 63 | // If that fails try the index based approach. |
46 | let navs = db | 64 | let navs = db |
47 | .index_resolve(name_ref)? | 65 | .index_resolve(name_ref)? |
@@ -105,6 +123,31 @@ mod tests { | |||
105 | } | 123 | } |
106 | 124 | ||
107 | #[test] | 125 | #[test] |
126 | fn goto_definition_resolves_correct_name() { | ||
127 | let (analysis, pos) = analysis_and_position( | ||
128 | " | ||
129 | //- /lib.rs | ||
130 | use a::Foo; | ||
131 | mod a; | ||
132 | mod b; | ||
133 | enum E { X(Foo<|>) } | ||
134 | //- /a.rs | ||
135 | struct Foo; | ||
136 | //- /b.rs | ||
137 | struct Foo; | ||
138 | ", | ||
139 | ); | ||
140 | |||
141 | let symbols = analysis.goto_definition(pos).unwrap().unwrap(); | ||
142 | assert_eq_dbg( | ||
143 | r#"[NavigationTarget { file_id: FileId(2), name: "Foo", | ||
144 | kind: STRUCT_DEF, range: [0; 11), | ||
145 | ptr: Some(LocalSyntaxPtr { range: [0; 11), kind: STRUCT_DEF }) }]"#, | ||
146 | &symbols, | ||
147 | ); | ||
148 | } | ||
149 | |||
150 | #[test] | ||
108 | fn goto_definition_works_for_module_declaration() { | 151 | fn goto_definition_works_for_module_declaration() { |
109 | let (analysis, pos) = analysis_and_position( | 152 | let (analysis, pos) = analysis_and_position( |
110 | " | 153 | " |
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index f505959ce..65d21d899 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -33,7 +33,8 @@ mod syntax_highlighting; | |||
33 | 33 | ||
34 | use std::{fmt, sync::Arc}; | 34 | use std::{fmt, sync::Arc}; |
35 | 35 | ||
36 | use ra_syntax::{SmolStr, SourceFile, TreePtr, SyntaxKind, TextRange, TextUnit}; | 36 | use hir::{Def, ModuleSource, Name}; |
37 | use ra_syntax::{SmolStr, SourceFile, TreePtr, SyntaxKind, SyntaxNode, TextRange, TextUnit, AstNode}; | ||
37 | use ra_text_edit::TextEdit; | 38 | use ra_text_edit::TextEdit; |
38 | use ra_db::{SyntaxDatabase, FilesDatabase, LocalSyntaxPtr, BaseDatabase}; | 39 | use ra_db::{SyntaxDatabase, FilesDatabase, LocalSyntaxPtr, BaseDatabase}; |
39 | use rayon::prelude::*; | 40 | use rayon::prelude::*; |
@@ -268,6 +269,67 @@ impl NavigationTarget { | |||
268 | } | 269 | } |
269 | } | 270 | } |
270 | 271 | ||
272 | fn from_syntax(name: Option<Name>, file_id: FileId, node: &SyntaxNode) -> NavigationTarget { | ||
273 | NavigationTarget { | ||
274 | file_id, | ||
275 | name: name.map(|n| n.to_string().into()).unwrap_or("".into()), | ||
276 | kind: node.kind(), | ||
277 | range: node.range(), | ||
278 | ptr: Some(LocalSyntaxPtr::new(node)), | ||
279 | } | ||
280 | } | ||
281 | // TODO once Def::Item is gone, this should be able to always return a NavigationTarget | ||
282 | fn from_def(db: &db::RootDatabase, def: Def) -> Cancelable<Option<NavigationTarget>> { | ||
283 | Ok(match def { | ||
284 | Def::Struct(s) => { | ||
285 | let (file_id, node) = s.source(db)?; | ||
286 | Some(NavigationTarget::from_syntax( | ||
287 | s.name(db)?, | ||
288 | file_id.original_file(db), | ||
289 | node.syntax(), | ||
290 | )) | ||
291 | } | ||
292 | Def::Enum(e) => { | ||
293 | let (file_id, node) = e.source(db)?; | ||
294 | Some(NavigationTarget::from_syntax( | ||
295 | e.name(db)?, | ||
296 | file_id.original_file(db), | ||
297 | node.syntax(), | ||
298 | )) | ||
299 | } | ||
300 | Def::EnumVariant(ev) => { | ||
301 | let (file_id, node) = ev.source(db)?; | ||
302 | Some(NavigationTarget::from_syntax( | ||
303 | ev.name(db)?, | ||
304 | file_id.original_file(db), | ||
305 | node.syntax(), | ||
306 | )) | ||
307 | } | ||
308 | Def::Function(f) => { | ||
309 | let (file_id, node) = f.source(db)?; | ||
310 | let name = f.signature(db).name().clone(); | ||
311 | Some(NavigationTarget::from_syntax( | ||
312 | Some(name), | ||
313 | file_id.original_file(db), | ||
314 | node.syntax(), | ||
315 | )) | ||
316 | } | ||
317 | Def::Module(m) => { | ||
318 | let (file_id, source) = m.definition_source(db)?; | ||
319 | let name = m.name(db)?; | ||
320 | match source { | ||
321 | ModuleSource::SourceFile(node) => { | ||
322 | Some(NavigationTarget::from_syntax(name, file_id, node.syntax())) | ||
323 | } | ||
324 | ModuleSource::Module(node) => { | ||
325 | Some(NavigationTarget::from_syntax(name, file_id, node.syntax())) | ||
326 | } | ||
327 | } | ||
328 | } | ||
329 | Def::Item => None, | ||
330 | }) | ||
331 | } | ||
332 | |||
271 | pub fn name(&self) -> &SmolStr { | 333 | pub fn name(&self) -> &SmolStr { |
272 | &self.name | 334 | &self.name |
273 | } | 335 | } |