aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-12-09 15:41:35 +0000
committerAleksey Kladov <[email protected]>2020-12-09 15:42:07 +0000
commit5e3891c2559de5a6540d69bc14ded281484479f9 (patch)
treed0f1fb876c99dea1bbd709a9dda006a7941f1eee /crates
parent42be522c80cf0cc2d49b60f3c1d66afdc51fcbbb (diff)
.
Diffstat (limited to 'crates')
-rw-r--r--crates/base_db/src/lib.rs7
-rw-r--r--crates/vfs/src/anchored_path.rs39
-rw-r--r--crates/vfs/src/file_set.rs8
-rw-r--r--crates/vfs/src/lib.rs6
4 files changed, 52 insertions, 8 deletions
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs
index 5571af495..a2cc1e099 100644
--- a/crates/base_db/src/lib.rs
+++ b/crates/base_db/src/lib.rs
@@ -18,7 +18,7 @@ pub use crate::{
18 }, 18 },
19}; 19};
20pub use salsa; 20pub use salsa;
21pub use vfs::{file_set::FileSet, FileId, VfsPath}; 21pub use vfs::{file_set::FileSet, AnchoredPath, AnchoredPathBuf, FileId, VfsPath};
22 22
23#[macro_export] 23#[macro_export]
24macro_rules! impl_intern_key { 24macro_rules! impl_intern_key {
@@ -156,10 +156,11 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
156 SourceDatabaseExt::file_text(self.0, file_id) 156 SourceDatabaseExt::file_text(self.0, file_id)
157 } 157 }
158 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { 158 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> {
159 let path = AnchoredPath { anchor, path };
159 // FIXME: this *somehow* should be platform agnostic... 160 // FIXME: this *somehow* should be platform agnostic...
160 let source_root = self.0.file_source_root(anchor); 161 let source_root = self.0.file_source_root(path.anchor);
161 let source_root = self.0.source_root(source_root); 162 let source_root = self.0.source_root(source_root);
162 source_root.file_set.resolve_path(anchor, path) 163 source_root.file_set.resolve_path(path)
163 } 164 }
164 165
165 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { 166 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
diff --git a/crates/vfs/src/anchored_path.rs b/crates/vfs/src/anchored_path.rs
new file mode 100644
index 000000000..02720a32e
--- /dev/null
+++ b/crates/vfs/src/anchored_path.rs
@@ -0,0 +1,39 @@
1//! Analysis-level representation of file-system paths.
2//!
3//! The primary goal of this is to losslessly represent paths like
4//!
5//! ```
6//! #[path = "./bar.rs"]
7//! mod foo;
8//! ```
9//!
10//! The first approach one might reach for is to use `PathBuf`. The problem here
11//! is that `PathBuf` depends on host target (windows or linux), but
12//! rust-analyzer should be capable to process `#[path = r"C:\bar.rs"]` on Unix.
13//!
14//! The second try is to use a `String`. This also fails, however. Consider a
15//! hypothetical scenario, where rust-analyzer operates in a
16//! networked/distributed mode. There's one global instance of rust-analyzer,
17//! which processes requests from different machines. Now, the semantics of
18//! `#[path = "/abs/path.rs"]` actually depends on which file-system we are at!
19//! That is, even absolute paths exist relative to a file system!
20//!
21//! A more realistic scenario here is virtual VFS paths we use for testing. More
22//! generally, there can be separate "universes" of VFS paths.
23//!
24//! That's why we use anchored representation -- each path carries an info about
25//! a file this path originates from. We can fetch fs/"universe" information
26//! from the anchor than.
27use crate::FileId;
28
29#[derive(Clone, PartialEq, Eq, Debug)]
30pub struct AnchoredPathBuf {
31 pub anchor: FileId,
32 pub path: String,
33}
34
35#[derive(Clone, Copy, PartialEq, Eq, Debug)]
36pub struct AnchoredPath<'a> {
37 pub anchor: FileId,
38 pub path: &'a str,
39}
diff --git a/crates/vfs/src/file_set.rs b/crates/vfs/src/file_set.rs
index 9093fbd97..49ca593ac 100644
--- a/crates/vfs/src/file_set.rs
+++ b/crates/vfs/src/file_set.rs
@@ -7,7 +7,7 @@ use std::fmt;
7use fst::{IntoStreamer, Streamer}; 7use fst::{IntoStreamer, Streamer};
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9 9
10use crate::{FileId, Vfs, VfsPath}; 10use crate::{AnchoredPath, FileId, Vfs, VfsPath};
11 11
12#[derive(Default, Clone, Eq, PartialEq)] 12#[derive(Default, Clone, Eq, PartialEq)]
13pub struct FileSet { 13pub struct FileSet {
@@ -19,10 +19,10 @@ impl FileSet {
19 pub fn len(&self) -> usize { 19 pub fn len(&self) -> usize {
20 self.files.len() 20 self.files.len()
21 } 21 }
22 pub fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { 22 pub fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
23 let mut base = self.paths[&anchor].clone(); 23 let mut base = self.paths[&path.anchor].clone();
24 base.pop(); 24 base.pop();
25 let path = base.join(path)?; 25 let path = base.join(path.path)?;
26 self.files.get(&path).copied() 26 self.files.get(&path).copied()
27 } 27 }
28 28
diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs
index cdf6f1fd0..a3be579a7 100644
--- a/crates/vfs/src/lib.rs
+++ b/crates/vfs/src/lib.rs
@@ -36,6 +36,7 @@
36//! have a single `FileSet` which unions the two sources. 36//! have a single `FileSet` which unions the two sources.
37mod vfs_path; 37mod vfs_path;
38mod path_interner; 38mod path_interner;
39mod anchored_path;
39pub mod file_set; 40pub mod file_set;
40pub mod loader; 41pub mod loader;
41 42
@@ -43,7 +44,10 @@ use std::{fmt, mem};
43 44
44use crate::path_interner::PathInterner; 45use crate::path_interner::PathInterner;
45 46
46pub use crate::vfs_path::VfsPath; 47pub use crate::{
48 anchored_path::{AnchoredPath, AnchoredPathBuf},
49 vfs_path::VfsPath,
50};
47pub use paths::{AbsPath, AbsPathBuf}; 51pub use paths::{AbsPath, AbsPathBuf};
48 52
49#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] 53#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]