diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_db/src/fixture.rs | 2 | ||||
-rw-r--r-- | crates/ra_db/src/input.rs | 17 | ||||
-rw-r--r-- | crates/ra_ide/src/mock_analysis.rs | 4 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 87 | ||||
-rw-r--r-- | crates/ra_project_model/src/project_json.rs | 43 | ||||
-rw-r--r-- | crates/rust-analyzer/src/reload.rs | 40 | ||||
-rw-r--r-- | crates/vfs/src/loader.rs | 2 |
7 files changed, 89 insertions, 106 deletions
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs index 209713987..2aafb9965 100644 --- a/crates/ra_db/src/fixture.rs +++ b/crates/ra_db/src/fixture.rs | |||
@@ -222,7 +222,7 @@ impl From<Fixture> for FileMeta { | |||
222 | .edition | 222 | .edition |
223 | .as_ref() | 223 | .as_ref() |
224 | .map_or(Edition::Edition2018, |v| Edition::from_str(&v).unwrap()), | 224 | .map_or(Edition::Edition2018, |v| Edition::from_str(&v).unwrap()), |
225 | env: Env::from(f.env.iter()), | 225 | env: f.env.into_iter().collect(), |
226 | } | 226 | } |
227 | } | 227 | } |
228 | } | 228 | } |
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index aaa492759..6f2e5cfc7 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -6,7 +6,7 @@ | |||
6 | //! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how | 6 | //! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how |
7 | //! actual IO is done and lowered to input. | 7 | //! actual IO is done and lowered to input. |
8 | 8 | ||
9 | use std::{fmt, ops, str::FromStr, sync::Arc}; | 9 | use std::{fmt, iter::FromIterator, ops, str::FromStr, sync::Arc}; |
10 | 10 | ||
11 | use ra_cfg::CfgOptions; | 11 | use ra_cfg::CfgOptions; |
12 | use ra_syntax::SmolStr; | 12 | use ra_syntax::SmolStr; |
@@ -298,18 +298,9 @@ impl fmt::Display for Edition { | |||
298 | } | 298 | } |
299 | } | 299 | } |
300 | 300 | ||
301 | impl<'a, T> From<T> for Env | 301 | impl FromIterator<(String, String)> for Env { |
302 | where | 302 | fn from_iter<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self { |
303 | T: Iterator<Item = (&'a String, &'a String)>, | 303 | Env { entries: FromIterator::from_iter(iter) } |
304 | { | ||
305 | fn from(iter: T) -> Self { | ||
306 | let mut result = Self::default(); | ||
307 | |||
308 | for (k, v) in iter { | ||
309 | result.entries.insert(k.to_owned(), v.to_owned()); | ||
310 | } | ||
311 | |||
312 | result | ||
313 | } | 304 | } |
314 | } | 305 | } |
315 | 306 | ||
diff --git a/crates/ra_ide/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs index b28054688..c7e0f4b58 100644 --- a/crates/ra_ide/src/mock_analysis.rs +++ b/crates/ra_ide/src/mock_analysis.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use ra_cfg::CfgOptions; | 4 | use ra_cfg::CfgOptions; |
5 | use ra_db::{CrateName, Env, FileSet, SourceRoot, VfsPath}; | 5 | use ra_db::{CrateName, FileSet, SourceRoot, VfsPath}; |
6 | use test_utils::{ | 6 | use test_utils::{ |
7 | extract_annotations, extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER, | 7 | extract_annotations, extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER, |
8 | }; | 8 | }; |
@@ -110,7 +110,7 @@ impl MockAnalysis { | |||
110 | data.edition.and_then(|it| it.parse().ok()).unwrap_or(Edition::Edition2018); | 110 | data.edition.and_then(|it| it.parse().ok()).unwrap_or(Edition::Edition2018); |
111 | 111 | ||
112 | let file_id = FileId(i as u32 + 1); | 112 | let file_id = FileId(i as u32 + 1); |
113 | let env = Env::from(data.env.iter()); | 113 | let env = data.env.into_iter().collect(); |
114 | if path == "/lib.rs" || path == "/main.rs" { | 114 | if path == "/lib.rs" || path == "/main.rs" { |
115 | root_crate = Some(crate_graph.add_crate_root( | 115 | root_crate = Some(crate_graph.add_crate_root( |
116 | file_id, | 116 | file_id, |
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index b9c5424bf..6da4d7928 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -7,7 +7,6 @@ mod sysroot; | |||
7 | use std::{ | 7 | use std::{ |
8 | fs::{self, read_dir, ReadDir}, | 8 | fs::{self, read_dir, ReadDir}, |
9 | io, | 9 | io, |
10 | path::Path, | ||
11 | process::{Command, Output}, | 10 | process::{Command, Output}, |
12 | }; | 11 | }; |
13 | 12 | ||
@@ -35,30 +34,12 @@ pub enum ProjectWorkspace { | |||
35 | /// `PackageRoot` describes a package root folder. | 34 | /// `PackageRoot` describes a package root folder. |
36 | /// Which may be an external dependency, or a member of | 35 | /// Which may be an external dependency, or a member of |
37 | /// the current workspace. | 36 | /// the current workspace. |
38 | #[derive(Debug, Clone)] | 37 | #[derive(Debug, Clone, Eq, PartialEq, Hash)] |
39 | pub struct PackageRoot { | 38 | pub struct PackageRoot { |
40 | /// Path to the root folder | ||
41 | path: AbsPathBuf, | ||
42 | /// Is a member of the current workspace | 39 | /// Is a member of the current workspace |
43 | is_member: bool, | 40 | pub is_member: bool, |
44 | out_dir: Option<AbsPathBuf>, | 41 | pub include: Vec<AbsPathBuf>, |
45 | } | 42 | pub exclude: Vec<AbsPathBuf>, |
46 | impl PackageRoot { | ||
47 | pub fn new_member(path: AbsPathBuf) -> PackageRoot { | ||
48 | Self { path, is_member: true, out_dir: None } | ||
49 | } | ||
50 | pub fn new_non_member(path: AbsPathBuf) -> PackageRoot { | ||
51 | Self { path, is_member: false, out_dir: None } | ||
52 | } | ||
53 | pub fn path(&self) -> &AbsPath { | ||
54 | &self.path | ||
55 | } | ||
56 | pub fn out_dir(&self) -> Option<&AbsPath> { | ||
57 | self.out_dir.as_deref() | ||
58 | } | ||
59 | pub fn is_member(&self) -> bool { | ||
60 | self.is_member | ||
61 | } | ||
62 | } | 43 | } |
63 | 44 | ||
64 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] | 45 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] |
@@ -195,18 +176,40 @@ impl ProjectWorkspace { | |||
195 | /// the root is a member of the current workspace | 176 | /// the root is a member of the current workspace |
196 | pub fn to_roots(&self) -> Vec<PackageRoot> { | 177 | pub fn to_roots(&self) -> Vec<PackageRoot> { |
197 | match self { | 178 | match self { |
198 | ProjectWorkspace::Json { project } => { | 179 | ProjectWorkspace::Json { project } => project |
199 | project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect() | 180 | .crates |
200 | } | 181 | .iter() |
182 | .map(|krate| PackageRoot { | ||
183 | is_member: krate.is_workspace_member, | ||
184 | include: krate.include.clone(), | ||
185 | exclude: krate.exclude.clone(), | ||
186 | }) | ||
187 | .collect::<FxHashSet<_>>() | ||
188 | .into_iter() | ||
189 | .collect::<Vec<_>>(), | ||
201 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo | 190 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo |
202 | .packages() | 191 | .packages() |
203 | .map(|pkg| PackageRoot { | 192 | .map(|pkg| { |
204 | path: cargo[pkg].root().to_path_buf(), | 193 | let is_member = cargo[pkg].is_member; |
205 | is_member: cargo[pkg].is_member, | 194 | let pkg_root = cargo[pkg].root().to_path_buf(); |
206 | out_dir: cargo[pkg].out_dir.clone(), | 195 | |
196 | let mut include = vec![pkg_root.clone()]; | ||
197 | include.extend(cargo[pkg].out_dir.clone()); | ||
198 | |||
199 | let mut exclude = vec![pkg_root.join(".git")]; | ||
200 | if is_member { | ||
201 | exclude.push(pkg_root.join("target")); | ||
202 | } else { | ||
203 | exclude.push(pkg_root.join("tests")); | ||
204 | exclude.push(pkg_root.join("examples")); | ||
205 | exclude.push(pkg_root.join("benches")); | ||
206 | } | ||
207 | PackageRoot { is_member, include, exclude } | ||
207 | }) | 208 | }) |
208 | .chain(sysroot.crates().map(|krate| { | 209 | .chain(sysroot.crates().map(|krate| PackageRoot { |
209 | PackageRoot::new_non_member(sysroot[krate].root_dir().to_path_buf()) | 210 | is_member: false, |
211 | include: vec![sysroot[krate].root_dir().to_path_buf()], | ||
212 | exclude: Vec::new(), | ||
210 | })) | 213 | })) |
211 | .collect(), | 214 | .collect(), |
212 | } | 215 | } |
@@ -255,13 +258,7 @@ impl ProjectWorkspace { | |||
255 | let file_path = &krate.root_module; | 258 | let file_path = &krate.root_module; |
256 | let file_id = load(&file_path)?; | 259 | let file_id = load(&file_path)?; |
257 | 260 | ||
258 | let mut env = Env::default(); | 261 | let env = krate.env.clone().into_iter().collect(); |
259 | if let Some(out_dir) = &krate.out_dir { | ||
260 | // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!() | ||
261 | if let Some(out_dir) = out_dir.to_str().map(|s| s.to_owned()) { | ||
262 | env.set("OUT_DIR", out_dir); | ||
263 | } | ||
264 | } | ||
265 | let proc_macro = krate | 262 | let proc_macro = krate |
266 | .proc_macro_dylib_path | 263 | .proc_macro_dylib_path |
267 | .clone() | 264 | .clone() |
@@ -503,18 +500,6 @@ impl ProjectWorkspace { | |||
503 | } | 500 | } |
504 | crate_graph | 501 | crate_graph |
505 | } | 502 | } |
506 | |||
507 | pub fn workspace_root_for(&self, path: &Path) -> Option<&AbsPath> { | ||
508 | match self { | ||
509 | ProjectWorkspace::Cargo { cargo, .. } => { | ||
510 | Some(cargo.workspace_root()).filter(|root| path.starts_with(root)) | ||
511 | } | ||
512 | ProjectWorkspace::Json { project: ProjectJson { roots, .. }, .. } => roots | ||
513 | .iter() | ||
514 | .find(|root| path.starts_with(&root.path)) | ||
515 | .map(|root| root.path.as_path()), | ||
516 | } | ||
517 | } | ||
518 | } | 503 | } |
519 | 504 | ||
520 | fn get_rustc_cfg_options(target: Option<&str>) -> CfgOptions { | 505 | fn get_rustc_cfg_options(target: Option<&str>) -> CfgOptions { |
diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs index 778cc84ef..e9a333191 100644 --- a/crates/ra_project_model/src/project_json.rs +++ b/crates/ra_project_model/src/project_json.rs | |||
@@ -5,24 +5,16 @@ use std::path::PathBuf; | |||
5 | use paths::{AbsPath, AbsPathBuf}; | 5 | use paths::{AbsPath, AbsPathBuf}; |
6 | use ra_cfg::CfgOptions; | 6 | use ra_cfg::CfgOptions; |
7 | use ra_db::{CrateId, CrateName, Dependency, Edition}; | 7 | use ra_db::{CrateId, CrateName, Dependency, Edition}; |
8 | use rustc_hash::FxHashSet; | 8 | use rustc_hash::{FxHashMap, FxHashSet}; |
9 | use serde::{de, Deserialize}; | 9 | use serde::{de, Deserialize}; |
10 | use stdx::split_delim; | 10 | use stdx::split_delim; |
11 | 11 | ||
12 | /// Roots and crates that compose this Rust project. | 12 | /// Roots and crates that compose this Rust project. |
13 | #[derive(Clone, Debug, Eq, PartialEq)] | 13 | #[derive(Clone, Debug, Eq, PartialEq)] |
14 | pub struct ProjectJson { | 14 | pub struct ProjectJson { |
15 | pub(crate) roots: Vec<Root>, | ||
16 | pub(crate) crates: Vec<Crate>, | 15 | pub(crate) crates: Vec<Crate>, |
17 | } | 16 | } |
18 | 17 | ||
19 | /// A root points to the directory which contains Rust crates. rust-analyzer watches all files in | ||
20 | /// all roots. Roots might be nested. | ||
21 | #[derive(Clone, Debug, Eq, PartialEq)] | ||
22 | pub struct Root { | ||
23 | pub(crate) path: AbsPathBuf, | ||
24 | } | ||
25 | |||
26 | /// A crate points to the root module of a crate and lists the dependencies of the crate. This is | 18 | /// A crate points to the root module of a crate and lists the dependencies of the crate. This is |
27 | /// useful in creating the crate graph. | 19 | /// useful in creating the crate graph. |
28 | #[derive(Clone, Debug, Eq, PartialEq)] | 20 | #[derive(Clone, Debug, Eq, PartialEq)] |
@@ -32,15 +24,16 @@ pub struct Crate { | |||
32 | pub(crate) deps: Vec<Dependency>, | 24 | pub(crate) deps: Vec<Dependency>, |
33 | pub(crate) cfg: CfgOptions, | 25 | pub(crate) cfg: CfgOptions, |
34 | pub(crate) target: Option<String>, | 26 | pub(crate) target: Option<String>, |
35 | pub(crate) out_dir: Option<AbsPathBuf>, | 27 | pub(crate) env: FxHashMap<String, String>, |
36 | pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>, | 28 | pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>, |
37 | pub(crate) is_workspace_member: bool, | 29 | pub(crate) is_workspace_member: bool, |
30 | pub(crate) include: Vec<AbsPathBuf>, | ||
31 | pub(crate) exclude: Vec<AbsPathBuf>, | ||
38 | } | 32 | } |
39 | 33 | ||
40 | impl ProjectJson { | 34 | impl ProjectJson { |
41 | pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson { | 35 | pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson { |
42 | ProjectJson { | 36 | ProjectJson { |
43 | roots: data.roots.into_iter().map(|path| Root { path: base.join(path) }).collect(), | ||
44 | crates: data | 37 | crates: data |
45 | .crates | 38 | .crates |
46 | .into_iter() | 39 | .into_iter() |
@@ -50,8 +43,19 @@ impl ProjectJson { | |||
50 | && !crate_data.root_module.starts_with("..") | 43 | && !crate_data.root_module.starts_with("..") |
51 | || crate_data.root_module.starts_with(base) | 44 | || crate_data.root_module.starts_with(base) |
52 | }); | 45 | }); |
46 | let root_module = base.join(crate_data.root_module); | ||
47 | let (include, exclude) = match crate_data.source { | ||
48 | Some(src) => { | ||
49 | let absolutize = |dirs: Vec<PathBuf>| { | ||
50 | dirs.into_iter().map(|it| base.join(it)).collect::<Vec<_>>() | ||
51 | }; | ||
52 | (absolutize(src.include_dirs), absolutize(src.exclude_dirs)) | ||
53 | } | ||
54 | None => (vec![root_module.parent().unwrap().to_path_buf()], Vec::new()), | ||
55 | }; | ||
56 | |||
53 | Crate { | 57 | Crate { |
54 | root_module: base.join(crate_data.root_module), | 58 | root_module, |
55 | edition: crate_data.edition.into(), | 59 | edition: crate_data.edition.into(), |
56 | deps: crate_data | 60 | deps: crate_data |
57 | .deps | 61 | .deps |
@@ -74,11 +78,13 @@ impl ProjectJson { | |||
74 | cfg | 78 | cfg |
75 | }, | 79 | }, |
76 | target: crate_data.target, | 80 | target: crate_data.target, |
77 | out_dir: crate_data.out_dir.map(|it| base.join(it)), | 81 | env: crate_data.env, |
78 | proc_macro_dylib_path: crate_data | 82 | proc_macro_dylib_path: crate_data |
79 | .proc_macro_dylib_path | 83 | .proc_macro_dylib_path |
80 | .map(|it| base.join(it)), | 84 | .map(|it| base.join(it)), |
81 | is_workspace_member, | 85 | is_workspace_member, |
86 | include, | ||
87 | exclude, | ||
82 | } | 88 | } |
83 | }) | 89 | }) |
84 | .collect::<Vec<_>>(), | 90 | .collect::<Vec<_>>(), |
@@ -88,7 +94,6 @@ impl ProjectJson { | |||
88 | 94 | ||
89 | #[derive(Deserialize)] | 95 | #[derive(Deserialize)] |
90 | pub struct ProjectJsonData { | 96 | pub struct ProjectJsonData { |
91 | roots: Vec<PathBuf>, | ||
92 | crates: Vec<CrateData>, | 97 | crates: Vec<CrateData>, |
93 | } | 98 | } |
94 | 99 | ||
@@ -100,9 +105,11 @@ struct CrateData { | |||
100 | #[serde(default)] | 105 | #[serde(default)] |
101 | cfg: FxHashSet<String>, | 106 | cfg: FxHashSet<String>, |
102 | target: Option<String>, | 107 | target: Option<String>, |
103 | out_dir: Option<PathBuf>, | 108 | #[serde(default)] |
109 | env: FxHashMap<String, String>, | ||
104 | proc_macro_dylib_path: Option<PathBuf>, | 110 | proc_macro_dylib_path: Option<PathBuf>, |
105 | is_workspace_member: Option<bool>, | 111 | is_workspace_member: Option<bool>, |
112 | source: Option<CrateSource>, | ||
106 | } | 113 | } |
107 | 114 | ||
108 | #[derive(Deserialize)] | 115 | #[derive(Deserialize)] |
@@ -132,6 +139,12 @@ struct DepData { | |||
132 | name: CrateName, | 139 | name: CrateName, |
133 | } | 140 | } |
134 | 141 | ||
142 | #[derive(Deserialize)] | ||
143 | struct CrateSource { | ||
144 | include_dirs: Vec<PathBuf>, | ||
145 | exclude_dirs: Vec<PathBuf>, | ||
146 | } | ||
147 | |||
135 | fn deserialize_crate_name<'de, D>(de: D) -> Result<CrateName, D::Error> | 148 | fn deserialize_crate_name<'de, D>(de: D) -> Result<CrateName, D::Error> |
136 | where | 149 | where |
137 | D: de::Deserializer<'de>, | 150 | D: de::Deserializer<'de>, |
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index d7ae00b07..1907f2f13 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs | |||
@@ -5,7 +5,7 @@ use flycheck::FlycheckHandle; | |||
5 | use ra_db::{CrateGraph, SourceRoot, VfsPath}; | 5 | use ra_db::{CrateGraph, SourceRoot, VfsPath}; |
6 | use ra_ide::AnalysisChange; | 6 | use ra_ide::AnalysisChange; |
7 | use ra_prof::profile; | 7 | use ra_prof::profile; |
8 | use ra_project_model::{PackageRoot, ProcMacroClient, ProjectWorkspace}; | 8 | use ra_project_model::{ProcMacroClient, ProjectWorkspace}; |
9 | use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind}; | 9 | use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind}; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
@@ -149,8 +149,10 @@ impl GlobalState { | |||
149 | watchers: workspaces | 149 | watchers: workspaces |
150 | .iter() | 150 | .iter() |
151 | .flat_map(ProjectWorkspace::to_roots) | 151 | .flat_map(ProjectWorkspace::to_roots) |
152 | .filter(PackageRoot::is_member) | 152 | .filter(|it| it.is_member) |
153 | .map(|root| format!("{}/**/*.rs", root.path().display())) | 153 | .flat_map(|root| { |
154 | root.include.into_iter().map(|it| format!("{}/**/*.rs", it.display())) | ||
155 | }) | ||
154 | .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None }) | 156 | .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None }) |
155 | .collect(), | 157 | .collect(), |
156 | }; | 158 | }; |
@@ -261,31 +263,23 @@ impl ProjectFolders { | |||
261 | let mut local_filesets = vec![]; | 263 | let mut local_filesets = vec![]; |
262 | 264 | ||
263 | for root in workspaces.iter().flat_map(|it| it.to_roots()) { | 265 | for root in workspaces.iter().flat_map(|it| it.to_roots()) { |
264 | let path = root.path().to_owned(); | 266 | let file_set_roots: Vec<VfsPath> = |
265 | 267 | root.include.iter().cloned().map(VfsPath::from).collect(); | |
266 | let mut file_set_roots: Vec<VfsPath> = vec![]; | ||
267 | 268 | ||
268 | let entry = if root.is_member() { | 269 | let entry = { |
269 | vfs::loader::Entry::local_cargo_package(path.to_path_buf()) | 270 | let mut dirs = vfs::loader::Directories::default(); |
270 | } else { | 271 | dirs.extensions.push("rs".into()); |
271 | vfs::loader::Entry::cargo_package_dependency(path.to_path_buf()) | 272 | dirs.include.extend(root.include); |
273 | dirs.exclude.extend(root.exclude); | ||
274 | vfs::loader::Entry::Directories(dirs) | ||
272 | }; | 275 | }; |
273 | res.load.push(entry); | ||
274 | if root.is_member() { | ||
275 | res.watch.push(res.load.len() - 1); | ||
276 | } | ||
277 | 276 | ||
278 | if let Some(out_dir) = root.out_dir() { | 277 | if root.is_member { |
279 | let out_dir = out_dir.to_path_buf(); | 278 | res.watch.push(res.load.len()); |
280 | res.load.push(vfs::loader::Entry::rs_files_recursively(out_dir.clone())); | ||
281 | if root.is_member() { | ||
282 | res.watch.push(res.load.len() - 1); | ||
283 | } | ||
284 | file_set_roots.push(out_dir.into()); | ||
285 | } | 279 | } |
286 | file_set_roots.push(path.to_path_buf().into()); | 280 | res.load.push(entry); |
287 | 281 | ||
288 | if root.is_member() { | 282 | if root.is_member { |
289 | local_filesets.push(fsc.len()); | 283 | local_filesets.push(fsc.len()); |
290 | } | 284 | } |
291 | fsc.add_file_set(file_set_roots) | 285 | fsc.add_file_set(file_set_roots) |
diff --git a/crates/vfs/src/loader.rs b/crates/vfs/src/loader.rs index 04e257f53..40cf96020 100644 --- a/crates/vfs/src/loader.rs +++ b/crates/vfs/src/loader.rs | |||
@@ -17,7 +17,7 @@ pub enum Entry { | |||
17 | /// * it is not under `exclude` path | 17 | /// * it is not under `exclude` path |
18 | /// | 18 | /// |
19 | /// If many include/exclude paths match, the longest one wins. | 19 | /// If many include/exclude paths match, the longest one wins. |
20 | #[derive(Debug, Clone)] | 20 | #[derive(Debug, Clone, Default)] |
21 | pub struct Directories { | 21 | pub struct Directories { |
22 | pub extensions: Vec<String>, | 22 | pub extensions: Vec<String>, |
23 | pub include: Vec<AbsPathBuf>, | 23 | pub include: Vec<AbsPathBuf>, |