Skip to content

Commit 1c7d5f5

Browse files
bors[bot]kjeremy
andauthored
Merge #5481
5481: Track document versions in the server r=kjeremy a=kjeremy This also pushes diagnostics for the correct file version on close so that when it is reopened stale diagnostics are not shown. Closes #5452 Co-authored-by: kjeremy <[email protected]> Co-authored-by: Jeremy Kolb <[email protected]>
2 parents dba534a + 4f4582a commit 1c7d5f5

File tree

3 files changed

+40
-15
lines changed

3 files changed

+40
-15
lines changed

crates/rust-analyzer/src/global_state.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use parking_lot::RwLock;
1212
use ra_db::{CrateId, VfsPath};
1313
use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FileId};
1414
use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target};
15-
use rustc_hash::{FxHashMap, FxHashSet};
15+
use rustc_hash::FxHashMap;
1616

1717
use crate::{
1818
config::Config,
@@ -69,7 +69,7 @@ pub(crate) struct GlobalState {
6969
pub(crate) config: Config,
7070
pub(crate) analysis_host: AnalysisHost,
7171
pub(crate) diagnostics: DiagnosticCollection,
72-
pub(crate) mem_docs: FxHashSet<VfsPath>,
72+
pub(crate) mem_docs: FxHashMap<VfsPath, Option<i64>>,
7373
pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
7474
pub(crate) status: Status,
7575
pub(crate) source_root_config: SourceRootConfig,
@@ -84,6 +84,7 @@ pub(crate) struct GlobalStateSnapshot {
8484
pub(crate) analysis: Analysis,
8585
pub(crate) check_fixes: CheckFixes,
8686
pub(crate) latest_requests: Arc<RwLock<LatestRequests>>,
87+
mem_docs: FxHashMap<VfsPath, Option<i64>>,
8788
vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
8889
pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
8990
}
@@ -117,7 +118,7 @@ impl GlobalState {
117118
config,
118119
analysis_host,
119120
diagnostics: Default::default(),
120-
mem_docs: FxHashSet::default(),
121+
mem_docs: FxHashMap::default(),
121122
vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))),
122123
status: Status::default(),
123124
source_root_config: SourceRootConfig::default(),
@@ -183,6 +184,7 @@ impl GlobalState {
183184
vfs: Arc::clone(&self.vfs),
184185
latest_requests: Arc::clone(&self.latest_requests),
185186
check_fixes: Arc::clone(&self.diagnostics.check_fixes),
187+
mem_docs: self.mem_docs.clone(),
186188
}
187189
}
188190

@@ -255,6 +257,11 @@ impl GlobalStateSnapshot {
255257
self.vfs.read().1[&id]
256258
}
257259

260+
pub(crate) fn url_file_version(&self, url: &Url) -> Option<i64> {
261+
let path = from_proto::vfs_path(&url).ok()?;
262+
self.mem_docs.get(&path).copied()?
263+
}
264+
258265
pub(crate) fn anchored_path(&self, file_id: FileId, path: &str) -> Url {
259266
let mut base = self.vfs.read().0.file_path(file_id);
260267
base.pop();

crates/rust-analyzer/src/main_loop.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ impl GlobalState {
210210
let vfs = &mut self.vfs.write().0;
211211
for (path, contents) in files {
212212
let path = VfsPath::from(path);
213-
if !self.mem_docs.contains(&path) {
213+
if !self.mem_docs.contains_key(&path) {
214214
vfs.set_file_contents(path, contents)
215215
}
216216
}
@@ -299,7 +299,7 @@ impl GlobalState {
299299
if self.status == Status::Ready && (state_changed || prev_status == Status::Loading) {
300300
let subscriptions = self
301301
.mem_docs
302-
.iter()
302+
.keys()
303303
.map(|path| self.vfs.read().0.file_id(&path).unwrap())
304304
.collect::<Vec<_>>();
305305

@@ -310,8 +310,12 @@ impl GlobalState {
310310
for file_id in diagnostic_changes {
311311
let url = file_id_to_url(&self.vfs.read().0, file_id);
312312
let diagnostics = self.diagnostics.diagnostics_for(file_id).cloned().collect();
313+
let version = from_proto::vfs_path(&url)
314+
.map(|path| self.mem_docs.get(&path).copied().flatten())
315+
.unwrap_or_default();
316+
313317
self.send_notification::<lsp_types::notification::PublishDiagnostics>(
314-
lsp_types::PublishDiagnosticsParams { uri: url, diagnostics, version: None },
318+
lsp_types::PublishDiagnosticsParams { uri: url, diagnostics, version },
315319
);
316320
}
317321
}
@@ -400,7 +404,11 @@ impl GlobalState {
400404
})?
401405
.on::<lsp_types::notification::DidOpenTextDocument>(|this, params| {
402406
if let Ok(path) = from_proto::vfs_path(&params.text_document.uri) {
403-
if !this.mem_docs.insert(path.clone()) {
407+
if this
408+
.mem_docs
409+
.insert(path.clone(), Some(params.text_document.version))
410+
.is_some()
411+
{
404412
log::error!("duplicate DidOpenTextDocument: {}", path)
405413
}
406414
this.vfs
@@ -412,29 +420,38 @@ impl GlobalState {
412420
})?
413421
.on::<lsp_types::notification::DidChangeTextDocument>(|this, params| {
414422
if let Ok(path) = from_proto::vfs_path(&params.text_document.uri) {
415-
assert!(this.mem_docs.contains(&path));
423+
*this.mem_docs.get_mut(&path).unwrap() = params.text_document.version;
416424
let vfs = &mut this.vfs.write().0;
417425
let file_id = vfs.file_id(&path).unwrap();
418426
let mut text = String::from_utf8(vfs.file_contents(file_id).to_vec()).unwrap();
419427
apply_document_changes(&mut text, params.content_changes);
420-
vfs.set_file_contents(path, Some(text.into_bytes()))
428+
vfs.set_file_contents(path.clone(), Some(text.into_bytes()));
429+
430+
this.mem_docs.insert(path, params.text_document.version);
421431
}
422432
Ok(())
423433
})?
424434
.on::<lsp_types::notification::DidCloseTextDocument>(|this, params| {
435+
let mut version = None;
425436
if let Ok(path) = from_proto::vfs_path(&params.text_document.uri) {
426-
if !this.mem_docs.remove(&path) {
427-
log::error!("orphan DidCloseTextDocument: {}", path)
437+
match this.mem_docs.remove(&path) {
438+
Some(entry) => version = entry,
439+
None => log::error!("orphan DidCloseTextDocument: {}", path),
428440
}
441+
429442
if let Some(path) = path.as_path() {
430443
this.loader.handle.invalidate(path.to_path_buf());
431444
}
432445
}
446+
447+
// Clear the diagnostics for the previously known version of the file.
448+
// This prevents stale "cargo check" diagnostics if the file is
449+
// closed, "cargo check" is run and then the file is reopened.
433450
this.send_notification::<lsp_types::notification::PublishDiagnostics>(
434451
lsp_types::PublishDiagnosticsParams {
435452
uri: params.text_document.uri,
436453
diagnostics: Vec::new(),
437-
version: None,
454+
version,
438455
},
439456
);
440457
Ok(())

crates/rust-analyzer/src/to_proto.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -480,9 +480,10 @@ pub(crate) fn url_from_abs_path(path: &Path) -> lsp_types::Url {
480480
pub(crate) fn versioned_text_document_identifier(
481481
snap: &GlobalStateSnapshot,
482482
file_id: FileId,
483-
version: Option<i64>,
484483
) -> lsp_types::VersionedTextDocumentIdentifier {
485-
lsp_types::VersionedTextDocumentIdentifier { uri: url(snap, file_id), version }
484+
let url = url(snap, file_id);
485+
let version = snap.url_file_version(&url);
486+
lsp_types::VersionedTextDocumentIdentifier { uri: url, version }
486487
}
487488

488489
pub(crate) fn location(
@@ -571,7 +572,7 @@ pub(crate) fn snippet_text_document_edit(
571572
is_snippet: bool,
572573
source_file_edit: SourceFileEdit,
573574
) -> Result<lsp_ext::SnippetTextDocumentEdit> {
574-
let text_document = versioned_text_document_identifier(snap, source_file_edit.file_id, None);
575+
let text_document = versioned_text_document_identifier(snap, source_file_edit.file_id);
575576
let line_index = snap.analysis.file_line_index(source_file_edit.file_id)?;
576577
let line_endings = snap.file_line_endings(source_file_edit.file_id);
577578
let edits = source_file_edit

0 commit comments

Comments
 (0)