diff options
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 129 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/load_cargo.rs | 11 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 5 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop/subscriptions.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/vfs_glob.rs | 10 | ||||
-rw-r--r-- | crates/rust-analyzer/src/world.rs | 57 |
6 files changed, 94 insertions, 120 deletions
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index dd9c80691..0ab64a1e0 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -62,16 +62,16 @@ pub struct PackageRoot { | |||
62 | /// Is a member of the current workspace | 62 | /// Is a member of the current workspace |
63 | is_member: bool, | 63 | is_member: bool, |
64 | } | 64 | } |
65 | |||
66 | impl PackageRoot { | 65 | impl PackageRoot { |
67 | pub fn new(path: PathBuf, is_member: bool) -> PackageRoot { | 66 | pub fn new_member(path: PathBuf) -> PackageRoot { |
68 | PackageRoot { path, is_member } | 67 | Self { path, is_member: true } |
69 | } | 68 | } |
70 | 69 | pub fn new_non_member(path: PathBuf) -> PackageRoot { | |
71 | pub fn path(&self) -> &PathBuf { | 70 | Self { path, is_member: false } |
71 | } | ||
72 | pub fn path(&self) -> &Path { | ||
72 | &self.path | 73 | &self.path |
73 | } | 74 | } |
74 | |||
75 | pub fn is_member(&self) -> bool { | 75 | pub fn is_member(&self) -> bool { |
76 | self.is_member | 76 | self.is_member |
77 | } | 77 | } |
@@ -130,70 +130,45 @@ impl ProjectWorkspace { | |||
130 | pub fn to_roots(&self) -> Vec<PackageRoot> { | 130 | pub fn to_roots(&self) -> Vec<PackageRoot> { |
131 | match self { | 131 | match self { |
132 | ProjectWorkspace::Json { project } => { | 132 | ProjectWorkspace::Json { project } => { |
133 | let mut roots = Vec::with_capacity(project.roots.len()); | 133 | project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect() |
134 | for root in &project.roots { | ||
135 | roots.push(PackageRoot::new(root.path.clone(), true)); | ||
136 | } | ||
137 | roots | ||
138 | } | ||
139 | ProjectWorkspace::Cargo { cargo, sysroot } => { | ||
140 | let mut roots = Vec::with_capacity(cargo.packages().len() + sysroot.crates().len()); | ||
141 | for pkg in cargo.packages() { | ||
142 | let root = cargo[pkg].root().to_path_buf(); | ||
143 | let member = cargo[pkg].is_member; | ||
144 | roots.push(PackageRoot::new(root, member)); | ||
145 | } | ||
146 | for krate in sysroot.crates() { | ||
147 | roots.push(PackageRoot::new(sysroot[krate].root_dir().to_path_buf(), false)) | ||
148 | } | ||
149 | roots | ||
150 | } | 134 | } |
135 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo | ||
136 | .packages() | ||
137 | .map(|pkg| PackageRoot { | ||
138 | path: cargo[pkg].root().to_path_buf(), | ||
139 | is_member: cargo[pkg].is_member, | ||
140 | }) | ||
141 | .chain(sysroot.crates().map(|krate| { | ||
142 | PackageRoot::new_non_member(sysroot[krate].root_dir().to_path_buf()) | ||
143 | })) | ||
144 | .collect(), | ||
151 | } | 145 | } |
152 | } | 146 | } |
153 | 147 | ||
154 | pub fn out_dirs(&self) -> Vec<PathBuf> { | 148 | pub fn out_dirs(&self) -> Vec<PathBuf> { |
155 | match self { | 149 | match self { |
156 | ProjectWorkspace::Json { project } => { | 150 | ProjectWorkspace::Json { project } => { |
157 | let mut out_dirs = Vec::with_capacity(project.crates.len()); | 151 | project.crates.iter().filter_map(|krate| krate.out_dir.as_ref()).cloned().collect() |
158 | for krate in &project.crates { | ||
159 | if let Some(out_dir) = &krate.out_dir { | ||
160 | out_dirs.push(out_dir.to_path_buf()); | ||
161 | } | ||
162 | } | ||
163 | out_dirs | ||
164 | } | 152 | } |
165 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { | 153 | ProjectWorkspace::Cargo { cargo, sysroot: _ } => { |
166 | let mut out_dirs = Vec::with_capacity(cargo.packages().len()); | 154 | cargo.packages().filter_map(|pkg| cargo[pkg].out_dir.as_ref()).cloned().collect() |
167 | for pkg in cargo.packages() { | ||
168 | if let Some(out_dir) = &cargo[pkg].out_dir { | ||
169 | out_dirs.push(out_dir.to_path_buf()); | ||
170 | } | ||
171 | } | ||
172 | out_dirs | ||
173 | } | 155 | } |
174 | } | 156 | } |
175 | } | 157 | } |
176 | 158 | ||
177 | pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { | 159 | pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { |
178 | match self { | 160 | match self { |
179 | ProjectWorkspace::Json { project } => { | 161 | ProjectWorkspace::Json { project } => project |
180 | let mut proc_macro_dylib_paths = Vec::with_capacity(project.crates.len()); | 162 | .crates |
181 | for krate in &project.crates { | 163 | .iter() |
182 | if let Some(out_dir) = &krate.proc_macro_dylib_path { | 164 | .filter_map(|krate| krate.proc_macro_dylib_path.as_ref()) |
183 | proc_macro_dylib_paths.push(out_dir.to_path_buf()); | 165 | .cloned() |
184 | } | 166 | .collect(), |
185 | } | 167 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo |
186 | proc_macro_dylib_paths | 168 | .packages() |
187 | } | 169 | .filter_map(|pkg| cargo[pkg].proc_macro_dylib_path.as_ref()) |
188 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { | 170 | .cloned() |
189 | let mut proc_macro_dylib_paths = Vec::with_capacity(cargo.packages().len()); | 171 | .collect(), |
190 | for pkg in cargo.packages() { | ||
191 | if let Some(dylib_path) = &cargo[pkg].proc_macro_dylib_path { | ||
192 | proc_macro_dylib_paths.push(dylib_path.to_path_buf()); | ||
193 | } | ||
194 | } | ||
195 | proc_macro_dylib_paths | ||
196 | } | ||
197 | } | 172 | } |
198 | } | 173 | } |
199 | 174 | ||
@@ -216,10 +191,12 @@ impl ProjectWorkspace { | |||
216 | let mut crate_graph = CrateGraph::default(); | 191 | let mut crate_graph = CrateGraph::default(); |
217 | match self { | 192 | match self { |
218 | ProjectWorkspace::Json { project } => { | 193 | ProjectWorkspace::Json { project } => { |
219 | let mut crates = FxHashMap::default(); | 194 | let crates: FxHashMap<_, _> = project |
220 | for (id, krate) in project.crates.iter().enumerate() { | 195 | .crates |
221 | let crate_id = json_project::CrateId(id); | 196 | .iter() |
222 | if let Some(file_id) = load(&krate.root_module) { | 197 | .enumerate() |
198 | .filter_map(|(seq_index, krate)| { | ||
199 | let file_id = load(&krate.root_module)?; | ||
223 | let edition = match krate.edition { | 200 | let edition = match krate.edition { |
224 | json_project::Edition::Edition2015 => Edition::Edition2015, | 201 | json_project::Edition::Edition2015 => Edition::Edition2015, |
225 | json_project::Edition::Edition2018 => Edition::Edition2018, | 202 | json_project::Edition::Edition2018 => Edition::Edition2018, |
@@ -249,8 +226,8 @@ impl ProjectWorkspace { | |||
249 | .clone() | 226 | .clone() |
250 | .map(|it| proc_macro_client.by_dylib_path(&it)); | 227 | .map(|it| proc_macro_client.by_dylib_path(&it)); |
251 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env | 228 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env |
252 | crates.insert( | 229 | Some(( |
253 | crate_id, | 230 | json_project::CrateId(seq_index), |
254 | crate_graph.add_crate_root( | 231 | crate_graph.add_crate_root( |
255 | file_id, | 232 | file_id, |
256 | edition, | 233 | edition, |
@@ -261,9 +238,9 @@ impl ProjectWorkspace { | |||
261 | extern_source, | 238 | extern_source, |
262 | proc_macro.unwrap_or_default(), | 239 | proc_macro.unwrap_or_default(), |
263 | ), | 240 | ), |
264 | ); | 241 | )) |
265 | } | 242 | }) |
266 | } | 243 | .collect(); |
267 | 244 | ||
268 | for (id, krate) in project.crates.iter().enumerate() { | 245 | for (id, krate) in project.crates.iter().enumerate() { |
269 | for dep in &krate.deps { | 246 | for dep in &krate.deps { |
@@ -287,9 +264,11 @@ impl ProjectWorkspace { | |||
287 | } | 264 | } |
288 | } | 265 | } |
289 | ProjectWorkspace::Cargo { cargo, sysroot } => { | 266 | ProjectWorkspace::Cargo { cargo, sysroot } => { |
290 | let mut sysroot_crates = FxHashMap::default(); | 267 | let sysroot_crates: FxHashMap<_, _> = sysroot |
291 | for krate in sysroot.crates() { | 268 | .crates() |
292 | if let Some(file_id) = load(&sysroot[krate].root) { | 269 | .filter_map(|krate| { |
270 | let file_id = load(&sysroot[krate].root)?; | ||
271 | |||
293 | // Crates from sysroot have `cfg(test)` disabled | 272 | // Crates from sysroot have `cfg(test)` disabled |
294 | let cfg_options = { | 273 | let cfg_options = { |
295 | let mut opts = default_cfg_options.clone(); | 274 | let mut opts = default_cfg_options.clone(); |
@@ -300,22 +279,22 @@ impl ProjectWorkspace { | |||
300 | let env = Env::default(); | 279 | let env = Env::default(); |
301 | let extern_source = ExternSource::default(); | 280 | let extern_source = ExternSource::default(); |
302 | let proc_macro = vec![]; | 281 | let proc_macro = vec![]; |
282 | let crate_name = CrateName::new(&sysroot[krate].name) | ||
283 | .expect("Sysroot crate names should not contain dashes"); | ||
303 | 284 | ||
304 | let crate_id = crate_graph.add_crate_root( | 285 | let crate_id = crate_graph.add_crate_root( |
305 | file_id, | 286 | file_id, |
306 | Edition::Edition2018, | 287 | Edition::Edition2018, |
307 | Some( | 288 | Some(crate_name), |
308 | CrateName::new(&sysroot[krate].name) | ||
309 | .expect("Sysroot crate names should not contain dashes"), | ||
310 | ), | ||
311 | cfg_options, | 289 | cfg_options, |
312 | env, | 290 | env, |
313 | extern_source, | 291 | extern_source, |
314 | proc_macro, | 292 | proc_macro, |
315 | ); | 293 | ); |
316 | sysroot_crates.insert(krate, crate_id); | 294 | Some((krate, crate_id)) |
317 | } | 295 | }) |
318 | } | 296 | .collect(); |
297 | |||
319 | for from in sysroot.crates() { | 298 | for from in sysroot.crates() { |
320 | for &to in sysroot[from].deps.iter() { | 299 | for &to in sysroot[from].deps.iter() { |
321 | let name = &sysroot[to].name; | 300 | let name = &sysroot[to].name; |
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 2c0bde920..69133e4e4 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -36,8 +36,7 @@ pub(crate) fn load_cargo( | |||
36 | extern_dirs.extend(ws.out_dirs()); | 36 | extern_dirs.extend(ws.out_dirs()); |
37 | 37 | ||
38 | let mut project_roots = ws.to_roots(); | 38 | let mut project_roots = ws.to_roots(); |
39 | project_roots | 39 | project_roots.extend(extern_dirs.iter().cloned().map(PackageRoot::new_non_member)); |
40 | .extend(extern_dirs.iter().map(|path| PackageRoot::new(path.to_path_buf(), false))); | ||
41 | 40 | ||
42 | let (sender, receiver) = unbounded(); | 41 | let (sender, receiver) = unbounded(); |
43 | let sender = Box::new(move |t| sender.send(t).unwrap()); | 42 | let sender = Box::new(move |t| sender.send(t).unwrap()); |
@@ -46,7 +45,7 @@ pub(crate) fn load_cargo( | |||
46 | .iter() | 45 | .iter() |
47 | .map(|pkg_root| { | 46 | .map(|pkg_root| { |
48 | RootEntry::new( | 47 | RootEntry::new( |
49 | pkg_root.path().clone(), | 48 | pkg_root.path().to_owned(), |
50 | RustPackageFilterBuilder::default() | 49 | RustPackageFilterBuilder::default() |
51 | .set_member(pkg_root.is_member()) | 50 | .set_member(pkg_root.is_member()) |
52 | .into_vfs_filter(), | 51 | .into_vfs_filter(), |
@@ -58,12 +57,12 @@ pub(crate) fn load_cargo( | |||
58 | ); | 57 | ); |
59 | 58 | ||
60 | let source_roots = roots | 59 | let source_roots = roots |
61 | .iter() | 60 | .into_iter() |
62 | .map(|&vfs_root| { | 61 | .map(|vfs_root| { |
63 | let source_root_id = vfs_root_to_id(vfs_root); | 62 | let source_root_id = vfs_root_to_id(vfs_root); |
64 | let project_root = project_roots | 63 | let project_root = project_roots |
65 | .iter() | 64 | .iter() |
66 | .find(|it| it.path() == &vfs.root2path(vfs_root)) | 65 | .find(|it| it.path() == vfs.root2path(vfs_root)) |
67 | .unwrap() | 66 | .unwrap() |
68 | .clone(); | 67 | .clone(); |
69 | (source_root_id, project_root) | 68 | (source_root_id, project_root) |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 95e676e0f..8d1429196 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -23,6 +23,7 @@ use lsp_types::{ | |||
23 | use ra_flycheck::{url_from_path_with_drive_lowercasing, CheckTask}; | 23 | use ra_flycheck::{url_from_path_with_drive_lowercasing, CheckTask}; |
24 | use ra_ide::{Canceled, FileId, LibraryData, SourceRootId}; | 24 | use ra_ide::{Canceled, FileId, LibraryData, SourceRootId}; |
25 | use ra_prof::profile; | 25 | use ra_prof::profile; |
26 | use ra_project_model::{PackageRoot, ProjectWorkspace}; | ||
26 | use ra_vfs::{VfsFile, VfsTask, Watch}; | 27 | use ra_vfs::{VfsFile, VfsTask, Watch}; |
27 | use relative_path::RelativePathBuf; | 28 | use relative_path::RelativePathBuf; |
28 | use rustc_hash::FxHashSet; | 29 | use rustc_hash::FxHashSet; |
@@ -131,8 +132,8 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection) | |||
131 | let registration_options = req::DidChangeWatchedFilesRegistrationOptions { | 132 | let registration_options = req::DidChangeWatchedFilesRegistrationOptions { |
132 | watchers: workspaces | 133 | watchers: workspaces |
133 | .iter() | 134 | .iter() |
134 | .flat_map(|ws| ws.to_roots()) | 135 | .flat_map(ProjectWorkspace::to_roots) |
135 | .filter(|root| root.is_member()) | 136 | .filter(PackageRoot::is_member) |
136 | .map(|root| format!("{}/**/*.rs", root.path().display())) | 137 | .map(|root| format!("{}/**/*.rs", root.path().display())) |
137 | .map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None }) | 138 | .map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None }) |
138 | .collect(), | 139 | .collect(), |
diff --git a/crates/rust-analyzer/src/main_loop/subscriptions.rs b/crates/rust-analyzer/src/main_loop/subscriptions.rs index bee6437cf..2c76418be 100644 --- a/crates/rust-analyzer/src/main_loop/subscriptions.rs +++ b/crates/rust-analyzer/src/main_loop/subscriptions.rs | |||
@@ -17,6 +17,6 @@ impl Subscriptions { | |||
17 | self.subs.remove(&file_id); | 17 | self.subs.remove(&file_id); |
18 | } | 18 | } |
19 | pub(crate) fn subscriptions(&self) -> Vec<FileId> { | 19 | pub(crate) fn subscriptions(&self) -> Vec<FileId> { |
20 | self.subs.iter().cloned().collect() | 20 | self.subs.iter().copied().collect() |
21 | } | 21 | } |
22 | } | 22 | } |
diff --git a/crates/rust-analyzer/src/vfs_glob.rs b/crates/rust-analyzer/src/vfs_glob.rs index 91b33f94e..ff37a7008 100644 --- a/crates/rust-analyzer/src/vfs_glob.rs +++ b/crates/rust-analyzer/src/vfs_glob.rs | |||
@@ -29,10 +29,14 @@ impl RustPackageFilterBuilder { | |||
29 | self.is_member = is_member; | 29 | self.is_member = is_member; |
30 | self | 30 | self |
31 | } | 31 | } |
32 | pub fn exclude(mut self, glob: Glob) -> RustPackageFilterBuilder { | 32 | |
33 | self.exclude.add(glob); | 33 | pub fn exclude(mut self, globs: impl IntoIterator<Item = Glob>) -> RustPackageFilterBuilder { |
34 | for glob in globs.into_iter() { | ||
35 | self.exclude.add(glob); | ||
36 | } | ||
34 | self | 37 | self |
35 | } | 38 | } |
39 | |||
36 | pub fn into_vfs_filter(self) -> Box<dyn Filter> { | 40 | pub fn into_vfs_filter(self) -> Box<dyn Filter> { |
37 | let RustPackageFilterBuilder { is_member, mut exclude } = self; | 41 | let RustPackageFilterBuilder { is_member, mut exclude } = self; |
38 | for &glob in ALWAYS_IGNORED { | 42 | for &glob in ALWAYS_IGNORED { |
@@ -87,7 +91,7 @@ fn test_globs() { | |||
87 | 91 | ||
88 | let filter = RustPackageFilterBuilder::default() | 92 | let filter = RustPackageFilterBuilder::default() |
89 | .set_member(true) | 93 | .set_member(true) |
90 | .exclude(Glob::new("src/llvm-project/**").unwrap()) | 94 | .exclude(std::iter::once(Glob::new("src/llvm-project/**").unwrap())) |
91 | .into_vfs_filter(); | 95 | .into_vfs_filter(); |
92 | 96 | ||
93 | assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang"))); | 97 | assert!(!filter.include_dir(RelativePath::new("src/llvm-project/clang"))); |
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index 5674f42ef..365f57d8c 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs | |||
@@ -87,44 +87,35 @@ impl WorldState { | |||
87 | ) -> WorldState { | 87 | ) -> WorldState { |
88 | let mut change = AnalysisChange::new(); | 88 | let mut change = AnalysisChange::new(); |
89 | 89 | ||
90 | let mut roots = Vec::new(); | 90 | let extern_dirs: FxHashSet<_> = |
91 | roots.extend(folder_roots.iter().map(|path| { | 91 | workspaces.iter().flat_map(ProjectWorkspace::out_dirs).collect(); |
92 | let mut filter = RustPackageFilterBuilder::default().set_member(true); | 92 | |
93 | for glob in exclude_globs.iter() { | 93 | let roots: Vec<_> = { |
94 | filter = filter.exclude(glob.clone()); | 94 | let create_filter = |is_member| { |
95 | } | 95 | RustPackageFilterBuilder::default() |
96 | RootEntry::new(path.clone(), filter.into_vfs_filter()) | 96 | .set_member(is_member) |
97 | })); | 97 | .exclude(exclude_globs.iter().cloned()) |
98 | for ws in workspaces.iter() { | 98 | .into_vfs_filter() |
99 | roots.extend(ws.to_roots().into_iter().map(|pkg_root| { | 99 | }; |
100 | let mut filter = | 100 | folder_roots |
101 | RustPackageFilterBuilder::default().set_member(pkg_root.is_member()); | 101 | .iter() |
102 | for glob in exclude_globs.iter() { | 102 | .map(|path| RootEntry::new(path.clone(), create_filter(true))) |
103 | filter = filter.exclude(glob.clone()); | 103 | .chain(workspaces.iter().flat_map(ProjectWorkspace::to_roots).map(|pkg_root| { |
104 | } | 104 | RootEntry::new(pkg_root.path().to_owned(), create_filter(pkg_root.is_member())) |
105 | RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter()) | 105 | })) |
106 | })); | 106 | .chain( |
107 | } | 107 | extern_dirs |
108 | 108 | .iter() | |
109 | let mut extern_dirs = FxHashSet::default(); | 109 | .map(|path| RootEntry::new(path.to_owned(), create_filter(false))), |
110 | for ws in workspaces.iter() { | 110 | ) |
111 | extern_dirs.extend(ws.out_dirs()); | 111 | .collect() |
112 | } | 112 | }; |
113 | |||
114 | let mut extern_source_roots = FxHashMap::default(); | ||
115 | |||
116 | roots.extend(extern_dirs.iter().map(|path| { | ||
117 | let mut filter = RustPackageFilterBuilder::default().set_member(false); | ||
118 | for glob in exclude_globs.iter() { | ||
119 | filter = filter.exclude(glob.clone()); | ||
120 | } | ||
121 | RootEntry::new(PathBuf::from(&path), filter.into_vfs_filter()) | ||
122 | })); | ||
123 | 113 | ||
124 | let (task_sender, task_receiver) = unbounded(); | 114 | let (task_sender, task_receiver) = unbounded(); |
125 | let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); | 115 | let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); |
126 | let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); | 116 | let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); |
127 | 117 | ||
118 | let mut extern_source_roots = FxHashMap::default(); | ||
128 | for r in vfs_roots { | 119 | for r in vfs_roots { |
129 | let vfs_root_path = vfs.root2path(r); | 120 | let vfs_root_path = vfs.root2path(r); |
130 | let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); | 121 | let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); |