aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src')
-rw-r--r--crates/ra_analysis/src/completion.rs17
-rw-r--r--crates/ra_analysis/src/input.rs2
-rw-r--r--crates/ra_analysis/src/lib.rs3
-rw-r--r--crates/ra_analysis/src/mock_analysis.rs84
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)]
370mod tests { 370mod 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;
13mod symbol_index; 13mod symbol_index;
14mod completion; 14mod completion;
15mod syntax_ptr; 15mod syntax_ptr;
16mod mock_analysis; 16pub mod mock_analysis;
17 17
18use std::{ 18use 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};
38pub use ra_editor::{ 37pub 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 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use relative_path::{RelativePath, RelativePathBuf}; 4use relative_path::{RelativePath, RelativePathBuf};
5use ra_syntax::TextUnit;
6use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER};
5 7
6use crate::{ 8use crate::{
7 AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver, 9 AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver,
8}; 10};
9 11
12#[derive(Debug)]
13pub 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 <|>.
102pub 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.
108pub 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 <|>.
115pub 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)]
48struct FileMap(Vec<(FileId, RelativePathBuf)>); 122struct FileMap(Vec<(FileId, RelativePathBuf)>);
49 123