diff options
author | Aleksey Kladov <[email protected]> | 2018-10-31 19:34:31 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-10-31 19:35:01 +0000 |
commit | dfba29e4fb66457d101db295e3c356a932ac005e (patch) | |
tree | 57907040a40ce65a6ed2377469204a6c79bb645e /crates/ra_analysis/src | |
parent | 41adf1bc4f8b88139afd550209c0be612c10ffa8 (diff) |
Add MockAnalysis to make testing easier
Diffstat (limited to 'crates/ra_analysis/src')
-rw-r--r-- | crates/ra_analysis/src/completion.rs | 17 | ||||
-rw-r--r-- | crates/ra_analysis/src/input.rs | 2 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_analysis/src/mock_analysis.rs | 84 |
4 files changed, 87 insertions, 19 deletions
diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs index 340ae3f66..286b6c376 100644 --- a/crates/ra_analysis/src/completion.rs +++ b/crates/ra_analysis/src/completion.rs | |||
@@ -368,18 +368,15 @@ fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<Completi | |||
368 | 368 | ||
369 | #[cfg(test)] | 369 | #[cfg(test)] |
370 | mod tests { | 370 | mod tests { |
371 | use test_utils::{assert_eq_dbg, extract_offset}; | 371 | use test_utils::{assert_eq_dbg}; |
372 | 372 | ||
373 | use crate::FileId; | 373 | use crate::mock_analysis::{single_file_with_position}; |
374 | use crate::mock_analysis::MockAnalysis; | ||
375 | 374 | ||
376 | use super::*; | 375 | use super::*; |
377 | 376 | ||
378 | fn check_scope_completion(code: &str, expected_completions: &str) { | 377 | fn check_scope_completion(code: &str, expected_completions: &str) { |
379 | let (off, code) = extract_offset(&code); | 378 | let (analysis, position) = single_file_with_position(code); |
380 | let analysis = MockAnalysis::with_files(&[("/main.rs", &code)]).analysis(); | 379 | let completions = scope_completion(&analysis.imp.db, position.file_id, position.offset) |
381 | let file_id = FileId(1); | ||
382 | let completions = scope_completion(&analysis.imp.db, file_id, off) | ||
383 | .unwrap() | 380 | .unwrap() |
384 | .into_iter() | 381 | .into_iter() |
385 | .filter(|c| c.snippet.is_none()) | 382 | .filter(|c| c.snippet.is_none()) |
@@ -388,10 +385,8 @@ mod tests { | |||
388 | } | 385 | } |
389 | 386 | ||
390 | fn check_snippet_completion(code: &str, expected_completions: &str) { | 387 | fn check_snippet_completion(code: &str, expected_completions: &str) { |
391 | let (off, code) = extract_offset(&code); | 388 | let (analysis, position) = single_file_with_position(code); |
392 | let analysis = MockAnalysis::with_files(&[("/main.rs", &code)]).analysis(); | 389 | let completions = scope_completion(&analysis.imp.db, position.file_id, position.offset) |
393 | let file_id = FileId(1); | ||
394 | let completions = scope_completion(&analysis.imp.db, file_id, off) | ||
395 | .unwrap() | 390 | .unwrap() |
396 | .into_iter() | 391 | .into_iter() |
397 | .filter(|c| c.snippet.is_some()) | 392 | .filter(|c| c.snippet.is_some()) |
diff --git a/crates/ra_analysis/src/input.rs b/crates/ra_analysis/src/input.rs index fd63182c7..b89b45133 100644 --- a/crates/ra_analysis/src/input.rs +++ b/crates/ra_analysis/src/input.rs | |||
@@ -25,7 +25,7 @@ impl CrateGraph { | |||
25 | pub fn new() -> CrateGraph { | 25 | pub fn new() -> CrateGraph { |
26 | CrateGraph::default() | 26 | CrateGraph::default() |
27 | } | 27 | } |
28 | pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId{ | 28 | pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId { |
29 | let crate_id = CrateId(self.crate_roots.len() as u32); | 29 | let crate_id = CrateId(self.crate_roots.len() as u32); |
30 | let prev = self.crate_roots.insert(crate_id, file_id); | 30 | let prev = self.crate_roots.insert(crate_id, file_id); |
31 | assert!(prev.is_none()); | 31 | assert!(prev.is_none()); |
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 776010281..e75411ec9 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -13,7 +13,7 @@ mod imp; | |||
13 | mod symbol_index; | 13 | mod symbol_index; |
14 | mod completion; | 14 | mod completion; |
15 | mod syntax_ptr; | 15 | mod syntax_ptr; |
16 | mod mock_analysis; | 16 | pub mod mock_analysis; |
17 | 17 | ||
18 | use std::{ | 18 | use std::{ |
19 | fmt, | 19 | fmt, |
@@ -33,7 +33,6 @@ pub use crate::{ | |||
33 | descriptors::function::FnDescriptor, | 33 | descriptors::function::FnDescriptor, |
34 | completion::CompletionItem, | 34 | completion::CompletionItem, |
35 | input::{FileId, FileResolver, CrateGraph, CrateId}, | 35 | input::{FileId, FileResolver, CrateGraph, CrateId}, |
36 | mock_analysis::MockAnalysis, | ||
37 | }; | 36 | }; |
38 | pub use ra_editor::{ | 37 | pub use ra_editor::{ |
39 | FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, | 38 | FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, |
diff --git a/crates/ra_analysis/src/mock_analysis.rs b/crates/ra_analysis/src/mock_analysis.rs index 1c1dbee7c..f72911192 100644 --- a/crates/ra_analysis/src/mock_analysis.rs +++ b/crates/ra_analysis/src/mock_analysis.rs | |||
@@ -2,11 +2,19 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use relative_path::{RelativePath, RelativePathBuf}; | 4 | use relative_path::{RelativePath, RelativePathBuf}; |
5 | use ra_syntax::TextUnit; | ||
6 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; | ||
5 | 7 | ||
6 | use crate::{ | 8 | use crate::{ |
7 | AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver, | 9 | AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver, |
8 | }; | 10 | }; |
9 | 11 | ||
12 | #[derive(Debug)] | ||
13 | pub struct FilePosition { | ||
14 | pub file_id: FileId, | ||
15 | pub offset: TextUnit, | ||
16 | } | ||
17 | |||
10 | /// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis | 18 | /// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis |
11 | /// from a set of in-memory files. | 19 | /// from a set of in-memory files. |
12 | #[derive(Debug, Default)] | 20 | #[derive(Debug, Default)] |
@@ -18,11 +26,57 @@ impl MockAnalysis { | |||
18 | pub fn new() -> MockAnalysis { | 26 | pub fn new() -> MockAnalysis { |
19 | MockAnalysis::default() | 27 | MockAnalysis::default() |
20 | } | 28 | } |
21 | pub fn with_files(files: &[(&str, &str)]) -> MockAnalysis { | 29 | /// Creates `MockAnalysis` using a fixture data in the following format: |
22 | let files = files.iter() | 30 | /// |
23 | .map(|it| (it.0.to_string(), it.1.to_string())) | 31 | /// ```notrust |
24 | .collect(); | 32 | /// //- /main.rs |
25 | MockAnalysis { files } | 33 | /// mod foo; |
34 | /// fn main() {} | ||
35 | /// | ||
36 | /// //- /foo.rs | ||
37 | /// struct Baz; | ||
38 | /// ``` | ||
39 | pub fn with_files(fixture: &str) -> MockAnalysis { | ||
40 | let mut res = MockAnalysis::new(); | ||
41 | for entry in parse_fixture(fixture) { | ||
42 | res.add_file(&entry.meta, &entry.text); | ||
43 | } | ||
44 | res | ||
45 | } | ||
46 | |||
47 | /// Same as `with_files`, but requires that a single file contains a `<|>` marker, | ||
48 | /// whose position is also returned. | ||
49 | pub fn with_files_and_position(fixture: &str) -> (MockAnalysis, FilePosition) { | ||
50 | let mut position = None; | ||
51 | let mut res = MockAnalysis::new(); | ||
52 | for entry in parse_fixture(fixture) { | ||
53 | if entry.text.contains(CURSOR_MARKER) { | ||
54 | assert!(position.is_none(), "only one marker (<|>) per fixture is allowed"); | ||
55 | position = Some(res.add_file_with_position(&entry.meta, &entry.text)); | ||
56 | } else { | ||
57 | res.add_file(&entry.meta, &entry.text); | ||
58 | } | ||
59 | } | ||
60 | let position = position.expect("expected a marker (<|>)"); | ||
61 | (res, position) | ||
62 | } | ||
63 | |||
64 | pub fn add_file(&mut self, path: &str, text: &str) -> FileId { | ||
65 | let file_id = FileId((self.files.len() + 1) as u32); | ||
66 | self.files.push((path.to_string(), text.to_string())); | ||
67 | file_id | ||
68 | } | ||
69 | pub fn add_file_with_position(&mut self, path: &str, text: &str) -> FilePosition { | ||
70 | let (offset, text) = extract_offset(text); | ||
71 | let file_id = FileId((self.files.len() + 1) as u32); | ||
72 | self.files.push((path.to_string(), text.to_string())); | ||
73 | FilePosition { file_id, offset } | ||
74 | } | ||
75 | pub fn id_of(&self, path: &str) -> FileId { | ||
76 | let (idx, _) = self.files.iter().enumerate() | ||
77 | .find(|(_, (p, _text))| path == p) | ||
78 | .expect("no file in this mock"); | ||
79 | FileId(idx as u32 + 1) | ||
26 | } | 80 | } |
27 | pub fn analysis_host(self) -> AnalysisHost { | 81 | pub fn analysis_host(self) -> AnalysisHost { |
28 | let mut host = AnalysisHost::new(); | 82 | let mut host = AnalysisHost::new(); |
@@ -44,6 +98,26 @@ impl MockAnalysis { | |||
44 | } | 98 | } |
45 | } | 99 | } |
46 | 100 | ||
101 | /// Creates analysis from a multi-file fixture, returns positions marked with <|>. | ||
102 | pub fn analysis_and_position(fixture: &str) -> (Analysis, FilePosition) { | ||
103 | let (mock, position) = MockAnalysis::with_files_and_position(fixture); | ||
104 | (mock.analysis(), position) | ||
105 | } | ||
106 | |||
107 | /// Creates analysis for a single file. | ||
108 | pub fn single_file(code: &str) -> (Analysis, FileId) { | ||
109 | let mut mock = MockAnalysis::new(); | ||
110 | let file_id = mock.add_file("/main.rs", code); | ||
111 | (mock.analysis(), file_id) | ||
112 | } | ||
113 | |||
114 | /// Creates analysis for a single file, returns position marked with <|>. | ||
115 | pub fn single_file_with_position(code: &str) -> (Analysis, FilePosition) { | ||
116 | let mut mock = MockAnalysis::new(); | ||
117 | let pos = mock.add_file_with_position("/main.rs", code); | ||
118 | (mock.analysis(), pos) | ||
119 | } | ||
120 | |||
47 | #[derive(Debug)] | 121 | #[derive(Debug)] |
48 | struct FileMap(Vec<(FileId, RelativePathBuf)>); | 122 | struct FileMap(Vec<(FileId, RelativePathBuf)>); |
49 | 123 | ||