aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/path_map.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-16 10:54:24 +0100
committerAleksey Kladov <[email protected]>2018-09-16 11:07:39 +0100
commitb5021411a84822cb3f1e3aeffad9550dd15bdeb6 (patch)
tree9dca564f8e51b298dced01c4ce669c756dce3142 /crates/ra_lsp_server/src/path_map.rs
parentba0bfeee12e19da40b5eabc8d0408639af10e96f (diff)
rename all things
Diffstat (limited to 'crates/ra_lsp_server/src/path_map.rs')
-rw-r--r--crates/ra_lsp_server/src/path_map.rs110
1 files changed, 110 insertions, 0 deletions
diff --git a/crates/ra_lsp_server/src/path_map.rs b/crates/ra_lsp_server/src/path_map.rs
new file mode 100644
index 000000000..19c3b1d3b
--- /dev/null
+++ b/crates/ra_lsp_server/src/path_map.rs
@@ -0,0 +1,110 @@
1use std::path::{PathBuf, Path, Component};
2use im;
3use relative_path::RelativePath;
4use ra_analysis::{FileId, FileResolver};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Root {
8 Workspace, Lib
9}
10
11#[derive(Debug, Default, Clone)]
12pub struct PathMap {
13 next_id: u32,
14 path2id: im::HashMap<PathBuf, FileId>,
15 id2path: im::HashMap<FileId, PathBuf>,
16 id2root: im::HashMap<FileId, Root>,
17}
18
19impl PathMap {
20 pub fn new() -> PathMap {
21 Default::default()
22 }
23 pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> FileId {
24 self.path2id.get(path.as_path())
25 .map(|&id| id)
26 .unwrap_or_else(|| {
27 let id = self.new_file_id();
28 self.insert(path, id, root);
29 id
30 })
31 }
32 pub fn get_id(&self, path: &Path) -> Option<FileId> {
33 self.path2id.get(path).map(|&id| id)
34 }
35 pub fn get_path(&self, file_id: FileId) -> &Path {
36 self.id2path.get(&file_id)
37 .unwrap()
38 .as_path()
39 }
40 pub fn get_root(&self, file_id: FileId) -> Root {
41 self.id2root[&file_id]
42 }
43 fn insert(&mut self, path: PathBuf, file_id: FileId, root: Root) {
44 self.path2id.insert(path.clone(), file_id);
45 self.id2path.insert(file_id, path.clone());
46 self.id2root.insert(file_id, root);
47 }
48
49 fn new_file_id(&mut self) -> FileId {
50 let id = FileId(self.next_id);
51 self.next_id += 1;
52 id
53 }
54}
55
56impl FileResolver for PathMap {
57 fn file_stem(&self, file_id: FileId) -> String {
58 self.get_path(file_id).file_stem().unwrap().to_str().unwrap().to_string()
59 }
60
61 fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId> {
62 let path = path.to_path(&self.get_path(file_id));
63 let path = normalize(&path);
64 self.get_id(&path)
65 }
66}
67
68fn normalize(path: &Path) -> PathBuf {
69 let mut components = path.components().peekable();
70 let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
71 components.next();
72 PathBuf::from(c.as_os_str())
73 } else {
74 PathBuf::new()
75 };
76
77 for component in components {
78 match component {
79 Component::Prefix(..) => unreachable!(),
80 Component::RootDir => {
81 ret.push(component.as_os_str());
82 }
83 Component::CurDir => {}
84 Component::ParentDir => {
85 ret.pop();
86 }
87 Component::Normal(c) => {
88 ret.push(c);
89 }
90 }
91 }
92 ret
93}
94
95#[cfg(test)]
96mod test {
97 use super::*;
98
99 #[test]
100 fn test_resolve() {
101 let mut m = PathMap::new();
102 let id1 = m.get_or_insert(PathBuf::from("/foo"), Root::Workspace);
103 let id2 = m.get_or_insert(PathBuf::from("/foo/bar.rs"), Root::Workspace);
104 assert_eq!(
105 m.resolve(id1, &RelativePath::new("bar.rs")),
106 Some(id2),
107 )
108 }
109}
110