diff options
Diffstat (limited to 'crates/rust-analyzer/src/global_state.rs')
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 113 |
1 files changed, 48 insertions, 65 deletions
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 21116e165..1527c9947 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -12,42 +12,34 @@ use crossbeam_channel::{unbounded, Receiver}; | |||
12 | use lsp_types::Url; | 12 | use lsp_types::Url; |
13 | use parking_lot::RwLock; | 13 | use parking_lot::RwLock; |
14 | use ra_flycheck::{Flycheck, FlycheckConfig}; | 14 | use ra_flycheck::{Flycheck, FlycheckConfig}; |
15 | use ra_ide::{ | 15 | use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, SourceRootId}; |
16 | Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId, | 16 | use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; |
17 | }; | 17 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsTask, Watch}; |
18 | use ra_project_model::{ProcMacroClient, ProjectWorkspace}; | ||
19 | use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; | ||
20 | use relative_path::RelativePathBuf; | ||
21 | use stdx::format_to; | 18 | use stdx::format_to; |
22 | 19 | ||
23 | use crate::{ | 20 | use crate::{ |
24 | config::Config, | 21 | config::{Config, FilesWatcher}, |
25 | diagnostics::{ | 22 | diagnostics::{CheckFixes, DiagnosticCollection}, |
26 | to_proto::url_from_path_with_drive_lowercasing, CheckFixes, DiagnosticCollection, | ||
27 | }, | ||
28 | main_loop::pending_requests::{CompletedRequest, LatestRequests}, | 23 | main_loop::pending_requests::{CompletedRequest, LatestRequests}, |
24 | to_proto::url_from_abs_path, | ||
29 | vfs_glob::{Glob, RustPackageFilterBuilder}, | 25 | vfs_glob::{Glob, RustPackageFilterBuilder}, |
30 | LspError, Result, | 26 | LspError, Result, |
31 | }; | 27 | }; |
32 | use ra_db::ExternSourceId; | 28 | use ra_db::{CrateId, ExternSourceId}; |
33 | use rustc_hash::{FxHashMap, FxHashSet}; | 29 | use rustc_hash::{FxHashMap, FxHashSet}; |
34 | 30 | ||
35 | fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) -> Option<Flycheck> { | 31 | fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) -> Option<Flycheck> { |
36 | // FIXME: Figure out the multi-workspace situation | 32 | // FIXME: Figure out the multi-workspace situation |
37 | workspaces | 33 | workspaces.iter().find_map(|w| match w { |
38 | .iter() | 34 | ProjectWorkspace::Cargo { cargo, .. } => { |
39 | .find_map(|w| match w { | ||
40 | ProjectWorkspace::Cargo { cargo, .. } => Some(cargo), | ||
41 | ProjectWorkspace::Json { .. } => None, | ||
42 | }) | ||
43 | .map(|cargo| { | ||
44 | let cargo_project_root = cargo.workspace_root().to_path_buf(); | 35 | let cargo_project_root = cargo.workspace_root().to_path_buf(); |
45 | Some(Flycheck::new(config.clone(), cargo_project_root)) | 36 | Some(Flycheck::new(config.clone(), cargo_project_root)) |
46 | }) | 37 | } |
47 | .unwrap_or_else(|| { | 38 | ProjectWorkspace::Json { .. } => { |
48 | log::warn!("Cargo check watching only supported for cargo workspaces, disabling"); | 39 | log::warn!("Cargo check watching only supported for cargo workspaces, disabling"); |
49 | None | 40 | None |
50 | }) | 41 | } |
42 | }) | ||
51 | } | 43 | } |
52 | 44 | ||
53 | /// `GlobalState` is the primary mutable state of the language server | 45 | /// `GlobalState` is the primary mutable state of the language server |
@@ -84,7 +76,6 @@ impl GlobalState { | |||
84 | workspaces: Vec<ProjectWorkspace>, | 76 | workspaces: Vec<ProjectWorkspace>, |
85 | lru_capacity: Option<usize>, | 77 | lru_capacity: Option<usize>, |
86 | exclude_globs: &[Glob], | 78 | exclude_globs: &[Glob], |
87 | watch: Watch, | ||
88 | config: Config, | 79 | config: Config, |
89 | ) -> GlobalState { | 80 | ) -> GlobalState { |
90 | let mut change = AnalysisChange::new(); | 81 | let mut change = AnalysisChange::new(); |
@@ -119,6 +110,7 @@ impl GlobalState { | |||
119 | 110 | ||
120 | let (task_sender, task_receiver) = unbounded(); | 111 | let (task_sender, task_receiver) = unbounded(); |
121 | let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); | 112 | let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); |
113 | let watch = Watch(matches!(config.files.watcher, FilesWatcher::Notify)); | ||
122 | let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); | 114 | let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); |
123 | 115 | ||
124 | let mut extern_source_roots = FxHashMap::default(); | 116 | let mut extern_source_roots = FxHashMap::default(); |
@@ -196,32 +188,18 @@ impl GlobalState { | |||
196 | 188 | ||
197 | /// Returns a vec of libraries | 189 | /// Returns a vec of libraries |
198 | /// FIXME: better API here | 190 | /// FIXME: better API here |
199 | pub fn process_changes( | 191 | pub fn process_changes(&mut self, roots_scanned: &mut usize) -> bool { |
200 | &mut self, | ||
201 | roots_scanned: &mut usize, | ||
202 | ) -> Option<Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc<String>)>)>> { | ||
203 | let changes = self.vfs.write().commit_changes(); | 192 | let changes = self.vfs.write().commit_changes(); |
204 | if changes.is_empty() { | 193 | if changes.is_empty() { |
205 | return None; | 194 | return false; |
206 | } | 195 | } |
207 | let mut libs = Vec::new(); | ||
208 | let mut change = AnalysisChange::new(); | 196 | let mut change = AnalysisChange::new(); |
209 | for c in changes { | 197 | for c in changes { |
210 | match c { | 198 | match c { |
211 | VfsChange::AddRoot { root, files } => { | 199 | VfsChange::AddRoot { root, files } => { |
212 | let root_path = self.vfs.read().root2path(root); | 200 | *roots_scanned += 1; |
213 | let is_local = self.local_roots.iter().any(|r| root_path.starts_with(r)); | 201 | for (file, path, text) in files { |
214 | if is_local { | 202 | change.add_file(SourceRootId(root.0), FileId(file.0), path, text); |
215 | *roots_scanned += 1; | ||
216 | for (file, path, text) in files { | ||
217 | change.add_file(SourceRootId(root.0), FileId(file.0), path, text); | ||
218 | } | ||
219 | } else { | ||
220 | let files = files | ||
221 | .into_iter() | ||
222 | .map(|(vfsfile, path, text)| (FileId(vfsfile.0), path, text)) | ||
223 | .collect(); | ||
224 | libs.push((SourceRootId(root.0), files)); | ||
225 | } | 203 | } |
226 | } | 204 | } |
227 | VfsChange::AddFile { root, file, path, text } => { | 205 | VfsChange::AddFile { root, file, path, text } => { |
@@ -236,13 +214,7 @@ impl GlobalState { | |||
236 | } | 214 | } |
237 | } | 215 | } |
238 | self.analysis_host.apply_change(change); | 216 | self.analysis_host.apply_change(change); |
239 | Some(libs) | 217 | true |
240 | } | ||
241 | |||
242 | pub fn add_lib(&mut self, data: LibraryData) { | ||
243 | let mut change = AnalysisChange::new(); | ||
244 | change.add_library(data); | ||
245 | self.analysis_host.apply_change(change); | ||
246 | } | 218 | } |
247 | 219 | ||
248 | pub fn snapshot(&self) -> GlobalStateSnapshot { | 220 | pub fn snapshot(&self) -> GlobalStateSnapshot { |
@@ -274,8 +246,8 @@ impl GlobalStateSnapshot { | |||
274 | &self.analysis | 246 | &self.analysis |
275 | } | 247 | } |
276 | 248 | ||
277 | pub fn uri_to_file_id(&self, uri: &Url) -> Result<FileId> { | 249 | pub fn url_to_file_id(&self, url: &Url) -> Result<FileId> { |
278 | let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?; | 250 | let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?; |
279 | let file = self.vfs.read().path2file(&path).ok_or_else(|| { | 251 | let file = self.vfs.read().path2file(&path).ok_or_else(|| { |
280 | // Show warning as this file is outside current workspace | 252 | // Show warning as this file is outside current workspace |
281 | // FIXME: just handle such files, and remove `LspError::UNKNOWN_FILE`. | 253 | // FIXME: just handle such files, and remove `LspError::UNKNOWN_FILE`. |
@@ -287,27 +259,33 @@ impl GlobalStateSnapshot { | |||
287 | Ok(FileId(file.0)) | 259 | Ok(FileId(file.0)) |
288 | } | 260 | } |
289 | 261 | ||
290 | pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> { | 262 | pub fn file_id_to_url(&self, id: FileId) -> Url { |
291 | let path = self.vfs.read().file2path(VfsFile(id.0)); | 263 | file_id_to_url(&self.vfs.read(), id) |
292 | let url = url_from_path_with_drive_lowercasing(path)?; | ||
293 | |||
294 | Ok(url) | ||
295 | } | ||
296 | |||
297 | pub fn file_id_to_path(&self, id: FileId) -> PathBuf { | ||
298 | self.vfs.read().file2path(VfsFile(id.0)) | ||
299 | } | 264 | } |
300 | 265 | ||
301 | pub fn file_line_endings(&self, id: FileId) -> LineEndings { | 266 | pub fn file_line_endings(&self, id: FileId) -> LineEndings { |
302 | self.vfs.read().file_line_endings(VfsFile(id.0)) | 267 | self.vfs.read().file_line_endings(VfsFile(id.0)) |
303 | } | 268 | } |
304 | 269 | ||
305 | pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> { | 270 | pub fn anchored_path(&self, file_id: FileId, path: &str) -> Url { |
306 | let base = self.vfs.read().root2path(VfsRoot(root.0)); | 271 | let mut base = self.vfs.read().file2path(VfsFile(file_id.0)); |
307 | let path = path.to_path(base); | 272 | base.pop(); |
308 | let url = Url::from_file_path(&path) | 273 | let path = base.join(path); |
309 | .map_err(|_| format!("can't convert path to url: {}", path.display()))?; | 274 | url_from_abs_path(&path) |
310 | Ok(url) | 275 | } |
276 | |||
277 | pub(crate) fn cargo_target_for_crate_root( | ||
278 | &self, | ||
279 | crate_id: CrateId, | ||
280 | ) -> Option<(&CargoWorkspace, Target)> { | ||
281 | let file_id = self.analysis().crate_root(crate_id).ok()?; | ||
282 | let path = self.vfs.read().file2path(VfsFile(file_id.0)); | ||
283 | self.workspaces.iter().find_map(|ws| match ws { | ||
284 | ProjectWorkspace::Cargo { cargo, .. } => { | ||
285 | cargo.target_by_root(&path).map(|it| (cargo, it)) | ||
286 | } | ||
287 | ProjectWorkspace::Json { .. } => None, | ||
288 | }) | ||
311 | } | 289 | } |
312 | 290 | ||
313 | pub fn status(&self) -> String { | 291 | pub fn status(&self) -> String { |
@@ -335,3 +313,8 @@ impl GlobalStateSnapshot { | |||
335 | self.workspaces.iter().find_map(|ws| ws.workspace_root_for(&path)) | 313 | self.workspaces.iter().find_map(|ws| ws.workspace_root_for(&path)) |
336 | } | 314 | } |
337 | } | 315 | } |
316 | |||
317 | pub(crate) fn file_id_to_url(vfs: &Vfs, id: FileId) -> Url { | ||
318 | let path = vfs.file2path(VfsFile(id.0)); | ||
319 | url_from_abs_path(&path) | ||
320 | } | ||