diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/mock_analysis.rs | 93 |
1 files changed, 77 insertions, 16 deletions
diff --git a/crates/ra_ide/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs index 64c0684c5..8d8e30714 100644 --- a/crates/ra_ide/src/mock_analysis.rs +++ b/crates/ra_ide/src/mock_analysis.rs | |||
@@ -4,18 +4,61 @@ use std::sync::Arc; | |||
4 | 4 | ||
5 | use ra_cfg::CfgOptions; | 5 | use ra_cfg::CfgOptions; |
6 | use ra_db::{CrateName, Env, RelativePathBuf}; | 6 | use ra_db::{CrateName, Env, RelativePathBuf}; |
7 | use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; | 7 | use test_utils::{extract_offset, extract_range, parse_fixture, FixtureEntry, CURSOR_MARKER}; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, Edition::Edition2018, FileId, FilePosition, | 10 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, Edition::Edition2018, FileId, FilePosition, |
11 | FileRange, SourceRootId, | 11 | FileRange, SourceRootId, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | #[derive(Debug)] | ||
15 | enum MockFileData { | ||
16 | Plain { path: String, content: String }, | ||
17 | Fixture(FixtureEntry), | ||
18 | } | ||
19 | |||
20 | impl MockFileData { | ||
21 | fn new(path: String, content: String) -> Self { | ||
22 | // `Self::Plain` causes a false warning: 'variant is never constructed: `Plain` ' | ||
23 | // see https://github.com/rust-lang/rust/issues/69018 | ||
24 | MockFileData::Plain { path, content } | ||
25 | } | ||
26 | |||
27 | fn path(&self) -> &str { | ||
28 | match self { | ||
29 | MockFileData::Plain { path, .. } => path.as_str(), | ||
30 | MockFileData::Fixture(f) => f.meta.path().as_str(), | ||
31 | } | ||
32 | } | ||
33 | |||
34 | fn content(&self) -> &str { | ||
35 | match self { | ||
36 | MockFileData::Plain { content, .. } => content, | ||
37 | MockFileData::Fixture(f) => f.text.as_str(), | ||
38 | } | ||
39 | } | ||
40 | |||
41 | fn cfg_options(&self) -> CfgOptions { | ||
42 | match self { | ||
43 | MockFileData::Fixture(f) => { | ||
44 | f.meta.cfg_options().map_or_else(Default::default, |o| o.clone()) | ||
45 | } | ||
46 | _ => CfgOptions::default(), | ||
47 | } | ||
48 | } | ||
49 | } | ||
50 | |||
51 | impl From<FixtureEntry> for MockFileData { | ||
52 | fn from(fixture: FixtureEntry) -> Self { | ||
53 | Self::Fixture(fixture) | ||
54 | } | ||
55 | } | ||
56 | |||
14 | /// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis | 57 | /// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis |
15 | /// from a set of in-memory files. | 58 | /// from a set of in-memory files. |
16 | #[derive(Debug, Default)] | 59 | #[derive(Debug, Default)] |
17 | pub struct MockAnalysis { | 60 | pub struct MockAnalysis { |
18 | files: Vec<(String, String)>, | 61 | files: Vec<MockFileData>, |
19 | } | 62 | } |
20 | 63 | ||
21 | impl MockAnalysis { | 64 | impl MockAnalysis { |
@@ -35,7 +78,7 @@ impl MockAnalysis { | |||
35 | pub fn with_files(fixture: &str) -> MockAnalysis { | 78 | pub fn with_files(fixture: &str) -> MockAnalysis { |
36 | let mut res = MockAnalysis::new(); | 79 | let mut res = MockAnalysis::new(); |
37 | for entry in parse_fixture(fixture) { | 80 | for entry in parse_fixture(fixture) { |
38 | res.add_file(entry.meta.path().as_str(), &entry.text); | 81 | res.add_file_fixture(entry); |
39 | } | 82 | } |
40 | res | 83 | res |
41 | } | 84 | } |
@@ -48,31 +91,44 @@ impl MockAnalysis { | |||
48 | for entry in parse_fixture(fixture) { | 91 | for entry in parse_fixture(fixture) { |
49 | if entry.text.contains(CURSOR_MARKER) { | 92 | if entry.text.contains(CURSOR_MARKER) { |
50 | assert!(position.is_none(), "only one marker (<|>) per fixture is allowed"); | 93 | assert!(position.is_none(), "only one marker (<|>) per fixture is allowed"); |
51 | position = | 94 | position = Some(res.add_file_fixture_with_position(entry)); |
52 | Some(res.add_file_with_position(&entry.meta.path().as_str(), &entry.text)); | ||
53 | } else { | 95 | } else { |
54 | res.add_file(&entry.meta.path().as_str(), &entry.text); | 96 | res.add_file_fixture(entry); |
55 | } | 97 | } |
56 | } | 98 | } |
57 | let position = position.expect("expected a marker (<|>)"); | 99 | let position = position.expect("expected a marker (<|>)"); |
58 | (res, position) | 100 | (res, position) |
59 | } | 101 | } |
60 | 102 | ||
103 | pub fn add_file_fixture(&mut self, fixture: FixtureEntry) -> FileId { | ||
104 | let file_id = self.next_id(); | ||
105 | self.files.push(MockFileData::from(fixture)); | ||
106 | file_id | ||
107 | } | ||
108 | |||
109 | pub fn add_file_fixture_with_position(&mut self, mut fixture: FixtureEntry) -> FilePosition { | ||
110 | let (offset, text) = extract_offset(&fixture.text); | ||
111 | fixture.text = text; | ||
112 | let file_id = self.next_id(); | ||
113 | self.files.push(MockFileData::from(fixture)); | ||
114 | FilePosition { file_id, offset } | ||
115 | } | ||
116 | |||
61 | pub fn add_file(&mut self, path: &str, text: &str) -> FileId { | 117 | pub fn add_file(&mut self, path: &str, text: &str) -> FileId { |
62 | let file_id = FileId((self.files.len() + 1) as u32); | 118 | let file_id = self.next_id(); |
63 | self.files.push((path.to_string(), text.to_string())); | 119 | self.files.push(MockFileData::new(path.to_string(), text.to_string())); |
64 | file_id | 120 | file_id |
65 | } | 121 | } |
66 | pub fn add_file_with_position(&mut self, path: &str, text: &str) -> FilePosition { | 122 | pub fn add_file_with_position(&mut self, path: &str, text: &str) -> FilePosition { |
67 | let (offset, text) = extract_offset(text); | 123 | let (offset, text) = extract_offset(text); |
68 | let file_id = FileId((self.files.len() + 1) as u32); | 124 | let file_id = self.next_id(); |
69 | self.files.push((path.to_string(), text)); | 125 | self.files.push(MockFileData::new(path.to_string(), text)); |
70 | FilePosition { file_id, offset } | 126 | FilePosition { file_id, offset } |
71 | } | 127 | } |
72 | pub fn add_file_with_range(&mut self, path: &str, text: &str) -> FileRange { | 128 | pub fn add_file_with_range(&mut self, path: &str, text: &str) -> FileRange { |
73 | let (range, text) = extract_range(text); | 129 | let (range, text) = extract_range(text); |
74 | let file_id = FileId((self.files.len() + 1) as u32); | 130 | let file_id = self.next_id(); |
75 | self.files.push((path.to_string(), text)); | 131 | self.files.push(MockFileData::new(path.to_string(), text)); |
76 | FileRange { file_id, range } | 132 | FileRange { file_id, range } |
77 | } | 133 | } |
78 | pub fn id_of(&self, path: &str) -> FileId { | 134 | pub fn id_of(&self, path: &str) -> FileId { |
@@ -80,7 +136,7 @@ impl MockAnalysis { | |||
80 | .files | 136 | .files |
81 | .iter() | 137 | .iter() |
82 | .enumerate() | 138 | .enumerate() |
83 | .find(|(_, (p, _text))| path == p) | 139 | .find(|(_, data)| path == data.path()) |
84 | .expect("no file in this mock"); | 140 | .expect("no file in this mock"); |
85 | FileId(idx as u32 + 1) | 141 | FileId(idx as u32 + 1) |
86 | } | 142 | } |
@@ -91,11 +147,12 @@ impl MockAnalysis { | |||
91 | change.add_root(source_root, true); | 147 | change.add_root(source_root, true); |
92 | let mut crate_graph = CrateGraph::default(); | 148 | let mut crate_graph = CrateGraph::default(); |
93 | let mut root_crate = None; | 149 | let mut root_crate = None; |
94 | for (i, (path, contents)) in self.files.into_iter().enumerate() { | 150 | for (i, data) in self.files.into_iter().enumerate() { |
151 | let path = data.path(); | ||
95 | assert!(path.starts_with('/')); | 152 | assert!(path.starts_with('/')); |
96 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); | 153 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); |
154 | let cfg_options = data.cfg_options(); | ||
97 | let file_id = FileId(i as u32 + 1); | 155 | let file_id = FileId(i as u32 + 1); |
98 | let cfg_options = CfgOptions::default(); | ||
99 | if path == "/lib.rs" || path == "/main.rs" { | 156 | if path == "/lib.rs" || path == "/main.rs" { |
100 | root_crate = Some(crate_graph.add_crate_root( | 157 | root_crate = Some(crate_graph.add_crate_root( |
101 | file_id, | 158 | file_id, |
@@ -123,7 +180,7 @@ impl MockAnalysis { | |||
123 | .unwrap(); | 180 | .unwrap(); |
124 | } | 181 | } |
125 | } | 182 | } |
126 | change.add_file(source_root, file_id, path, Arc::new(contents)); | 183 | change.add_file(source_root, file_id, path, Arc::new(data.content().to_owned())); |
127 | } | 184 | } |
128 | change.set_crate_graph(crate_graph); | 185 | change.set_crate_graph(crate_graph); |
129 | host.apply_change(change); | 186 | host.apply_change(change); |
@@ -132,6 +189,10 @@ impl MockAnalysis { | |||
132 | pub fn analysis(self) -> Analysis { | 189 | pub fn analysis(self) -> Analysis { |
133 | self.analysis_host().analysis() | 190 | self.analysis_host().analysis() |
134 | } | 191 | } |
192 | |||
193 | fn next_id(&self) -> FileId { | ||
194 | FileId((self.files.len() + 1) as u32) | ||
195 | } | ||
135 | } | 196 | } |
136 | 197 | ||
137 | /// Creates analysis from a multi-file fixture, returns positions marked with <|>. | 198 | /// Creates analysis from a multi-file fixture, returns positions marked with <|>. |