diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-08 19:48:48 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-08 19:48:48 +0000 |
commit | 46f74e33ca53a7897e9020d3de75cc76a6b89d79 (patch) | |
tree | 2bc001c8ecf58b49ac9a0da1f20d5644ce29fb3a /crates/ra_ide_api/src/mock_analysis.rs | |
parent | 4f4f7933b1b7ff34f8633b1686b18b2d1b994c47 (diff) | |
parent | 0c62b1bb7a49bf527780ce1f8cade5eb4fbfdb2d (diff) |
Merge #471
471: rename crates to match reality r=matklad a=matklad
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_ide_api/src/mock_analysis.rs')
-rw-r--r-- | crates/ra_ide_api/src/mock_analysis.rs | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs new file mode 100644 index 000000000..846c76cfe --- /dev/null +++ b/crates/ra_ide_api/src/mock_analysis.rs | |||
@@ -0,0 +1,135 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use relative_path::RelativePathBuf; | ||
4 | use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; | ||
5 | use ra_db::mock::FileMap; | ||
6 | |||
7 | use crate::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, FilePosition, FileRange, SourceRootId}; | ||
8 | |||
9 | /// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis | ||
10 | /// from a set of in-memory files. | ||
11 | #[derive(Debug, Default)] | ||
12 | pub struct MockAnalysis { | ||
13 | files: Vec<(String, String)>, | ||
14 | } | ||
15 | |||
16 | impl MockAnalysis { | ||
17 | pub fn new() -> MockAnalysis { | ||
18 | MockAnalysis::default() | ||
19 | } | ||
20 | /// Creates `MockAnalysis` using a fixture data in the following format: | ||
21 | /// | ||
22 | /// ```notrust | ||
23 | /// //- /main.rs | ||
24 | /// mod foo; | ||
25 | /// fn main() {} | ||
26 | /// | ||
27 | /// //- /foo.rs | ||
28 | /// struct Baz; | ||
29 | /// ``` | ||
30 | pub fn with_files(fixture: &str) -> MockAnalysis { | ||
31 | let mut res = MockAnalysis::new(); | ||
32 | for entry in parse_fixture(fixture) { | ||
33 | res.add_file(&entry.meta, &entry.text); | ||
34 | } | ||
35 | res | ||
36 | } | ||
37 | |||
38 | /// Same as `with_files`, but requires that a single file contains a `<|>` marker, | ||
39 | /// whose position is also returned. | ||
40 | pub fn with_files_and_position(fixture: &str) -> (MockAnalysis, FilePosition) { | ||
41 | let mut position = None; | ||
42 | let mut res = MockAnalysis::new(); | ||
43 | for entry in parse_fixture(fixture) { | ||
44 | if entry.text.contains(CURSOR_MARKER) { | ||
45 | assert!( | ||
46 | position.is_none(), | ||
47 | "only one marker (<|>) per fixture is allowed" | ||
48 | ); | ||
49 | position = Some(res.add_file_with_position(&entry.meta, &entry.text)); | ||
50 | } else { | ||
51 | res.add_file(&entry.meta, &entry.text); | ||
52 | } | ||
53 | } | ||
54 | let position = position.expect("expected a marker (<|>)"); | ||
55 | (res, position) | ||
56 | } | ||
57 | |||
58 | pub fn add_file(&mut self, path: &str, text: &str) -> FileId { | ||
59 | let file_id = FileId((self.files.len() + 1) as u32); | ||
60 | self.files.push((path.to_string(), text.to_string())); | ||
61 | file_id | ||
62 | } | ||
63 | pub fn add_file_with_position(&mut self, path: &str, text: &str) -> FilePosition { | ||
64 | let (offset, text) = extract_offset(text); | ||
65 | let file_id = FileId((self.files.len() + 1) as u32); | ||
66 | self.files.push((path.to_string(), text.to_string())); | ||
67 | FilePosition { file_id, offset } | ||
68 | } | ||
69 | pub fn add_file_with_range(&mut self, path: &str, text: &str) -> FileRange { | ||
70 | let (range, text) = extract_range(text); | ||
71 | let file_id = FileId((self.files.len() + 1) as u32); | ||
72 | self.files.push((path.to_string(), text.to_string())); | ||
73 | FileRange { file_id, range } | ||
74 | } | ||
75 | pub fn id_of(&self, path: &str) -> FileId { | ||
76 | let (idx, _) = self | ||
77 | .files | ||
78 | .iter() | ||
79 | .enumerate() | ||
80 | .find(|(_, (p, _text))| path == p) | ||
81 | .expect("no file in this mock"); | ||
82 | FileId(idx as u32 + 1) | ||
83 | } | ||
84 | pub fn analysis_host(self) -> AnalysisHost { | ||
85 | let mut host = AnalysisHost::default(); | ||
86 | let mut file_map = FileMap::default(); | ||
87 | let source_root = SourceRootId(0); | ||
88 | let mut change = AnalysisChange::new(); | ||
89 | change.add_root(source_root, true); | ||
90 | let mut crate_graph = CrateGraph::default(); | ||
91 | for (path, contents) in self.files.into_iter() { | ||
92 | assert!(path.starts_with('/')); | ||
93 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); | ||
94 | let file_id = file_map.add(path.clone()); | ||
95 | if path == "/lib.rs" || path == "/main.rs" { | ||
96 | crate_graph.add_crate_root(file_id); | ||
97 | } | ||
98 | change.add_file(source_root, file_id, path, Arc::new(contents)); | ||
99 | } | ||
100 | change.set_crate_graph(crate_graph); | ||
101 | // change.set_file_resolver(Arc::new(file_map)); | ||
102 | host.apply_change(change); | ||
103 | host | ||
104 | } | ||
105 | pub fn analysis(self) -> Analysis { | ||
106 | self.analysis_host().analysis() | ||
107 | } | ||
108 | } | ||
109 | |||
110 | /// Creates analysis from a multi-file fixture, returns positions marked with <|>. | ||
111 | pub fn analysis_and_position(fixture: &str) -> (Analysis, FilePosition) { | ||
112 | let (mock, position) = MockAnalysis::with_files_and_position(fixture); | ||
113 | (mock.analysis(), position) | ||
114 | } | ||
115 | |||
116 | /// Creates analysis for a single file. | ||
117 | pub fn single_file(code: &str) -> (Analysis, FileId) { | ||
118 | let mut mock = MockAnalysis::new(); | ||
119 | let file_id = mock.add_file("/main.rs", code); | ||
120 | (mock.analysis(), file_id) | ||
121 | } | ||
122 | |||
123 | /// Creates analysis for a single file, returns position marked with <|>. | ||
124 | pub fn single_file_with_position(code: &str) -> (Analysis, FilePosition) { | ||
125 | let mut mock = MockAnalysis::new(); | ||
126 | let pos = mock.add_file_with_position("/main.rs", code); | ||
127 | (mock.analysis(), pos) | ||
128 | } | ||
129 | |||
130 | /// Creates analysis for a single file, returns range marked with a pair of <|>. | ||
131 | pub fn single_file_with_range(code: &str) -> (Analysis, FileRange) { | ||
132 | let mut mock = MockAnalysis::new(); | ||
133 | let pos = mock.add_file_with_range("/main.rs", code); | ||
134 | (mock.analysis(), pos) | ||
135 | } | ||