diff options
author | Ekaterina Babshukova <[email protected]> | 2019-10-12 18:30:53 +0100 |
---|---|---|
committer | Ekaterina Babshukova <[email protected]> | 2019-10-22 21:47:31 +0100 |
commit | 835173d065dbe1fdd7369ea49336c0b785be8cb8 (patch) | |
tree | e19916b78f4fff145ec59b790c626e2a9f538bbb /crates/ra_ide_api/src/references | |
parent | d26d0ada50fd0063c03e28bc2673f9f63fd23d95 (diff) |
replace trait by a bunch of functions
Diffstat (limited to 'crates/ra_ide_api/src/references')
-rw-r--r-- | crates/ra_ide_api/src/references/classify.rs | 196 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/definition.rs | 177 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/name_definition.rs | 104 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/search_scope.rs | 4 |
4 files changed, 217 insertions, 264 deletions
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 0b604a5cf..2ba1cf71c 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs | |||
@@ -1,47 +1,90 @@ | |||
1 | use hir::{ | 1 | use hir::{Either, FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; |
2 | AssocItem, Either, EnumVariant, FromSource, Module, ModuleDef, ModuleSource, Path, | ||
3 | PathResolution, Source, SourceAnalyzer, StructField, | ||
4 | }; | ||
5 | use ra_db::FileId; | 2 | use ra_db::FileId; |
6 | use ra_syntax::{ast, match_ast, AstNode, AstPtr}; | 3 | use ra_syntax::{ast, match_ast, AstNode, AstPtr}; |
7 | 4 | ||
8 | use super::{definition::HasDefinition, Definition, NameKind}; | 5 | use super::{ |
6 | name_definition::{from_assoc_item, from_module_def, from_pat, from_struct_field}, | ||
7 | NameDefinition, NameKind, | ||
8 | }; | ||
9 | use crate::db::RootDatabase; | 9 | use crate::db::RootDatabase; |
10 | 10 | ||
11 | use hir::{db::AstDatabase, HirFileId}; | ||
12 | |||
13 | pub(crate) fn classify_name( | 11 | pub(crate) fn classify_name( |
14 | db: &RootDatabase, | 12 | db: &RootDatabase, |
15 | file_id: FileId, | 13 | file_id: FileId, |
16 | name: &ast::Name, | 14 | name: &ast::Name, |
17 | ) -> Option<Definition> { | 15 | ) -> Option<NameDefinition> { |
18 | let parent = name.syntax().parent()?; | 16 | let parent = name.syntax().parent()?; |
19 | let file_id = file_id.into(); | 17 | let file_id = file_id.into(); |
20 | 18 | ||
19 | // FIXME: add ast::MacroCall(it) | ||
21 | match_ast! { | 20 | match_ast! { |
22 | match parent { | 21 | match parent { |
23 | ast::BindPat(it) => { | 22 | ast::BindPat(it) => { |
24 | decl_from_pat(db, file_id, AstPtr::new(&it)) | 23 | from_pat(db, file_id, AstPtr::new(&it)) |
25 | }, | 24 | }, |
26 | ast::RecordFieldDef(it) => { | 25 | ast::RecordFieldDef(it) => { |
27 | StructField::from_def(db, file_id, it) | 26 | let ast = hir::FieldSource::Named(it); |
27 | let src = hir::Source { file_id, ast }; | ||
28 | let field = hir::StructField::from_source(db, src)?; | ||
29 | Some(from_struct_field(db, field)) | ||
30 | }, | ||
31 | ast::Module(it) => { | ||
32 | let ast = hir::ModuleSource::Module(it); | ||
33 | let src = hir::Source { file_id, ast }; | ||
34 | let def = hir::Module::from_definition(db, src)?; | ||
35 | Some(from_module_def(db, def.into())) | ||
28 | }, | 36 | }, |
29 | ast::ImplItem(it) => { | 37 | ast::StructDef(it) => { |
30 | AssocItem::from_def(db, file_id, it.clone()).or_else(|| { | 38 | let src = hir::Source { file_id, ast: it }; |
31 | match it { | 39 | let def = hir::Struct::from_source(db, src)?; |
32 | ast::ImplItem::FnDef(f) => ModuleDef::from_def(db, file_id, f.into()), | 40 | Some(from_module_def(db, def.into())) |
33 | ast::ImplItem::ConstDef(c) => ModuleDef::from_def(db, file_id, c.into()), | 41 | }, |
34 | ast::ImplItem::TypeAliasDef(a) => ModuleDef::from_def(db, file_id, a.into()), | 42 | ast::EnumDef(it) => { |
35 | } | 43 | let src = hir::Source { file_id, ast: it }; |
36 | }) | 44 | let def = hir::Enum::from_source(db, src)?; |
45 | Some(from_module_def(db, def.into())) | ||
46 | }, | ||
47 | ast::TraitDef(it) => { | ||
48 | let src = hir::Source { file_id, ast: it }; | ||
49 | let def = hir::Trait::from_source(db, src)?; | ||
50 | Some(from_module_def(db, def.into())) | ||
51 | }, | ||
52 | ast::StaticDef(it) => { | ||
53 | let src = hir::Source { file_id, ast: it }; | ||
54 | let def = hir::Static::from_source(db, src)?; | ||
55 | Some(from_module_def(db, def.into())) | ||
37 | }, | 56 | }, |
38 | ast::EnumVariant(it) => { | 57 | ast::EnumVariant(it) => { |
39 | let src = hir::Source { file_id, ast: it.clone() }; | 58 | let src = hir::Source { file_id, ast: it }; |
40 | let def: ModuleDef = EnumVariant::from_source(db, src)?.into(); | 59 | let def = hir::EnumVariant::from_source(db, src)?; |
41 | Some(def.definition(db)) | 60 | Some(from_module_def(db, def.into())) |
61 | }, | ||
62 | ast::FnDef(it) => { | ||
63 | let src = hir::Source { file_id, ast: it }; | ||
64 | let def = hir::Function::from_source(db, src)?; | ||
65 | if parent.parent().and_then(ast::ItemList::cast).is_some() { | ||
66 | Some(from_assoc_item(db, def.into())) | ||
67 | } else { | ||
68 | Some(from_module_def(db, def.into())) | ||
69 | } | ||
70 | }, | ||
71 | ast::ConstDef(it) => { | ||
72 | let src = hir::Source { file_id, ast: it }; | ||
73 | let def = hir::Const::from_source(db, src)?; | ||
74 | if parent.parent().and_then(ast::ItemList::cast).is_some() { | ||
75 | Some(from_assoc_item(db, def.into())) | ||
76 | } else { | ||
77 | Some(from_module_def(db, def.into())) | ||
78 | } | ||
42 | }, | 79 | }, |
43 | ast::ModuleItem(it) => { | 80 | ast::TypeAliasDef(it) => { |
44 | ModuleDef::from_def(db, file_id, it) | 81 | let src = hir::Source { file_id, ast: it }; |
82 | let def = hir::TypeAlias::from_source(db, src)?; | ||
83 | if parent.parent().and_then(ast::ItemList::cast).is_some() { | ||
84 | Some(from_assoc_item(db, def.into())) | ||
85 | } else { | ||
86 | Some(from_module_def(db, def.into())) | ||
87 | } | ||
45 | }, | 88 | }, |
46 | _ => None, | 89 | _ => None, |
47 | } | 90 | } |
@@ -52,92 +95,75 @@ pub(crate) fn classify_name_ref( | |||
52 | db: &RootDatabase, | 95 | db: &RootDatabase, |
53 | file_id: FileId, | 96 | file_id: FileId, |
54 | name_ref: &ast::NameRef, | 97 | name_ref: &ast::NameRef, |
55 | ) -> Option<Definition> { | 98 | ) -> Option<NameDefinition> { |
56 | let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); | 99 | use PathResolution::*; |
100 | |||
57 | let parent = name_ref.syntax().parent()?; | 101 | let parent = name_ref.syntax().parent()?; |
58 | match_ast! { | 102 | let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); |
59 | match parent { | 103 | |
60 | ast::MethodCallExpr(it) => { | 104 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
61 | return AssocItem::from_ref(db, &analyzer, it); | 105 | let func = analyzer.resolve_method_call(&method_call)?; |
62 | }, | 106 | return Some(from_assoc_item(db, func.into())); |
63 | ast::FieldExpr(it) => { | 107 | } |
64 | if let Some(field) = analyzer.resolve_field(&it) { | 108 | |
65 | return Some(field.definition(db)); | 109 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
66 | } | 110 | if let Some(field) = analyzer.resolve_field(&field_expr) { |
67 | }, | 111 | return Some(from_struct_field(db, field)); |
68 | ast::RecordField(it) => { | 112 | } |
69 | if let Some(record_lit) = it.syntax().ancestors().find_map(ast::RecordLit::cast) { | 113 | } |
70 | let variant_def = analyzer.resolve_record_literal(&record_lit)?; | 114 | |
71 | let hir_path = Path::from_name_ref(name_ref); | 115 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { |
72 | let hir_name = hir_path.as_ident()?; | 116 | if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) { |
73 | let field = variant_def.field(db, hir_name)?; | 117 | let variant_def = analyzer.resolve_record_literal(&record_lit)?; |
74 | return Some(field.definition(db)); | 118 | let hir_path = Path::from_name_ref(name_ref); |
75 | } | 119 | let hir_name = hir_path.as_ident()?; |
76 | }, | 120 | let field = variant_def.field(db, hir_name)?; |
77 | _ => (), | 121 | return Some(from_struct_field(db, field)); |
78 | } | 122 | } |
79 | } | 123 | } |
80 | 124 | ||
81 | let ast = ModuleSource::from_child_node(db, file_id, &parent); | 125 | let ast = ModuleSource::from_child_node(db, file_id, &parent); |
82 | let file_id = file_id.into(); | 126 | let file_id = file_id.into(); |
127 | // FIXME: find correct container and visibility for each case | ||
83 | let container = Module::from_definition(db, Source { file_id, ast })?; | 128 | let container = Module::from_definition(db, Source { file_id, ast })?; |
84 | let visibility = None; | 129 | let visibility = None; |
85 | 130 | ||
86 | if let Some(macro_call) = | 131 | if let Some(macro_call) = |
87 | parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) | 132 | parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) |
88 | { | 133 | { |
89 | if let Some(mac) = analyzer.resolve_macro_call(db, ¯o_call) { | 134 | if let Some(macro_def) = analyzer.resolve_macro_call(db, ¯o_call) { |
90 | return Some(Definition { item: NameKind::Macro(mac), container, visibility }); | 135 | return Some(NameDefinition { |
136 | item: NameKind::Macro(macro_def), | ||
137 | container, | ||
138 | visibility, | ||
139 | }); | ||
91 | } | 140 | } |
92 | } | 141 | } |
93 | 142 | ||
94 | // General case, a path or a local: | ||
95 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | 143 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; |
96 | let resolved = analyzer.resolve_path(db, &path)?; | 144 | let resolved = analyzer.resolve_path(db, &path)?; |
97 | match resolved { | 145 | match resolved { |
98 | PathResolution::Def(def) => Some(def.definition(db)), | 146 | Def(def) => Some(from_module_def(db, def)), |
99 | PathResolution::LocalBinding(Either::A(pat)) => decl_from_pat(db, file_id, pat), | 147 | AssocItem(item) => Some(from_assoc_item(db, item)), |
100 | PathResolution::LocalBinding(Either::B(par)) => { | 148 | LocalBinding(Either::A(pat)) => from_pat(db, file_id, pat), |
101 | Some(Definition { item: NameKind::SelfParam(par), container, visibility }) | 149 | LocalBinding(Either::B(par)) => { |
150 | let item = NameKind::SelfParam(par); | ||
151 | Some(NameDefinition { item, container, visibility }) | ||
102 | } | 152 | } |
103 | PathResolution::GenericParam(par) => { | 153 | GenericParam(par) => { |
104 | // FIXME: get generic param def | 154 | // FIXME: get generic param def |
105 | Some(Definition { item: NameKind::GenericParam(par), container, visibility }) | 155 | let item = NameKind::GenericParam(par); |
156 | Some(NameDefinition { item, container, visibility }) | ||
106 | } | 157 | } |
107 | PathResolution::Macro(def) => { | 158 | Macro(def) => { |
108 | Some(Definition { item: NameKind::Macro(def), container, visibility }) | 159 | let item = NameKind::Macro(def); |
160 | Some(NameDefinition { item, container, visibility }) | ||
109 | } | 161 | } |
110 | PathResolution::SelfType(impl_block) => { | 162 | SelfType(impl_block) => { |
111 | let ty = impl_block.target_ty(db); | 163 | let ty = impl_block.target_ty(db); |
164 | let item = NameKind::SelfType(ty); | ||
112 | let container = impl_block.module(); | 165 | let container = impl_block.module(); |
113 | Some(Definition { item: NameKind::SelfType(ty), container, visibility }) | 166 | Some(NameDefinition { item, container, visibility }) |
114 | } | 167 | } |
115 | PathResolution::AssocItem(assoc) => Some(assoc.definition(db)), | ||
116 | } | 168 | } |
117 | } | 169 | } |
118 | |||
119 | fn decl_from_pat( | ||
120 | db: &RootDatabase, | ||
121 | file_id: HirFileId, | ||
122 | pat: AstPtr<ast::BindPat>, | ||
123 | ) -> Option<Definition> { | ||
124 | let root = db.parse_or_expand(file_id)?; | ||
125 | // FIXME: use match_ast! | ||
126 | let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { | ||
127 | if let Some(it) = ast::FnDef::cast(node.clone()) { | ||
128 | let src = hir::Source { file_id, ast: it }; | ||
129 | Some(hir::Function::from_source(db, src)?.into()) | ||
130 | } else if let Some(it) = ast::ConstDef::cast(node.clone()) { | ||
131 | let src = hir::Source { file_id, ast: it }; | ||
132 | Some(hir::Const::from_source(db, src)?.into()) | ||
133 | } else if let Some(it) = ast::StaticDef::cast(node.clone()) { | ||
134 | let src = hir::Source { file_id, ast: it }; | ||
135 | Some(hir::Static::from_source(db, src)?.into()) | ||
136 | } else { | ||
137 | None | ||
138 | } | ||
139 | })?; | ||
140 | let item = NameKind::Pat((def, pat)); | ||
141 | let container = def.module(db); | ||
142 | Some(Definition { item, container, visibility: None }) | ||
143 | } | ||
diff --git a/crates/ra_ide_api/src/references/definition.rs b/crates/ra_ide_api/src/references/definition.rs deleted file mode 100644 index 65b1f8dd7..000000000 --- a/crates/ra_ide_api/src/references/definition.rs +++ /dev/null | |||
@@ -1,177 +0,0 @@ | |||
1 | use hir::{ | ||
2 | db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef, | ||
3 | Module, ModuleDef, SourceAnalyzer, StructField, Ty, VariantDef, | ||
4 | }; | ||
5 | use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr}; | ||
6 | |||
7 | use crate::db::RootDatabase; | ||
8 | |||
9 | #[derive(Debug, PartialEq, Eq)] | ||
10 | pub enum NameKind { | ||
11 | Macro(MacroDef), | ||
12 | FieldAccess(StructField), | ||
13 | AssocItem(AssocItem), | ||
14 | Def(ModuleDef), | ||
15 | SelfType(Ty), | ||
16 | Pat((DefWithBody, AstPtr<ast::BindPat>)), | ||
17 | SelfParam(AstPtr<ast::SelfParam>), | ||
18 | GenericParam(u32), | ||
19 | } | ||
20 | |||
21 | #[derive(PartialEq, Eq)] | ||
22 | pub(crate) struct Definition { | ||
23 | pub visibility: Option<ast::Visibility>, | ||
24 | pub container: Module, | ||
25 | pub item: NameKind, | ||
26 | } | ||
27 | |||
28 | pub(super) trait HasDefinition { | ||
29 | type Def; | ||
30 | type Ref; | ||
31 | |||
32 | fn definition(self, db: &RootDatabase) -> Definition; | ||
33 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition>; | ||
34 | fn from_ref( | ||
35 | db: &RootDatabase, | ||
36 | analyzer: &SourceAnalyzer, | ||
37 | refer: Self::Ref, | ||
38 | ) -> Option<Definition>; | ||
39 | } | ||
40 | |||
41 | // fn decl_from_pat( | ||
42 | // db: &RootDatabase, | ||
43 | // file_id: HirFileId, | ||
44 | // pat: AstPtr<ast::BindPat>, | ||
45 | // ) -> Option<Definition> { | ||
46 | // let root = db.parse_or_expand(file_id)?; | ||
47 | // // FIXME: use match_ast! | ||
48 | // let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { | ||
49 | // if let Some(it) = ast::FnDef::cast(node.clone()) { | ||
50 | // let src = hir::Source { file_id, ast: it }; | ||
51 | // Some(hir::Function::from_source(db, src)?.into()) | ||
52 | // } else if let Some(it) = ast::ConstDef::cast(node.clone()) { | ||
53 | // let src = hir::Source { file_id, ast: it }; | ||
54 | // Some(hir::Const::from_source(db, src)?.into()) | ||
55 | // } else if let Some(it) = ast::StaticDef::cast(node.clone()) { | ||
56 | // let src = hir::Source { file_id, ast: it }; | ||
57 | // Some(hir::Static::from_source(db, src)?.into()) | ||
58 | // } else { | ||
59 | // None | ||
60 | // } | ||
61 | // })?; | ||
62 | // let item = NameKind::Pat((def, pat)); | ||
63 | // let container = def.module(db); | ||
64 | // Some(Definition { item, container, visibility: None }) | ||
65 | // } | ||
66 | |||
67 | impl HasDefinition for StructField { | ||
68 | type Def = ast::RecordFieldDef; | ||
69 | type Ref = ast::FieldExpr; | ||
70 | |||
71 | fn definition(self, db: &RootDatabase) -> Definition { | ||
72 | let item = NameKind::FieldAccess(self); | ||
73 | let parent = self.parent_def(db); | ||
74 | let container = parent.module(db); | ||
75 | let visibility = match parent { | ||
76 | VariantDef::Struct(s) => s.source(db).ast.visibility(), | ||
77 | VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), | ||
78 | }; | ||
79 | Definition { item, container, visibility } | ||
80 | } | ||
81 | |||
82 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> { | ||
83 | let src = hir::Source { file_id, ast: hir::FieldSource::Named(def) }; | ||
84 | let field = StructField::from_source(db, src)?; | ||
85 | Some(field.definition(db)) | ||
86 | } | ||
87 | |||
88 | fn from_ref( | ||
89 | db: &RootDatabase, | ||
90 | analyzer: &SourceAnalyzer, | ||
91 | refer: Self::Ref, | ||
92 | ) -> Option<Definition> { | ||
93 | let field = analyzer.resolve_field(&refer)?; | ||
94 | Some(field.definition(db)) | ||
95 | } | ||
96 | } | ||
97 | |||
98 | impl HasDefinition for AssocItem { | ||
99 | type Def = ast::ImplItem; | ||
100 | type Ref = ast::MethodCallExpr; | ||
101 | |||
102 | fn definition(self, db: &RootDatabase) -> Definition { | ||
103 | let item = NameKind::AssocItem(self); | ||
104 | let container = self.module(db); | ||
105 | let visibility = match self { | ||
106 | AssocItem::Function(f) => f.source(db).ast.visibility(), | ||
107 | AssocItem::Const(c) => c.source(db).ast.visibility(), | ||
108 | AssocItem::TypeAlias(a) => a.source(db).ast.visibility(), | ||
109 | }; | ||
110 | Definition { item, container, visibility } | ||
111 | } | ||
112 | |||
113 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> { | ||
114 | if def.syntax().parent().and_then(ast::ItemList::cast).is_none() { | ||
115 | return None; | ||
116 | } | ||
117 | let src = hir::Source { file_id, ast: def }; | ||
118 | let item = AssocItem::from_source(db, src)?; | ||
119 | Some(item.definition(db)) | ||
120 | } | ||
121 | |||
122 | fn from_ref( | ||
123 | db: &RootDatabase, | ||
124 | analyzer: &SourceAnalyzer, | ||
125 | refer: Self::Ref, | ||
126 | ) -> Option<Definition> { | ||
127 | let func: AssocItem = analyzer.resolve_method_call(&refer)?.into(); | ||
128 | Some(func.definition(db)) | ||
129 | } | ||
130 | } | ||
131 | |||
132 | impl HasDefinition for ModuleDef { | ||
133 | type Def = ast::ModuleItem; | ||
134 | type Ref = ast::Path; | ||
135 | |||
136 | fn definition(self, db: &RootDatabase) -> Definition { | ||
137 | let (container, visibility) = match self { | ||
138 | ModuleDef::Module(it) => { | ||
139 | let container = it.parent(db).or_else(|| Some(it)).unwrap(); | ||
140 | let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility()); | ||
141 | (container, visibility) | ||
142 | } | ||
143 | ModuleDef::EnumVariant(it) => { | ||
144 | let container = it.module(db); | ||
145 | let visibility = it.source(db).ast.parent_enum().visibility(); | ||
146 | (container, visibility) | ||
147 | } | ||
148 | ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()), | ||
149 | ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()), | ||
150 | ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()), | ||
151 | ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()), | ||
152 | ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()), | ||
153 | ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()), | ||
154 | ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()), | ||
155 | ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()), | ||
156 | ModuleDef::BuiltinType(..) => unreachable!(), | ||
157 | }; | ||
158 | let item = NameKind::Def(self); | ||
159 | Definition { item, container, visibility } | ||
160 | } | ||
161 | |||
162 | fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> { | ||
163 | let src = hir::Source { file_id, ast: def }; | ||
164 | let def = ModuleDef::from_source(db, src)?; | ||
165 | Some(def.definition(db)) | ||
166 | } | ||
167 | |||
168 | fn from_ref( | ||
169 | db: &RootDatabase, | ||
170 | analyzer: &SourceAnalyzer, | ||
171 | refer: Self::Ref, | ||
172 | ) -> Option<Definition> { | ||
173 | None | ||
174 | } | ||
175 | } | ||
176 | |||
177 | // FIXME: impl HasDefinition for hir::MacroDef | ||
diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs new file mode 100644 index 000000000..19702eba0 --- /dev/null +++ b/crates/ra_ide_api/src/references/name_definition.rs | |||
@@ -0,0 +1,104 @@ | |||
1 | use hir::{ | ||
2 | db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef, | ||
3 | Module, ModuleDef, StructField, Ty, VariantDef, | ||
4 | }; | ||
5 | use ra_syntax::{ast, ast::VisibilityOwner, match_ast, AstNode, AstPtr}; | ||
6 | |||
7 | use crate::db::RootDatabase; | ||
8 | |||
9 | #[derive(Debug, PartialEq, Eq)] | ||
10 | pub enum NameKind { | ||
11 | Macro(MacroDef), | ||
12 | Field(StructField), | ||
13 | AssocItem(AssocItem), | ||
14 | Def(ModuleDef), | ||
15 | SelfType(Ty), | ||
16 | Pat((DefWithBody, AstPtr<ast::BindPat>)), | ||
17 | SelfParam(AstPtr<ast::SelfParam>), | ||
18 | GenericParam(u32), | ||
19 | } | ||
20 | |||
21 | #[derive(PartialEq, Eq)] | ||
22 | pub(crate) struct NameDefinition { | ||
23 | pub visibility: Option<ast::Visibility>, | ||
24 | pub container: Module, | ||
25 | pub item: NameKind, | ||
26 | } | ||
27 | |||
28 | pub(super) fn from_pat( | ||
29 | db: &RootDatabase, | ||
30 | file_id: HirFileId, | ||
31 | pat: AstPtr<ast::BindPat>, | ||
32 | ) -> Option<NameDefinition> { | ||
33 | let root = db.parse_or_expand(file_id)?; | ||
34 | let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { | ||
35 | match_ast! { | ||
36 | match node { | ||
37 | ast::FnDef(it) => { | ||
38 | let src = hir::Source { file_id, ast: it }; | ||
39 | Some(hir::Function::from_source(db, src)?.into()) | ||
40 | }, | ||
41 | ast::ConstDef(it) => { | ||
42 | let src = hir::Source { file_id, ast: it }; | ||
43 | Some(hir::Const::from_source(db, src)?.into()) | ||
44 | }, | ||
45 | ast::StaticDef(it) => { | ||
46 | let src = hir::Source { file_id, ast: it }; | ||
47 | Some(hir::Static::from_source(db, src)?.into()) | ||
48 | }, | ||
49 | _ => None, | ||
50 | } | ||
51 | } | ||
52 | })?; | ||
53 | let item = NameKind::Pat((def, pat)); | ||
54 | let container = def.module(db); | ||
55 | Some(NameDefinition { item, container, visibility: None }) | ||
56 | } | ||
57 | |||
58 | pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition { | ||
59 | let container = item.module(db); | ||
60 | let visibility = match item { | ||
61 | AssocItem::Function(f) => f.source(db).ast.visibility(), | ||
62 | AssocItem::Const(c) => c.source(db).ast.visibility(), | ||
63 | AssocItem::TypeAlias(a) => a.source(db).ast.visibility(), | ||
64 | }; | ||
65 | let item = NameKind::AssocItem(item); | ||
66 | NameDefinition { item, container, visibility } | ||
67 | } | ||
68 | |||
69 | pub(super) fn from_struct_field(db: &RootDatabase, field: StructField) -> NameDefinition { | ||
70 | let item = NameKind::Field(field); | ||
71 | let parent = field.parent_def(db); | ||
72 | let container = parent.module(db); | ||
73 | let visibility = match parent { | ||
74 | VariantDef::Struct(s) => s.source(db).ast.visibility(), | ||
75 | VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), | ||
76 | }; | ||
77 | NameDefinition { item, container, visibility } | ||
78 | } | ||
79 | |||
80 | pub(super) fn from_module_def(db: &RootDatabase, def: ModuleDef) -> NameDefinition { | ||
81 | let item = NameKind::Def(def); | ||
82 | let (container, visibility) = match def { | ||
83 | ModuleDef::Module(it) => { | ||
84 | let container = it.parent(db).or_else(|| Some(it)).unwrap(); | ||
85 | let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility()); | ||
86 | (container, visibility) | ||
87 | } | ||
88 | ModuleDef::EnumVariant(it) => { | ||
89 | let container = it.module(db); | ||
90 | let visibility = it.source(db).ast.parent_enum().visibility(); | ||
91 | (container, visibility) | ||
92 | } | ||
93 | ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()), | ||
94 | ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()), | ||
95 | ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()), | ||
96 | ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()), | ||
97 | ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()), | ||
98 | ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()), | ||
99 | ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()), | ||
100 | ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()), | ||
101 | ModuleDef::BuiltinType(..) => unreachable!(), | ||
102 | }; | ||
103 | NameDefinition { item, container, visibility } | ||
104 | } | ||
diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide_api/src/references/search_scope.rs index 557ee7b57..346815d31 100644 --- a/crates/ra_ide_api/src/references/search_scope.rs +++ b/crates/ra_ide_api/src/references/search_scope.rs | |||
@@ -4,13 +4,13 @@ use ra_syntax::{AstNode, TextRange}; | |||
4 | 4 | ||
5 | use crate::db::RootDatabase; | 5 | use crate::db::RootDatabase; |
6 | 6 | ||
7 | use super::{Definition, NameKind}; | 7 | use super::{NameDefinition, NameKind}; |
8 | 8 | ||
9 | pub(crate) struct SearchScope { | 9 | pub(crate) struct SearchScope { |
10 | pub scope: Vec<(FileId, Option<TextRange>)>, | 10 | pub scope: Vec<(FileId, Option<TextRange>)>, |
11 | } | 11 | } |
12 | 12 | ||
13 | impl Definition { | 13 | impl NameDefinition { |
14 | pub fn scope(&self, db: &RootDatabase) -> SearchScope { | 14 | pub fn scope(&self, db: &RootDatabase) -> SearchScope { |
15 | let module_src = self.container.definition_source(db); | 15 | let module_src = self.container.definition_source(db); |
16 | let file_id = module_src.file_id.original_file(db); | 16 | let file_id = module_src.file_id.original_file(db); |