aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/base_db/src/change.rs97
-rw-r--r--crates/base_db/src/fixture.rs175
-rw-r--r--crates/base_db/src/lib.rs2
-rw-r--r--crates/ide/src/call_hierarchy.rs56
-rw-r--r--crates/ide/src/call_info.rs4
-rw-r--r--crates/ide/src/completion.rs4
-rw-r--r--crates/ide/src/completion/complete_keyword.rs8
-rw-r--r--crates/ide/src/completion/complete_mod.rs4
-rw-r--r--crates/ide/src/completion/complete_qualified_path.rs4
-rw-r--r--crates/ide/src/completion/complete_unqualified_path.rs14
-rw-r--r--crates/ide/src/completion/presentation.rs4
-rw-r--r--crates/ide/src/completion/test_utils.rs9
-rw-r--r--crates/ide/src/diagnostics.rs39
-rw-r--r--crates/ide/src/display/navigation_target.rs10
-rw-r--r--crates/ide/src/expand_macro.rs4
-rw-r--r--crates/ide/src/extend_selection.rs4
-rw-r--r--crates/ide/src/fixture.rs70
-rw-r--r--crates/ide/src/fn_references.rs10
-rw-r--r--crates/ide/src/goto_definition.rs24
-rw-r--r--crates/ide/src/goto_implementation.rs6
-rw-r--r--crates/ide/src/goto_type_definition.rs7
-rw-r--r--crates/ide/src/hover.rs108
-rw-r--r--crates/ide/src/inlay_hints.rs6
-rw-r--r--crates/ide/src/lib.rs9
-rw-r--r--crates/ide/src/mock_analysis.rs176
-rw-r--r--crates/ide/src/parent_module.rs46
-rw-r--r--crates/ide/src/references.rs118
-rw-r--r--crates/ide/src/references/rename.rs42
-rw-r--r--crates/ide/src/runnables.rs44
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs16
-rw-r--r--crates/ide/src/syntax_tree.rs16
-rw-r--r--crates/ide/src/typing/on_enter.rs4
-rw-r--r--crates/ide_db/src/apply_change.rs (renamed from crates/ide_db/src/change.rs)78
-rw-r--r--crates/ide_db/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/cli/analysis_bench.rs7
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs4
-rw-r--r--crates/rust-analyzer/src/global_state.rs4
-rw-r--r--crates/rust-analyzer/src/reload.rs4
38 files changed, 567 insertions, 672 deletions
diff --git a/crates/base_db/src/change.rs b/crates/base_db/src/change.rs
new file mode 100644
index 000000000..043e03bba
--- /dev/null
+++ b/crates/base_db/src/change.rs
@@ -0,0 +1,97 @@
1//! Defines a unit of change that can applied to the database to get the next
2//! state. Changes are transactional.
3
4use std::{fmt, sync::Arc};
5
6use rustc_hash::FxHashSet;
7use salsa::Durability;
8use vfs::FileId;
9
10use crate::{CrateGraph, SourceDatabaseExt, SourceRoot, SourceRootId};
11
12/// Encapsulate a bunch of raw `.set` calls on the database.
13#[derive(Default)]
14pub struct Change {
15 pub roots: Option<Vec<SourceRoot>>,
16 pub files_changed: Vec<(FileId, Option<Arc<String>>)>,
17 pub crate_graph: Option<CrateGraph>,
18}
19
20impl fmt::Debug for Change {
21 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
22 let mut d = fmt.debug_struct("AnalysisChange");
23 if let Some(roots) = &self.roots {
24 d.field("roots", roots);
25 }
26 if !self.files_changed.is_empty() {
27 d.field("files_changed", &self.files_changed.len());
28 }
29 if self.crate_graph.is_some() {
30 d.field("crate_graph", &self.crate_graph);
31 }
32 d.finish()
33 }
34}
35
36impl Change {
37 pub fn new() -> Change {
38 Change::default()
39 }
40
41 pub fn set_roots(&mut self, roots: Vec<SourceRoot>) {
42 self.roots = Some(roots);
43 }
44
45 pub fn change_file(&mut self, file_id: FileId, new_text: Option<Arc<String>>) {
46 self.files_changed.push((file_id, new_text))
47 }
48
49 pub fn set_crate_graph(&mut self, graph: CrateGraph) {
50 self.crate_graph = Some(graph);
51 }
52
53 pub fn apply(self, db: &mut dyn SourceDatabaseExt) {
54 let _p = profile::span("RootDatabase::apply_change");
55 // db.request_cancellation();
56 // log::info!("apply_change {:?}", change);
57 if let Some(roots) = self.roots {
58 let mut local_roots = FxHashSet::default();
59 let mut library_roots = FxHashSet::default();
60 for (idx, root) in roots.into_iter().enumerate() {
61 let root_id = SourceRootId(idx as u32);
62 let durability = durability(&root);
63 if root.is_library {
64 library_roots.insert(root_id);
65 } else {
66 local_roots.insert(root_id);
67 }
68 for file_id in root.iter() {
69 db.set_file_source_root_with_durability(file_id, root_id, durability);
70 }
71 db.set_source_root_with_durability(root_id, Arc::new(root), durability);
72 }
73 // db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
74 // db.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH);
75 }
76
77 for (file_id, text) in self.files_changed {
78 let source_root_id = db.file_source_root(file_id);
79 let source_root = db.source_root(source_root_id);
80 let durability = durability(&source_root);
81 // XXX: can't actually remove the file, just reset the text
82 let text = text.unwrap_or_default();
83 db.set_file_text_with_durability(file_id, text, durability)
84 }
85 if let Some(crate_graph) = self.crate_graph {
86 db.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
87 }
88 }
89}
90
91fn durability(source_root: &SourceRoot) -> Durability {
92 if source_root.is_library {
93 Durability::HIGH
94 } else {
95 Durability::LOW
96 }
97}
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs
index 5ff8ead0e..b7286fc7d 100644
--- a/crates/base_db/src/fixture.rs
+++ b/crates/base_db/src/fixture.rs
@@ -65,24 +65,26 @@ use test_utils::{extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER}
65use vfs::{file_set::FileSet, VfsPath}; 65use vfs::{file_set::FileSet, VfsPath};
66 66
67use crate::{ 67use crate::{
68 input::CrateName, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, SourceDatabaseExt, 68 input::CrateName, Change, CrateGraph, CrateId, Edition, Env, FileId, FilePosition,
69 SourceRoot, SourceRootId, 69 SourceDatabaseExt, SourceRoot, SourceRootId,
70}; 70};
71 71
72pub const WORKSPACE: SourceRootId = SourceRootId(0); 72pub const WORKSPACE: SourceRootId = SourceRootId(0);
73 73
74pub trait WithFixture: Default + SourceDatabaseExt + 'static { 74pub trait WithFixture: Default + SourceDatabaseExt + 'static {
75 fn with_single_file(text: &str) -> (Self, FileId) { 75 fn with_single_file(text: &str) -> (Self, FileId) {
76 let fixture = ChangeFixture::parse(text);
76 let mut db = Self::default(); 77 let mut db = Self::default();
77 let (_, files) = with_files(&mut db, text); 78 fixture.change.apply(&mut db);
78 assert_eq!(files.len(), 1); 79 assert_eq!(fixture.files.len(), 1);
79 (db, files[0]) 80 (db, fixture.files[0])
80 } 81 }
81 82
82 fn with_files(ra_fixture: &str) -> Self { 83 fn with_files(ra_fixture: &str) -> Self {
84 let fixture = ChangeFixture::parse(ra_fixture);
83 let mut db = Self::default(); 85 let mut db = Self::default();
84 let (pos, _) = with_files(&mut db, ra_fixture); 86 fixture.change.apply(&mut db);
85 assert!(pos.is_none()); 87 assert!(fixture.file_position.is_none());
86 db 88 db
87 } 89 }
88 90
@@ -96,9 +98,10 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
96 } 98 }
97 99
98 fn with_range_or_offset(ra_fixture: &str) -> (Self, FileId, RangeOrOffset) { 100 fn with_range_or_offset(ra_fixture: &str) -> (Self, FileId, RangeOrOffset) {
101 let fixture = ChangeFixture::parse(ra_fixture);
99 let mut db = Self::default(); 102 let mut db = Self::default();
100 let (pos, _) = with_files(&mut db, ra_fixture); 103 fixture.change.apply(&mut db);
101 let (file_id, range_or_offset) = pos.unwrap(); 104 let (file_id, range_or_offset) = fixture.file_position.unwrap();
102 (db, file_id, range_or_offset) 105 (db, file_id, range_or_offset)
103 } 106 }
104 107
@@ -113,89 +116,95 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
113 116
114impl<DB: SourceDatabaseExt + Default + 'static> WithFixture for DB {} 117impl<DB: SourceDatabaseExt + Default + 'static> WithFixture for DB {}
115 118
116fn with_files( 119pub struct ChangeFixture {
117 db: &mut dyn SourceDatabaseExt, 120 pub file_position: Option<(FileId, RangeOrOffset)>,
118 fixture: &str, 121 pub files: Vec<FileId>,
119) -> (Option<(FileId, RangeOrOffset)>, Vec<FileId>) { 122 pub change: Change,
120 let fixture = Fixture::parse(fixture); 123}
121
122 let mut files = Vec::new();
123 let mut crate_graph = CrateGraph::default();
124 let mut crates = FxHashMap::default();
125 let mut crate_deps = Vec::new();
126 let mut default_crate_root: Option<FileId> = None;
127
128 let mut file_set = FileSet::default();
129 let source_root_id = WORKSPACE;
130 let source_root_prefix = "/".to_string();
131 let mut file_id = FileId(0);
132
133 let mut file_position = None;
134
135 for entry in fixture {
136 let text = if entry.text.contains(CURSOR_MARKER) {
137 let (range_or_offset, text) = extract_range_or_offset(&entry.text);
138 assert!(file_position.is_none());
139 file_position = Some((file_id, range_or_offset));
140 text.to_string()
141 } else {
142 entry.text.clone()
143 };
144 124
145 let meta = FileMeta::from(entry); 125impl ChangeFixture {
146 assert!(meta.path.starts_with(&source_root_prefix)); 126 pub fn parse(ra_fixture: &str) -> ChangeFixture {
127 let fixture = Fixture::parse(ra_fixture);
128 let mut change = Change::new();
129
130 let mut files = Vec::new();
131 let mut crate_graph = CrateGraph::default();
132 let mut crates = FxHashMap::default();
133 let mut crate_deps = Vec::new();
134 let mut default_crate_root: Option<FileId> = None;
135 let mut default_cfg = CfgOptions::default();
136
137 let mut file_set = FileSet::default();
138 let source_root_prefix = "/".to_string();
139 let mut file_id = FileId(0);
140
141 let mut file_position = None;
142
143 for entry in fixture {
144 let text = if entry.text.contains(CURSOR_MARKER) {
145 let (range_or_offset, text) = extract_range_or_offset(&entry.text);
146 assert!(file_position.is_none());
147 file_position = Some((file_id, range_or_offset));
148 text.to_string()
149 } else {
150 entry.text.clone()
151 };
152
153 let meta = FileMeta::from(entry);
154 assert!(meta.path.starts_with(&source_root_prefix));
155
156 if let Some(krate) = meta.krate {
157 let crate_id = crate_graph.add_crate_root(
158 file_id,
159 meta.edition,
160 Some(krate.clone()),
161 meta.cfg,
162 meta.env,
163 Default::default(),
164 );
165 let crate_name = CrateName::new(&krate).unwrap();
166 let prev = crates.insert(crate_name.clone(), crate_id);
167 assert!(prev.is_none());
168 for dep in meta.deps {
169 let dep = CrateName::new(&dep).unwrap();
170 crate_deps.push((crate_name.clone(), dep))
171 }
172 } else if meta.path == "/main.rs" || meta.path == "/lib.rs" {
173 assert!(default_crate_root.is_none());
174 default_crate_root = Some(file_id);
175 default_cfg = meta.cfg;
176 }
177
178 change.change_file(file_id, Some(Arc::new(text)));
179 let path = VfsPath::new_virtual_path(meta.path);
180 file_set.insert(file_id, path.into());
181 files.push(file_id);
182 file_id.0 += 1;
183 }
147 184
148 if let Some(krate) = meta.krate { 185 if crates.is_empty() {
149 let crate_id = crate_graph.add_crate_root( 186 let crate_root = default_crate_root.unwrap();
150 file_id, 187 crate_graph.add_crate_root(
151 meta.edition, 188 crate_root,
152 Some(krate.clone()), 189 Edition::Edition2018,
153 meta.cfg, 190 Some("test".to_string()),
154 meta.env, 191 default_cfg,
192 Env::default(),
155 Default::default(), 193 Default::default(),
156 ); 194 );
157 let crate_name = CrateName::new(&krate).unwrap(); 195 } else {
158 let prev = crates.insert(crate_name.clone(), crate_id); 196 for (from, to) in crate_deps {
159 assert!(prev.is_none()); 197 let from_id = crates[&from];
160 for dep in meta.deps { 198 let to_id = crates[&to];
161 let dep = CrateName::new(&dep).unwrap(); 199 crate_graph.add_dep(from_id, CrateName::new(&to).unwrap(), to_id).unwrap();
162 crate_deps.push((crate_name.clone(), dep))
163 } 200 }
164 } else if meta.path == "/main.rs" || meta.path == "/lib.rs" {
165 assert!(default_crate_root.is_none());
166 default_crate_root = Some(file_id);
167 } 201 }
168 202
169 db.set_file_text(file_id, Arc::new(text)); 203 change.set_roots(vec![SourceRoot::new_local(file_set)]);
170 db.set_file_source_root(file_id, source_root_id); 204 change.set_crate_graph(crate_graph);
171 let path = VfsPath::new_virtual_path(meta.path);
172 file_set.insert(file_id, path.into());
173 files.push(file_id);
174 file_id.0 += 1;
175 }
176 205
177 if crates.is_empty() { 206 ChangeFixture { file_position, files, change }
178 let crate_root = default_crate_root.unwrap();
179 crate_graph.add_crate_root(
180 crate_root,
181 Edition::Edition2018,
182 None,
183 CfgOptions::default(),
184 Env::default(),
185 Default::default(),
186 );
187 } else {
188 for (from, to) in crate_deps {
189 let from_id = crates[&from];
190 let to_id = crates[&to];
191 crate_graph.add_dep(from_id, CrateName::new(&to).unwrap(), to_id).unwrap();
192 }
193 } 207 }
194
195 db.set_source_root(source_root_id, Arc::new(SourceRoot::new_local(file_set)));
196 db.set_crate_graph(Arc::new(crate_graph));
197
198 (file_position, files)
199} 208}
200 209
201struct FileMeta { 210struct FileMeta {
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs
index ee3415850..e38aa7257 100644
--- a/crates/base_db/src/lib.rs
+++ b/crates/base_db/src/lib.rs
@@ -1,6 +1,7 @@
1//! base_db defines basic database traits. The concrete DB is defined by ide. 1//! base_db defines basic database traits. The concrete DB is defined by ide.
2mod cancellation; 2mod cancellation;
3mod input; 3mod input;
4mod change;
4pub mod fixture; 5pub mod fixture;
5 6
6use std::{panic, sync::Arc}; 7use std::{panic, sync::Arc};
@@ -10,6 +11,7 @@ use syntax::{ast, Parse, SourceFile, TextRange, TextSize};
10 11
11pub use crate::{ 12pub use crate::{
12 cancellation::Canceled, 13 cancellation::Canceled,
14 change::Change,
13 input::{ 15 input::{
14 CrateData, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, FileId, ProcMacroId, 16 CrateData, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, FileId, ProcMacroId,
15 SourceRoot, SourceRootId, 17 SourceRoot, SourceRootId,
diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs
index 58e26b94c..d2cf2cc7d 100644
--- a/crates/ide/src/call_hierarchy.rs
+++ b/crates/ide/src/call_hierarchy.rs
@@ -139,7 +139,7 @@ impl CallLocations {
139mod tests { 139mod tests {
140 use base_db::FilePosition; 140 use base_db::FilePosition;
141 141
142 use crate::mock_analysis::analysis_and_position; 142 use crate::fixture;
143 143
144 fn check_hierarchy( 144 fn check_hierarchy(
145 ra_fixture: &str, 145 ra_fixture: &str,
@@ -147,7 +147,7 @@ mod tests {
147 expected_incoming: &[&str], 147 expected_incoming: &[&str],
148 expected_outgoing: &[&str], 148 expected_outgoing: &[&str],
149 ) { 149 ) {
150 let (analysis, pos) = analysis_and_position(ra_fixture); 150 let (analysis, pos) = fixture::position(ra_fixture);
151 151
152 let mut navs = analysis.call_hierarchy(pos).unwrap().unwrap().info; 152 let mut navs = analysis.call_hierarchy(pos).unwrap().unwrap().info;
153 assert_eq!(navs.len(), 1); 153 assert_eq!(navs.len(), 1);
@@ -181,8 +181,8 @@ fn caller() {
181 call<|>ee(); 181 call<|>ee();
182} 182}
183"#, 183"#,
184 "callee FN FileId(1) 0..14 3..9", 184 "callee FN FileId(0) 0..14 3..9",
185 &["caller FN FileId(1) 15..44 18..24 : [33..39]"], 185 &["caller FN FileId(0) 15..44 18..24 : [33..39]"],
186 &[], 186 &[],
187 ); 187 );
188 } 188 }
@@ -197,8 +197,8 @@ fn caller() {
197 callee(); 197 callee();
198} 198}
199"#, 199"#,
200 "callee FN FileId(1) 0..14 3..9", 200 "callee FN FileId(0) 0..14 3..9",
201 &["caller FN FileId(1) 15..44 18..24 : [33..39]"], 201 &["caller FN FileId(0) 15..44 18..24 : [33..39]"],
202 &[], 202 &[],
203 ); 203 );
204 } 204 }
@@ -214,8 +214,8 @@ fn caller() {
214 callee(); 214 callee();
215} 215}
216"#, 216"#,
217 "callee FN FileId(1) 0..14 3..9", 217 "callee FN FileId(0) 0..14 3..9",
218 &["caller FN FileId(1) 15..58 18..24 : [33..39, 47..53]"], 218 &["caller FN FileId(0) 15..58 18..24 : [33..39, 47..53]"],
219 &[], 219 &[],
220 ); 220 );
221 } 221 }
@@ -234,10 +234,10 @@ fn caller2() {
234 callee(); 234 callee();
235} 235}
236"#, 236"#,
237 "callee FN FileId(1) 0..14 3..9", 237 "callee FN FileId(0) 0..14 3..9",
238 &[ 238 &[
239 "caller1 FN FileId(1) 15..45 18..25 : [34..40]", 239 "caller1 FN FileId(0) 15..45 18..25 : [34..40]",
240 "caller2 FN FileId(1) 47..77 50..57 : [66..72]", 240 "caller2 FN FileId(0) 47..77 50..57 : [66..72]",
241 ], 241 ],
242 &[], 242 &[],
243 ); 243 );
@@ -263,10 +263,10 @@ mod tests {
263 } 263 }
264} 264}
265"#, 265"#,
266 "callee FN FileId(1) 0..14 3..9", 266 "callee FN FileId(0) 0..14 3..9",
267 &[ 267 &[
268 "caller1 FN FileId(1) 15..45 18..25 : [34..40]", 268 "caller1 FN FileId(0) 15..45 18..25 : [34..40]",
269 "test_caller FN FileId(1) 95..149 110..121 : [134..140]", 269 "test_caller FN FileId(0) 95..149 110..121 : [134..140]",
270 ], 270 ],
271 &[], 271 &[],
272 ); 272 );
@@ -287,8 +287,8 @@ fn caller() {
287//- /foo/mod.rs 287//- /foo/mod.rs
288pub fn callee() {} 288pub fn callee() {}
289"#, 289"#,
290 "callee FN FileId(2) 0..18 7..13", 290 "callee FN FileId(1) 0..18 7..13",
291 &["caller FN FileId(1) 27..56 30..36 : [45..51]"], 291 &["caller FN FileId(0) 27..56 30..36 : [45..51]"],
292 &[], 292 &[],
293 ); 293 );
294 } 294 }
@@ -304,9 +304,9 @@ fn call<|>er() {
304 callee(); 304 callee();
305} 305}
306"#, 306"#,
307 "caller FN FileId(1) 15..58 18..24", 307 "caller FN FileId(0) 15..58 18..24",
308 &[], 308 &[],
309 &["callee FN FileId(1) 0..14 3..9 : [33..39, 47..53]"], 309 &["callee FN FileId(0) 0..14 3..9 : [33..39, 47..53]"],
310 ); 310 );
311 } 311 }
312 312
@@ -325,9 +325,9 @@ fn call<|>er() {
325//- /foo/mod.rs 325//- /foo/mod.rs
326pub fn callee() {} 326pub fn callee() {}
327"#, 327"#,
328 "caller FN FileId(1) 27..56 30..36", 328 "caller FN FileId(0) 27..56 30..36",
329 &[], 329 &[],
330 &["callee FN FileId(2) 0..18 7..13 : [45..51]"], 330 &["callee FN FileId(1) 0..18 7..13 : [45..51]"],
331 ); 331 );
332 } 332 }
333 333
@@ -348,9 +348,9 @@ fn caller3() {
348 348
349} 349}
350"#, 350"#,
351 "caller2 FN FileId(1) 33..64 36..43", 351 "caller2 FN FileId(0) 33..64 36..43",
352 &["caller1 FN FileId(1) 0..31 3..10 : [19..26]"], 352 &["caller1 FN FileId(0) 0..31 3..10 : [19..26]"],
353 &["caller3 FN FileId(1) 66..83 69..76 : [52..59]"], 353 &["caller3 FN FileId(0) 66..83 69..76 : [52..59]"],
354 ); 354 );
355 } 355 }
356 356
@@ -368,9 +368,9 @@ fn main() {
368 a<|>() 368 a<|>()
369} 369}
370"#, 370"#,
371 "a FN FileId(1) 0..18 3..4", 371 "a FN FileId(0) 0..18 3..4",
372 &["main FN FileId(1) 31..52 34..38 : [47..48]"], 372 &["main FN FileId(0) 31..52 34..38 : [47..48]"],
373 &["b FN FileId(1) 20..29 23..24 : [13..14]"], 373 &["b FN FileId(0) 20..29 23..24 : [13..14]"],
374 ); 374 );
375 375
376 check_hierarchy( 376 check_hierarchy(
@@ -385,8 +385,8 @@ fn main() {
385 a() 385 a()
386} 386}
387"#, 387"#,
388 "b FN FileId(1) 20..29 23..24", 388 "b FN FileId(0) 20..29 23..24",
389 &["a FN FileId(1) 0..18 3..4 : [13..14]"], 389 &["a FN FileId(0) 0..18 3..4 : [13..14]"],
390 &[], 390 &[],
391 ); 391 );
392 } 392 }
diff --git a/crates/ide/src/call_info.rs b/crates/ide/src/call_info.rs
index 7e99c6b72..d7b2b926e 100644
--- a/crates/ide/src/call_info.rs
+++ b/crates/ide/src/call_info.rs
@@ -232,10 +232,10 @@ mod tests {
232 use expect_test::{expect, Expect}; 232 use expect_test::{expect, Expect};
233 use test_utils::mark; 233 use test_utils::mark;
234 234
235 use crate::mock_analysis::analysis_and_position; 235 use crate::fixture;
236 236
237 fn check(ra_fixture: &str, expect: Expect) { 237 fn check(ra_fixture: &str, expect: Expect) {
238 let (analysis, position) = analysis_and_position(ra_fixture); 238 let (analysis, position) = fixture::position(ra_fixture);
239 let call_info = analysis.call_info(position).unwrap(); 239 let call_info = analysis.call_info(position).unwrap();
240 let actual = match call_info { 240 let actual = match call_info {
241 Some(call_info) => { 241 Some(call_info) => {
diff --git a/crates/ide/src/completion.rs b/crates/ide/src/completion.rs
index daea2aa95..697f691b0 100644
--- a/crates/ide/src/completion.rs
+++ b/crates/ide/src/completion.rs
@@ -133,7 +133,7 @@ pub(crate) fn completions(
133#[cfg(test)] 133#[cfg(test)]
134mod tests { 134mod tests {
135 use crate::completion::completion_config::CompletionConfig; 135 use crate::completion::completion_config::CompletionConfig;
136 use crate::mock_analysis::analysis_and_position; 136 use crate::fixture;
137 137
138 struct DetailAndDocumentation<'a> { 138 struct DetailAndDocumentation<'a> {
139 detail: &'a str, 139 detail: &'a str,
@@ -141,7 +141,7 @@ mod tests {
141 } 141 }
142 142
143 fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) { 143 fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) {
144 let (analysis, position) = analysis_and_position(ra_fixture); 144 let (analysis, position) = fixture::position(ra_fixture);
145 let config = CompletionConfig::default(); 145 let config = CompletionConfig::default();
146 let completions = analysis.completions(&config, position).unwrap().unwrap(); 146 let completions = analysis.completions(&config, position).unwrap().unwrap();
147 for item in completions { 147 for item in completions {
diff --git a/crates/ide/src/completion/complete_keyword.rs b/crates/ide/src/completion/complete_keyword.rs
index 5645b41fa..e59747095 100644
--- a/crates/ide/src/completion/complete_keyword.rs
+++ b/crates/ide/src/completion/complete_keyword.rs
@@ -495,13 +495,13 @@ Some multi-line comment<|>
495 fn test_completion_await_impls_future() { 495 fn test_completion_await_impls_future() {
496 check( 496 check(
497 r#" 497 r#"
498//- /main.rs 498//- /main.rs crate:main deps:std
499use std::future::*; 499use std::future::*;
500struct A {} 500struct A {}
501impl Future for A {} 501impl Future for A {}
502fn foo(a: A) { a.<|> } 502fn foo(a: A) { a.<|> }
503 503
504//- /std/lib.rs 504//- /std/lib.rs crate:std
505pub mod future { 505pub mod future {
506 #[lang = "future_trait"] 506 #[lang = "future_trait"]
507 pub trait Future {} 507 pub trait Future {}
@@ -514,14 +514,14 @@ pub mod future {
514 514
515 check( 515 check(
516 r#" 516 r#"
517//- /main.rs 517//- /main.rs crate:main deps:std
518use std::future::*; 518use std::future::*;
519fn foo() { 519fn foo() {
520 let a = async {}; 520 let a = async {};
521 a.<|> 521 a.<|>
522} 522}
523 523
524//- /std/lib.rs 524//- /std/lib.rs crate:std
525pub mod future { 525pub mod future {
526 #[lang = "future_trait"] 526 #[lang = "future_trait"]
527 pub trait Future { 527 pub trait Future {
diff --git a/crates/ide/src/completion/complete_mod.rs b/crates/ide/src/completion/complete_mod.rs
index 3cfc2e131..c7a99bdc3 100644
--- a/crates/ide/src/completion/complete_mod.rs
+++ b/crates/ide/src/completion/complete_mod.rs
@@ -300,7 +300,7 @@ mod tests {
300 // "#, 300 // "#,
301 // expect![[r#" 301 // expect![[r#"
302 // md bar; 302 // md bar;
303 // "#]], 303 // "#]],foo
304 // ); 304 // );
305 // } 305 // }
306 306
@@ -308,7 +308,7 @@ mod tests {
308 fn already_declared_bin_module_completion_omitted() { 308 fn already_declared_bin_module_completion_omitted() {
309 check( 309 check(
310 r#" 310 r#"
311 //- /src/bin.rs 311 //- /src/bin.rs crate:main
312 fn main() {} 312 fn main() {}
313 //- /src/bin/foo.rs 313 //- /src/bin/foo.rs
314 mod <|> 314 mod <|>
diff --git a/crates/ide/src/completion/complete_qualified_path.rs b/crates/ide/src/completion/complete_qualified_path.rs
index 00e89f0fd..2fafedd47 100644
--- a/crates/ide/src/completion/complete_qualified_path.rs
+++ b/crates/ide/src/completion/complete_qualified_path.rs
@@ -422,10 +422,10 @@ fn foo() { let _ = U::<|> }
422 fn completes_use_paths_across_crates() { 422 fn completes_use_paths_across_crates() {
423 check( 423 check(
424 r#" 424 r#"
425//- /main.rs 425//- /main.rs crate:main deps:foo
426use foo::<|>; 426use foo::<|>;
427 427
428//- /foo/lib.rs 428//- /foo/lib.rs crate:foo
429pub mod bar { pub struct S; } 429pub mod bar { pub struct S; }
430"#, 430"#,
431 expect![[r#" 431 expect![[r#"
diff --git a/crates/ide/src/completion/complete_unqualified_path.rs b/crates/ide/src/completion/complete_unqualified_path.rs
index 8eda4b64d..2010d9a2f 100644
--- a/crates/ide/src/completion/complete_unqualified_path.rs
+++ b/crates/ide/src/completion/complete_unqualified_path.rs
@@ -271,10 +271,10 @@ fn quux() { <|> }
271 fn completes_extern_prelude() { 271 fn completes_extern_prelude() {
272 check( 272 check(
273 r#" 273 r#"
274//- /lib.rs 274//- /lib.rs crate:main deps:other_crate
275use <|>; 275use <|>;
276 276
277//- /other_crate/lib.rs 277//- /other_crate/lib.rs crate:other_crate
278// nothing here 278// nothing here
279"#, 279"#,
280 expect![[r#" 280 expect![[r#"
@@ -350,10 +350,10 @@ fn foo() {
350 fn completes_prelude() { 350 fn completes_prelude() {
351 check( 351 check(
352 r#" 352 r#"
353//- /main.rs 353//- /main.rs crate:main deps:std
354fn foo() { let x: <|> } 354fn foo() { let x: <|> }
355 355
356//- /std/lib.rs 356//- /std/lib.rs crate:std
357#[prelude_import] 357#[prelude_import]
358use prelude::*; 358use prelude::*;
359 359
@@ -371,16 +371,16 @@ mod prelude { struct Option; }
371 fn completes_std_prelude_if_core_is_defined() { 371 fn completes_std_prelude_if_core_is_defined() {
372 check( 372 check(
373 r#" 373 r#"
374//- /main.rs 374//- /main.rs crate:main deps:core,std
375fn foo() { let x: <|> } 375fn foo() { let x: <|> }
376 376
377//- /core/lib.rs 377//- /core/lib.rs crate:core
378#[prelude_import] 378#[prelude_import]
379use prelude::*; 379use prelude::*;
380 380
381mod prelude { struct Option; } 381mod prelude { struct Option; }
382 382
383//- /std/lib.rs 383//- /std/lib.rs crate:std deps:core
384#[prelude_import] 384#[prelude_import]
385use prelude::*; 385use prelude::*;
386 386
diff --git a/crates/ide/src/completion/presentation.rs b/crates/ide/src/completion/presentation.rs
index 987cbfa7a..a5172b87e 100644
--- a/crates/ide/src/completion/presentation.rs
+++ b/crates/ide/src/completion/presentation.rs
@@ -1172,9 +1172,9 @@ fn foo(xs: Vec<i128>)
1172 check_edit( 1172 check_edit(
1173 "frobnicate!", 1173 "frobnicate!",
1174 r#" 1174 r#"
1175//- /main.rs 1175//- /main.rs crate:main deps:foo
1176use foo::<|>; 1176use foo::<|>;
1177//- /foo/lib.rs 1177//- /foo/lib.rs crate:foo
1178#[macro_export] 1178#[macro_export]
1179macro_rules frobnicate { () => () } 1179macro_rules frobnicate { () => () }
1180"#, 1180"#,
diff --git a/crates/ide/src/completion/test_utils.rs b/crates/ide/src/completion/test_utils.rs
index 1452d7e9e..feb8cd2a6 100644
--- a/crates/ide/src/completion/test_utils.rs
+++ b/crates/ide/src/completion/test_utils.rs
@@ -8,8 +8,7 @@ use test_utils::assert_eq_text;
8 8
9use crate::{ 9use crate::{
10 completion::{completion_item::CompletionKind, CompletionConfig}, 10 completion::{completion_item::CompletionKind, CompletionConfig},
11 mock_analysis::analysis_and_position, 11 fixture, CompletionItem,
12 CompletionItem,
13}; 12};
14 13
15pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { 14pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
@@ -80,7 +79,7 @@ pub(crate) fn check_edit_with_config(
80 ra_fixture_after: &str, 79 ra_fixture_after: &str,
81) { 80) {
82 let ra_fixture_after = trim_indent(ra_fixture_after); 81 let ra_fixture_after = trim_indent(ra_fixture_after);
83 let (analysis, position) = analysis_and_position(ra_fixture_before); 82 let (analysis, position) = fixture::position(ra_fixture_before);
84 let completions: Vec<CompletionItem> = 83 let completions: Vec<CompletionItem> =
85 analysis.completions(&config, position).unwrap().unwrap().into(); 84 analysis.completions(&config, position).unwrap().unwrap().into();
86 let (completion,) = completions 85 let (completion,) = completions
@@ -94,7 +93,7 @@ pub(crate) fn check_edit_with_config(
94} 93}
95 94
96pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) { 95pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) {
97 let (analysis, pos) = analysis_and_position(code); 96 let (analysis, pos) = fixture::position(code);
98 analysis 97 analysis
99 .with_db(|db| { 98 .with_db(|db| {
100 let sema = Semantics::new(db); 99 let sema = Semantics::new(db);
@@ -109,6 +108,6 @@ pub(crate) fn get_all_completion_items(
109 config: CompletionConfig, 108 config: CompletionConfig,
110 code: &str, 109 code: &str,
111) -> Vec<CompletionItem> { 110) -> Vec<CompletionItem> {
112 let (analysis, position) = analysis_and_position(code); 111 let (analysis, position) = fixture::position(code);
113 analysis.completions(&config, position).unwrap().unwrap().into() 112 analysis.completions(&config, position).unwrap().unwrap().into()
114} 113}
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index dc815a483..f5d627b6e 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -218,10 +218,7 @@ mod tests {
218 use stdx::trim_indent; 218 use stdx::trim_indent;
219 use test_utils::assert_eq_text; 219 use test_utils::assert_eq_text;
220 220
221 use crate::{ 221 use crate::{fixture, DiagnosticsConfig};
222 mock_analysis::{analysis_and_position, single_file, MockAnalysis},
223 DiagnosticsConfig,
224 };
225 222
226 /// Takes a multi-file input fixture with annotated cursor positions, 223 /// Takes a multi-file input fixture with annotated cursor positions,
227 /// and checks that: 224 /// and checks that:
@@ -231,7 +228,7 @@ mod tests {
231 fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) { 228 fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) {
232 let after = trim_indent(ra_fixture_after); 229 let after = trim_indent(ra_fixture_after);
233 230
234 let (analysis, file_position) = analysis_and_position(ra_fixture_before); 231 let (analysis, file_position) = fixture::position(ra_fixture_before);
235 let diagnostic = analysis 232 let diagnostic = analysis
236 .diagnostics(&DiagnosticsConfig::default(), file_position.file_id) 233 .diagnostics(&DiagnosticsConfig::default(), file_position.file_id)
237 .unwrap() 234 .unwrap()
@@ -260,7 +257,7 @@ mod tests {
260 /// which has a fix that can apply to other files. 257 /// which has a fix that can apply to other files.
261 fn check_apply_diagnostic_fix_in_other_file(ra_fixture_before: &str, ra_fixture_after: &str) { 258 fn check_apply_diagnostic_fix_in_other_file(ra_fixture_before: &str, ra_fixture_after: &str) {
262 let ra_fixture_after = &trim_indent(ra_fixture_after); 259 let ra_fixture_after = &trim_indent(ra_fixture_after);
263 let (analysis, file_pos) = analysis_and_position(ra_fixture_before); 260 let (analysis, file_pos) = fixture::position(ra_fixture_before);
264 let current_file_id = file_pos.file_id; 261 let current_file_id = file_pos.file_id;
265 let diagnostic = analysis 262 let diagnostic = analysis
266 .diagnostics(&DiagnosticsConfig::default(), current_file_id) 263 .diagnostics(&DiagnosticsConfig::default(), current_file_id)
@@ -282,9 +279,7 @@ mod tests {
282 /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics 279 /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics
283 /// apply to the file containing the cursor. 280 /// apply to the file containing the cursor.
284 fn check_no_diagnostics(ra_fixture: &str) { 281 fn check_no_diagnostics(ra_fixture: &str) {
285 let mock = MockAnalysis::with_files(ra_fixture); 282 let (analysis, files) = fixture::files(ra_fixture);
286 let files = mock.files().map(|(it, _)| it).collect::<Vec<_>>();
287 let analysis = mock.analysis();
288 let diagnostics = files 283 let diagnostics = files
289 .into_iter() 284 .into_iter()
290 .flat_map(|file_id| { 285 .flat_map(|file_id| {
@@ -295,7 +290,7 @@ mod tests {
295 } 290 }
296 291
297 fn check_expect(ra_fixture: &str, expect: Expect) { 292 fn check_expect(ra_fixture: &str, expect: Expect) {
298 let (analysis, file_id) = single_file(ra_fixture); 293 let (analysis, file_id) = fixture::file(ra_fixture);
299 let diagnostics = analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap(); 294 let diagnostics = analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap();
300 expect.assert_debug_eq(&diagnostics) 295 expect.assert_debug_eq(&diagnostics)
301 } 296 }
@@ -304,7 +299,7 @@ mod tests {
304 fn test_wrap_return_type() { 299 fn test_wrap_return_type() {
305 check_fix( 300 check_fix(
306 r#" 301 r#"
307//- /main.rs 302//- /main.rs crate:main deps:core
308use core::result::Result::{self, Ok, Err}; 303use core::result::Result::{self, Ok, Err};
309 304
310fn div(x: i32, y: i32) -> Result<i32, ()> { 305fn div(x: i32, y: i32) -> Result<i32, ()> {
@@ -313,7 +308,7 @@ fn div(x: i32, y: i32) -> Result<i32, ()> {
313 } 308 }
314 x / y<|> 309 x / y<|>
315} 310}
316//- /core/lib.rs 311//- /core/lib.rs crate:core
317pub mod result { 312pub mod result {
318 pub enum Result<T, E> { Ok(T), Err(E) } 313 pub enum Result<T, E> { Ok(T), Err(E) }
319} 314}
@@ -335,7 +330,7 @@ fn div(x: i32, y: i32) -> Result<i32, ()> {
335 fn test_wrap_return_type_handles_generic_functions() { 330 fn test_wrap_return_type_handles_generic_functions() {
336 check_fix( 331 check_fix(
337 r#" 332 r#"
338//- /main.rs 333//- /main.rs crate:main deps:core
339use core::result::Result::{self, Ok, Err}; 334use core::result::Result::{self, Ok, Err};
340 335
341fn div<T>(x: T) -> Result<T, i32> { 336fn div<T>(x: T) -> Result<T, i32> {
@@ -344,7 +339,7 @@ fn div<T>(x: T) -> Result<T, i32> {
344 } 339 }
345 <|>x 340 <|>x
346} 341}
347//- /core/lib.rs 342//- /core/lib.rs crate:core
348pub mod result { 343pub mod result {
349 pub enum Result<T, E> { Ok(T), Err(E) } 344 pub enum Result<T, E> { Ok(T), Err(E) }
350} 345}
@@ -366,7 +361,7 @@ fn div<T>(x: T) -> Result<T, i32> {
366 fn test_wrap_return_type_handles_type_aliases() { 361 fn test_wrap_return_type_handles_type_aliases() {
367 check_fix( 362 check_fix(
368 r#" 363 r#"
369//- /main.rs 364//- /main.rs crate:main deps:core
370use core::result::Result::{self, Ok, Err}; 365use core::result::Result::{self, Ok, Err};
371 366
372type MyResult<T> = Result<T, ()>; 367type MyResult<T> = Result<T, ()>;
@@ -377,7 +372,7 @@ fn div(x: i32, y: i32) -> MyResult<i32> {
377 } 372 }
378 x <|>/ y 373 x <|>/ y
379} 374}
380//- /core/lib.rs 375//- /core/lib.rs crate:core
381pub mod result { 376pub mod result {
382 pub enum Result<T, E> { Ok(T), Err(E) } 377 pub enum Result<T, E> { Ok(T), Err(E) }
383} 378}
@@ -401,12 +396,12 @@ fn div(x: i32, y: i32) -> MyResult<i32> {
401 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() { 396 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
402 check_no_diagnostics( 397 check_no_diagnostics(
403 r#" 398 r#"
404//- /main.rs 399//- /main.rs crate:main deps:core
405use core::result::Result::{self, Ok, Err}; 400use core::result::Result::{self, Ok, Err};
406 401
407fn foo() -> Result<(), i32> { 0 } 402fn foo() -> Result<(), i32> { 0 }
408 403
409//- /core/lib.rs 404//- /core/lib.rs crate:core
410pub mod result { 405pub mod result {
411 pub enum Result<T, E> { Ok(T), Err(E) } 406 pub enum Result<T, E> { Ok(T), Err(E) }
412} 407}
@@ -418,14 +413,14 @@ pub mod result {
418 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() { 413 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result() {
419 check_no_diagnostics( 414 check_no_diagnostics(
420 r#" 415 r#"
421//- /main.rs 416//- /main.rs crate:main deps:core
422use core::result::Result::{self, Ok, Err}; 417use core::result::Result::{self, Ok, Err};
423 418
424enum SomeOtherEnum { Ok(i32), Err(String) } 419enum SomeOtherEnum { Ok(i32), Err(String) }
425 420
426fn foo() -> SomeOtherEnum { 0 } 421fn foo() -> SomeOtherEnum { 0 }
427 422
428//- /core/lib.rs 423//- /core/lib.rs crate:core
429pub mod result { 424pub mod result {
430 pub enum Result<T, E> { Ok(T), Err(E) } 425 pub enum Result<T, E> { Ok(T), Err(E) }
431} 426}
@@ -567,7 +562,7 @@ fn test_fn() {
567 file_system_edits: [ 562 file_system_edits: [
568 CreateFile { 563 CreateFile {
569 anchor: FileId( 564 anchor: FileId(
570 1, 565 0,
571 ), 566 ),
572 dst: "foo.rs", 567 dst: "foo.rs",
573 }, 568 },
@@ -787,7 +782,7 @@ struct Foo {
787 let mut config = DiagnosticsConfig::default(); 782 let mut config = DiagnosticsConfig::default();
788 config.disabled.insert("unresolved-module".into()); 783 config.disabled.insert("unresolved-module".into());
789 784
790 let (analysis, file_id) = single_file(r#"mod foo;"#); 785 let (analysis, file_id) = fixture::file(r#"mod foo;"#);
791 786
792 let diagnostics = analysis.diagnostics(&config, file_id).unwrap(); 787 let diagnostics = analysis.diagnostics(&config, file_id).unwrap();
793 assert!(diagnostics.is_empty()); 788 assert!(diagnostics.is_empty());
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index 1ee80c2dd..cf9d617dc 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -423,11 +423,11 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) ->
423mod tests { 423mod tests {
424 use expect_test::expect; 424 use expect_test::expect;
425 425
426 use crate::{mock_analysis::single_file, Query}; 426 use crate::{fixture, Query};
427 427
428 #[test] 428 #[test]
429 fn test_nav_for_symbol() { 429 fn test_nav_for_symbol() {
430 let (analysis, _) = single_file( 430 let (analysis, _) = fixture::file(
431 r#" 431 r#"
432enum FooInner { } 432enum FooInner { }
433fn foo() { enum FooInner { } } 433fn foo() { enum FooInner { } }
@@ -439,7 +439,7 @@ fn foo() { enum FooInner { } }
439 [ 439 [
440 NavigationTarget { 440 NavigationTarget {
441 file_id: FileId( 441 file_id: FileId(
442 1, 442 0,
443 ), 443 ),
444 full_range: 0..17, 444 full_range: 0..17,
445 focus_range: Some( 445 focus_range: Some(
@@ -455,7 +455,7 @@ fn foo() { enum FooInner { } }
455 }, 455 },
456 NavigationTarget { 456 NavigationTarget {
457 file_id: FileId( 457 file_id: FileId(
458 1, 458 0,
459 ), 459 ),
460 full_range: 29..46, 460 full_range: 29..46,
461 focus_range: Some( 461 focus_range: Some(
@@ -478,7 +478,7 @@ fn foo() { enum FooInner { } }
478 478
479 #[test] 479 #[test]
480 fn test_world_symbols_are_case_sensitive() { 480 fn test_world_symbols_are_case_sensitive() {
481 let (analysis, _) = single_file( 481 let (analysis, _) = fixture::file(
482 r#" 482 r#"
483fn foo() {} 483fn foo() {}
484struct Foo; 484struct Foo;
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index 8a285bcf7..8d75e0f05 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -122,10 +122,10 @@ fn insert_whitespaces(syn: SyntaxNode) -> String {
122mod tests { 122mod tests {
123 use expect_test::{expect, Expect}; 123 use expect_test::{expect, Expect};
124 124
125 use crate::mock_analysis::analysis_and_position; 125 use crate::fixture;
126 126
127 fn check(ra_fixture: &str, expect: Expect) { 127 fn check(ra_fixture: &str, expect: Expect) {
128 let (analysis, pos) = analysis_and_position(ra_fixture); 128 let (analysis, pos) = fixture::position(ra_fixture);
129 let expansion = analysis.expand_macro(pos).unwrap().unwrap(); 129 let expansion = analysis.expand_macro(pos).unwrap().unwrap();
130 let actual = format!("{}\n{}", expansion.name, expansion.expansion); 130 let actual = format!("{}\n{}", expansion.name, expansion.expansion);
131 expect.assert_eq(&actual); 131 expect.assert_eq(&actual);
diff --git a/crates/ide/src/extend_selection.rs b/crates/ide/src/extend_selection.rs
index 34563a026..3ee0af8ad 100644
--- a/crates/ide/src/extend_selection.rs
+++ b/crates/ide/src/extend_selection.rs
@@ -315,12 +315,12 @@ fn adj_comments(comment: &ast::Comment, dir: Direction) -> ast::Comment {
315 315
316#[cfg(test)] 316#[cfg(test)]
317mod tests { 317mod tests {
318 use crate::mock_analysis::analysis_and_position; 318 use crate::fixture;
319 319
320 use super::*; 320 use super::*;
321 321
322 fn do_check(before: &str, afters: &[&str]) { 322 fn do_check(before: &str, afters: &[&str]) {
323 let (analysis, position) = analysis_and_position(&before); 323 let (analysis, position) = fixture::position(&before);
324 let before = analysis.file_text(position.file_id).unwrap(); 324 let before = analysis.file_text(position.file_id).unwrap();
325 let range = TextRange::empty(position.offset); 325 let range = TextRange::empty(position.offset);
326 let mut frange = FileRange { file_id: position.file_id, range }; 326 let mut frange = FileRange { file_id: position.file_id, range };
diff --git a/crates/ide/src/fixture.rs b/crates/ide/src/fixture.rs
new file mode 100644
index 000000000..ed06689f0
--- /dev/null
+++ b/crates/ide/src/fixture.rs
@@ -0,0 +1,70 @@
1//! Utilities for creating `Analysis` instances for tests.
2use base_db::fixture::ChangeFixture;
3use test_utils::{extract_annotations, RangeOrOffset};
4
5use crate::{Analysis, AnalysisHost, FileId, FilePosition, FileRange};
6
7/// Creates analysis for a single file.
8pub(crate) fn file(ra_fixture: &str) -> (Analysis, FileId) {
9 let mut host = AnalysisHost::default();
10 let change_fixture = ChangeFixture::parse(ra_fixture);
11 host.db.apply_change(change_fixture.change);
12 (host.analysis(), change_fixture.files[0])
13}
14
15/// Creates analysis for many files.
16pub(crate) fn files(ra_fixture: &str) -> (Analysis, Vec<FileId>) {
17 let mut host = AnalysisHost::default();
18 let change_fixture = ChangeFixture::parse(ra_fixture);
19 host.db.apply_change(change_fixture.change);
20 (host.analysis(), change_fixture.files)
21}
22
23/// Creates analysis from a multi-file fixture, returns positions marked with <|>.
24pub(crate) fn position(ra_fixture: &str) -> (Analysis, FilePosition) {
25 let mut host = AnalysisHost::default();
26 let change_fixture = ChangeFixture::parse(ra_fixture);
27 host.db.apply_change(change_fixture.change);
28 let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)");
29 let offset = match range_or_offset {
30 RangeOrOffset::Range(_) => panic!(),
31 RangeOrOffset::Offset(it) => it,
32 };
33 (host.analysis(), FilePosition { file_id, offset })
34}
35
36/// Creates analysis for a single file, returns range marked with a pair of <|>.
37pub(crate) fn range(ra_fixture: &str) -> (Analysis, FileRange) {
38 let mut host = AnalysisHost::default();
39 let change_fixture = ChangeFixture::parse(ra_fixture);
40 host.db.apply_change(change_fixture.change);
41 let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)");
42 let range = match range_or_offset {
43 RangeOrOffset::Range(it) => it,
44 RangeOrOffset::Offset(_) => panic!(),
45 };
46 (host.analysis(), FileRange { file_id, range })
47}
48
49/// Creates analysis from a multi-file fixture, returns positions marked with <|>.
50pub(crate) fn annotations(ra_fixture: &str) -> (Analysis, FilePosition, Vec<(FileRange, String)>) {
51 let mut host = AnalysisHost::default();
52 let change_fixture = ChangeFixture::parse(ra_fixture);
53 host.db.apply_change(change_fixture.change);
54 let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)");
55 let offset = match range_or_offset {
56 RangeOrOffset::Range(_) => panic!(),
57 RangeOrOffset::Offset(it) => it,
58 };
59
60 let annotations = change_fixture
61 .files
62 .iter()
63 .flat_map(|&file_id| {
64 let file_text = host.analysis().file_text(file_id).unwrap();
65 let annotations = extract_annotations(&file_text);
66 annotations.into_iter().map(move |(range, data)| (FileRange { file_id, range }, data))
67 })
68 .collect();
69 (host.analysis(), FilePosition { file_id, offset }, annotations)
70}
diff --git a/crates/ide/src/fn_references.rs b/crates/ide/src/fn_references.rs
index 1989a562b..459f201ed 100644
--- a/crates/ide/src/fn_references.rs
+++ b/crates/ide/src/fn_references.rs
@@ -25,15 +25,14 @@ fn method_range(item: SyntaxNode, file_id: FileId) -> Option<FileRange> {
25 25
26#[cfg(test)] 26#[cfg(test)]
27mod tests { 27mod tests {
28 use crate::mock_analysis::analysis_and_position; 28 use crate::fixture;
29 use crate::{FileRange, TextSize}; 29 use crate::{FileRange, TextSize};
30 use std::ops::RangeInclusive; 30 use std::ops::RangeInclusive;
31 31
32 #[test] 32 #[test]
33 fn test_find_all_methods() { 33 fn test_find_all_methods() {
34 let (analysis, pos) = analysis_and_position( 34 let (analysis, pos) = fixture::position(
35 r#" 35 r#"
36 //- /lib.rs
37 fn private_fn() {<|>} 36 fn private_fn() {<|>}
38 37
39 pub fn pub_fn() {} 38 pub fn pub_fn() {}
@@ -48,9 +47,8 @@ mod tests {
48 47
49 #[test] 48 #[test]
50 fn test_find_trait_methods() { 49 fn test_find_trait_methods() {
51 let (analysis, pos) = analysis_and_position( 50 let (analysis, pos) = fixture::position(
52 r#" 51 r#"
53 //- /lib.rs
54 trait Foo { 52 trait Foo {
55 fn bar() {<|>} 53 fn bar() {<|>}
56 fn baz() {} 54 fn baz() {}
@@ -64,7 +62,7 @@ mod tests {
64 62
65 #[test] 63 #[test]
66 fn test_skip_tests() { 64 fn test_skip_tests() {
67 let (analysis, pos) = analysis_and_position( 65 let (analysis, pos) = fixture::position(
68 r#" 66 r#"
69 //- /lib.rs 67 //- /lib.rs
70 #[test] 68 #[test]
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 15e9b7fad..582bf4837 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -103,12 +103,11 @@ mod tests {
103 use base_db::FileRange; 103 use base_db::FileRange;
104 use syntax::{TextRange, TextSize}; 104 use syntax::{TextRange, TextSize};
105 105
106 use crate::mock_analysis::MockAnalysis; 106 use crate::fixture;
107 107
108 fn check(ra_fixture: &str) { 108 fn check(ra_fixture: &str) {
109 let (mock, position) = MockAnalysis::with_files_and_position(ra_fixture); 109 let (analysis, position, mut annotations) = fixture::annotations(ra_fixture);
110 let (mut expected, data) = mock.annotation(); 110 let (mut expected, data) = annotations.pop().unwrap();
111 let analysis = mock.analysis();
112 match data.as_str() { 111 match data.as_str() {
113 "" => (), 112 "" => (),
114 "file" => { 113 "file" => {
@@ -133,9 +132,9 @@ mod tests {
133 fn goto_def_for_extern_crate() { 132 fn goto_def_for_extern_crate() {
134 check( 133 check(
135 r#" 134 r#"
136 //- /main.rs 135 //- /main.rs crate:main deps:std
137 extern crate std<|>; 136 extern crate std<|>;
138 //- /std/lib.rs 137 //- /std/lib.rs crate:std
139 // empty 138 // empty
140 //^ file 139 //^ file
141 "#, 140 "#,
@@ -146,9 +145,9 @@ mod tests {
146 fn goto_def_for_renamed_extern_crate() { 145 fn goto_def_for_renamed_extern_crate() {
147 check( 146 check(
148 r#" 147 r#"
149 //- /main.rs 148 //- /main.rs crate:main deps:std
150 extern crate std as abc<|>; 149 extern crate std as abc<|>;
151 //- /std/lib.rs 150 //- /std/lib.rs crate:std
152 // empty 151 // empty
153 //^ file 152 //^ file
154 "#, 153 "#,
@@ -342,10 +341,10 @@ fn bar() {
342 fn goto_def_for_use_alias() { 341 fn goto_def_for_use_alias() {
343 check( 342 check(
344 r#" 343 r#"
345//- /lib.rs 344//- /lib.rs crate:main deps:foo
346use foo as bar<|>; 345use foo as bar<|>;
347 346
348//- /foo/lib.rs 347//- /foo/lib.rs crate:foo
349// empty 348// empty
350//^ file 349//^ file
351"#, 350"#,
@@ -356,10 +355,10 @@ use foo as bar<|>;
356 fn goto_def_for_use_alias_foo_macro() { 355 fn goto_def_for_use_alias_foo_macro() {
357 check( 356 check(
358 r#" 357 r#"
359//- /lib.rs 358//- /lib.rs crate:main deps:foo
360use foo::foo as bar<|>; 359use foo::foo as bar<|>;
361 360
362//- /foo/lib.rs 361//- /foo/lib.rs crate:foo
363#[macro_export] 362#[macro_export]
364macro_rules! foo { () => { () } } 363macro_rules! foo { () => { () } }
365 //^^^ 364 //^^^
@@ -371,7 +370,6 @@ macro_rules! foo { () => { () } }
371 fn goto_def_for_methods() { 370 fn goto_def_for_methods() {
372 check( 371 check(
373 r#" 372 r#"
374//- /lib.rs
375struct Foo; 373struct Foo;
376impl Foo { 374impl Foo {
377 fn frobnicate(&self) { } 375 fn frobnicate(&self) { }
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index f503f4ec5..6c586bbd1 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -76,12 +76,10 @@ fn impls_for_trait(
76mod tests { 76mod tests {
77 use base_db::FileRange; 77 use base_db::FileRange;
78 78
79 use crate::mock_analysis::MockAnalysis; 79 use crate::fixture;
80 80
81 fn check(ra_fixture: &str) { 81 fn check(ra_fixture: &str) {
82 let (mock, position) = MockAnalysis::with_files_and_position(ra_fixture); 82 let (analysis, position, annotations) = fixture::annotations(ra_fixture);
83 let annotations = mock.annotations();
84 let analysis = mock.analysis();
85 83
86 let navs = analysis.goto_implementation(position).unwrap().unwrap().info; 84 let navs = analysis.goto_implementation(position).unwrap().unwrap().info;
87 85
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs
index 4a151b150..6d0df04dd 100644
--- a/crates/ide/src/goto_type_definition.rs
+++ b/crates/ide/src/goto_type_definition.rs
@@ -56,13 +56,12 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
56mod tests { 56mod tests {
57 use base_db::FileRange; 57 use base_db::FileRange;
58 58
59 use crate::mock_analysis::MockAnalysis; 59 use crate::fixture;
60 60
61 fn check(ra_fixture: &str) { 61 fn check(ra_fixture: &str) {
62 let (mock, position) = MockAnalysis::with_files_and_position(ra_fixture); 62 let (analysis, position, mut annotations) = fixture::annotations(ra_fixture);
63 let (expected, data) = mock.annotation(); 63 let (expected, data) = annotations.pop().unwrap();
64 assert!(data.is_empty()); 64 assert!(data.is_empty());
65 let analysis = mock.analysis();
66 65
67 let mut navs = analysis.goto_type_definition(position).unwrap().unwrap().info; 66 let mut navs = analysis.goto_type_definition(position).unwrap().unwrap().info;
68 assert_eq!(navs.len(), 1); 67 assert_eq!(navs.len(), 1);
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index bb9f12cd3..9cf02f0a3 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -377,17 +377,17 @@ mod tests {
377 use base_db::FileLoader; 377 use base_db::FileLoader;
378 use expect_test::{expect, Expect}; 378 use expect_test::{expect, Expect};
379 379
380 use crate::mock_analysis::analysis_and_position; 380 use crate::fixture;
381 381
382 use super::*; 382 use super::*;
383 383
384 fn check_hover_no_result(ra_fixture: &str) { 384 fn check_hover_no_result(ra_fixture: &str) {
385 let (analysis, position) = analysis_and_position(ra_fixture); 385 let (analysis, position) = fixture::position(ra_fixture);
386 assert!(analysis.hover(position, true).unwrap().is_none()); 386 assert!(analysis.hover(position, true).unwrap().is_none());
387 } 387 }
388 388
389 fn check(ra_fixture: &str, expect: Expect) { 389 fn check(ra_fixture: &str, expect: Expect) {
390 let (analysis, position) = analysis_and_position(ra_fixture); 390 let (analysis, position) = fixture::position(ra_fixture);
391 let hover = analysis.hover(position, true).unwrap().unwrap(); 391 let hover = analysis.hover(position, true).unwrap().unwrap();
392 392
393 let content = analysis.db.file_text(position.file_id); 393 let content = analysis.db.file_text(position.file_id);
@@ -398,7 +398,7 @@ mod tests {
398 } 398 }
399 399
400 fn check_hover_no_links(ra_fixture: &str, expect: Expect) { 400 fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
401 let (analysis, position) = analysis_and_position(ra_fixture); 401 let (analysis, position) = fixture::position(ra_fixture);
402 let hover = analysis.hover(position, false).unwrap().unwrap(); 402 let hover = analysis.hover(position, false).unwrap().unwrap();
403 403
404 let content = analysis.db.file_text(position.file_id); 404 let content = analysis.db.file_text(position.file_id);
@@ -409,7 +409,7 @@ mod tests {
409 } 409 }
410 410
411 fn check_actions(ra_fixture: &str, expect: Expect) { 411 fn check_actions(ra_fixture: &str, expect: Expect) {
412 let (analysis, position) = analysis_and_position(ra_fixture); 412 let (analysis, position) = fixture::position(ra_fixture);
413 let hover = analysis.hover(position, true).unwrap().unwrap(); 413 let hover = analysis.hover(position, true).unwrap().unwrap();
414 expect.assert_debug_eq(&hover.info.actions) 414 expect.assert_debug_eq(&hover.info.actions)
415 } 415 }
@@ -963,7 +963,7 @@ impl Thing {
963 "#]], 963 "#]],
964 ) 964 )
965 } /* FIXME: revive these tests 965 } /* FIXME: revive these tests
966 let (analysis, position) = analysis_and_position( 966 let (analysis, position) = fixture::position(
967 " 967 "
968 struct Thing { x: u32 } 968 struct Thing { x: u32 }
969 impl Thing { 969 impl Thing {
@@ -977,7 +977,7 @@ impl Thing {
977 let hover = analysis.hover(position).unwrap().unwrap(); 977 let hover = analysis.hover(position).unwrap().unwrap();
978 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); 978 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing"));
979 979
980 let (analysis, position) = analysis_and_position( 980 let (analysis, position) = fixture::position(
981 " 981 "
982 enum Thing { A } 982 enum Thing { A }
983 impl Thing { 983 impl Thing {
@@ -990,7 +990,7 @@ impl Thing {
990 let hover = analysis.hover(position).unwrap().unwrap(); 990 let hover = analysis.hover(position).unwrap().unwrap();
991 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); 991 assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing"));
992 992
993 let (analysis, position) = analysis_and_position( 993 let (analysis, position) = fixture::position(
994 " 994 "
995 enum Thing { A } 995 enum Thing { A }
996 impl Thing { 996 impl Thing {
@@ -1275,7 +1275,7 @@ fn bar() { fo<|>o(); }
1275 Implementaion( 1275 Implementaion(
1276 FilePosition { 1276 FilePosition {
1277 file_id: FileId( 1277 file_id: FileId(
1278 1, 1278 0,
1279 ), 1279 ),
1280 offset: 13, 1280 offset: 13,
1281 }, 1281 },
@@ -1289,9 +1289,9 @@ fn bar() { fo<|>o(); }
1289 fn test_hover_extern_crate() { 1289 fn test_hover_extern_crate() {
1290 check( 1290 check(
1291 r#" 1291 r#"
1292//- /main.rs 1292//- /main.rs crate:main deps:std
1293extern crate st<|>d; 1293extern crate st<|>d;
1294//- /std/lib.rs 1294//- /std/lib.rs crate:std
1295//! Standard library for this test 1295//! Standard library for this test
1296//! 1296//!
1297//! Printed? 1297//! Printed?
@@ -1307,9 +1307,9 @@ extern crate st<|>d;
1307 ); 1307 );
1308 check( 1308 check(
1309 r#" 1309 r#"
1310//- /main.rs 1310//- /main.rs crate:main deps:std
1311extern crate std as ab<|>c; 1311extern crate std as ab<|>c;
1312//- /std/lib.rs 1312//- /std/lib.rs crate:std
1313//! Standard library for this test 1313//! Standard library for this test
1314//! 1314//!
1315//! Printed? 1315//! Printed?
@@ -1989,7 +1989,7 @@ fn foo() { let bar = Bar; bar.fo<|>o(); }
1989 Implementaion( 1989 Implementaion(
1990 FilePosition { 1990 FilePosition {
1991 file_id: FileId( 1991 file_id: FileId(
1992 1, 1992 0,
1993 ), 1993 ),
1994 offset: 6, 1994 offset: 6,
1995 }, 1995 },
@@ -2008,7 +2008,7 @@ fn foo() { let bar = Bar; bar.fo<|>o(); }
2008 Implementaion( 2008 Implementaion(
2009 FilePosition { 2009 FilePosition {
2010 file_id: FileId( 2010 file_id: FileId(
2011 1, 2011 0,
2012 ), 2012 ),
2013 offset: 7, 2013 offset: 7,
2014 }, 2014 },
@@ -2027,7 +2027,7 @@ fn foo() { let bar = Bar; bar.fo<|>o(); }
2027 Implementaion( 2027 Implementaion(
2028 FilePosition { 2028 FilePosition {
2029 file_id: FileId( 2029 file_id: FileId(
2030 1, 2030 0,
2031 ), 2031 ),
2032 offset: 6, 2032 offset: 6,
2033 }, 2033 },
@@ -2046,7 +2046,7 @@ fn foo() { let bar = Bar; bar.fo<|>o(); }
2046 Implementaion( 2046 Implementaion(
2047 FilePosition { 2047 FilePosition {
2048 file_id: FileId( 2048 file_id: FileId(
2049 1, 2049 0,
2050 ), 2050 ),
2051 offset: 5, 2051 offset: 5,
2052 }, 2052 },
@@ -2069,7 +2069,7 @@ fn foo_<|>test() {}
2069 Runnable { 2069 Runnable {
2070 nav: NavigationTarget { 2070 nav: NavigationTarget {
2071 file_id: FileId( 2071 file_id: FileId(
2072 1, 2072 0,
2073 ), 2073 ),
2074 full_range: 0..24, 2074 full_range: 0..24,
2075 focus_range: Some( 2075 focus_range: Some(
@@ -2112,7 +2112,7 @@ mod tests<|> {
2112 Runnable { 2112 Runnable {
2113 nav: NavigationTarget { 2113 nav: NavigationTarget {
2114 file_id: FileId( 2114 file_id: FileId(
2115 1, 2115 0,
2116 ), 2116 ),
2117 full_range: 0..46, 2117 full_range: 0..46,
2118 focus_range: Some( 2118 focus_range: Some(
@@ -2151,7 +2151,7 @@ fn main() { let s<|>t = S{ f1:0 }; }
2151 mod_path: "test::S", 2151 mod_path: "test::S",
2152 nav: NavigationTarget { 2152 nav: NavigationTarget {
2153 file_id: FileId( 2153 file_id: FileId(
2154 1, 2154 0,
2155 ), 2155 ),
2156 full_range: 0..19, 2156 full_range: 0..19,
2157 focus_range: Some( 2157 focus_range: Some(
@@ -2190,7 +2190,7 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; }
2190 mod_path: "test::S", 2190 mod_path: "test::S",
2191 nav: NavigationTarget { 2191 nav: NavigationTarget {
2192 file_id: FileId( 2192 file_id: FileId(
2193 1, 2193 0,
2194 ), 2194 ),
2195 full_range: 17..37, 2195 full_range: 17..37,
2196 focus_range: Some( 2196 focus_range: Some(
@@ -2209,7 +2209,7 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; }
2209 mod_path: "test::Arg", 2209 mod_path: "test::Arg",
2210 nav: NavigationTarget { 2210 nav: NavigationTarget {
2211 file_id: FileId( 2211 file_id: FileId(
2212 1, 2212 0,
2213 ), 2213 ),
2214 full_range: 0..16, 2214 full_range: 0..16,
2215 focus_range: Some( 2215 focus_range: Some(
@@ -2248,7 +2248,7 @@ fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
2248 mod_path: "test::S", 2248 mod_path: "test::S",
2249 nav: NavigationTarget { 2249 nav: NavigationTarget {
2250 file_id: FileId( 2250 file_id: FileId(
2251 1, 2251 0,
2252 ), 2252 ),
2253 full_range: 17..37, 2253 full_range: 17..37,
2254 focus_range: Some( 2254 focus_range: Some(
@@ -2267,7 +2267,7 @@ fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
2267 mod_path: "test::Arg", 2267 mod_path: "test::Arg",
2268 nav: NavigationTarget { 2268 nav: NavigationTarget {
2269 file_id: FileId( 2269 file_id: FileId(
2270 1, 2270 0,
2271 ), 2271 ),
2272 full_range: 0..16, 2272 full_range: 0..16,
2273 focus_range: Some( 2273 focus_range: Some(
@@ -2309,7 +2309,7 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
2309 mod_path: "test::A", 2309 mod_path: "test::A",
2310 nav: NavigationTarget { 2310 nav: NavigationTarget {
2311 file_id: FileId( 2311 file_id: FileId(
2312 1, 2312 0,
2313 ), 2313 ),
2314 full_range: 0..14, 2314 full_range: 0..14,
2315 focus_range: Some( 2315 focus_range: Some(
@@ -2328,7 +2328,7 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
2328 mod_path: "test::B", 2328 mod_path: "test::B",
2329 nav: NavigationTarget { 2329 nav: NavigationTarget {
2330 file_id: FileId( 2330 file_id: FileId(
2331 1, 2331 0,
2332 ), 2332 ),
2333 full_range: 15..29, 2333 full_range: 15..29,
2334 focus_range: Some( 2334 focus_range: Some(
@@ -2347,7 +2347,7 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
2347 mod_path: "test::M::C", 2347 mod_path: "test::M::C",
2348 nav: NavigationTarget { 2348 nav: NavigationTarget {
2349 file_id: FileId( 2349 file_id: FileId(
2350 1, 2350 0,
2351 ), 2351 ),
2352 full_range: 42..60, 2352 full_range: 42..60,
2353 focus_range: Some( 2353 focus_range: Some(
@@ -2386,7 +2386,7 @@ fn main() { let s<|>t = foo(); }
2386 mod_path: "test::Foo", 2386 mod_path: "test::Foo",
2387 nav: NavigationTarget { 2387 nav: NavigationTarget {
2388 file_id: FileId( 2388 file_id: FileId(
2389 1, 2389 0,
2390 ), 2390 ),
2391 full_range: 0..12, 2391 full_range: 0..12,
2392 focus_range: Some( 2392 focus_range: Some(
@@ -2426,7 +2426,7 @@ fn main() { let s<|>t = foo(); }
2426 mod_path: "test::Foo", 2426 mod_path: "test::Foo",
2427 nav: NavigationTarget { 2427 nav: NavigationTarget {
2428 file_id: FileId( 2428 file_id: FileId(
2429 1, 2429 0,
2430 ), 2430 ),
2431 full_range: 0..15, 2431 full_range: 0..15,
2432 focus_range: Some( 2432 focus_range: Some(
@@ -2445,7 +2445,7 @@ fn main() { let s<|>t = foo(); }
2445 mod_path: "test::S", 2445 mod_path: "test::S",
2446 nav: NavigationTarget { 2446 nav: NavigationTarget {
2447 file_id: FileId( 2447 file_id: FileId(
2448 1, 2448 0,
2449 ), 2449 ),
2450 full_range: 16..25, 2450 full_range: 16..25,
2451 focus_range: Some( 2451 focus_range: Some(
@@ -2485,7 +2485,7 @@ fn main() { let s<|>t = foo(); }
2485 mod_path: "test::Foo", 2485 mod_path: "test::Foo",
2486 nav: NavigationTarget { 2486 nav: NavigationTarget {
2487 file_id: FileId( 2487 file_id: FileId(
2488 1, 2488 0,
2489 ), 2489 ),
2490 full_range: 0..12, 2490 full_range: 0..12,
2491 focus_range: Some( 2491 focus_range: Some(
@@ -2504,7 +2504,7 @@ fn main() { let s<|>t = foo(); }
2504 mod_path: "test::Bar", 2504 mod_path: "test::Bar",
2505 nav: NavigationTarget { 2505 nav: NavigationTarget {
2506 file_id: FileId( 2506 file_id: FileId(
2507 1, 2507 0,
2508 ), 2508 ),
2509 full_range: 13..25, 2509 full_range: 13..25,
2510 focus_range: Some( 2510 focus_range: Some(
@@ -2547,7 +2547,7 @@ fn main() { let s<|>t = foo(); }
2547 mod_path: "test::Foo", 2547 mod_path: "test::Foo",
2548 nav: NavigationTarget { 2548 nav: NavigationTarget {
2549 file_id: FileId( 2549 file_id: FileId(
2550 1, 2550 0,
2551 ), 2551 ),
2552 full_range: 0..15, 2552 full_range: 0..15,
2553 focus_range: Some( 2553 focus_range: Some(
@@ -2566,7 +2566,7 @@ fn main() { let s<|>t = foo(); }
2566 mod_path: "test::Bar", 2566 mod_path: "test::Bar",
2567 nav: NavigationTarget { 2567 nav: NavigationTarget {
2568 file_id: FileId( 2568 file_id: FileId(
2569 1, 2569 0,
2570 ), 2570 ),
2571 full_range: 16..31, 2571 full_range: 16..31,
2572 focus_range: Some( 2572 focus_range: Some(
@@ -2585,7 +2585,7 @@ fn main() { let s<|>t = foo(); }
2585 mod_path: "test::S1", 2585 mod_path: "test::S1",
2586 nav: NavigationTarget { 2586 nav: NavigationTarget {
2587 file_id: FileId( 2587 file_id: FileId(
2588 1, 2588 0,
2589 ), 2589 ),
2590 full_range: 32..44, 2590 full_range: 32..44,
2591 focus_range: Some( 2591 focus_range: Some(
@@ -2604,7 +2604,7 @@ fn main() { let s<|>t = foo(); }
2604 mod_path: "test::S2", 2604 mod_path: "test::S2",
2605 nav: NavigationTarget { 2605 nav: NavigationTarget {
2606 file_id: FileId( 2606 file_id: FileId(
2607 1, 2607 0,
2608 ), 2608 ),
2609 full_range: 45..57, 2609 full_range: 45..57,
2610 focus_range: Some( 2610 focus_range: Some(
@@ -2641,7 +2641,7 @@ fn foo(ar<|>g: &impl Foo) {}
2641 mod_path: "test::Foo", 2641 mod_path: "test::Foo",
2642 nav: NavigationTarget { 2642 nav: NavigationTarget {
2643 file_id: FileId( 2643 file_id: FileId(
2644 1, 2644 0,
2645 ), 2645 ),
2646 full_range: 0..12, 2646 full_range: 0..12,
2647 focus_range: Some( 2647 focus_range: Some(
@@ -2681,7 +2681,7 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
2681 mod_path: "test::Foo", 2681 mod_path: "test::Foo",
2682 nav: NavigationTarget { 2682 nav: NavigationTarget {
2683 file_id: FileId( 2683 file_id: FileId(
2684 1, 2684 0,
2685 ), 2685 ),
2686 full_range: 0..12, 2686 full_range: 0..12,
2687 focus_range: Some( 2687 focus_range: Some(
@@ -2700,7 +2700,7 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
2700 mod_path: "test::Bar", 2700 mod_path: "test::Bar",
2701 nav: NavigationTarget { 2701 nav: NavigationTarget {
2702 file_id: FileId( 2702 file_id: FileId(
2703 1, 2703 0,
2704 ), 2704 ),
2705 full_range: 13..28, 2705 full_range: 13..28,
2706 focus_range: Some( 2706 focus_range: Some(
@@ -2719,7 +2719,7 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
2719 mod_path: "test::S", 2719 mod_path: "test::S",
2720 nav: NavigationTarget { 2720 nav: NavigationTarget {
2721 file_id: FileId( 2721 file_id: FileId(
2722 1, 2722 0,
2723 ), 2723 ),
2724 full_range: 29..39, 2724 full_range: 29..39,
2725 focus_range: Some( 2725 focus_range: Some(
@@ -2764,7 +2764,7 @@ mod future {
2764 mod_path: "test::future::Future", 2764 mod_path: "test::future::Future",
2765 nav: NavigationTarget { 2765 nav: NavigationTarget {
2766 file_id: FileId( 2766 file_id: FileId(
2767 1, 2767 0,
2768 ), 2768 ),
2769 full_range: 101..163, 2769 full_range: 101..163,
2770 focus_range: Some( 2770 focus_range: Some(
@@ -2783,7 +2783,7 @@ mod future {
2783 mod_path: "test::S", 2783 mod_path: "test::S",
2784 nav: NavigationTarget { 2784 nav: NavigationTarget {
2785 file_id: FileId( 2785 file_id: FileId(
2786 1, 2786 0,
2787 ), 2787 ),
2788 full_range: 0..9, 2788 full_range: 0..9,
2789 focus_range: Some( 2789 focus_range: Some(
@@ -2821,7 +2821,7 @@ fn foo(ar<|>g: &impl Foo<S>) {}
2821 mod_path: "test::Foo", 2821 mod_path: "test::Foo",
2822 nav: NavigationTarget { 2822 nav: NavigationTarget {
2823 file_id: FileId( 2823 file_id: FileId(
2824 1, 2824 0,
2825 ), 2825 ),
2826 full_range: 0..15, 2826 full_range: 0..15,
2827 focus_range: Some( 2827 focus_range: Some(
@@ -2840,7 +2840,7 @@ fn foo(ar<|>g: &impl Foo<S>) {}
2840 mod_path: "test::S", 2840 mod_path: "test::S",
2841 nav: NavigationTarget { 2841 nav: NavigationTarget {
2842 file_id: FileId( 2842 file_id: FileId(
2843 1, 2843 0,
2844 ), 2844 ),
2845 full_range: 16..27, 2845 full_range: 16..27,
2846 focus_range: Some( 2846 focus_range: Some(
@@ -2883,7 +2883,7 @@ fn main() { let s<|>t = foo(); }
2883 mod_path: "test::B", 2883 mod_path: "test::B",
2884 nav: NavigationTarget { 2884 nav: NavigationTarget {
2885 file_id: FileId( 2885 file_id: FileId(
2886 1, 2886 0,
2887 ), 2887 ),
2888 full_range: 42..55, 2888 full_range: 42..55,
2889 focus_range: Some( 2889 focus_range: Some(
@@ -2902,7 +2902,7 @@ fn main() { let s<|>t = foo(); }
2902 mod_path: "test::Foo", 2902 mod_path: "test::Foo",
2903 nav: NavigationTarget { 2903 nav: NavigationTarget {
2904 file_id: FileId( 2904 file_id: FileId(
2905 1, 2905 0,
2906 ), 2906 ),
2907 full_range: 0..12, 2907 full_range: 0..12,
2908 focus_range: Some( 2908 focus_range: Some(
@@ -2939,7 +2939,7 @@ fn foo(ar<|>g: &dyn Foo) {}
2939 mod_path: "test::Foo", 2939 mod_path: "test::Foo",
2940 nav: NavigationTarget { 2940 nav: NavigationTarget {
2941 file_id: FileId( 2941 file_id: FileId(
2942 1, 2942 0,
2943 ), 2943 ),
2944 full_range: 0..12, 2944 full_range: 0..12,
2945 focus_range: Some( 2945 focus_range: Some(
@@ -2977,7 +2977,7 @@ fn foo(ar<|>g: &dyn Foo<S>) {}
2977 mod_path: "test::Foo", 2977 mod_path: "test::Foo",
2978 nav: NavigationTarget { 2978 nav: NavigationTarget {
2979 file_id: FileId( 2979 file_id: FileId(
2980 1, 2980 0,
2981 ), 2981 ),
2982 full_range: 0..15, 2982 full_range: 0..15,
2983 focus_range: Some( 2983 focus_range: Some(
@@ -2996,7 +2996,7 @@ fn foo(ar<|>g: &dyn Foo<S>) {}
2996 mod_path: "test::S", 2996 mod_path: "test::S",
2997 nav: NavigationTarget { 2997 nav: NavigationTarget {
2998 file_id: FileId( 2998 file_id: FileId(
2999 1, 2999 0,
3000 ), 3000 ),
3001 full_range: 16..27, 3001 full_range: 16..27,
3002 focus_range: Some( 3002 focus_range: Some(
@@ -3037,7 +3037,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3037 mod_path: "test::ImplTrait", 3037 mod_path: "test::ImplTrait",
3038 nav: NavigationTarget { 3038 nav: NavigationTarget {
3039 file_id: FileId( 3039 file_id: FileId(
3040 1, 3040 0,
3041 ), 3041 ),
3042 full_range: 0..21, 3042 full_range: 0..21,
3043 focus_range: Some( 3043 focus_range: Some(
@@ -3056,7 +3056,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3056 mod_path: "test::B", 3056 mod_path: "test::B",
3057 nav: NavigationTarget { 3057 nav: NavigationTarget {
3058 file_id: FileId( 3058 file_id: FileId(
3059 1, 3059 0,
3060 ), 3060 ),
3061 full_range: 43..57, 3061 full_range: 43..57,
3062 focus_range: Some( 3062 focus_range: Some(
@@ -3075,7 +3075,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3075 mod_path: "test::DynTrait", 3075 mod_path: "test::DynTrait",
3076 nav: NavigationTarget { 3076 nav: NavigationTarget {
3077 file_id: FileId( 3077 file_id: FileId(
3078 1, 3078 0,
3079 ), 3079 ),
3080 full_range: 22..42, 3080 full_range: 22..42,
3081 focus_range: Some( 3081 focus_range: Some(
@@ -3094,7 +3094,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
3094 mod_path: "test::S", 3094 mod_path: "test::S",
3095 nav: NavigationTarget { 3095 nav: NavigationTarget {
3096 file_id: FileId( 3096 file_id: FileId(
3097 1, 3097 0,
3098 ), 3098 ),
3099 full_range: 58..69, 3099 full_range: 58..69,
3100 focus_range: Some( 3100 focus_range: Some(
@@ -3142,7 +3142,7 @@ fn main() { let s<|>t = test().get(); }
3142 mod_path: "test::Foo", 3142 mod_path: "test::Foo",
3143 nav: NavigationTarget { 3143 nav: NavigationTarget {
3144 file_id: FileId( 3144 file_id: FileId(
3145 1, 3145 0,
3146 ), 3146 ),
3147 full_range: 0..62, 3147 full_range: 0..62,
3148 focus_range: Some( 3148 focus_range: Some(
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 583f39d85..0afe5f8fd 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -339,14 +339,14 @@ mod tests {
339 use expect_test::{expect, Expect}; 339 use expect_test::{expect, Expect};
340 use test_utils::extract_annotations; 340 use test_utils::extract_annotations;
341 341
342 use crate::{inlay_hints::InlayHintsConfig, mock_analysis::single_file}; 342 use crate::{fixture, inlay_hints::InlayHintsConfig};
343 343
344 fn check(ra_fixture: &str) { 344 fn check(ra_fixture: &str) {
345 check_with_config(InlayHintsConfig::default(), ra_fixture); 345 check_with_config(InlayHintsConfig::default(), ra_fixture);
346 } 346 }
347 347
348 fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) { 348 fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) {
349 let (analysis, file_id) = single_file(ra_fixture); 349 let (analysis, file_id) = fixture::file(ra_fixture);
350 let expected = extract_annotations(&*analysis.file_text(file_id).unwrap()); 350 let expected = extract_annotations(&*analysis.file_text(file_id).unwrap());
351 let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); 351 let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap();
352 let actual = 352 let actual =
@@ -355,7 +355,7 @@ mod tests {
355 } 355 }
356 356
357 fn check_expect(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) { 357 fn check_expect(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) {
358 let (analysis, file_id) = single_file(ra_fixture); 358 let (analysis, file_id) = fixture::file(ra_fixture);
359 let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap(); 359 let inlay_hints = analysis.inlay_hints(file_id, &config).unwrap();
360 expect.assert_debug_eq(&inlay_hints) 360 expect.assert_debug_eq(&inlay_hints)
361 } 361 }
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index bab3ec1ff..1aa673cf8 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -16,7 +16,7 @@ macro_rules! eprintln {
16} 16}
17 17
18#[cfg(test)] 18#[cfg(test)]
19mod mock_analysis; 19mod fixture;
20 20
21mod markup; 21mod markup;
22mod prime_caches; 22mod prime_caches;
@@ -87,12 +87,11 @@ pub use assists::{
87 utils::MergeBehaviour, Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist, 87 utils::MergeBehaviour, Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist,
88}; 88};
89pub use base_db::{ 89pub use base_db::{
90 Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot, 90 Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot,
91 SourceRootId, 91 SourceRootId,
92}; 92};
93pub use hir::{Documentation, Semantics}; 93pub use hir::{Documentation, Semantics};
94pub use ide_db::{ 94pub use ide_db::{
95 change::AnalysisChange,
96 label::Label, 95 label::Label,
97 line_index::{LineCol, LineIndex}, 96 line_index::{LineCol, LineIndex},
98 search::SearchScope, 97 search::SearchScope,
@@ -141,7 +140,7 @@ impl AnalysisHost {
141 140
142 /// Applies changes to the current state of the world. If there are 141 /// Applies changes to the current state of the world. If there are
143 /// outstanding snapshots, they will be canceled. 142 /// outstanding snapshots, they will be canceled.
144 pub fn apply_change(&mut self, change: AnalysisChange) { 143 pub fn apply_change(&mut self, change: Change) {
145 self.db.apply_change(change) 144 self.db.apply_change(change)
146 } 145 }
147 146
@@ -195,7 +194,7 @@ impl Analysis {
195 file_set.insert(file_id, VfsPath::new_virtual_path("/main.rs".to_string())); 194 file_set.insert(file_id, VfsPath::new_virtual_path("/main.rs".to_string()));
196 let source_root = SourceRoot::new_local(file_set); 195 let source_root = SourceRoot::new_local(file_set);
197 196
198 let mut change = AnalysisChange::new(); 197 let mut change = Change::new();
199 change.set_roots(vec![source_root]); 198 change.set_roots(vec![source_root]);
200 let mut crate_graph = CrateGraph::default(); 199 let mut crate_graph = CrateGraph::default();
201 // FIXME: cfg options 200 // FIXME: cfg options
diff --git a/crates/ide/src/mock_analysis.rs b/crates/ide/src/mock_analysis.rs
deleted file mode 100644
index 327cdf91e..000000000
--- a/crates/ide/src/mock_analysis.rs
+++ /dev/null
@@ -1,176 +0,0 @@
1//! FIXME: write short doc here
2use std::sync::Arc;
3
4use base_db::{CrateName, FileSet, SourceRoot, VfsPath};
5use cfg::CfgOptions;
6use test_utils::{
7 extract_annotations, extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER,
8};
9
10use crate::{
11 Analysis, AnalysisChange, AnalysisHost, CrateGraph, Edition, FileId, FilePosition, FileRange,
12};
13
14/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis
15/// from a set of in-memory files.
16#[derive(Debug, Default)]
17pub(crate) struct MockAnalysis {
18 files: Vec<Fixture>,
19}
20
21impl MockAnalysis {
22 /// Creates `MockAnalysis` using a fixture data in the following format:
23 ///
24 /// ```not_rust
25 /// //- /main.rs
26 /// mod foo;
27 /// fn main() {}
28 ///
29 /// //- /foo.rs
30 /// struct Baz;
31 /// ```
32 pub(crate) fn with_files(ra_fixture: &str) -> MockAnalysis {
33 let (res, pos) = MockAnalysis::with_fixture(ra_fixture);
34 assert!(pos.is_none());
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(crate) fn with_files_and_position(fixture: &str) -> (MockAnalysis, FilePosition) {
41 let (res, position) = MockAnalysis::with_fixture(fixture);
42 let (file_id, range_or_offset) = position.expect("expected a marker (<|>)");
43 let offset = match range_or_offset {
44 RangeOrOffset::Range(_) => panic!(),
45 RangeOrOffset::Offset(it) => it,
46 };
47 (res, FilePosition { file_id, offset })
48 }
49
50 fn with_fixture(fixture: &str) -> (MockAnalysis, Option<(FileId, RangeOrOffset)>) {
51 let mut position = None;
52 let mut res = MockAnalysis::default();
53 for mut entry in Fixture::parse(fixture) {
54 if entry.text.contains(CURSOR_MARKER) {
55 assert!(position.is_none(), "only one marker (<|>) per fixture is allowed");
56 let (range_or_offset, text) = extract_range_or_offset(&entry.text);
57 entry.text = text;
58 let file_id = res.add_file_fixture(entry);
59 position = Some((file_id, range_or_offset));
60 } else {
61 res.add_file_fixture(entry);
62 }
63 }
64 (res, position)
65 }
66
67 fn add_file_fixture(&mut self, fixture: Fixture) -> FileId {
68 let file_id = FileId((self.files.len() + 1) as u32);
69 self.files.push(fixture);
70 file_id
71 }
72
73 pub(crate) fn id_of(&self, path: &str) -> FileId {
74 let (file_id, _) =
75 self.files().find(|(_, data)| path == data.path).expect("no file in this mock");
76 file_id
77 }
78 pub(crate) fn annotations(&self) -> Vec<(FileRange, String)> {
79 self.files()
80 .flat_map(|(file_id, fixture)| {
81 let annotations = extract_annotations(&fixture.text);
82 annotations
83 .into_iter()
84 .map(move |(range, data)| (FileRange { file_id, range }, data))
85 })
86 .collect()
87 }
88 pub(crate) fn files(&self) -> impl Iterator<Item = (FileId, &Fixture)> + '_ {
89 self.files.iter().enumerate().map(|(idx, fixture)| (FileId(idx as u32 + 1), fixture))
90 }
91 pub(crate) fn annotation(&self) -> (FileRange, String) {
92 let mut all = self.annotations();
93 assert_eq!(all.len(), 1);
94 all.pop().unwrap()
95 }
96 pub(crate) fn analysis_host(self) -> AnalysisHost {
97 let mut host = AnalysisHost::default();
98 let mut change = AnalysisChange::new();
99 let mut file_set = FileSet::default();
100 let mut crate_graph = CrateGraph::default();
101 let mut root_crate = None;
102 for (i, data) in self.files.into_iter().enumerate() {
103 let path = data.path;
104 assert!(path.starts_with('/'));
105
106 let mut cfg = CfgOptions::default();
107 data.cfg_atoms.iter().for_each(|it| cfg.insert_atom(it.into()));
108 data.cfg_key_values.iter().for_each(|(k, v)| cfg.insert_key_value(k.into(), v.into()));
109 let edition: Edition =
110 data.edition.and_then(|it| it.parse().ok()).unwrap_or(Edition::Edition2018);
111
112 let file_id = FileId(i as u32 + 1);
113 let env = data.env.into_iter().collect();
114 if path == "/lib.rs" || path == "/main.rs" {
115 root_crate = Some(crate_graph.add_crate_root(
116 file_id,
117 edition,
118 Some("test".to_string()),
119 cfg,
120 env,
121 Default::default(),
122 ));
123 } else if path.ends_with("/lib.rs") {
124 let base = &path[..path.len() - "/lib.rs".len()];
125 let crate_name = &base[base.rfind('/').unwrap() + '/'.len_utf8()..];
126 let other_crate = crate_graph.add_crate_root(
127 file_id,
128 edition,
129 Some(crate_name.to_string()),
130 cfg,
131 env,
132 Default::default(),
133 );
134 if let Some(root_crate) = root_crate {
135 crate_graph
136 .add_dep(root_crate, CrateName::new(crate_name).unwrap(), other_crate)
137 .unwrap();
138 }
139 }
140 let path = VfsPath::new_virtual_path(path.to_string());
141 file_set.insert(file_id, path);
142 change.change_file(file_id, Some(Arc::new(data.text).to_owned()));
143 }
144 change.set_crate_graph(crate_graph);
145 change.set_roots(vec![SourceRoot::new_local(file_set)]);
146 host.apply_change(change);
147 host
148 }
149 pub(crate) fn analysis(self) -> Analysis {
150 self.analysis_host().analysis()
151 }
152}
153
154/// Creates analysis from a multi-file fixture, returns positions marked with <|>.
155pub(crate) fn analysis_and_position(ra_fixture: &str) -> (Analysis, FilePosition) {
156 let (mock, position) = MockAnalysis::with_files_and_position(ra_fixture);
157 (mock.analysis(), position)
158}
159
160/// Creates analysis for a single file.
161pub(crate) fn single_file(ra_fixture: &str) -> (Analysis, FileId) {
162 let mock = MockAnalysis::with_files(ra_fixture);
163 let file_id = mock.id_of("/main.rs");
164 (mock.analysis(), file_id)
165}
166
167/// Creates analysis for a single file, returns range marked with a pair of <|>.
168pub(crate) fn analysis_and_range(ra_fixture: &str) -> (Analysis, FileRange) {
169 let (res, position) = MockAnalysis::with_fixture(ra_fixture);
170 let (file_id, range_or_offset) = position.expect("expected a marker (<|>)");
171 let range = match range_or_offset {
172 RangeOrOffset::Range(it) => it,
173 RangeOrOffset::Offset(_) => panic!(),
174 };
175 (res.analysis(), FileRange { file_id, range })
176}
diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs
index 59ed2967c..ef94acfec 100644
--- a/crates/ide/src/parent_module.rs
+++ b/crates/ide/src/parent_module.rs
@@ -63,19 +63,13 @@ pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
63 63
64#[cfg(test)] 64#[cfg(test)]
65mod tests { 65mod tests {
66 use base_db::Env;
67 use cfg::CfgOptions;
68 use test_utils::mark; 66 use test_utils::mark;
69 67
70 use crate::{ 68 use crate::fixture::{self};
71 mock_analysis::{analysis_and_position, MockAnalysis},
72 AnalysisChange, CrateGraph,
73 Edition::Edition2018,
74 };
75 69
76 #[test] 70 #[test]
77 fn test_resolve_parent_module() { 71 fn test_resolve_parent_module() {
78 let (analysis, pos) = analysis_and_position( 72 let (analysis, pos) = fixture::position(
79 " 73 "
80 //- /lib.rs 74 //- /lib.rs
81 mod foo; 75 mod foo;
@@ -84,13 +78,13 @@ mod tests {
84 ", 78 ",
85 ); 79 );
86 let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); 80 let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
87 nav.assert_match("foo MODULE FileId(1) 0..8"); 81 nav.assert_match("foo MODULE FileId(0) 0..8");
88 } 82 }
89 83
90 #[test] 84 #[test]
91 fn test_resolve_parent_module_on_module_decl() { 85 fn test_resolve_parent_module_on_module_decl() {
92 mark::check!(test_resolve_parent_module_on_module_decl); 86 mark::check!(test_resolve_parent_module_on_module_decl);
93 let (analysis, pos) = analysis_and_position( 87 let (analysis, pos) = fixture::position(
94 " 88 "
95 //- /lib.rs 89 //- /lib.rs
96 mod foo; 90 mod foo;
@@ -103,12 +97,12 @@ mod tests {
103 ", 97 ",
104 ); 98 );
105 let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); 99 let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
106 nav.assert_match("foo MODULE FileId(1) 0..8"); 100 nav.assert_match("foo MODULE FileId(0) 0..8");
107 } 101 }
108 102
109 #[test] 103 #[test]
110 fn test_resolve_parent_module_for_inline() { 104 fn test_resolve_parent_module_for_inline() {
111 let (analysis, pos) = analysis_and_position( 105 let (analysis, pos) = fixture::position(
112 " 106 "
113 //- /lib.rs 107 //- /lib.rs
114 mod foo { 108 mod foo {
@@ -119,37 +113,19 @@ mod tests {
119 ", 113 ",
120 ); 114 );
121 let nav = analysis.parent_module(pos).unwrap().pop().unwrap(); 115 let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
122 nav.assert_match("baz MODULE FileId(1) 32..44"); 116 nav.assert_match("baz MODULE FileId(0) 32..44");
123 } 117 }
124 118
125 #[test] 119 #[test]
126 fn test_resolve_crate_root() { 120 fn test_resolve_crate_root() {
127 let mock = MockAnalysis::with_files( 121 let (analysis, file_id) = fixture::file(
128 r#" 122 r#"
129//- /bar.rs 123//- /main.rs
130mod foo; 124mod foo;
131//- /foo.rs 125//- /foo.rs
132// empty 126<|>
133"#, 127"#,
134 ); 128 );
135 let root_file = mock.id_of("/bar.rs"); 129 assert_eq!(analysis.crate_for(file_id).unwrap().len(), 1);
136 let mod_file = mock.id_of("/foo.rs");
137 let mut host = mock.analysis_host();
138 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty());
139
140 let mut crate_graph = CrateGraph::default();
141 let crate_id = crate_graph.add_crate_root(
142 root_file,
143 Edition2018,
144 None,
145 CfgOptions::default(),
146 Env::default(),
147 Default::default(),
148 );
149 let mut change = AnalysisChange::new();
150 change.set_crate_graph(crate_graph);
151 host.apply_change(change);
152
153 assert_eq!(host.analysis().crate_for(mod_file).unwrap(), vec![crate_id]);
154 } 130 }
155} 131}
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 1e3e944e9..e0830eb4f 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -190,10 +190,11 @@ fn get_struct_def_name_for_struct_literal_search(
190 190
191#[cfg(test)] 191#[cfg(test)]
192mod tests { 192mod tests {
193 use base_db::FileId;
193 use expect_test::{expect, Expect}; 194 use expect_test::{expect, Expect};
194 use stdx::format_to; 195 use stdx::format_to;
195 196
196 use crate::{mock_analysis::MockAnalysis, SearchScope}; 197 use crate::{fixture, SearchScope};
197 198
198 #[test] 199 #[test]
199 fn test_struct_literal_after_space() { 200 fn test_struct_literal_after_space() {
@@ -211,9 +212,9 @@ fn main() {
211} 212}
212"#, 213"#,
213 expect![[r#" 214 expect![[r#"
214 Foo STRUCT FileId(1) 0..26 7..10 Other 215 Foo STRUCT FileId(0) 0..26 7..10 Other
215 216
216 FileId(1) 101..104 StructLiteral 217 FileId(0) 101..104 StructLiteral
217 "#]], 218 "#]],
218 ); 219 );
219 } 220 }
@@ -229,10 +230,10 @@ struct Foo<|> {}
229} 230}
230"#, 231"#,
231 expect![[r#" 232 expect![[r#"
232 Foo STRUCT FileId(1) 0..13 7..10 Other 233 Foo STRUCT FileId(0) 0..13 7..10 Other
233 234
234 FileId(1) 41..44 Other 235 FileId(0) 41..44 Other
235 FileId(1) 54..57 StructLiteral 236 FileId(0) 54..57 StructLiteral
236 "#]], 237 "#]],
237 ); 238 );
238 } 239 }
@@ -248,9 +249,9 @@ struct Foo<T> <|>{}
248} 249}
249"#, 250"#,
250 expect![[r#" 251 expect![[r#"
251 Foo STRUCT FileId(1) 0..16 7..10 Other 252 Foo STRUCT FileId(0) 0..16 7..10 Other
252 253
253 FileId(1) 64..67 StructLiteral 254 FileId(0) 64..67 StructLiteral
254 "#]], 255 "#]],
255 ); 256 );
256 } 257 }
@@ -267,9 +268,9 @@ fn main() {
267} 268}
268"#, 269"#,
269 expect![[r#" 270 expect![[r#"
270 Foo STRUCT FileId(1) 0..16 7..10 Other 271 Foo STRUCT FileId(0) 0..16 7..10 Other
271 272
272 FileId(1) 54..57 StructLiteral 273 FileId(0) 54..57 StructLiteral
273 "#]], 274 "#]],
274 ); 275 );
275 } 276 }
@@ -290,12 +291,12 @@ fn main() {
290 i = 5; 291 i = 5;
291}"#, 292}"#,
292 expect![[r#" 293 expect![[r#"
293 i IDENT_PAT FileId(1) 24..25 Other Write 294 i IDENT_PAT FileId(0) 24..25 Other Write
294 295
295 FileId(1) 50..51 Other Write 296 FileId(0) 50..51 Other Write
296 FileId(1) 54..55 Other Read 297 FileId(0) 54..55 Other Read
297 FileId(1) 76..77 Other Write 298 FileId(0) 76..77 Other Write
298 FileId(1) 94..95 Other Write 299 FileId(0) 94..95 Other Write
299 "#]], 300 "#]],
300 ); 301 );
301 } 302 }
@@ -314,10 +315,10 @@ fn bar() {
314} 315}
315"#, 316"#,
316 expect![[r#" 317 expect![[r#"
317 spam IDENT_PAT FileId(1) 19..23 Other 318 spam IDENT_PAT FileId(0) 19..23 Other
318 319
319 FileId(1) 34..38 Other Read 320 FileId(0) 34..38 Other Read
320 FileId(1) 41..45 Other Read 321 FileId(0) 41..45 Other Read
321 "#]], 322 "#]],
322 ); 323 );
323 } 324 }
@@ -329,9 +330,9 @@ fn bar() {
329fn foo(i : u32) -> u32 { i<|> } 330fn foo(i : u32) -> u32 { i<|> }
330"#, 331"#,
331 expect![[r#" 332 expect![[r#"
332 i IDENT_PAT FileId(1) 7..8 Other 333 i IDENT_PAT FileId(0) 7..8 Other
333 334
334 FileId(1) 25..26 Other Read 335 FileId(0) 25..26 Other Read
335 "#]], 336 "#]],
336 ); 337 );
337 } 338 }
@@ -343,9 +344,9 @@ fn foo(i : u32) -> u32 { i<|> }
343fn foo(i<|> : u32) -> u32 { i } 344fn foo(i<|> : u32) -> u32 { i }
344"#, 345"#,
345 expect![[r#" 346 expect![[r#"
346 i IDENT_PAT FileId(1) 7..8 Other 347 i IDENT_PAT FileId(0) 7..8 Other
347 348
348 FileId(1) 25..26 Other Read 349 FileId(0) 25..26 Other Read
349 "#]], 350 "#]],
350 ); 351 );
351 } 352 }
@@ -364,9 +365,9 @@ fn main(s: Foo) {
364} 365}
365"#, 366"#,
366 expect![[r#" 367 expect![[r#"
367 spam RECORD_FIELD FileId(1) 17..30 21..25 Other 368 spam RECORD_FIELD FileId(0) 17..30 21..25 Other
368 369
369 FileId(1) 67..71 Other Read 370 FileId(0) 67..71 Other Read
370 "#]], 371 "#]],
371 ); 372 );
372 } 373 }
@@ -381,7 +382,7 @@ impl Foo {
381} 382}
382"#, 383"#,
383 expect![[r#" 384 expect![[r#"
384 f FN FileId(1) 27..43 30..31 Other 385 f FN FileId(0) 27..43 30..31 Other
385 386
386 "#]], 387 "#]],
387 ); 388 );
@@ -398,7 +399,7 @@ enum Foo {
398} 399}
399"#, 400"#,
400 expect![[r#" 401 expect![[r#"
401 B VARIANT FileId(1) 22..23 22..23 Other 402 B VARIANT FileId(0) 22..23 22..23 Other
402 403
403 "#]], 404 "#]],
404 ); 405 );
@@ -439,10 +440,10 @@ fn f() {
439} 440}
440"#, 441"#,
441 expect![[r#" 442 expect![[r#"
442 Foo STRUCT FileId(2) 17..51 28..31 Other 443 Foo STRUCT FileId(1) 17..51 28..31 Other
443 444
444 FileId(1) 53..56 StructLiteral 445 FileId(0) 53..56 StructLiteral
445 FileId(3) 79..82 StructLiteral 446 FileId(2) 79..82 StructLiteral
446 "#]], 447 "#]],
447 ); 448 );
448 } 449 }
@@ -469,9 +470,9 @@ pub struct Foo {
469} 470}
470"#, 471"#,
471 expect![[r#" 472 expect![[r#"
472 foo SOURCE_FILE FileId(2) 0..35 Other 473 foo SOURCE_FILE FileId(1) 0..35 Other
473 474
474 FileId(1) 14..17 Other 475 FileId(0) 14..17 Other
475 "#]], 476 "#]],
476 ); 477 );
477 } 478 }
@@ -497,10 +498,10 @@ pub(super) struct Foo<|> {
497} 498}
498"#, 499"#,
499 expect![[r#" 500 expect![[r#"
500 Foo STRUCT FileId(3) 0..41 18..21 Other 501 Foo STRUCT FileId(2) 0..41 18..21 Other
501 502
502 FileId(2) 20..23 Other 503 FileId(1) 20..23 Other
503 FileId(2) 47..50 StructLiteral 504 FileId(1) 47..50 StructLiteral
504 "#]], 505 "#]],
505 ); 506 );
506 } 507 }
@@ -525,20 +526,20 @@ pub(super) struct Foo<|> {
525 code, 526 code,
526 None, 527 None,
527 expect![[r#" 528 expect![[r#"
528 quux FN FileId(1) 19..35 26..30 Other 529 quux FN FileId(0) 19..35 26..30 Other
529 530
531 FileId(1) 16..20 StructLiteral
530 FileId(2) 16..20 StructLiteral 532 FileId(2) 16..20 StructLiteral
531 FileId(3) 16..20 StructLiteral
532 "#]], 533 "#]],
533 ); 534 );
534 535
535 check_with_scope( 536 check_with_scope(
536 code, 537 code,
537 Some("/bar.rs"), 538 Some(SearchScope::single_file(FileId(2))),
538 expect![[r#" 539 expect![[r#"
539 quux FN FileId(1) 19..35 26..30 Other 540 quux FN FileId(0) 19..35 26..30 Other
540 541
541 FileId(3) 16..20 StructLiteral 542 FileId(2) 16..20 StructLiteral
542 "#]], 543 "#]],
543 ); 544 );
544 } 545 }
@@ -556,10 +557,10 @@ fn foo() {
556} 557}
557"#, 558"#,
558 expect![[r#" 559 expect![[r#"
559 m1 MACRO_CALL FileId(1) 0..46 29..31 Other 560 m1 MACRO_CALL FileId(0) 0..46 29..31 Other
560 561
561 FileId(1) 63..65 StructLiteral 562 FileId(0) 63..65 StructLiteral
562 FileId(1) 73..75 StructLiteral 563 FileId(0) 73..75 StructLiteral
563 "#]], 564 "#]],
564 ); 565 );
565 } 566 }
@@ -574,10 +575,10 @@ fn foo() {
574} 575}
575"#, 576"#,
576 expect![[r#" 577 expect![[r#"
577 i IDENT_PAT FileId(1) 23..24 Other Write 578 i IDENT_PAT FileId(0) 23..24 Other Write
578 579
579 FileId(1) 34..35 Other Write 580 FileId(0) 34..35 Other Write
580 FileId(1) 38..39 Other Read 581 FileId(0) 38..39 Other Read
581 "#]], 582 "#]],
582 ); 583 );
583 } 584 }
@@ -596,10 +597,10 @@ fn foo() {
596} 597}
597"#, 598"#,
598 expect![[r#" 599 expect![[r#"
599 f RECORD_FIELD FileId(1) 15..21 15..16 Other 600 f RECORD_FIELD FileId(0) 15..21 15..16 Other
600 601
601 FileId(1) 55..56 Other Read 602 FileId(0) 55..56 Other Read
602 FileId(1) 68..69 Other Write 603 FileId(0) 68..69 Other Write
603 "#]], 604 "#]],
604 ); 605 );
605 } 606 }
@@ -614,9 +615,9 @@ fn foo() {
614} 615}
615"#, 616"#,
616 expect![[r#" 617 expect![[r#"
617 i IDENT_PAT FileId(1) 19..20 Other 618 i IDENT_PAT FileId(0) 19..20 Other
618 619
619 FileId(1) 26..27 Other Write 620 FileId(0) 26..27 Other Write
620 "#]], 621 "#]],
621 ); 622 );
622 } 623 }
@@ -638,9 +639,9 @@ fn main() {
638} 639}
639"#, 640"#,
640 expect![[r#" 641 expect![[r#"
641 new FN FileId(1) 54..81 61..64 Other 642 new FN FileId(0) 54..81 61..64 Other
642 643
643 FileId(1) 126..129 StructLiteral 644 FileId(0) 126..129 StructLiteral
644 "#]], 645 "#]],
645 ); 646 );
646 } 647 }
@@ -660,10 +661,10 @@ use crate::f;
660fn g() { f(); } 661fn g() { f(); }
661"#, 662"#,
662 expect![[r#" 663 expect![[r#"
663 f FN FileId(1) 22..31 25..26 Other 664 f FN FileId(0) 22..31 25..26 Other
664 665
665 FileId(2) 11..12 Other 666 FileId(1) 11..12 Other
666 FileId(2) 24..25 StructLiteral 667 FileId(1) 24..25 StructLiteral
667 "#]], 668 "#]],
668 ); 669 );
669 } 670 }
@@ -672,11 +673,8 @@ fn g() { f(); }
672 check_with_scope(ra_fixture, None, expect) 673 check_with_scope(ra_fixture, None, expect)
673 } 674 }
674 675
675 fn check_with_scope(ra_fixture: &str, search_scope: Option<&str>, expect: Expect) { 676 fn check_with_scope(ra_fixture: &str, search_scope: Option<SearchScope>, expect: Expect) {
676 let (mock_analysis, pos) = MockAnalysis::with_files_and_position(ra_fixture); 677 let (analysis, pos) = fixture::position(ra_fixture);
677 let search_scope =
678 search_scope.map(|path| SearchScope::single_file(mock_analysis.id_of(path)));
679 let analysis = mock_analysis.analysis();
680 let refs = analysis.find_all_refs(pos, search_scope).unwrap().unwrap(); 678 let refs = analysis.find_all_refs(pos, search_scope).unwrap().unwrap();
681 679
682 let mut actual = String::new(); 680 let mut actual = String::new();
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 301629763..8cbe1ae5a 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -275,11 +275,11 @@ mod tests {
275 use test_utils::{assert_eq_text, mark}; 275 use test_utils::{assert_eq_text, mark};
276 use text_edit::TextEdit; 276 use text_edit::TextEdit;
277 277
278 use crate::{mock_analysis::analysis_and_position, FileId}; 278 use crate::{fixture, FileId};
279 279
280 fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 280 fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
281 let ra_fixture_after = &trim_indent(ra_fixture_after); 281 let ra_fixture_after = &trim_indent(ra_fixture_after);
282 let (analysis, position) = analysis_and_position(ra_fixture_before); 282 let (analysis, position) = fixture::position(ra_fixture_before);
283 let source_change = analysis.rename(position, new_name).unwrap(); 283 let source_change = analysis.rename(position, new_name).unwrap();
284 let mut text_edit_builder = TextEdit::builder(); 284 let mut text_edit_builder = TextEdit::builder();
285 let mut file_id: Option<FileId> = None; 285 let mut file_id: Option<FileId> = None;
@@ -297,7 +297,7 @@ mod tests {
297 } 297 }
298 298
299 fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) { 299 fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) {
300 let (analysis, position) = analysis_and_position(ra_fixture); 300 let (analysis, position) = fixture::position(ra_fixture);
301 let source_change = analysis.rename(position, new_name).unwrap().unwrap(); 301 let source_change = analysis.rename(position, new_name).unwrap().unwrap();
302 expect.assert_debug_eq(&source_change) 302 expect.assert_debug_eq(&source_change)
303 } 303 }
@@ -314,7 +314,7 @@ mod tests {
314 314
315 #[test] 315 #[test]
316 fn test_rename_to_invalid_identifier() { 316 fn test_rename_to_invalid_identifier() {
317 let (analysis, position) = analysis_and_position(r#"fn main() { let i<|> = 1; }"#); 317 let (analysis, position) = fixture::position(r#"fn main() { let i<|> = 1; }"#);
318 let new_name = "invalid!"; 318 let new_name = "invalid!";
319 let source_change = analysis.rename(position, new_name).unwrap(); 319 let source_change = analysis.rename(position, new_name).unwrap();
320 assert!(source_change.is_none()); 320 assert!(source_change.is_none());
@@ -602,7 +602,7 @@ mod foo<|>;
602 source_file_edits: [ 602 source_file_edits: [
603 SourceFileEdit { 603 SourceFileEdit {
604 file_id: FileId( 604 file_id: FileId(
605 2, 605 1,
606 ), 606 ),
607 edit: TextEdit { 607 edit: TextEdit {
608 indels: [ 608 indels: [
@@ -617,10 +617,10 @@ mod foo<|>;
617 file_system_edits: [ 617 file_system_edits: [
618 MoveFile { 618 MoveFile {
619 src: FileId( 619 src: FileId(
620 3, 620 2,
621 ), 621 ),
622 anchor: FileId( 622 anchor: FileId(
623 3, 623 2,
624 ), 624 ),
625 dst: "foo2.rs", 625 dst: "foo2.rs",
626 }, 626 },
@@ -655,7 +655,7 @@ use crate::foo<|>::FooContent;
655 source_file_edits: [ 655 source_file_edits: [
656 SourceFileEdit { 656 SourceFileEdit {
657 file_id: FileId( 657 file_id: FileId(
658 1, 658 0,
659 ), 659 ),
660 edit: TextEdit { 660 edit: TextEdit {
661 indels: [ 661 indels: [
@@ -668,7 +668,7 @@ use crate::foo<|>::FooContent;
668 }, 668 },
669 SourceFileEdit { 669 SourceFileEdit {
670 file_id: FileId( 670 file_id: FileId(
671 3, 671 2,
672 ), 672 ),
673 edit: TextEdit { 673 edit: TextEdit {
674 indels: [ 674 indels: [
@@ -683,10 +683,10 @@ use crate::foo<|>::FooContent;
683 file_system_edits: [ 683 file_system_edits: [
684 MoveFile { 684 MoveFile {
685 src: FileId( 685 src: FileId(
686 2, 686 1,
687 ), 687 ),
688 anchor: FileId( 688 anchor: FileId(
689 2, 689 1,
690 ), 690 ),
691 dst: "quux.rs", 691 dst: "quux.rs",
692 }, 692 },
@@ -715,7 +715,7 @@ mod fo<|>o;
715 source_file_edits: [ 715 source_file_edits: [
716 SourceFileEdit { 716 SourceFileEdit {
717 file_id: FileId( 717 file_id: FileId(
718 1, 718 0,
719 ), 719 ),
720 edit: TextEdit { 720 edit: TextEdit {
721 indels: [ 721 indels: [
@@ -730,10 +730,10 @@ mod fo<|>o;
730 file_system_edits: [ 730 file_system_edits: [
731 MoveFile { 731 MoveFile {
732 src: FileId( 732 src: FileId(
733 2, 733 1,
734 ), 734 ),
735 anchor: FileId( 735 anchor: FileId(
736 2, 736 1,
737 ), 737 ),
738 dst: "../foo2/mod.rs", 738 dst: "../foo2/mod.rs",
739 }, 739 },
@@ -763,7 +763,7 @@ mod outer { mod fo<|>o; }
763 source_file_edits: [ 763 source_file_edits: [
764 SourceFileEdit { 764 SourceFileEdit {
765 file_id: FileId( 765 file_id: FileId(
766 1, 766 0,
767 ), 767 ),
768 edit: TextEdit { 768 edit: TextEdit {
769 indels: [ 769 indels: [
@@ -778,10 +778,10 @@ mod outer { mod fo<|>o; }
778 file_system_edits: [ 778 file_system_edits: [
779 MoveFile { 779 MoveFile {
780 src: FileId( 780 src: FileId(
781 2, 781 1,
782 ), 782 ),
783 anchor: FileId( 783 anchor: FileId(
784 2, 784 1,
785 ), 785 ),
786 dst: "bar.rs", 786 dst: "bar.rs",
787 }, 787 },
@@ -834,7 +834,7 @@ pub mod foo<|>;
834 source_file_edits: [ 834 source_file_edits: [
835 SourceFileEdit { 835 SourceFileEdit {
836 file_id: FileId( 836 file_id: FileId(
837 2, 837 1,
838 ), 838 ),
839 edit: TextEdit { 839 edit: TextEdit {
840 indels: [ 840 indels: [
@@ -847,7 +847,7 @@ pub mod foo<|>;
847 }, 847 },
848 SourceFileEdit { 848 SourceFileEdit {
849 file_id: FileId( 849 file_id: FileId(
850 1, 850 0,
851 ), 851 ),
852 edit: TextEdit { 852 edit: TextEdit {
853 indels: [ 853 indels: [
@@ -862,10 +862,10 @@ pub mod foo<|>;
862 file_system_edits: [ 862 file_system_edits: [
863 MoveFile { 863 MoveFile {
864 src: FileId( 864 src: FileId(
865 3, 865 2,
866 ), 866 ),
867 anchor: FileId( 867 anchor: FileId(
868 3, 868 2,
869 ), 869 ),
870 dst: "foo2.rs", 870 dst: "foo2.rs",
871 }, 871 },
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index cfeff40c1..752ef2f21 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -292,7 +292,7 @@ fn has_test_function_or_multiple_test_submodules(module: &ast::Module) -> bool {
292mod tests { 292mod tests {
293 use expect_test::{expect, Expect}; 293 use expect_test::{expect, Expect};
294 294
295 use crate::mock_analysis::analysis_and_position; 295 use crate::fixture;
296 296
297 use super::{RunnableAction, BENCH, BIN, DOCTEST, TEST}; 297 use super::{RunnableAction, BENCH, BIN, DOCTEST, TEST};
298 298
@@ -302,7 +302,7 @@ mod tests {
302 actions: &[&RunnableAction], 302 actions: &[&RunnableAction],
303 expect: Expect, 303 expect: Expect,
304 ) { 304 ) {
305 let (analysis, position) = analysis_and_position(ra_fixture); 305 let (analysis, position) = fixture::position(ra_fixture);
306 let runnables = analysis.runnables(position.file_id).unwrap(); 306 let runnables = analysis.runnables(position.file_id).unwrap();
307 expect.assert_debug_eq(&runnables); 307 expect.assert_debug_eq(&runnables);
308 assert_eq!( 308 assert_eq!(
@@ -335,7 +335,7 @@ fn bench() {}
335 Runnable { 335 Runnable {
336 nav: NavigationTarget { 336 nav: NavigationTarget {
337 file_id: FileId( 337 file_id: FileId(
338 1, 338 0,
339 ), 339 ),
340 full_range: 1..13, 340 full_range: 1..13,
341 focus_range: Some( 341 focus_range: Some(
@@ -353,7 +353,7 @@ fn bench() {}
353 Runnable { 353 Runnable {
354 nav: NavigationTarget { 354 nav: NavigationTarget {
355 file_id: FileId( 355 file_id: FileId(
356 1, 356 0,
357 ), 357 ),
358 full_range: 15..39, 358 full_range: 15..39,
359 focus_range: Some( 359 focus_range: Some(
@@ -378,7 +378,7 @@ fn bench() {}
378 Runnable { 378 Runnable {
379 nav: NavigationTarget { 379 nav: NavigationTarget {
380 file_id: FileId( 380 file_id: FileId(
381 1, 381 0,
382 ), 382 ),
383 full_range: 41..75, 383 full_range: 41..75,
384 focus_range: Some( 384 focus_range: Some(
@@ -403,7 +403,7 @@ fn bench() {}
403 Runnable { 403 Runnable {
404 nav: NavigationTarget { 404 nav: NavigationTarget {
405 file_id: FileId( 405 file_id: FileId(
406 1, 406 0,
407 ), 407 ),
408 full_range: 77..99, 408 full_range: 77..99,
409 focus_range: Some( 409 focus_range: Some(
@@ -494,7 +494,7 @@ fn should_have_no_runnable_6() {}
494 Runnable { 494 Runnable {
495 nav: NavigationTarget { 495 nav: NavigationTarget {
496 file_id: FileId( 496 file_id: FileId(
497 1, 497 0,
498 ), 498 ),
499 full_range: 1..13, 499 full_range: 1..13,
500 focus_range: Some( 500 focus_range: Some(
@@ -512,7 +512,7 @@ fn should_have_no_runnable_6() {}
512 Runnable { 512 Runnable {
513 nav: NavigationTarget { 513 nav: NavigationTarget {
514 file_id: FileId( 514 file_id: FileId(
515 1, 515 0,
516 ), 516 ),
517 full_range: 15..74, 517 full_range: 15..74,
518 focus_range: None, 518 focus_range: None,
@@ -532,7 +532,7 @@ fn should_have_no_runnable_6() {}
532 Runnable { 532 Runnable {
533 nav: NavigationTarget { 533 nav: NavigationTarget {
534 file_id: FileId( 534 file_id: FileId(
535 1, 535 0,
536 ), 536 ),
537 full_range: 76..148, 537 full_range: 76..148,
538 focus_range: None, 538 focus_range: None,
@@ -552,7 +552,7 @@ fn should_have_no_runnable_6() {}
552 Runnable { 552 Runnable {
553 nav: NavigationTarget { 553 nav: NavigationTarget {
554 file_id: FileId( 554 file_id: FileId(
555 1, 555 0,
556 ), 556 ),
557 full_range: 150..254, 557 full_range: 150..254,
558 focus_range: None, 558 focus_range: None,
@@ -596,7 +596,7 @@ impl Data {
596 Runnable { 596 Runnable {
597 nav: NavigationTarget { 597 nav: NavigationTarget {
598 file_id: FileId( 598 file_id: FileId(
599 1, 599 0,
600 ), 600 ),
601 full_range: 1..13, 601 full_range: 1..13,
602 focus_range: Some( 602 focus_range: Some(
@@ -614,7 +614,7 @@ impl Data {
614 Runnable { 614 Runnable {
615 nav: NavigationTarget { 615 nav: NavigationTarget {
616 file_id: FileId( 616 file_id: FileId(
617 1, 617 0,
618 ), 618 ),
619 full_range: 44..98, 619 full_range: 44..98,
620 focus_range: None, 620 focus_range: None,
@@ -653,7 +653,7 @@ mod test_mod {
653 Runnable { 653 Runnable {
654 nav: NavigationTarget { 654 nav: NavigationTarget {
655 file_id: FileId( 655 file_id: FileId(
656 1, 656 0,
657 ), 657 ),
658 full_range: 1..51, 658 full_range: 1..51,
659 focus_range: Some( 659 focus_range: Some(
@@ -673,7 +673,7 @@ mod test_mod {
673 Runnable { 673 Runnable {
674 nav: NavigationTarget { 674 nav: NavigationTarget {
675 file_id: FileId( 675 file_id: FileId(
676 1, 676 0,
677 ), 677 ),
678 full_range: 20..49, 678 full_range: 20..49,
679 focus_range: Some( 679 focus_range: Some(
@@ -733,7 +733,7 @@ mod root_tests {
733 Runnable { 733 Runnable {
734 nav: NavigationTarget { 734 nav: NavigationTarget {
735 file_id: FileId( 735 file_id: FileId(
736 1, 736 0,
737 ), 737 ),
738 full_range: 22..323, 738 full_range: 22..323,
739 focus_range: Some( 739 focus_range: Some(
@@ -753,7 +753,7 @@ mod root_tests {
753 Runnable { 753 Runnable {
754 nav: NavigationTarget { 754 nav: NavigationTarget {
755 file_id: FileId( 755 file_id: FileId(
756 1, 756 0,
757 ), 757 ),
758 full_range: 51..192, 758 full_range: 51..192,
759 focus_range: Some( 759 focus_range: Some(
@@ -773,7 +773,7 @@ mod root_tests {
773 Runnable { 773 Runnable {
774 nav: NavigationTarget { 774 nav: NavigationTarget {
775 file_id: FileId( 775 file_id: FileId(
776 1, 776 0,
777 ), 777 ),
778 full_range: 84..126, 778 full_range: 84..126,
779 focus_range: Some( 779 focus_range: Some(
@@ -798,7 +798,7 @@ mod root_tests {
798 Runnable { 798 Runnable {
799 nav: NavigationTarget { 799 nav: NavigationTarget {
800 file_id: FileId( 800 file_id: FileId(
801 1, 801 0,
802 ), 802 ),
803 full_range: 140..182, 803 full_range: 140..182,
804 focus_range: Some( 804 focus_range: Some(
@@ -823,7 +823,7 @@ mod root_tests {
823 Runnable { 823 Runnable {
824 nav: NavigationTarget { 824 nav: NavigationTarget {
825 file_id: FileId( 825 file_id: FileId(
826 1, 826 0,
827 ), 827 ),
828 full_range: 202..286, 828 full_range: 202..286,
829 focus_range: Some( 829 focus_range: Some(
@@ -843,7 +843,7 @@ mod root_tests {
843 Runnable { 843 Runnable {
844 nav: NavigationTarget { 844 nav: NavigationTarget {
845 file_id: FileId( 845 file_id: FileId(
846 1, 846 0,
847 ), 847 ),
848 full_range: 235..276, 848 full_range: 235..276,
849 focus_range: Some( 849 focus_range: Some(
@@ -886,7 +886,7 @@ fn test_foo1() {}
886 Runnable { 886 Runnable {
887 nav: NavigationTarget { 887 nav: NavigationTarget {
888 file_id: FileId( 888 file_id: FileId(
889 1, 889 0,
890 ), 890 ),
891 full_range: 1..50, 891 full_range: 1..50,
892 focus_range: Some( 892 focus_range: Some(
@@ -934,7 +934,7 @@ fn test_foo1() {}
934 Runnable { 934 Runnable {
935 nav: NavigationTarget { 935 nav: NavigationTarget {
936 file_id: FileId( 936 file_id: FileId(
937 1, 937 0,
938 ), 938 ),
939 full_range: 1..72, 939 full_range: 1..72,
940 focus_range: Some( 940 focus_range: Some(
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index 211e62ea1..694c4b7fa 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -3,7 +3,7 @@ use std::fs;
3use expect_test::{expect_file, ExpectFile}; 3use expect_test::{expect_file, ExpectFile};
4use test_utils::project_dir; 4use test_utils::project_dir;
5 5
6use crate::{mock_analysis::single_file, FileRange, TextRange}; 6use crate::{fixture, FileRange, TextRange};
7 7
8#[test] 8#[test]
9fn test_highlighting() { 9fn test_highlighting() {
@@ -178,7 +178,7 @@ fn accidentally_quadratic() {
178 let file = project_dir().join("crates/syntax/test_data/accidentally_quadratic"); 178 let file = project_dir().join("crates/syntax/test_data/accidentally_quadratic");
179 let src = fs::read_to_string(file).unwrap(); 179 let src = fs::read_to_string(file).unwrap();
180 180
181 let (analysis, file_id) = single_file(&src); 181 let (analysis, file_id) = fixture::file(&src);
182 182
183 // let t = std::time::Instant::now(); 183 // let t = std::time::Instant::now();
184 let _ = analysis.highlight(file_id).unwrap(); 184 let _ = analysis.highlight(file_id).unwrap();
@@ -187,7 +187,7 @@ fn accidentally_quadratic() {
187 187
188#[test] 188#[test]
189fn test_ranges() { 189fn test_ranges() {
190 let (analysis, file_id) = single_file( 190 let (analysis, file_id) = fixture::file(
191 r#" 191 r#"
192#[derive(Clone, Debug)] 192#[derive(Clone, Debug)]
193struct Foo { 193struct Foo {
@@ -228,7 +228,7 @@ fn main() {
228 228
229#[test] 229#[test]
230fn ranges_sorted() { 230fn ranges_sorted() {
231 let (analysis, file_id) = single_file( 231 let (analysis, file_id) = fixture::file(
232 r#" 232 r#"
233#[foo(bar = "bar")] 233#[foo(bar = "bar")]
234macro_rules! test {} 234macro_rules! test {}
@@ -462,12 +462,12 @@ macro_rules! noop {
462fn test_extern_crate() { 462fn test_extern_crate() {
463 check_highlighting( 463 check_highlighting(
464 r#" 464 r#"
465 //- /main.rs 465 //- /main.rs crate:main deps:std,alloc
466 extern crate std; 466 extern crate std;
467 extern crate alloc as abc; 467 extern crate alloc as abc;
468 //- /std/lib.rs 468 //- /std/lib.rs crate:std
469 pub struct S; 469 pub struct S;
470 //- /alloc/lib.rs 470 //- /alloc/lib.rs crate:alloc
471 pub struct A 471 pub struct A
472 "#, 472 "#,
473 expect_file!["./test_data/highlight_extern_crate.html"], 473 expect_file!["./test_data/highlight_extern_crate.html"],
@@ -479,7 +479,7 @@ fn test_extern_crate() {
479/// result as HTML, and compares it with the HTML file given as `snapshot`. 479/// result as HTML, and compares it with the HTML file given as `snapshot`.
480/// Note that the `snapshot` file is overwritten by the rendered HTML. 480/// Note that the `snapshot` file is overwritten by the rendered HTML.
481fn check_highlighting(ra_fixture: &str, expect: ExpectFile, rainbow: bool) { 481fn check_highlighting(ra_fixture: &str, expect: ExpectFile, rainbow: bool) {
482 let (analysis, file_id) = single_file(ra_fixture); 482 let (analysis, file_id) = fixture::file(ra_fixture);
483 let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap(); 483 let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap();
484 expect.assert_eq(actual_html) 484 expect.assert_eq(actual_html)
485} 485}
diff --git a/crates/ide/src/syntax_tree.rs b/crates/ide/src/syntax_tree.rs
index f80044959..0eed2dbd7 100644
--- a/crates/ide/src/syntax_tree.rs
+++ b/crates/ide/src/syntax_tree.rs
@@ -104,12 +104,12 @@ fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<St
104mod tests { 104mod tests {
105 use test_utils::assert_eq_text; 105 use test_utils::assert_eq_text;
106 106
107 use crate::mock_analysis::{analysis_and_range, single_file}; 107 use crate::fixture;
108 108
109 #[test] 109 #[test]
110 fn test_syntax_tree_without_range() { 110 fn test_syntax_tree_without_range() {
111 // Basic syntax 111 // Basic syntax
112 let (analysis, file_id) = single_file(r#"fn foo() {}"#); 112 let (analysis, file_id) = fixture::file(r#"fn foo() {}"#);
113 let syn = analysis.syntax_tree(file_id, None).unwrap(); 113 let syn = analysis.syntax_tree(file_id, None).unwrap();
114 114
115 assert_eq_text!( 115 assert_eq_text!(
@@ -132,7 +132,7 @@ [email protected]
132 .trim() 132 .trim()
133 ); 133 );
134 134
135 let (analysis, file_id) = single_file( 135 let (analysis, file_id) = fixture::file(
136 r#" 136 r#"
137fn test() { 137fn test() {
138 assert!(" 138 assert!("
@@ -184,7 +184,7 @@ [email protected]
184 184
185 #[test] 185 #[test]
186 fn test_syntax_tree_with_range() { 186 fn test_syntax_tree_with_range() {
187 let (analysis, range) = analysis_and_range(r#"<|>fn foo() {}<|>"#.trim()); 187 let (analysis, range) = fixture::range(r#"<|>fn foo() {}<|>"#.trim());
188 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap(); 188 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
189 189
190 assert_eq_text!( 190 assert_eq_text!(
@@ -206,7 +206,7 @@ [email protected]
206 .trim() 206 .trim()
207 ); 207 );
208 208
209 let (analysis, range) = analysis_and_range( 209 let (analysis, range) = fixture::range(
210 r#"fn test() { 210 r#"fn test() {
211 <|>assert!(" 211 <|>assert!("
212 fn foo() { 212 fn foo() {
@@ -242,7 +242,7 @@ [email protected]
242 242
243 #[test] 243 #[test]
244 fn test_syntax_tree_inside_string() { 244 fn test_syntax_tree_inside_string() {
245 let (analysis, range) = analysis_and_range( 245 let (analysis, range) = fixture::range(
246 r#"fn test() { 246 r#"fn test() {
247 assert!(" 247 assert!("
248<|>fn foo() { 248<|>fn foo() {
@@ -276,7 +276,7 @@ [email protected]
276 ); 276 );
277 277
278 // With a raw string 278 // With a raw string
279 let (analysis, range) = analysis_and_range( 279 let (analysis, range) = fixture::range(
280 r###"fn test() { 280 r###"fn test() {
281 assert!(r#" 281 assert!(r#"
282<|>fn foo() { 282<|>fn foo() {
@@ -310,7 +310,7 @@ [email protected]
310 ); 310 );
311 311
312 // With a raw string 312 // With a raw string
313 let (analysis, range) = analysis_and_range( 313 let (analysis, range) = fixture::range(
314 r###"fn test() { 314 r###"fn test() {
315 assert!(r<|>#" 315 assert!(r<|>#"
316fn foo() { 316fn foo() {
diff --git a/crates/ide/src/typing/on_enter.rs b/crates/ide/src/typing/on_enter.rs
index f7d46146c..a0dc4b9df 100644
--- a/crates/ide/src/typing/on_enter.rs
+++ b/crates/ide/src/typing/on_enter.rs
@@ -109,10 +109,10 @@ mod tests {
109 use stdx::trim_indent; 109 use stdx::trim_indent;
110 use test_utils::{assert_eq_text, mark}; 110 use test_utils::{assert_eq_text, mark};
111 111
112 use crate::mock_analysis::analysis_and_position; 112 use crate::fixture;
113 113
114 fn apply_on_enter(before: &str) -> Option<String> { 114 fn apply_on_enter(before: &str) -> Option<String> {
115 let (analysis, position) = analysis_and_position(&before); 115 let (analysis, position) = fixture::position(&before);
116 let result = analysis.on_enter(position).unwrap()?; 116 let result = analysis.on_enter(position).unwrap()?;
117 117
118 let mut actual = analysis.file_text(position.file_id).unwrap().to_string(); 118 let mut actual = analysis.file_text(position.file_id).unwrap().to_string();
diff --git a/crates/ide_db/src/change.rs b/crates/ide_db/src/apply_change.rs
index 7f98111c4..da16fa21d 100644
--- a/crates/ide_db/src/change.rs
+++ b/crates/ide_db/src/apply_change.rs
@@ -1,58 +1,16 @@
1//! Defines a unit of change that can applied to a state of IDE to get the next 1//! Applies changes to the IDE state transactionally.
2//! state. Changes are transactional.
3 2
4use std::{fmt, sync::Arc}; 3use std::{fmt, sync::Arc};
5 4
6use base_db::{ 5use base_db::{
7 salsa::{Database, Durability, SweepStrategy}, 6 salsa::{Database, Durability, SweepStrategy},
8 CrateGraph, FileId, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId, 7 Change, FileId, SourceRootId,
9}; 8};
10use profile::{memory_usage, Bytes}; 9use profile::{memory_usage, Bytes};
11use rustc_hash::FxHashSet; 10use rustc_hash::FxHashSet;
12 11
13use crate::{symbol_index::SymbolsDatabase, RootDatabase}; 12use crate::{symbol_index::SymbolsDatabase, RootDatabase};
14 13
15#[derive(Default)]
16pub struct AnalysisChange {
17 roots: Option<Vec<SourceRoot>>,
18 files_changed: Vec<(FileId, Option<Arc<String>>)>,
19 crate_graph: Option<CrateGraph>,
20}
21
22impl fmt::Debug for AnalysisChange {
23 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
24 let mut d = fmt.debug_struct("AnalysisChange");
25 if let Some(roots) = &self.roots {
26 d.field("roots", roots);
27 }
28 if !self.files_changed.is_empty() {
29 d.field("files_changed", &self.files_changed.len());
30 }
31 if self.crate_graph.is_some() {
32 d.field("crate_graph", &self.crate_graph);
33 }
34 d.finish()
35 }
36}
37
38impl AnalysisChange {
39 pub fn new() -> AnalysisChange {
40 AnalysisChange::default()
41 }
42
43 pub fn set_roots(&mut self, roots: Vec<SourceRoot>) {
44 self.roots = Some(roots);
45 }
46
47 pub fn change_file(&mut self, file_id: FileId, new_text: Option<Arc<String>>) {
48 self.files_changed.push((file_id, new_text))
49 }
50
51 pub fn set_crate_graph(&mut self, graph: CrateGraph) {
52 self.crate_graph = Some(graph);
53 }
54}
55
56#[derive(Debug)] 14#[derive(Debug)]
57struct AddFile { 15struct AddFile {
58 file_id: FileId, 16 file_id: FileId,
@@ -87,41 +45,25 @@ impl RootDatabase {
87 self.salsa_runtime_mut().synthetic_write(Durability::LOW); 45 self.salsa_runtime_mut().synthetic_write(Durability::LOW);
88 } 46 }
89 47
90 pub fn apply_change(&mut self, change: AnalysisChange) { 48 pub fn apply_change(&mut self, change: Change) {
91 let _p = profile::span("RootDatabase::apply_change"); 49 let _p = profile::span("RootDatabase::apply_change");
92 self.request_cancellation(); 50 self.request_cancellation();
93 log::info!("apply_change {:?}", change); 51 log::info!("apply_change {:?}", change);
94 if let Some(roots) = change.roots { 52 if let Some(roots) = &change.roots {
95 let mut local_roots = FxHashSet::default(); 53 let mut local_roots = FxHashSet::default();
96 let mut library_roots = FxHashSet::default(); 54 let mut library_roots = FxHashSet::default();
97 for (idx, root) in roots.into_iter().enumerate() { 55 for (idx, root) in roots.iter().enumerate() {
98 let root_id = SourceRootId(idx as u32); 56 let root_id = SourceRootId(idx as u32);
99 let durability = durability(&root);
100 if root.is_library { 57 if root.is_library {
101 library_roots.insert(root_id); 58 library_roots.insert(root_id);
102 } else { 59 } else {
103 local_roots.insert(root_id); 60 local_roots.insert(root_id);
104 } 61 }
105 for file_id in root.iter() {
106 self.set_file_source_root_with_durability(file_id, root_id, durability);
107 }
108 self.set_source_root_with_durability(root_id, Arc::new(root), durability);
109 } 62 }
110 self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); 63 self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
111 self.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH); 64 self.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH);
112 } 65 }
113 66 change.apply(self);
114 for (file_id, text) in change.files_changed {
115 let source_root_id = self.file_source_root(file_id);
116 let source_root = self.source_root(source_root_id);
117 let durability = durability(&source_root);
118 // XXX: can't actually remove the file, just reset the text
119 let text = text.unwrap_or_default();
120 self.set_file_text_with_durability(file_id, text, durability)
121 }
122 if let Some(crate_graph) = change.crate_graph {
123 self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
124 }
125 } 67 }
126 68
127 pub fn collect_garbage(&mut self) { 69 pub fn collect_garbage(&mut self) {
@@ -295,11 +237,3 @@ impl RootDatabase {
295 acc 237 acc
296 } 238 }
297} 239}
298
299fn durability(source_root: &SourceRoot) -> Durability {
300 if source_root.is_library {
301 Durability::HIGH
302 } else {
303 Durability::LOW
304 }
305}
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs
index 0d209c6ec..7eff247c7 100644
--- a/crates/ide_db/src/lib.rs
+++ b/crates/ide_db/src/lib.rs
@@ -2,10 +2,10 @@
2//! 2//!
3//! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search. 3//! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search.
4 4
5mod apply_change;
5pub mod label; 6pub mod label;
6pub mod line_index; 7pub mod line_index;
7pub mod symbol_index; 8pub mod symbol_index;
8pub mod change;
9pub mod defs; 9pub mod defs;
10pub mod search; 10pub mod search;
11pub mod imports_locator; 11pub mod imports_locator;
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs
index c312e0a2e..d1c095ba5 100644
--- a/crates/rust-analyzer/src/cli/analysis_bench.rs
+++ b/crates/rust-analyzer/src/cli/analysis_bench.rs
@@ -8,8 +8,7 @@ use base_db::{
8 FileId, 8 FileId,
9}; 9};
10use ide::{ 10use ide::{
11 Analysis, AnalysisChange, AnalysisHost, CompletionConfig, DiagnosticsConfig, FilePosition, 11 Analysis, AnalysisHost, Change, CompletionConfig, DiagnosticsConfig, FilePosition, LineCol,
12 LineCol,
13}; 12};
14use vfs::AbsPathBuf; 13use vfs::AbsPathBuf;
15 14
@@ -143,7 +142,7 @@ fn do_work<F: Fn(&Analysis) -> T, T>(host: &mut AnalysisHost, file_id: FileId, w
143 { 142 {
144 let mut text = host.analysis().file_text(file_id).unwrap().to_string(); 143 let mut text = host.analysis().file_text(file_id).unwrap().to_string();
145 text.push_str("\n/* Hello world */\n"); 144 text.push_str("\n/* Hello world */\n");
146 let mut change = AnalysisChange::new(); 145 let mut change = Change::new();
147 change.change_file(file_id, Some(Arc::new(text))); 146 change.change_file(file_id, Some(Arc::new(text)));
148 host.apply_change(change); 147 host.apply_change(change);
149 } 148 }
@@ -156,7 +155,7 @@ fn do_work<F: Fn(&Analysis) -> T, T>(host: &mut AnalysisHost, file_id: FileId, w
156 { 155 {
157 let mut text = host.analysis().file_text(file_id).unwrap().to_string(); 156 let mut text = host.analysis().file_text(file_id).unwrap().to_string();
158 text.push_str("\npub fn _dummy() {}\n"); 157 text.push_str("\npub fn _dummy() {}\n");
159 let mut change = AnalysisChange::new(); 158 let mut change = Change::new();
160 change.change_file(file_id, Some(Arc::new(text))); 159 change.change_file(file_id, Some(Arc::new(text)));
161 host.apply_change(change); 160 host.apply_change(change);
162 } 161 }
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index c47cf6ef3..7ae1c9055 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -5,7 +5,7 @@ use std::{path::Path, sync::Arc};
5use anyhow::Result; 5use anyhow::Result;
6use base_db::CrateGraph; 6use base_db::CrateGraph;
7use crossbeam_channel::{unbounded, Receiver}; 7use crossbeam_channel::{unbounded, Receiver};
8use ide::{AnalysisChange, AnalysisHost}; 8use ide::{AnalysisHost, Change};
9use project_model::{CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace}; 9use project_model::{CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace};
10use vfs::{loader::Handle, AbsPath, AbsPathBuf}; 10use vfs::{loader::Handle, AbsPath, AbsPathBuf};
11 11
@@ -62,7 +62,7 @@ fn load(
62) -> AnalysisHost { 62) -> AnalysisHost {
63 let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); 63 let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
64 let mut host = AnalysisHost::new(lru_cap); 64 let mut host = AnalysisHost::new(lru_cap);
65 let mut analysis_change = AnalysisChange::new(); 65 let mut analysis_change = Change::new();
66 66
67 // wait until Vfs has loaded all roots 67 // wait until Vfs has loaded all roots
68 for task in receiver { 68 for task in receiver {
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 96313aaec..dafab6a6a 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -8,7 +8,7 @@ use std::{sync::Arc, time::Instant};
8use base_db::{CrateId, VfsPath}; 8use base_db::{CrateId, VfsPath};
9use crossbeam_channel::{unbounded, Receiver, Sender}; 9use crossbeam_channel::{unbounded, Receiver, Sender};
10use flycheck::FlycheckHandle; 10use flycheck::FlycheckHandle;
11use ide::{Analysis, AnalysisChange, AnalysisHost, FileId}; 11use ide::{Analysis, AnalysisHost, Change, FileId};
12use lsp_types::{SemanticTokens, Url}; 12use lsp_types::{SemanticTokens, Url};
13use parking_lot::{Mutex, RwLock}; 13use parking_lot::{Mutex, RwLock};
14use project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; 14use project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target};
@@ -139,7 +139,7 @@ impl GlobalState {
139 let mut has_fs_changes = false; 139 let mut has_fs_changes = false;
140 140
141 let change = { 141 let change = {
142 let mut change = AnalysisChange::new(); 142 let mut change = Change::new();
143 let (vfs, line_endings_map) = &mut *self.vfs.write(); 143 let (vfs, line_endings_map) = &mut *self.vfs.write();
144 let changed_files = vfs.take_changes(); 144 let changed_files = vfs.take_changes();
145 if changed_files.is_empty() { 145 if changed_files.is_empty() {
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index de0dbcad4..f7215f129 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -3,7 +3,7 @@ use std::{mem, sync::Arc};
3 3
4use base_db::{CrateGraph, SourceRoot, VfsPath}; 4use base_db::{CrateGraph, SourceRoot, VfsPath};
5use flycheck::{FlycheckConfig, FlycheckHandle}; 5use flycheck::{FlycheckConfig, FlycheckHandle};
6use ide::AnalysisChange; 6use ide::Change;
7use project_model::{ProcMacroClient, ProjectWorkspace}; 7use project_model::{ProcMacroClient, ProjectWorkspace};
8use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind}; 8use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind};
9 9
@@ -171,7 +171,7 @@ impl GlobalState {
171 ); 171 );
172 } 172 }
173 173
174 let mut change = AnalysisChange::new(); 174 let mut change = Change::new();
175 175
176 let project_folders = ProjectFolders::new(&workspaces); 176 let project_folders = ProjectFolders::new(&workspaces);
177 177