diff options
Diffstat (limited to 'crates/ra_ide/src/parent_module.rs')
-rw-r--r-- | crates/ra_ide/src/parent_module.rs | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs new file mode 100644 index 000000000..6027e7d54 --- /dev/null +++ b/crates/ra_ide/src/parent_module.rs | |||
@@ -0,0 +1,104 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use ra_db::{CrateId, FileId, FilePosition}; | ||
4 | |||
5 | use crate::{db::RootDatabase, NavigationTarget}; | ||
6 | |||
7 | /// This returns `Vec` because a module may be included from several places. We | ||
8 | /// don't handle this case yet though, so the Vec has length at most one. | ||
9 | pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { | ||
10 | let src = hir::ModuleSource::from_position(db, position); | ||
11 | let module = match hir::Module::from_definition( | ||
12 | db, | ||
13 | hir::Source { file_id: position.file_id.into(), value: src }, | ||
14 | ) { | ||
15 | None => return Vec::new(), | ||
16 | Some(it) => it, | ||
17 | }; | ||
18 | let nav = NavigationTarget::from_module_to_decl(db, module); | ||
19 | vec![nav] | ||
20 | } | ||
21 | |||
22 | /// Returns `Vec` for the same reason as `parent_module` | ||
23 | pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { | ||
24 | let src = hir::ModuleSource::from_file_id(db, file_id); | ||
25 | let module = | ||
26 | match hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), value: src }) | ||
27 | { | ||
28 | Some(it) => it, | ||
29 | None => return Vec::new(), | ||
30 | }; | ||
31 | let krate = module.krate(); | ||
32 | vec![krate.crate_id()] | ||
33 | } | ||
34 | |||
35 | #[cfg(test)] | ||
36 | mod tests { | ||
37 | use ra_cfg::CfgOptions; | ||
38 | use ra_db::Env; | ||
39 | |||
40 | use crate::{ | ||
41 | mock_analysis::{analysis_and_position, MockAnalysis}, | ||
42 | AnalysisChange, CrateGraph, | ||
43 | Edition::Edition2018, | ||
44 | }; | ||
45 | |||
46 | #[test] | ||
47 | fn test_resolve_parent_module() { | ||
48 | let (analysis, pos) = analysis_and_position( | ||
49 | " | ||
50 | //- /lib.rs | ||
51 | mod foo; | ||
52 | //- /foo.rs | ||
53 | <|>// empty | ||
54 | ", | ||
55 | ); | ||
56 | let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); | ||
57 | nav.assert_match("foo MODULE FileId(1) [0; 8)"); | ||
58 | } | ||
59 | |||
60 | #[test] | ||
61 | fn test_resolve_parent_module_for_inline() { | ||
62 | let (analysis, pos) = analysis_and_position( | ||
63 | " | ||
64 | //- /lib.rs | ||
65 | mod foo { | ||
66 | mod bar { | ||
67 | mod baz { <|> } | ||
68 | } | ||
69 | } | ||
70 | ", | ||
71 | ); | ||
72 | let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); | ||
73 | nav.assert_match("baz MODULE FileId(1) [32; 44)"); | ||
74 | } | ||
75 | |||
76 | #[test] | ||
77 | fn test_resolve_crate_root() { | ||
78 | let mock = MockAnalysis::with_files( | ||
79 | " | ||
80 | //- /bar.rs | ||
81 | mod foo; | ||
82 | //- /foo.rs | ||
83 | // empty <|> | ||
84 | ", | ||
85 | ); | ||
86 | let root_file = mock.id_of("/bar.rs"); | ||
87 | let mod_file = mock.id_of("/foo.rs"); | ||
88 | let mut host = mock.analysis_host(); | ||
89 | assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); | ||
90 | |||
91 | let mut crate_graph = CrateGraph::default(); | ||
92 | let crate_id = crate_graph.add_crate_root( | ||
93 | root_file, | ||
94 | Edition2018, | ||
95 | CfgOptions::default(), | ||
96 | Env::default(), | ||
97 | ); | ||
98 | let mut change = AnalysisChange::new(); | ||
99 | change.set_crate_graph(crate_graph); | ||
100 | host.apply_change(change); | ||
101 | |||
102 | assert_eq!(host.analysis().crate_for(mod_file).unwrap(), vec![crate_id]); | ||
103 | } | ||
104 | } | ||