Skip to content

Commit 63e6c2d

Browse files
committed
support unchagedReport and disable pullD if server supports pushD
Add a flag to `Client' that becomes true on the first PushDiagnostic from the server.
1 parent 2aff024 commit 63e6c2d

File tree

3 files changed

+71
-29
lines changed

3 files changed

+71
-29
lines changed

helix-lsp/src/client.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ use lsp_types as lsp;
1515
use parking_lot::Mutex;
1616
use serde::Deserialize;
1717
use serde_json::Value;
18-
use std::future::Future;
1918
use std::process::Stdio;
2019
use std::sync::{
2120
atomic::{AtomicU64, Ordering},
2221
Arc,
2322
};
2423
use std::{collections::HashMap, path::PathBuf};
24+
use std::{future::Future, sync::atomic::AtomicBool};
2525
use tokio::{
2626
io::{BufReader, BufWriter},
2727
process::{Child, Command},
@@ -57,6 +57,9 @@ pub struct Client {
5757
initialize_notify: Arc<Notify>,
5858
/// workspace folders added while the server is still initializing
5959
req_timeout: u64,
60+
// there is no server capability to know if server supports it
61+
// set to true on first PublishDiagnostic
62+
pub supports_publish_diagnostic: AtomicBool,
6063
}
6164

6265
impl Client {
@@ -238,6 +241,7 @@ impl Client {
238241
root_uri,
239242
workspace_folders: Mutex::new(workspace_folders),
240243
initialize_notify: initialize_notify.clone(),
244+
supports_publish_diagnostic: AtomicBool::new(false),
241245
};
242246

243247
Ok((client, server_rx, initialize_notify))

helix-term/src/application.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ use crate::{
3131
use log::{debug, error, warn};
3232
#[cfg(not(feature = "integration"))]
3333
use std::io::stdout;
34-
use std::{collections::btree_map::Entry, io::stdin, path::Path, sync::Arc};
34+
use std::{
35+
collections::btree_map::Entry,
36+
io::stdin,
37+
path::Path,
38+
sync::{atomic, Arc},
39+
};
3540

3641
use anyhow::{Context, Error};
3742

@@ -732,6 +737,9 @@ impl Application {
732737
log::error!("Discarding publishDiagnostic notification sent by an uninitialized server: {}", language_server.name());
733738
return;
734739
}
740+
language_server
741+
.supports_publish_diagnostic
742+
.fetch_or(true, atomic::Ordering::Relaxed);
735743
let offset_encoding = language_server.offset_encoding();
736744
let doc = self.editor.document_by_path_mut(&path).filter(|doc| {
737745
if let Some(version) = params.version {

helix-term/src/commands/lsp.rs

+57-27
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ use crate::{
4141

4242
use std::{
4343
cmp::Ordering,
44-
collections::{BTreeMap, HashSet},
44+
collections::{BTreeMap, HashMap, HashSet},
4545
fmt::Write,
4646
future::Future,
4747
path::PathBuf,
48-
sync::Arc,
48+
sync::{atomic, Arc},
4949
};
5050

5151
/// Gets the first language server that is attached to a document which supports a specific feature.
@@ -1498,17 +1498,13 @@ pub fn select_references_to_symbol_under_cursor(cx: &mut Context) {
14981498
}
14991499

15001500
pub fn pull_diagnostic_for_current_doc(editor: &mut Editor, jobs: &mut crate::job::Jobs) {
1501-
fn parse_diagnostic<P: AsRef<std::path::Path>>(
1502-
editor: &mut Editor,
1503-
path: P,
1501+
fn parse_diagnostic(
1502+
doc: &mut Document,
15041503
offset_encoding: OffsetEncoding,
15051504
server_id: usize,
15061505
report: Vec<lsp::Diagnostic>,
15071506
result_id: Option<String>,
15081507
) {
1509-
let Some(doc) = editor.document_by_path_mut(path) else {
1510-
return;
1511-
};
15121508
let diagnostics = lsp_diagnostic_to_diagnostic(
15131509
&report,
15141510
doc.text(),
@@ -1520,14 +1516,49 @@ pub fn pull_diagnostic_for_current_doc(editor: &mut Editor, jobs: &mut crate::jo
15201516
doc.replace_diagnostics(diagnostics, server_id);
15211517
}
15221518

1523-
let doc = doc!(editor);
1519+
fn handle_document_diagnostic_report_kind(
1520+
editor: &mut Editor,
1521+
offset_encoding: OffsetEncoding,
1522+
server_id: usize,
1523+
report: Option<HashMap<lsp::Url, lsp::DocumentDiagnosticReportKind>>,
1524+
) {
1525+
for (url, report) in report.into_iter().flatten() {
1526+
let Some(doc) = editor.document_by_path_mut(url.path())
1527+
else {
1528+
continue;
1529+
};
1530+
match report {
1531+
lsp::DocumentDiagnosticReportKind::Full(report) => {
1532+
parse_diagnostic(
1533+
doc,
1534+
offset_encoding,
1535+
server_id,
1536+
report.items,
1537+
report.result_id,
1538+
);
1539+
}
1540+
lsp::DocumentDiagnosticReportKind::Unchanged(report) => {
1541+
doc.previous_diagnostic_id = Some(report.result_id);
1542+
}
1543+
}
1544+
}
1545+
}
15241546

1547+
let doc = doc!(editor);
15251548
let Some(language_server) = doc
15261549
.language_servers_with_feature(LanguageServerFeature::PullDiagnostics)
15271550
.next()
15281551
else {
15291552
return;
15301553
};
1554+
// Specialization does not say whether it is possible to have both types of diagnostics.
1555+
// Assume we should prefer PublishDiagnostic if possible
1556+
if language_server
1557+
.supports_publish_diagnostic
1558+
.load(atomic::Ordering::Relaxed)
1559+
{
1560+
return;
1561+
}
15311562

15321563
let future = language_server
15331564
.text_document_diagnostic(doc.identifier(), doc.previous_diagnostic_id.clone());
@@ -1558,32 +1589,31 @@ pub fn pull_diagnostic_for_current_doc(editor: &mut Editor, jobs: &mut crate::jo
15581589
lsp::DocumentDiagnosticReport::Full(report) => {
15591590
// Original file diagnostic
15601591
parse_diagnostic(
1561-
editor,
1562-
&original_path,
1592+
doc,
15631593
offset_encoding,
15641594
server_id,
15651595
report.full_document_diagnostic_report.items,
15661596
report.full_document_diagnostic_report.result_id,
15671597
);
15681598

15691599
// Related file diagnostic
1570-
for (url, report) in report.related_documents.into_iter().flatten() {
1571-
match report {
1572-
lsp::DocumentDiagnosticReportKind::Full(report) => {
1573-
parse_diagnostic(
1574-
editor,
1575-
url.path(),
1576-
offset_encoding,
1577-
server_id,
1578-
report.items,
1579-
report.result_id,
1580-
);
1581-
}
1582-
lsp::DocumentDiagnosticReportKind::Unchanged(_) => (),
1583-
}
1584-
}
1600+
handle_document_diagnostic_report_kind(
1601+
editor,
1602+
offset_encoding,
1603+
server_id,
1604+
report.related_documents,
1605+
);
1606+
}
1607+
lsp::DocumentDiagnosticReport::Unchanged(report) => {
1608+
doc.previous_diagnostic_id =
1609+
Some(report.unchanged_document_diagnostic_report.result_id);
1610+
handle_document_diagnostic_report_kind(
1611+
editor,
1612+
offset_encoding,
1613+
server_id,
1614+
report.related_documents,
1615+
);
15851616
}
1586-
lsp::DocumentDiagnosticReport::Unchanged(_) => (),
15871617
}
15881618
}
15891619
},

0 commit comments

Comments
 (0)