aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/parent_module.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/parent_module.rs')
-rw-r--r--crates/ide/src/parent_module.rs79
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 @@
1use hir::Semantics; 1use hir::Semantics;
2use ide_db::base_db::{CrateId, FileId, FilePosition}; 2use ide_db::base_db::{CrateId, FileId, FilePosition};
3use ide_db::RootDatabase; 3use ide_db::RootDatabase;
4use itertools::Itertools;
4use syntax::{ 5use 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.
23pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { 23pub(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`
53pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { 54pub(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
127mod foo; 125mod foo;
126 //^^^
127#[path = "foo.rs"]
128mod 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
143mod 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
156mod baz;
157//- /bar.rs crate:bar
158mod baz;
159"#,
160 );
161 assert_eq!(analysis.crate_for(file_id).unwrap().len(), 2);
162 }
134} 163}