diff options
Diffstat (limited to 'crates/ra_analysis/src/mock_analysis.rs')
-rw-r--r-- | crates/ra_analysis/src/mock_analysis.rs | 84 |
1 files changed, 79 insertions, 5 deletions
diff --git a/crates/ra_analysis/src/mock_analysis.rs b/crates/ra_analysis/src/mock_analysis.rs index 1c1dbee7c..f72911192 100644 --- a/crates/ra_analysis/src/mock_analysis.rs +++ b/crates/ra_analysis/src/mock_analysis.rs | |||
@@ -2,11 +2,19 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use relative_path::{RelativePath, RelativePathBuf}; | 4 | use relative_path::{RelativePath, RelativePathBuf}; |
5 | use ra_syntax::TextUnit; | ||
6 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; | ||
5 | 7 | ||
6 | use crate::{ | 8 | use crate::{ |
7 | AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver, | 9 | AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver, |
8 | }; | 10 | }; |
9 | 11 | ||
12 | #[derive(Debug)] | ||
13 | pub struct FilePosition { | ||
14 | pub file_id: FileId, | ||
15 | pub offset: TextUnit, | ||
16 | } | ||
17 | |||
10 | /// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis | 18 | /// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis |
11 | /// from a set of in-memory files. | 19 | /// from a set of in-memory files. |
12 | #[derive(Debug, Default)] | 20 | #[derive(Debug, Default)] |
@@ -18,11 +26,57 @@ impl MockAnalysis { | |||
18 | pub fn new() -> MockAnalysis { | 26 | pub fn new() -> MockAnalysis { |
19 | MockAnalysis::default() | 27 | MockAnalysis::default() |
20 | } | 28 | } |
21 | pub fn with_files(files: &[(&str, &str)]) -> MockAnalysis { | 29 | /// Creates `MockAnalysis` using a fixture data in the following format: |
22 | let files = files.iter() | 30 | /// |
23 | .map(|it| (it.0.to_string(), it.1.to_string())) | 31 | /// ```notrust |
24 | .collect(); | 32 | /// //- /main.rs |
25 | MockAnalysis { files } | 33 | /// mod foo; |
34 | /// fn main() {} | ||
35 | /// | ||
36 | /// //- /foo.rs | ||
37 | /// struct Baz; | ||
38 | /// ``` | ||
39 | pub fn with_files(fixture: &str) -> MockAnalysis { | ||
40 | let mut res = MockAnalysis::new(); | ||
41 | for entry in parse_fixture(fixture) { | ||
42 | res.add_file(&entry.meta, &entry.text); | ||
43 | } | ||
44 | res | ||
45 | } | ||
46 | |||
47 | /// Same as `with_files`, but requires that a single file contains a `<|>` marker, | ||
48 | /// whose position is also returned. | ||
49 | pub fn with_files_and_position(fixture: &str) -> (MockAnalysis, FilePosition) { | ||
50 | let mut position = None; | ||
51 | let mut res = MockAnalysis::new(); | ||
52 | for entry in parse_fixture(fixture) { | ||
53 | if entry.text.contains(CURSOR_MARKER) { | ||
54 | assert!(position.is_none(), "only one marker (<|>) per fixture is allowed"); | ||
55 | position = Some(res.add_file_with_position(&entry.meta, &entry.text)); | ||
56 | } else { | ||
57 | res.add_file(&entry.meta, &entry.text); | ||
58 | } | ||
59 | } | ||
60 | let position = position.expect("expected a marker (<|>)"); | ||
61 | (res, position) | ||
62 | } | ||
63 | |||
64 | pub fn add_file(&mut self, path: &str, text: &str) -> FileId { | ||
65 | let file_id = FileId((self.files.len() + 1) as u32); | ||
66 | self.files.push((path.to_string(), text.to_string())); | ||
67 | file_id | ||
68 | } | ||
69 | pub fn add_file_with_position(&mut self, path: &str, text: &str) -> FilePosition { | ||
70 | let (offset, text) = extract_offset(text); | ||
71 | let file_id = FileId((self.files.len() + 1) as u32); | ||
72 | self.files.push((path.to_string(), text.to_string())); | ||
73 | FilePosition { file_id, offset } | ||
74 | } | ||
75 | pub fn id_of(&self, path: &str) -> FileId { | ||
76 | let (idx, _) = self.files.iter().enumerate() | ||
77 | .find(|(_, (p, _text))| path == p) | ||
78 | .expect("no file in this mock"); | ||
79 | FileId(idx as u32 + 1) | ||
26 | } | 80 | } |
27 | pub fn analysis_host(self) -> AnalysisHost { | 81 | pub fn analysis_host(self) -> AnalysisHost { |
28 | let mut host = AnalysisHost::new(); | 82 | let mut host = AnalysisHost::new(); |
@@ -44,6 +98,26 @@ impl MockAnalysis { | |||
44 | } | 98 | } |
45 | } | 99 | } |
46 | 100 | ||
101 | /// Creates analysis from a multi-file fixture, returns positions marked with <|>. | ||
102 | pub fn analysis_and_position(fixture: &str) -> (Analysis, FilePosition) { | ||
103 | let (mock, position) = MockAnalysis::with_files_and_position(fixture); | ||
104 | (mock.analysis(), position) | ||
105 | } | ||
106 | |||
107 | /// Creates analysis for a single file. | ||
108 | pub fn single_file(code: &str) -> (Analysis, FileId) { | ||
109 | let mut mock = MockAnalysis::new(); | ||
110 | let file_id = mock.add_file("/main.rs", code); | ||
111 | (mock.analysis(), file_id) | ||
112 | } | ||
113 | |||
114 | /// Creates analysis for a single file, returns position marked with <|>. | ||
115 | pub fn single_file_with_position(code: &str) -> (Analysis, FilePosition) { | ||
116 | let mut mock = MockAnalysis::new(); | ||
117 | let pos = mock.add_file_with_position("/main.rs", code); | ||
118 | (mock.analysis(), pos) | ||
119 | } | ||
120 | |||
47 | #[derive(Debug)] | 121 | #[derive(Debug)] |
48 | struct FileMap(Vec<(FileId, RelativePathBuf)>); | 122 | struct FileMap(Vec<(FileId, RelativePathBuf)>); |
49 | 123 | ||