diff options
author | Ekaterina Babshukova <[email protected]> | 2019-10-09 22:25:48 +0100 |
---|---|---|
committer | Ekaterina Babshukova <[email protected]> | 2019-10-22 21:47:31 +0100 |
commit | 01853e8d6c6f4b44801c74f4fcdef735d9e77b48 (patch) | |
tree | e26cd5c77688edd40a56dd140483eb56819ca6bf /crates/ra_ide_api/src | |
parent | 121aa35f12d282066651d906ea9a8b2da8209605 (diff) |
find scope for `Declaration` item
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/goto_definition.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide_api/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide_api/src/name_kind.rs | 65 | ||||
-rw-r--r-- | crates/ra_ide_api/src/search_scope.rs | 64 |
4 files changed, 86 insertions, 46 deletions
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index f49764513..fefd59cdd 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -207,7 +207,7 @@ fn named_target(file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget> | |||
207 | 207 | ||
208 | #[cfg(test)] | 208 | #[cfg(test)] |
209 | mod tests { | 209 | mod tests { |
210 | use test_utils::covers; | 210 | // use test_utils::covers; |
211 | 211 | ||
212 | use crate::mock_analysis::analysis_and_position; | 212 | use crate::mock_analysis::analysis_and_position; |
213 | 213 | ||
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index cbf79ce03..2dc3f0944 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -41,6 +41,7 @@ mod matching_brace; | |||
41 | mod display; | 41 | mod display; |
42 | mod inlay_hints; | 42 | mod inlay_hints; |
43 | mod wasm_shims; | 43 | mod wasm_shims; |
44 | mod search_scope; | ||
44 | 45 | ||
45 | #[cfg(test)] | 46 | #[cfg(test)] |
46 | mod marks; | 47 | mod marks; |
diff --git a/crates/ra_ide_api/src/name_kind.rs b/crates/ra_ide_api/src/name_kind.rs index 31f6f277d..6d1eb153f 100644 --- a/crates/ra_ide_api/src/name_kind.rs +++ b/crates/ra_ide_api/src/name_kind.rs | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | use hir::{ | 3 | use hir::{ |
4 | db::AstDatabase, Adt, AssocItem, DefWithBody, Either, EnumVariant, FromSource, HasSource, | 4 | db::AstDatabase, Adt, AssocItem, DefWithBody, Either, EnumVariant, FromSource, HasSource, |
5 | HirFileId, MacroDef, ModuleDef, ModuleSource, Path, PathResolution, SourceAnalyzer, | 5 | HirFileId, MacroDef, Module, ModuleDef, ModuleSource, Path, PathResolution, Source, |
6 | StructField, Ty, VariantDef, | 6 | SourceAnalyzer, StructField, Ty, VariantDef, |
7 | }; | 7 | }; |
8 | use ra_db::FileId; | 8 | use ra_db::FileId; |
9 | use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr}; | 9 | use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr}; |
@@ -22,8 +22,8 @@ pub enum NameKind { | |||
22 | } | 22 | } |
23 | 23 | ||
24 | pub(crate) struct Declaration { | 24 | pub(crate) struct Declaration { |
25 | visibility: Option<ast::Visibility>, | 25 | pub visibility: Option<ast::Visibility>, |
26 | container: ModuleSource, | 26 | pub container: Module, |
27 | pub item: NameKind, | 27 | pub item: NameKind, |
28 | } | 28 | } |
29 | 29 | ||
@@ -80,16 +80,9 @@ pub(crate) fn classify_name_ref( | |||
80 | } | 80 | } |
81 | } | 81 | } |
82 | 82 | ||
83 | let ast = ModuleSource::from_child_node(db, file_id, &parent); | ||
83 | let file_id = file_id.into(); | 84 | let file_id = file_id.into(); |
84 | let container = parent.ancestors().find_map(|node| { | 85 | let container = Module::from_definition(db, Source { file_id, ast })?; |
85 | if let Some(it) = ast::Module::cast(node.clone()) { | ||
86 | Some(ModuleSource::Module(it)) | ||
87 | } else if let Some(it) = ast::SourceFile::cast(node.clone()) { | ||
88 | Some(ModuleSource::SourceFile(it)) | ||
89 | } else { | ||
90 | None | ||
91 | } | ||
92 | })?; | ||
93 | 86 | ||
94 | if let Some(macro_call) = | 87 | if let Some(macro_call) = |
95 | parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) | 88 | parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) |
@@ -117,7 +110,7 @@ pub(crate) fn classify_name_ref( | |||
117 | } | 110 | } |
118 | PathResolution::SelfType(impl_block) => { | 111 | PathResolution::SelfType(impl_block) => { |
119 | let ty = impl_block.target_ty(db); | 112 | let ty = impl_block.target_ty(db); |
120 | let container = impl_block.module().definition_source(db).ast; | 113 | let container = impl_block.module(); |
121 | Some(Declaration { item: NameKind::SelfType(ty), container, visibility: None }) | 114 | Some(Declaration { item: NameKind::SelfType(ty), container, visibility: None }) |
122 | } | 115 | } |
123 | PathResolution::AssocItem(assoc) => Some(assoc.declaration(db)), | 116 | PathResolution::AssocItem(assoc) => Some(assoc.declaration(db)), |
@@ -184,7 +177,7 @@ fn decl_from_pat( | |||
184 | } | 177 | } |
185 | })?; | 178 | })?; |
186 | let item = NameKind::Pat((def, pat)); | 179 | let item = NameKind::Pat((def, pat)); |
187 | let container = def.module(db).definition_source(db).ast; | 180 | let container = def.module(db); |
188 | Some(Declaration { item, container, visibility: None }) | 181 | Some(Declaration { item, container, visibility: None }) |
189 | } | 182 | } |
190 | 183 | ||
@@ -195,7 +188,7 @@ impl HasDeclaration for StructField { | |||
195 | fn declaration(self, db: &RootDatabase) -> Declaration { | 188 | fn declaration(self, db: &RootDatabase) -> Declaration { |
196 | let item = NameKind::FieldAccess(self); | 189 | let item = NameKind::FieldAccess(self); |
197 | let parent = self.parent_def(db); | 190 | let parent = self.parent_def(db); |
198 | let container = parent.module(db).definition_source(db).ast; | 191 | let container = parent.module(db); |
199 | let visibility = match parent { | 192 | let visibility = match parent { |
200 | VariantDef::Struct(s) => s.source(db).ast.visibility(), | 193 | VariantDef::Struct(s) => s.source(db).ast.visibility(), |
201 | VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), | 194 | VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), |
@@ -225,7 +218,7 @@ impl HasDeclaration for AssocItem { | |||
225 | 218 | ||
226 | fn declaration(self, db: &RootDatabase) -> Declaration { | 219 | fn declaration(self, db: &RootDatabase) -> Declaration { |
227 | let item = NameKind::AssocItem(self); | 220 | let item = NameKind::AssocItem(self); |
228 | let container = self.module(db).definition_source(db).ast; | 221 | let container = self.module(db); |
229 | let visibility = match self { | 222 | let visibility = match self { |
230 | AssocItem::Function(f) => f.source(db).ast.visibility(), | 223 | AssocItem::Function(f) => f.source(db).ast.visibility(), |
231 | AssocItem::Const(c) => c.source(db).ast.visibility(), | 224 | AssocItem::Const(c) => c.source(db).ast.visibility(), |
@@ -255,43 +248,25 @@ impl HasDeclaration for ModuleDef { | |||
255 | type Ref = ast::Path; | 248 | type Ref = ast::Path; |
256 | 249 | ||
257 | fn declaration(self, db: &RootDatabase) -> Declaration { | 250 | fn declaration(self, db: &RootDatabase) -> Declaration { |
258 | // FIXME: use macro | ||
259 | let (container, visibility) = match self { | 251 | let (container, visibility) = match self { |
260 | ModuleDef::Module(it) => { | 252 | ModuleDef::Module(it) => { |
261 | let container = | 253 | let container = it.parent(db).or_else(|| Some(it)).unwrap(); |
262 | it.parent(db).or_else(|| Some(it)).unwrap().definition_source(db).ast; | ||
263 | let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility()); | 254 | let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility()); |
264 | (container, visibility) | 255 | (container, visibility) |
265 | } | 256 | } |
266 | ModuleDef::EnumVariant(it) => { | 257 | ModuleDef::EnumVariant(it) => { |
267 | let container = it.module(db).definition_source(db).ast; | 258 | let container = it.module(db); |
268 | let visibility = it.source(db).ast.parent_enum().visibility(); | 259 | let visibility = it.source(db).ast.parent_enum().visibility(); |
269 | (container, visibility) | 260 | (container, visibility) |
270 | } | 261 | } |
271 | ModuleDef::Function(it) => { | 262 | ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()), |
272 | (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) | 263 | ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()), |
273 | } | 264 | ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()), |
274 | ModuleDef::Const(it) => { | 265 | ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()), |
275 | (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) | 266 | ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()), |
276 | } | 267 | ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()), |
277 | ModuleDef::Static(it) => { | 268 | ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()), |
278 | (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) | 269 | ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()), |
279 | } | ||
280 | ModuleDef::Trait(it) => { | ||
281 | (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) | ||
282 | } | ||
283 | ModuleDef::TypeAlias(it) => { | ||
284 | (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) | ||
285 | } | ||
286 | ModuleDef::Adt(Adt::Struct(it)) => { | ||
287 | (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) | ||
288 | } | ||
289 | ModuleDef::Adt(Adt::Union(it)) => { | ||
290 | (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) | ||
291 | } | ||
292 | ModuleDef::Adt(Adt::Enum(it)) => { | ||
293 | (it.module(db).definition_source(db).ast, it.source(db).ast.visibility()) | ||
294 | } | ||
295 | ModuleDef::BuiltinType(..) => unreachable!(), | 270 | ModuleDef::BuiltinType(..) => unreachable!(), |
296 | }; | 271 | }; |
297 | let item = NameKind::Def(self); | 272 | let item = NameKind::Def(self); |
diff --git a/crates/ra_ide_api/src/search_scope.rs b/crates/ra_ide_api/src/search_scope.rs new file mode 100644 index 000000000..1cf1aed37 --- /dev/null +++ b/crates/ra_ide_api/src/search_scope.rs | |||
@@ -0,0 +1,64 @@ | |||
1 | use hir::{DefWithBody, HasSource, ModuleSource}; | ||
2 | use ra_db::{FileId, SourceDatabase}; | ||
3 | use ra_syntax::{AstNode, TextRange}; | ||
4 | |||
5 | use crate::{ | ||
6 | db::RootDatabase, | ||
7 | name_kind::{Declaration, NameKind}, | ||
8 | }; | ||
9 | |||
10 | pub struct SearchScope { | ||
11 | pub scope: Vec<(FileId, Option<TextRange>)>, | ||
12 | } | ||
13 | |||
14 | impl Declaration { | ||
15 | pub fn scope(self, db: &RootDatabase) -> Option<SearchScope> { | ||
16 | let module_src = self.container.definition_source(db); | ||
17 | let file_id = module_src.file_id.original_file(db); | ||
18 | |||
19 | if let NameKind::Pat((def, _)) = self.item { | ||
20 | let range = match def { | ||
21 | DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), | ||
22 | DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), | ||
23 | DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), | ||
24 | }; | ||
25 | return Some(SearchScope { scope: vec![(file_id, Some(range))] }); | ||
26 | } | ||
27 | |||
28 | if let Some(vis) = self.visibility { | ||
29 | let source_root_id = db.file_source_root(file_id); | ||
30 | let source_root = db.source_root(source_root_id); | ||
31 | let mut files = source_root.walk().map(|id| (id.into(), None)).collect::<Vec<_>>(); | ||
32 | |||
33 | if vis.syntax().text() == "pub(crate)" { | ||
34 | return Some(SearchScope { scope: files }); | ||
35 | } | ||
36 | if vis.syntax().text() == "pub" { | ||
37 | let krate = self.container.krate(db).unwrap(); | ||
38 | let crate_graph = db.crate_graph(); | ||
39 | |||
40 | for crate_id in crate_graph.iter() { | ||
41 | let mut crate_deps = crate_graph.dependencies(crate_id); | ||
42 | |||
43 | if crate_deps.any(|dep| dep.crate_id() == krate.crate_id()) { | ||
44 | let root_file = crate_graph.crate_root(crate_id); | ||
45 | let source_root_id = db.file_source_root(root_file); | ||
46 | let source_root = db.source_root(source_root_id); | ||
47 | files.extend(source_root.walk().map(|id| (id.into(), None))); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | return Some(SearchScope { scope: files }); | ||
52 | } | ||
53 | // FIXME: extend to "pub(super)" and "pub(in path)" cases, | ||
54 | // then remove `Option` | ||
55 | return None; | ||
56 | } | ||
57 | |||
58 | let range = match module_src.ast { | ||
59 | ModuleSource::Module(m) => Some(m.syntax().text_range()), | ||
60 | ModuleSource::SourceFile(_) => None, | ||
61 | }; | ||
62 | Some(SearchScope { scope: vec![(file_id, range)] }) | ||
63 | } | ||
64 | } | ||