diff options
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/src/parent_module.rs | 79 |
1 files changed, 54 insertions, 25 deletions
diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs index 03d71b380..22b0d6ecb 100644 --- a/crates/ide/src/parent_module.rs +++ b/crates/ide/src/parent_module.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use hir::Semantics; | 1 | use hir::Semantics; |
2 | use ide_db::base_db::{CrateId, FileId, FilePosition}; | 2 | use ide_db::base_db::{CrateId, FileId, FilePosition}; |
3 | use ide_db::RootDatabase; | 3 | use ide_db::RootDatabase; |
4 | use itertools::Itertools; | ||
4 | use syntax::{ | 5 | use syntax::{ |
5 | algo::find_node_at_offset, | 6 | algo::find_node_at_offset, |
6 | ast::{self, AstNode}, | 7 | ast::{self, AstNode}, |
@@ -18,8 +19,7 @@ use crate::NavigationTarget; | |||
18 | // | VS Code | **Rust Analyzer: Locate parent module** | 19 | // | VS Code | **Rust Analyzer: Locate parent module** |
19 | // |=== | 20 | // |=== |
20 | 21 | ||
21 | /// This returns `Vec` because a module may be included from several places. We | 22 | /// This returns `Vec` because a module may be included from several places. |
22 | /// don't handle this case yet though, so the Vec has length at most one. | ||
23 | pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { | 23 | pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { |
24 | let sema = Semantics::new(db); | 24 | let sema = Semantics::new(db); |
25 | let source_file = sema.parse(position.file_id); | 25 | let source_file = sema.parse(position.file_id); |
@@ -37,27 +37,23 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na | |||
37 | } | 37 | } |
38 | } | 38 | } |
39 | 39 | ||
40 | let module = match module { | 40 | match module { |
41 | Some(module) => sema.to_def(&module), | 41 | Some(module) => sema |
42 | None => sema.to_module_def(position.file_id), | 42 | .to_def(&module) |
43 | }; | 43 | .into_iter() |
44 | let module = match module { | 44 | .map(|module| NavigationTarget::from_module_to_decl(db, module)) |
45 | None => return Vec::new(), | 45 | .collect(), |
46 | Some(it) => it, | 46 | None => sema |
47 | }; | 47 | .to_module_defs(position.file_id) |
48 | let nav = NavigationTarget::from_module_to_decl(db, module); | 48 | .map(|module| NavigationTarget::from_module_to_decl(db, module)) |
49 | vec![nav] | 49 | .collect(), |
50 | } | ||
50 | } | 51 | } |
51 | 52 | ||
52 | /// Returns `Vec` for the same reason as `parent_module` | 53 | /// Returns `Vec` for the same reason as `parent_module` |
53 | pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { | 54 | pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { |
54 | let sema = Semantics::new(db); | 55 | let sema = Semantics::new(db); |
55 | let module = match sema.to_module_def(file_id) { | 56 | sema.to_module_defs(file_id).map(|module| module.krate().into()).unique().collect() |
56 | Some(it) => it, | ||
57 | None => return Vec::new(), | ||
58 | }; | ||
59 | let krate = module.krate(); | ||
60 | vec![krate.into()] | ||
61 | } | 57 | } |
62 | 58 | ||
63 | #[cfg(test)] | 59 | #[cfg(test)] |
@@ -67,11 +63,13 @@ mod tests { | |||
67 | use crate::fixture; | 63 | use crate::fixture; |
68 | 64 | ||
69 | fn check(ra_fixture: &str) { | 65 | fn check(ra_fixture: &str) { |
70 | let (analysis, position, expected) = fixture::nav_target_annotation(ra_fixture); | 66 | let (analysis, position, expected) = fixture::annotations(ra_fixture); |
71 | let mut navs = analysis.parent_module(position).unwrap(); | 67 | let navs = analysis.parent_module(position).unwrap(); |
72 | assert_eq!(navs.len(), 1); | 68 | let navs = navs |
73 | let nav = navs.pop().unwrap(); | 69 | .iter() |
74 | assert_eq!(expected, FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }); | 70 | .map(|nav| FileRange { file_id: nav.file_id, range: nav.focus_or_full_range() }) |
71 | .collect::<Vec<_>>(); | ||
72 | assert_eq!(expected.into_iter().map(|(fr, _)| fr).collect::<Vec<_>>(), navs); | ||
75 | } | 73 | } |
76 | 74 | ||
77 | #[test] | 75 | #[test] |
@@ -120,15 +118,46 @@ mod foo { | |||
120 | } | 118 | } |
121 | 119 | ||
122 | #[test] | 120 | #[test] |
123 | fn test_resolve_crate_root() { | 121 | fn test_resolve_multi_parent_module() { |
124 | let (analysis, file_id) = fixture::file( | 122 | check( |
125 | r#" | 123 | r#" |
126 | //- /main.rs | 124 | //- /main.rs |
127 | mod foo; | 125 | mod foo; |
126 | //^^^ | ||
127 | #[path = "foo.rs"] | ||
128 | mod bar; | ||
129 | //^^^ | ||
130 | //- /foo.rs | ||
131 | $0 | ||
132 | "#, | ||
133 | ); | ||
134 | } | ||
135 | |||
136 | #[test] | ||
137 | fn test_resolve_crate_root() { | ||
138 | let (analysis, file_id) = fixture::file( | ||
139 | r#" | ||
128 | //- /foo.rs | 140 | //- /foo.rs |
129 | $0 | 141 | $0 |
142 | //- /main.rs | ||
143 | mod foo; | ||
130 | "#, | 144 | "#, |
131 | ); | 145 | ); |
132 | assert_eq!(analysis.crate_for(file_id).unwrap().len(), 1); | 146 | assert_eq!(analysis.crate_for(file_id).unwrap().len(), 1); |
133 | } | 147 | } |
148 | |||
149 | #[test] | ||
150 | fn test_resolve_multi_parent_crate() { | ||
151 | let (analysis, file_id) = fixture::file( | ||
152 | r#" | ||
153 | //- /baz.rs | ||
154 | $0 | ||
155 | //- /foo.rs crate:foo | ||
156 | mod baz; | ||
157 | //- /bar.rs crate:bar | ||
158 | mod baz; | ||
159 | "#, | ||
160 | ); | ||
161 | assert_eq!(analysis.crate_for(file_id).unwrap().len(), 2); | ||
162 | } | ||
134 | } | 163 | } |