aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/mock_analysis.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-10-31 18:05:12 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-10-31 18:05:12 +0000
commit1dc5608d0bb6bf2eee5a1b9190fcb2f8cdfa2ef3 (patch)
treeb3c8a97880c625a81a814f4afa4e461ce5a58b82 /crates/ra_analysis/src/mock_analysis.rs
parente60ef6260f49b2b0438f8649ca71034fbafef631 (diff)
parentc09e14a4ff02f774460a70472e1aeb3c598e01dc (diff)
Merge #176
176: Move completio to ra_analysis r=matklad a=matklad While we should handle completion for isolated file, it's better achieved by using empty Analysis, rather than working only with &File: we need memoization for type inference even inside a single file. Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_analysis/src/mock_analysis.rs')
-rw-r--r--crates/ra_analysis/src/mock_analysis.rs71
1 files changed, 71 insertions, 0 deletions
diff --git a/crates/ra_analysis/src/mock_analysis.rs b/crates/ra_analysis/src/mock_analysis.rs
new file mode 100644
index 000000000..1c1dbee7c
--- /dev/null
+++ b/crates/ra_analysis/src/mock_analysis.rs
@@ -0,0 +1,71 @@
1
2use std::sync::Arc;
3
4use relative_path::{RelativePath, RelativePathBuf};
5
6use crate::{
7 AnalysisChange, Analysis, AnalysisHost, FileId, FileResolver,
8};
9
10/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis
11/// from a set of in-memory files.
12#[derive(Debug, Default)]
13pub struct MockAnalysis {
14 files: Vec<(String, String)>,
15}
16
17impl MockAnalysis {
18 pub fn new() -> MockAnalysis {
19 MockAnalysis::default()
20 }
21 pub fn with_files(files: &[(&str, &str)]) -> MockAnalysis {
22 let files = files.iter()
23 .map(|it| (it.0.to_string(), it.1.to_string()))
24 .collect();
25 MockAnalysis { files }
26 }
27 pub fn analysis_host(self) -> AnalysisHost {
28 let mut host = AnalysisHost::new();
29 let mut file_map = Vec::new();
30 let mut change = AnalysisChange::new();
31 for (id, (path, contents)) in self.files.into_iter().enumerate() {
32 let file_id = FileId((id + 1) as u32);
33 assert!(path.starts_with('/'));
34 let path = RelativePathBuf::from_path(&path[1..]).unwrap();
35 change.add_file(file_id, contents);
36 file_map.push((file_id, path));
37 }
38 change.set_file_resolver(Arc::new(FileMap(file_map)));
39 host.apply_change(change);
40 host
41 }
42 pub fn analysis(self) -> Analysis {
43 self.analysis_host().analysis()
44 }
45}
46
47#[derive(Debug)]
48struct FileMap(Vec<(FileId, RelativePathBuf)>);
49
50impl FileMap {
51 fn iter<'a>(&'a self) -> impl Iterator<Item = (FileId, &'a RelativePath)> + 'a {
52 self.0
53 .iter()
54 .map(|(id, path)| (*id, path.as_relative_path()))
55 }
56
57 fn path(&self, id: FileId) -> &RelativePath {
58 self.iter().find(|&(it, _)| it == id).unwrap().1
59 }
60}
61
62impl FileResolver for FileMap {
63 fn file_stem(&self, id: FileId) -> String {
64 self.path(id).file_stem().unwrap().to_string()
65 }
66 fn resolve(&self, id: FileId, rel: &RelativePath) -> Option<FileId> {
67 let path = self.path(id).join(rel).normalize();
68 let id = self.iter().find(|&(_, p)| path == p)?.0;
69 Some(id)
70 }
71}