diff options
Diffstat (limited to 'crates/ra_ide_api/src/name_kind.rs')
-rw-r--r-- | crates/ra_ide_api/src/name_kind.rs | 83 |
1 files changed, 43 insertions, 40 deletions
diff --git a/crates/ra_ide_api/src/name_kind.rs b/crates/ra_ide_api/src/name_kind.rs index 6d1eb153f..8eef540f6 100644 --- a/crates/ra_ide_api/src/name_kind.rs +++ b/crates/ra_ide_api/src/name_kind.rs | |||
@@ -10,6 +10,7 @@ use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr}; | |||
10 | 10 | ||
11 | use crate::db::RootDatabase; | 11 | use crate::db::RootDatabase; |
12 | 12 | ||
13 | #[derive(PartialEq, Eq)] | ||
13 | pub enum NameKind { | 14 | pub enum NameKind { |
14 | Macro(MacroDef), | 15 | Macro(MacroDef), |
15 | FieldAccess(StructField), | 16 | FieldAccess(StructField), |
@@ -21,23 +22,24 @@ pub enum NameKind { | |||
21 | GenericParam(u32), | 22 | GenericParam(u32), |
22 | } | 23 | } |
23 | 24 | ||
24 | pub(crate) struct Declaration { | 25 | #[derive(PartialEq, Eq)] |
26 | pub(crate) struct Definition { | ||
25 | pub visibility: Option<ast::Visibility>, | 27 | pub visibility: Option<ast::Visibility>, |
26 | pub container: Module, | 28 | pub container: Module, |
27 | pub item: NameKind, | 29 | pub item: NameKind, |
28 | } | 30 | } |
29 | 31 | ||
30 | trait HasDeclaration { | 32 | trait HasDefinition { |
31 | type Def; | 33 | type Def; |
32 | type Ref; | 34 | type Ref; |
33 | 35 | ||
34 | fn declaration(self, db: &RootDatabase) -> Declaration; | 36 | fn definition(self, db: &RootDatabase) -> Definition; |
35 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Declaration>; | 37 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition>; |
36 | fn from_ref( | 38 | fn from_ref( |
37 | db: &RootDatabase, | 39 | db: &RootDatabase, |
38 | analyzer: &SourceAnalyzer, | 40 | analyzer: &SourceAnalyzer, |
39 | refer: Self::Ref, | 41 | refer: Self::Ref, |
40 | ) -> Option<Declaration>; | 42 | ) -> Option<Definition>; |
41 | } | 43 | } |
42 | 44 | ||
43 | macro_rules! match_ast { | 45 | macro_rules! match_ast { |
@@ -55,7 +57,7 @@ pub(crate) fn classify_name_ref( | |||
55 | file_id: FileId, | 57 | file_id: FileId, |
56 | analyzer: &SourceAnalyzer, | 58 | analyzer: &SourceAnalyzer, |
57 | name_ref: &ast::NameRef, | 59 | name_ref: &ast::NameRef, |
58 | ) -> Option<Declaration> { | 60 | ) -> Option<Definition> { |
59 | let parent = name_ref.syntax().parent()?; | 61 | let parent = name_ref.syntax().parent()?; |
60 | match_ast! { | 62 | match_ast! { |
61 | match parent { | 63 | match parent { |
@@ -64,7 +66,7 @@ pub(crate) fn classify_name_ref( | |||
64 | }, | 66 | }, |
65 | ast::FieldExpr(it) => { | 67 | ast::FieldExpr(it) => { |
66 | if let Some(field) = analyzer.resolve_field(&it) { | 68 | if let Some(field) = analyzer.resolve_field(&it) { |
67 | return Some(field.declaration(db)); | 69 | return Some(field.definition(db)); |
68 | } | 70 | } |
69 | }, | 71 | }, |
70 | ast::RecordField(it) => { | 72 | ast::RecordField(it) => { |
@@ -73,7 +75,7 @@ pub(crate) fn classify_name_ref( | |||
73 | let hir_path = Path::from_name_ref(name_ref); | 75 | let hir_path = Path::from_name_ref(name_ref); |
74 | let hir_name = hir_path.as_ident()?; | 76 | let hir_name = hir_path.as_ident()?; |
75 | let field = variant_def.field(db, hir_name)?; | 77 | let field = variant_def.field(db, hir_name)?; |
76 | return Some(field.declaration(db)); | 78 | return Some(field.definition(db)); |
77 | } | 79 | } |
78 | }, | 80 | }, |
79 | _ => (), | 81 | _ => (), |
@@ -83,12 +85,13 @@ pub(crate) fn classify_name_ref( | |||
83 | let ast = ModuleSource::from_child_node(db, file_id, &parent); | 85 | let ast = ModuleSource::from_child_node(db, file_id, &parent); |
84 | let file_id = file_id.into(); | 86 | let file_id = file_id.into(); |
85 | let container = Module::from_definition(db, Source { file_id, ast })?; | 87 | let container = Module::from_definition(db, Source { file_id, ast })?; |
88 | let visibility = None; | ||
86 | 89 | ||
87 | if let Some(macro_call) = | 90 | if let Some(macro_call) = |
88 | parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) | 91 | parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) |
89 | { | 92 | { |
90 | if let Some(mac) = analyzer.resolve_macro_call(db, ¯o_call) { | 93 | if let Some(mac) = analyzer.resolve_macro_call(db, ¯o_call) { |
91 | return Some(Declaration { item: NameKind::Macro(mac), container, visibility: None }); | 94 | return Some(Definition { item: NameKind::Macro(mac), container, visibility }); |
92 | } | 95 | } |
93 | } | 96 | } |
94 | 97 | ||
@@ -96,24 +99,24 @@ pub(crate) fn classify_name_ref( | |||
96 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | 99 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; |
97 | let resolved = analyzer.resolve_path(db, &path)?; | 100 | let resolved = analyzer.resolve_path(db, &path)?; |
98 | match resolved { | 101 | match resolved { |
99 | PathResolution::Def(def) => Some(def.declaration(db)), | 102 | PathResolution::Def(def) => Some(def.definition(db)), |
100 | PathResolution::LocalBinding(Either::A(pat)) => decl_from_pat(db, file_id, pat), | 103 | PathResolution::LocalBinding(Either::A(pat)) => decl_from_pat(db, file_id, pat), |
101 | PathResolution::LocalBinding(Either::B(par)) => { | 104 | PathResolution::LocalBinding(Either::B(par)) => { |
102 | Some(Declaration { item: NameKind::SelfParam(par), container, visibility: None }) | 105 | Some(Definition { item: NameKind::SelfParam(par), container, visibility }) |
103 | } | 106 | } |
104 | PathResolution::GenericParam(par) => { | 107 | PathResolution::GenericParam(par) => { |
105 | // FIXME: get generic param def | 108 | // FIXME: get generic param def |
106 | Some(Declaration { item: NameKind::GenericParam(par), container, visibility: None }) | 109 | Some(Definition { item: NameKind::GenericParam(par), container, visibility }) |
107 | } | 110 | } |
108 | PathResolution::Macro(def) => { | 111 | PathResolution::Macro(def) => { |
109 | Some(Declaration { item: NameKind::Macro(def), container, visibility: None }) | 112 | Some(Definition { item: NameKind::Macro(def), container, visibility }) |
110 | } | 113 | } |
111 | PathResolution::SelfType(impl_block) => { | 114 | PathResolution::SelfType(impl_block) => { |
112 | let ty = impl_block.target_ty(db); | 115 | let ty = impl_block.target_ty(db); |
113 | let container = impl_block.module(); | 116 | let container = impl_block.module(); |
114 | Some(Declaration { item: NameKind::SelfType(ty), container, visibility: None }) | 117 | Some(Definition { item: NameKind::SelfType(ty), container, visibility }) |
115 | } | 118 | } |
116 | PathResolution::AssocItem(assoc) => Some(assoc.declaration(db)), | 119 | PathResolution::AssocItem(assoc) => Some(assoc.definition(db)), |
117 | } | 120 | } |
118 | } | 121 | } |
119 | 122 | ||
@@ -121,7 +124,7 @@ pub(crate) fn classify_name( | |||
121 | db: &RootDatabase, | 124 | db: &RootDatabase, |
122 | file_id: FileId, | 125 | file_id: FileId, |
123 | name: &ast::Name, | 126 | name: &ast::Name, |
124 | ) -> Option<Declaration> { | 127 | ) -> Option<Definition> { |
125 | let parent = name.syntax().parent()?; | 128 | let parent = name.syntax().parent()?; |
126 | let file_id = file_id.into(); | 129 | let file_id = file_id.into(); |
127 | 130 | ||
@@ -145,7 +148,7 @@ pub(crate) fn classify_name( | |||
145 | ast::EnumVariant(it) => { | 148 | ast::EnumVariant(it) => { |
146 | let src = hir::Source { file_id, ast: it.clone() }; | 149 | let src = hir::Source { file_id, ast: it.clone() }; |
147 | let def: ModuleDef = EnumVariant::from_source(db, src)?.into(); | 150 | let def: ModuleDef = EnumVariant::from_source(db, src)?.into(); |
148 | Some(def.declaration(db)) | 151 | Some(def.definition(db)) |
149 | }, | 152 | }, |
150 | ast::ModuleItem(it) => { | 153 | ast::ModuleItem(it) => { |
151 | ModuleDef::from_def(db, file_id, it) | 154 | ModuleDef::from_def(db, file_id, it) |
@@ -159,7 +162,7 @@ fn decl_from_pat( | |||
159 | db: &RootDatabase, | 162 | db: &RootDatabase, |
160 | file_id: HirFileId, | 163 | file_id: HirFileId, |
161 | pat: AstPtr<ast::BindPat>, | 164 | pat: AstPtr<ast::BindPat>, |
162 | ) -> Option<Declaration> { | 165 | ) -> Option<Definition> { |
163 | let root = db.parse_or_expand(file_id)?; | 166 | let root = db.parse_or_expand(file_id)?; |
164 | // FIXME: use match_ast! | 167 | // FIXME: use match_ast! |
165 | let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { | 168 | let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { |
@@ -178,14 +181,14 @@ fn decl_from_pat( | |||
178 | })?; | 181 | })?; |
179 | let item = NameKind::Pat((def, pat)); | 182 | let item = NameKind::Pat((def, pat)); |
180 | let container = def.module(db); | 183 | let container = def.module(db); |
181 | Some(Declaration { item, container, visibility: None }) | 184 | Some(Definition { item, container, visibility: None }) |
182 | } | 185 | } |
183 | 186 | ||
184 | impl HasDeclaration for StructField { | 187 | impl HasDefinition for StructField { |
185 | type Def = ast::RecordFieldDef; | 188 | type Def = ast::RecordFieldDef; |
186 | type Ref = ast::FieldExpr; | 189 | type Ref = ast::FieldExpr; |
187 | 190 | ||
188 | fn declaration(self, db: &RootDatabase) -> Declaration { | 191 | fn definition(self, db: &RootDatabase) -> Definition { |
189 | let item = NameKind::FieldAccess(self); | 192 | let item = NameKind::FieldAccess(self); |
190 | let parent = self.parent_def(db); | 193 | let parent = self.parent_def(db); |
191 | let container = parent.module(db); | 194 | let container = parent.module(db); |
@@ -193,30 +196,30 @@ impl HasDeclaration for StructField { | |||
193 | VariantDef::Struct(s) => s.source(db).ast.visibility(), | 196 | VariantDef::Struct(s) => s.source(db).ast.visibility(), |
194 | VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), | 197 | VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), |
195 | }; | 198 | }; |
196 | Declaration { item, container, visibility } | 199 | Definition { item, container, visibility } |
197 | } | 200 | } |
198 | 201 | ||
199 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Declaration> { | 202 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> { |
200 | let src = hir::Source { file_id, ast: hir::FieldSource::Named(def) }; | 203 | let src = hir::Source { file_id, ast: hir::FieldSource::Named(def) }; |
201 | let field = StructField::from_source(db, src)?; | 204 | let field = StructField::from_source(db, src)?; |
202 | Some(field.declaration(db)) | 205 | Some(field.definition(db)) |
203 | } | 206 | } |
204 | 207 | ||
205 | fn from_ref( | 208 | fn from_ref( |
206 | db: &RootDatabase, | 209 | db: &RootDatabase, |
207 | analyzer: &SourceAnalyzer, | 210 | analyzer: &SourceAnalyzer, |
208 | refer: Self::Ref, | 211 | refer: Self::Ref, |
209 | ) -> Option<Declaration> { | 212 | ) -> Option<Definition> { |
210 | let field = analyzer.resolve_field(&refer)?; | 213 | let field = analyzer.resolve_field(&refer)?; |
211 | Some(field.declaration(db)) | 214 | Some(field.definition(db)) |
212 | } | 215 | } |
213 | } | 216 | } |
214 | 217 | ||
215 | impl HasDeclaration for AssocItem { | 218 | impl HasDefinition for AssocItem { |
216 | type Def = ast::ImplItem; | 219 | type Def = ast::ImplItem; |
217 | type Ref = ast::MethodCallExpr; | 220 | type Ref = ast::MethodCallExpr; |
218 | 221 | ||
219 | fn declaration(self, db: &RootDatabase) -> Declaration { | 222 | fn definition(self, db: &RootDatabase) -> Definition { |
220 | let item = NameKind::AssocItem(self); | 223 | let item = NameKind::AssocItem(self); |
221 | let container = self.module(db); | 224 | let container = self.module(db); |
222 | let visibility = match self { | 225 | let visibility = match self { |
@@ -224,30 +227,30 @@ impl HasDeclaration for AssocItem { | |||
224 | AssocItem::Const(c) => c.source(db).ast.visibility(), | 227 | AssocItem::Const(c) => c.source(db).ast.visibility(), |
225 | AssocItem::TypeAlias(a) => a.source(db).ast.visibility(), | 228 | AssocItem::TypeAlias(a) => a.source(db).ast.visibility(), |
226 | }; | 229 | }; |
227 | Declaration { item, container, visibility } | 230 | Definition { item, container, visibility } |
228 | } | 231 | } |
229 | 232 | ||
230 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Declaration> { | 233 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> { |
231 | let src = hir::Source { file_id, ast: def }; | 234 | let src = hir::Source { file_id, ast: def }; |
232 | let item = AssocItem::from_source(db, src)?; | 235 | let item = AssocItem::from_source(db, src)?; |
233 | Some(item.declaration(db)) | 236 | Some(item.definition(db)) |
234 | } | 237 | } |
235 | 238 | ||
236 | fn from_ref( | 239 | fn from_ref( |
237 | db: &RootDatabase, | 240 | db: &RootDatabase, |
238 | analyzer: &SourceAnalyzer, | 241 | analyzer: &SourceAnalyzer, |
239 | refer: Self::Ref, | 242 | refer: Self::Ref, |
240 | ) -> Option<Declaration> { | 243 | ) -> Option<Definition> { |
241 | let func: AssocItem = analyzer.resolve_method_call(&refer)?.into(); | 244 | let func: AssocItem = analyzer.resolve_method_call(&refer)?.into(); |
242 | Some(func.declaration(db)) | 245 | Some(func.definition(db)) |
243 | } | 246 | } |
244 | } | 247 | } |
245 | 248 | ||
246 | impl HasDeclaration for ModuleDef { | 249 | impl HasDefinition for ModuleDef { |
247 | type Def = ast::ModuleItem; | 250 | type Def = ast::ModuleItem; |
248 | type Ref = ast::Path; | 251 | type Ref = ast::Path; |
249 | 252 | ||
250 | fn declaration(self, db: &RootDatabase) -> Declaration { | 253 | fn definition(self, db: &RootDatabase) -> Definition { |
251 | let (container, visibility) = match self { | 254 | let (container, visibility) = match self { |
252 | ModuleDef::Module(it) => { | 255 | ModuleDef::Module(it) => { |
253 | let container = it.parent(db).or_else(|| Some(it)).unwrap(); | 256 | let container = it.parent(db).or_else(|| Some(it)).unwrap(); |
@@ -270,22 +273,22 @@ impl HasDeclaration for ModuleDef { | |||
270 | ModuleDef::BuiltinType(..) => unreachable!(), | 273 | ModuleDef::BuiltinType(..) => unreachable!(), |
271 | }; | 274 | }; |
272 | let item = NameKind::Def(self); | 275 | let item = NameKind::Def(self); |
273 | Declaration { item, container, visibility } | 276 | Definition { item, container, visibility } |
274 | } | 277 | } |
275 | 278 | ||
276 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Declaration> { | 279 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> { |
277 | let src = hir::Source { file_id, ast: def }; | 280 | let src = hir::Source { file_id, ast: def }; |
278 | let def = ModuleDef::from_source(db, src)?; | 281 | let def = ModuleDef::from_source(db, src)?; |
279 | Some(def.declaration(db)) | 282 | Some(def.definition(db)) |
280 | } | 283 | } |
281 | 284 | ||
282 | fn from_ref( | 285 | fn from_ref( |
283 | db: &RootDatabase, | 286 | db: &RootDatabase, |
284 | analyzer: &SourceAnalyzer, | 287 | analyzer: &SourceAnalyzer, |
285 | refer: Self::Ref, | 288 | refer: Self::Ref, |
286 | ) -> Option<Declaration> { | 289 | ) -> Option<Definition> { |
287 | None | 290 | None |
288 | } | 291 | } |
289 | } | 292 | } |
290 | 293 | ||
291 | // FIXME: impl HasDeclaration for hir::MacroDef | 294 | // FIXME: impl HasDefinition for hir::MacroDef |