diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-01-14 10:13:57 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-01-14 10:13:57 +0000 |
commit | d635806ea5090426cd4a5a57601a7f823277e84c (patch) | |
tree | 7e25377045dbabc6063756af9fae72a1af9107a6 /crates/vfs/src/loader.rs | |
parent | 184f4cbf5df909146b05aaa3b7f2f0b27ac36590 (diff) | |
parent | 4b71c8332daf9ef461891d278f2cf3530baaa833 (diff) |
Merge #7257
7257: vfs documentation r=matklad a=arnaudgolfouse
This documents every item in the `vfs` crate, except for a few private, windows-specific items.
Co-authored-by: Arnaud <[email protected]>
Diffstat (limited to 'crates/vfs/src/loader.rs')
-rw-r--r-- | crates/vfs/src/loader.rs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/crates/vfs/src/loader.rs b/crates/vfs/src/loader.rs index 40cf96020..d3bdae562 100644 --- a/crates/vfs/src/loader.rs +++ b/crates/vfs/src/loader.rs | |||
@@ -3,9 +3,12 @@ use std::fmt; | |||
3 | 3 | ||
4 | use paths::{AbsPath, AbsPathBuf}; | 4 | use paths::{AbsPath, AbsPathBuf}; |
5 | 5 | ||
6 | /// A set of files on the file system. | ||
6 | #[derive(Debug, Clone)] | 7 | #[derive(Debug, Clone)] |
7 | pub enum Entry { | 8 | pub enum Entry { |
9 | /// The `Entry` is represented by a raw set of files. | ||
8 | Files(Vec<AbsPathBuf>), | 10 | Files(Vec<AbsPathBuf>), |
11 | /// The `Entry` is represented by `Directories`. | ||
9 | Directories(Directories), | 12 | Directories(Directories), |
10 | } | 13 | } |
11 | 14 | ||
@@ -17,6 +20,8 @@ pub enum Entry { | |||
17 | /// * it is not under `exclude` path | 20 | /// * it is not under `exclude` path |
18 | /// | 21 | /// |
19 | /// If many include/exclude paths match, the longest one wins. | 22 | /// If many include/exclude paths match, the longest one wins. |
23 | /// | ||
24 | /// If a path is in both `include` and `exclude`, the `exclude` one wins. | ||
20 | #[derive(Debug, Clone, Default)] | 25 | #[derive(Debug, Clone, Default)] |
21 | pub struct Directories { | 26 | pub struct Directories { |
22 | pub extensions: Vec<String>, | 27 | pub extensions: Vec<String>, |
@@ -24,45 +29,99 @@ pub struct Directories { | |||
24 | pub exclude: Vec<AbsPathBuf>, | 29 | pub exclude: Vec<AbsPathBuf>, |
25 | } | 30 | } |
26 | 31 | ||
32 | /// [`Handle`]'s configuration. | ||
27 | #[derive(Debug)] | 33 | #[derive(Debug)] |
28 | pub struct Config { | 34 | pub struct Config { |
35 | /// Set of initially loaded files. | ||
29 | pub load: Vec<Entry>, | 36 | pub load: Vec<Entry>, |
37 | /// Index of watched entries in `load`. | ||
38 | /// | ||
39 | /// If a path in a watched entry is modified,the [`Handle`] should notify it. | ||
30 | pub watch: Vec<usize>, | 40 | pub watch: Vec<usize>, |
31 | } | 41 | } |
32 | 42 | ||
43 | /// Message about an action taken by a [`Handle`]. | ||
33 | pub enum Message { | 44 | pub enum Message { |
45 | /// Indicate a gradual progress. | ||
46 | /// | ||
47 | /// This is supposed to be the number of loaded files. | ||
34 | Progress { n_total: usize, n_done: usize }, | 48 | Progress { n_total: usize, n_done: usize }, |
49 | /// The handle loaded the following files' content. | ||
35 | Loaded { files: Vec<(AbsPathBuf, Option<Vec<u8>>)> }, | 50 | Loaded { files: Vec<(AbsPathBuf, Option<Vec<u8>>)> }, |
36 | } | 51 | } |
37 | 52 | ||
53 | /// Type that will receive [`Messages`](Message) from a [`Handle`]. | ||
38 | pub type Sender = Box<dyn Fn(Message) + Send>; | 54 | pub type Sender = Box<dyn Fn(Message) + Send>; |
39 | 55 | ||
56 | /// Interface for reading and watching files. | ||
40 | pub trait Handle: fmt::Debug { | 57 | pub trait Handle: fmt::Debug { |
58 | /// Spawn a new handle with the given `sender`. | ||
41 | fn spawn(sender: Sender) -> Self | 59 | fn spawn(sender: Sender) -> Self |
42 | where | 60 | where |
43 | Self: Sized; | 61 | Self: Sized; |
62 | |||
63 | /// Set this handle's configuration. | ||
44 | fn set_config(&mut self, config: Config); | 64 | fn set_config(&mut self, config: Config); |
65 | |||
66 | /// The file's content at `path` has been modified, and should be reloaded. | ||
45 | fn invalidate(&mut self, path: AbsPathBuf); | 67 | fn invalidate(&mut self, path: AbsPathBuf); |
68 | |||
69 | /// Load the content of the given file, returning [`None`] if it does not | ||
70 | /// exists. | ||
46 | fn load_sync(&mut self, path: &AbsPath) -> Option<Vec<u8>>; | 71 | fn load_sync(&mut self, path: &AbsPath) -> Option<Vec<u8>>; |
47 | } | 72 | } |
48 | 73 | ||
49 | impl Entry { | 74 | impl Entry { |
75 | /// Returns: | ||
76 | /// ```text | ||
77 | /// Entry::Directories(Directories { | ||
78 | /// extensions: ["rs"], | ||
79 | /// include: [base], | ||
80 | /// exclude: [base/.git], | ||
81 | /// }) | ||
82 | /// ``` | ||
50 | pub fn rs_files_recursively(base: AbsPathBuf) -> Entry { | 83 | pub fn rs_files_recursively(base: AbsPathBuf) -> Entry { |
51 | Entry::Directories(dirs(base, &[".git"])) | 84 | Entry::Directories(dirs(base, &[".git"])) |
52 | } | 85 | } |
86 | |||
87 | /// Returns: | ||
88 | /// ```text | ||
89 | /// Entry::Directories(Directories { | ||
90 | /// extensions: ["rs"], | ||
91 | /// include: [base], | ||
92 | /// exclude: [base/.git, base/target], | ||
93 | /// }) | ||
94 | /// ``` | ||
53 | pub fn local_cargo_package(base: AbsPathBuf) -> Entry { | 95 | pub fn local_cargo_package(base: AbsPathBuf) -> Entry { |
54 | Entry::Directories(dirs(base, &[".git", "target"])) | 96 | Entry::Directories(dirs(base, &[".git", "target"])) |
55 | } | 97 | } |
98 | |||
99 | /// Returns: | ||
100 | /// ```text | ||
101 | /// Entry::Directories(Directories { | ||
102 | /// extensions: ["rs"], | ||
103 | /// include: [base], | ||
104 | /// exclude: [base/.git, /tests, /examples, /benches], | ||
105 | /// }) | ||
106 | /// ``` | ||
56 | pub fn cargo_package_dependency(base: AbsPathBuf) -> Entry { | 107 | pub fn cargo_package_dependency(base: AbsPathBuf) -> Entry { |
57 | Entry::Directories(dirs(base, &[".git", "/tests", "/examples", "/benches"])) | 108 | Entry::Directories(dirs(base, &[".git", "/tests", "/examples", "/benches"])) |
58 | } | 109 | } |
59 | 110 | ||
111 | /// Returns `true` if `path` is included in `self`. | ||
112 | /// | ||
113 | /// See [`Directories::contains_file`]. | ||
60 | pub fn contains_file(&self, path: &AbsPath) -> bool { | 114 | pub fn contains_file(&self, path: &AbsPath) -> bool { |
61 | match self { | 115 | match self { |
62 | Entry::Files(files) => files.iter().any(|it| it == path), | 116 | Entry::Files(files) => files.iter().any(|it| it == path), |
63 | Entry::Directories(dirs) => dirs.contains_file(path), | 117 | Entry::Directories(dirs) => dirs.contains_file(path), |
64 | } | 118 | } |
65 | } | 119 | } |
120 | |||
121 | /// Returns `true` if `path` is included in `self`. | ||
122 | /// | ||
123 | /// - If `self` is `Entry::Files`, returns `false` | ||
124 | /// - Else, see [`Directories::contains_dir`]. | ||
66 | pub fn contains_dir(&self, path: &AbsPath) -> bool { | 125 | pub fn contains_dir(&self, path: &AbsPath) -> bool { |
67 | match self { | 126 | match self { |
68 | Entry::Files(_) => false, | 127 | Entry::Files(_) => false, |
@@ -72,6 +131,7 @@ impl Entry { | |||
72 | } | 131 | } |
73 | 132 | ||
74 | impl Directories { | 133 | impl Directories { |
134 | /// Returns `true` if `path` is included in `self`. | ||
75 | pub fn contains_file(&self, path: &AbsPath) -> bool { | 135 | pub fn contains_file(&self, path: &AbsPath) -> bool { |
76 | let ext = path.extension().unwrap_or_default(); | 136 | let ext = path.extension().unwrap_or_default(); |
77 | if self.extensions.iter().all(|it| it.as_str() != ext) { | 137 | if self.extensions.iter().all(|it| it.as_str() != ext) { |
@@ -79,9 +139,21 @@ impl Directories { | |||
79 | } | 139 | } |
80 | self.includes_path(path) | 140 | self.includes_path(path) |
81 | } | 141 | } |
142 | |||
143 | /// Returns `true` if `path` is included in `self`. | ||
144 | /// | ||
145 | /// Since `path` is supposed to be a directory, this will not take extension | ||
146 | /// into account. | ||
82 | pub fn contains_dir(&self, path: &AbsPath) -> bool { | 147 | pub fn contains_dir(&self, path: &AbsPath) -> bool { |
83 | self.includes_path(path) | 148 | self.includes_path(path) |
84 | } | 149 | } |
150 | |||
151 | /// Returns `true` if `path` is included in `self`. | ||
152 | /// | ||
153 | /// It is included if | ||
154 | /// - An element in `self.include` is a prefix of `path`. | ||
155 | /// - This path is longer than any element in `self.exclude` that is a prefix | ||
156 | /// of `path`. In case of equality, exclusion wins. | ||
85 | fn includes_path(&self, path: &AbsPath) -> bool { | 157 | fn includes_path(&self, path: &AbsPath) -> bool { |
86 | let mut include: Option<&AbsPathBuf> = None; | 158 | let mut include: Option<&AbsPathBuf> = None; |
87 | for incl in &self.include { | 159 | for incl in &self.include { |
@@ -105,6 +177,14 @@ impl Directories { | |||
105 | } | 177 | } |
106 | } | 178 | } |
107 | 179 | ||
180 | /// Returns : | ||
181 | /// ```text | ||
182 | /// Directories { | ||
183 | /// extensions: ["rs"], | ||
184 | /// include: [base], | ||
185 | /// exclude: [base/<exclude>], | ||
186 | /// } | ||
187 | /// ``` | ||
108 | fn dirs(base: AbsPathBuf, exclude: &[&str]) -> Directories { | 188 | fn dirs(base: AbsPathBuf, exclude: &[&str]) -> Directories { |
109 | let exclude = exclude.iter().map(|it| base.join(it)).collect::<Vec<_>>(); | 189 | let exclude = exclude.iter().map(|it| base.join(it)).collect::<Vec<_>>(); |
110 | Directories { extensions: vec!["rs".to_string()], include: vec![base], exclude } | 190 | Directories { extensions: vec!["rs".to_string()], include: vec![base], exclude } |