Skip to content

Commit

Permalink
Fix clearing stale diagnostics (#1043)
Browse files Browse the repository at this point in the history
The `MultiMap::retain function` removes the entire entry if the associated `Vec` is empty. Switching to plain `HashMap` fixes the issue.

Fixes #1042.
  • Loading branch information
pfoerster authored Mar 16, 2024
1 parent 05b2f88 commit 726af3a
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 21 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed

- Fix clearing stale diagnostics reported by the server ([#1042](https://github.com/latex-lsp/texlab/issues/1042))

## [5.13.0] - 2024-03-10

### Added
Expand Down
24 changes: 16 additions & 8 deletions crates/diagnostics/src/citations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use base_db::{
util::queries::{self, Object},
Document, Project, Workspace,
};
use multimap::MultiMap;
use rustc_hash::FxHashSet;
use rustc_hash::{FxHashMap, FxHashSet};
use url::Url;

use crate::types::{BibError, Diagnostic, TexError};
Expand All @@ -14,7 +13,7 @@ const MAX_UNUSED_ENTRIES: usize = 1000;
pub fn detect_undefined_citations<'a>(
project: &Project<'a>,
document: &'a Document,
results: &mut MultiMap<Url, Diagnostic>,
results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) -> Option<()> {
let data = document.data.as_tex()?;

Expand All @@ -26,7 +25,10 @@ pub fn detect_undefined_citations<'a>(
let name = citation.name_text();
if name != "*" && !entries.contains(name) {
let diagnostic = Diagnostic::Tex(citation.name.range, TexError::UndefinedCitation);
results.insert(document.uri.clone(), diagnostic);
results
.entry(document.uri.clone())
.or_default()
.push(diagnostic);
}
}

Expand All @@ -36,7 +38,7 @@ pub fn detect_undefined_citations<'a>(
pub fn detect_unused_entries<'a>(
project: &Project<'a>,
document: &'a Document,
results: &mut MultiMap<Url, Diagnostic>,
results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) -> Option<()> {
let data = document.data.as_bib()?;

Expand All @@ -52,7 +54,10 @@ pub fn detect_unused_entries<'a>(
for entry in &data.semantics.entries {
if !citations.contains(entry.name.text.as_str()) {
let diagnostic = Diagnostic::Bib(entry.name.range, BibError::UnusedEntry);
results.insert(document.uri.clone(), diagnostic);
results
.entry(document.uri.clone())
.or_default()
.push(diagnostic);
}
}

Expand All @@ -61,7 +66,7 @@ pub fn detect_unused_entries<'a>(

pub fn detect_duplicate_entries<'a>(
workspace: &'a Workspace,
results: &mut MultiMap<Url, Diagnostic>,
results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) {
for conflict in queries::Conflict::find_all::<Entry>(workspace) {
let others = conflict
Expand All @@ -71,6 +76,9 @@ pub fn detect_duplicate_entries<'a>(
.collect();

let diagnostic = Diagnostic::Bib(conflict.main.range, BibError::DuplicateEntry(others));
results.insert(conflict.main.document.uri.clone(), diagnostic);
results
.entry(conflict.main.document.uri.clone())
.or_default()
.push(diagnostic);
}
}
25 changes: 18 additions & 7 deletions crates/diagnostics/src/labels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ use base_db::{
DocumentData, Workspace,
};
use itertools::Itertools;
use multimap::MultiMap;
use rustc_hash::FxHashSet;
use rustc_hash::{FxHashMap, FxHashSet};
use url::Url;

use crate::types::{Diagnostic, TexError};

pub fn detect_undefined_and_unused_labels(
workspace: &Workspace,
results: &mut MultiMap<Url, Diagnostic>,
results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) {
let graphs: Vec<_> = workspace
.iter()
Expand Down Expand Up @@ -45,18 +44,27 @@ pub fn detect_undefined_and_unused_labels(
for label in &data.semantics.labels {
if label.kind != LabelKind::Definition && !label_defs.contains(&label.name.text) {
let diagnostic = Diagnostic::Tex(label.name.range, TexError::UndefinedLabel);
results.insert(document.uri.clone(), diagnostic);
results
.entry(document.uri.clone())
.or_default()
.push(diagnostic);
}

if label.kind == LabelKind::Definition && !label_refs.contains(&label.name.text) {
let diagnostic = Diagnostic::Tex(label.name.range, TexError::UnusedLabel);
results.insert(document.uri.clone(), diagnostic);
results
.entry(document.uri.clone())
.or_default()
.push(diagnostic);
}
}
}
}

pub fn detect_duplicate_labels(workspace: &Workspace, results: &mut MultiMap<Url, Diagnostic>) {
pub fn detect_duplicate_labels(
workspace: &Workspace,
results: &mut FxHashMap<Url, Vec<Diagnostic>>,
) {
for conflict in queries::Conflict::find_all::<Label>(workspace) {
let others = conflict
.rest
Expand All @@ -65,6 +73,9 @@ pub fn detect_duplicate_labels(workspace: &Workspace, results: &mut MultiMap<Url
.collect();

let diagnostic = Diagnostic::Tex(conflict.main.range, TexError::DuplicateLabel(others));
results.insert(conflict.main.document.uri.clone(), diagnostic);
results
.entry(conflict.main.document.uri.clone())
.or_default()
.push(diagnostic);
}
}
19 changes: 14 additions & 5 deletions crates/diagnostics/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,31 @@ impl Manager {
}

/// Returns all filtered diagnostics for the given workspace.
pub fn get(&self, workspace: &Workspace) -> MultiMap<Url, Diagnostic> {
let mut results = MultiMap::default();
pub fn get(&self, workspace: &Workspace) -> FxHashMap<Url, Vec<Diagnostic>> {
let mut results: FxHashMap<Url, Vec<Diagnostic>> = FxHashMap::default();
for (uri, diagnostics) in &self.grammar {
results.insert_many_from_slice(uri.clone(), diagnostics);
results
.entry(uri.clone())
.or_default()
.extend(diagnostics.iter().cloned());
}

for (uri, diagnostics) in self.build_log.values().flatten() {
results.insert_many_from_slice(uri.clone(), diagnostics);
results
.entry(uri.clone())
.or_default()
.extend(diagnostics.iter().cloned());
}

for (uri, diagnostics) in &self.chktex {
if workspace
.lookup(uri)
.map_or(false, |document| document.owner == Owner::Client)
{
results.insert_many_from_slice(uri.clone(), diagnostics);
results
.entry(uri.clone())
.or_default()
.extend(diagnostics.iter().cloned());
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/diagnostics/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn check(input: &str, expect: Expect) {

let results = manager.get(&fixture.workspace);
let results = results
.iter_all()
.iter()
.filter(|(_, diags)| !diags.is_empty())
.sorted_by(|(uri1, _), (uri2, _)| uri1.cmp(&uri2))
.map(|(uri, diags)| (uri.as_str(), diags))
Expand Down

0 comments on commit 726af3a

Please sign in to comment.