From 8bf628c17b2abe995eeda643e29a71e92f529875 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 22 Jan 2022 08:46:37 -0700 Subject: [PATCH] =?UTF-8?q?Update=20new=20buffers=20with=20existing=20diag?= =?UTF-8?q?nostics=20in=20Project=20=E2=80=93=20after=20assigning=20langua?= =?UTF-8?q?ge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/project/src/project.rs | 62 +++++++++++++++++++++------------- crates/project/src/worktree.rs | 32 ++++++++++-------- 2 files changed, 56 insertions(+), 38 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index c036ded150cbc4e7527d3fc573272822cde7f597..5faa830df6ee8764703560fea9a963e8e7ed4fc0 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -489,20 +489,20 @@ impl Project { path: impl Into, cx: &mut ModelContext, ) -> Task>> { - let path = path.into(); - let worktree = if let Some(worktree) = self.worktree_for_id(path.worktree_id, cx) { + let project_path = path.into(); + let worktree = if let Some(worktree) = self.worktree_for_id(project_path.worktree_id, cx) { worktree } else { return Task::ready(Err(anyhow!("no such worktree"))); }; // If there is already a buffer for the given path, then return it. - let existing_buffer = self.get_open_buffer(&path, cx); + let existing_buffer = self.get_open_buffer(&project_path, cx); if let Some(existing_buffer) = existing_buffer { return Task::ready(Ok(existing_buffer)); } - let mut loading_watch = match self.loading_buffers.entry(path.clone()) { + let mut loading_watch = match self.loading_buffers.entry(project_path.clone()) { // If the given path is already being loaded, then wait for that existing // task to complete and return the same buffer. hash_map::Entry::Occupied(e) => e.get().clone(), @@ -512,16 +512,15 @@ impl Project { let (mut tx, rx) = postage::watch::channel(); entry.insert(rx.clone()); - let load_buffer = worktree.update(cx, |worktree, cx| match worktree { - Worktree::Local(worktree) => worktree.open_buffer(&path.path, cx), - Worktree::Remote(worktree) => worktree.open_buffer(&path.path, cx), + let load_buffer = worktree.update(cx, |worktree, cx| { + worktree.load_buffer(&project_path.path, cx) }); cx.spawn(move |this, mut cx| async move { let load_result = load_buffer.await; *tx.borrow_mut() = Some(this.update(&mut cx, |this, cx| { // Record the fact that the buffer is no longer loading. - this.loading_buffers.remove(&path); + this.loading_buffers.remove(&project_path); let buffer = load_result.map_err(Arc::new)?; this.open_buffers.insert( buffer.read(cx).remote_id() as usize, @@ -623,31 +622,46 @@ impl Project { buffer: &ModelHandle, cx: &mut ModelContext, ) -> Option<()> { + let (path, full_path) = { + let file = buffer.read(cx).file()?; + (file.path().clone(), file.full_path()) + }; + // Set the buffer's language - let full_path = buffer.read(cx).file()?.full_path(); let language = self.languages.select_language(&full_path)?.clone(); buffer.update(cx, |buffer, cx| { buffer.set_language(Some(language.clone()), cx); }); // For local worktrees, start a language server if needed. + // Also assign the language server and any previously stored diagnostics to the buffer. let worktree = worktree.read(cx); - let worktree_id = worktree.id(); - let worktree_abs_path = worktree.as_local()?.abs_path().clone(); - let language_server = match self - .language_servers - .entry((worktree_id, language.name().to_string())) - { - hash_map::Entry::Occupied(e) => Some(e.get().clone()), - hash_map::Entry::Vacant(e) => { - Self::start_language_server(self.client.clone(), language, &worktree_abs_path, cx) - .map(|server| e.insert(server).clone()) - } - }; + if let Some(local_worktree) = worktree.as_local() { + let worktree_id = local_worktree.id(); + let diagnostics = local_worktree.diagnostics_for_path(&path); + let worktree_abs_path = local_worktree.abs_path().clone(); + + let language_server = match self + .language_servers + .entry((worktree_id, language.name().to_string())) + { + hash_map::Entry::Occupied(e) => Some(e.get().clone()), + hash_map::Entry::Vacant(e) => Self::start_language_server( + self.client.clone(), + language, + &worktree_abs_path, + cx, + ) + .map(|server| e.insert(server).clone()), + }; - buffer.update(cx, |buffer, cx| { - buffer.set_language_server(language_server, cx) - }); + buffer.update(cx, |buffer, cx| { + buffer.set_language_server(language_server, cx); + if let Some(diagnostics) = diagnostics { + buffer.update_diagnostics(None, diagnostics, cx).log_err(); + } + }); + } None } diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index b364af2bf55c85db97eecc40323d3ffb647051c8..719049ce308cb9c32cce31f80f8c50ba61d65cbc 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -347,6 +347,17 @@ impl Worktree { } } + pub fn load_buffer( + &mut self, + path: &Path, + cx: &mut ModelContext, + ) -> Task>> { + match self { + Worktree::Local(worktree) => worktree.load_buffer(path, cx), + Worktree::Remote(worktree) => worktree.load_buffer(path, cx), + } + } + pub fn diagnostic_summaries<'a>( &'a self, ) -> impl Iterator, DiagnosticSummary)> + 'a { @@ -536,7 +547,7 @@ impl LocalWorktree { self.config.collaborators.clone() } - pub(crate) fn open_buffer( + pub(crate) fn load_buffer( &mut self, path: &Path, cx: &mut ModelContext, @@ -546,21 +557,14 @@ impl LocalWorktree { let (file, contents) = this .update(&mut cx, |t, cx| t.as_local().unwrap().load(&path, cx)) .await?; - - let diagnostics = this.update(&mut cx, |this, _| { - this.as_local_mut().unwrap().diagnostics.get(&path).cloned() - }); - - Ok(cx.add_model(|cx| { - let mut buffer = Buffer::from_file(0, contents, Box::new(file), cx); - if let Some(diagnostics) = diagnostics { - buffer.update_diagnostics(None, diagnostics, cx).unwrap(); - } - buffer - })) + Ok(cx.add_model(|cx| Buffer::from_file(0, contents, Box::new(file), cx))) }) } + pub fn diagnostics_for_path(&self, path: &Path) -> Option>> { + self.diagnostics.get(path).cloned() + } + pub fn update_diagnostics( &mut self, worktree_path: Arc, @@ -798,7 +802,7 @@ impl LocalWorktree { } impl RemoteWorktree { - pub(crate) fn open_buffer( + pub(crate) fn load_buffer( &mut self, path: &Path, cx: &mut ModelContext,