mirror of
https://github.com/helix-editor/helix.git
synced 2024-09-11 10:55:45 +03:00
Pull diagnostics on open
This commit is contained in:
parent
96a984c6a4
commit
a8f1b9ecd7
@ -1,6 +1,8 @@
|
||||
use helix_event::{events, register_event};
|
||||
use helix_view::document::Mode;
|
||||
use helix_view::events::{DiagnosticsDidChange, DocumentDidChange, SelectionDidChange};
|
||||
use helix_view::events::{
|
||||
DiagnosticsDidChange, DocumentDidChange, DocumentDidOpen, SelectionDidChange,
|
||||
};
|
||||
|
||||
use crate::commands;
|
||||
use crate::keymap::MappableCommand;
|
||||
@ -16,6 +18,7 @@ pub fn register() {
|
||||
register_event::<PostInsertChar>();
|
||||
register_event::<PostCommand>();
|
||||
register_event::<DocumentDidChange>();
|
||||
register_event::<DocumentDidOpen>();
|
||||
register_event::<SelectionDidChange>();
|
||||
register_event::<DiagnosticsDidChange>();
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
pub use completion::trigger_auto_completion;
|
||||
pub use helix_view::handlers::Handlers;
|
||||
|
||||
use self::diagnostics::PullDiagnosticsForDocumentsHandler;
|
||||
|
||||
mod auto_save;
|
||||
pub mod completion;
|
||||
mod diagnostics;
|
||||
@ -26,12 +28,14 @@ pub fn setup(config: Arc<ArcSwap<Config>>) -> Handlers {
|
||||
let signature_hints = SignatureHelpHandler::new().spawn();
|
||||
let auto_save = AutoSaveHandler::new().spawn();
|
||||
let pull_diagnostics = PullDiagnosticsHandler::new().spawn();
|
||||
let pull_diagnostics_document = PullDiagnosticsForDocumentsHandler::new().spawn();
|
||||
|
||||
let handlers = Handlers {
|
||||
completions,
|
||||
signature_hints,
|
||||
auto_save,
|
||||
pull_diagnostics,
|
||||
pull_diagnostics_document,
|
||||
};
|
||||
|
||||
completion::register_hooks(&handlers);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::time::Duration;
|
||||
|
||||
use helix_core::syntax::LanguageServerFeature;
|
||||
@ -7,11 +7,13 @@
|
||||
use helix_lsp::lsp::{self, Diagnostic};
|
||||
use helix_lsp::LanguageServerId;
|
||||
use helix_view::document::Mode;
|
||||
use helix_view::events::{DiagnosticsDidChange, DocumentDidChange};
|
||||
use helix_view::events::{DiagnosticsDidChange, DocumentDidChange, DocumentDidOpen};
|
||||
use helix_view::handlers::diagnostics::DiagnosticEvent;
|
||||
use helix_view::handlers::lsp::PullDiagnosticsEvent;
|
||||
use helix_view::handlers::lsp::{
|
||||
PullDiagnosticsForDocumentsEvent, PullDiagnosticsForLanguageServersEvent,
|
||||
};
|
||||
use helix_view::handlers::Handlers;
|
||||
use helix_view::Editor;
|
||||
use helix_view::{DocumentId, Editor};
|
||||
use tokio::time::Instant;
|
||||
|
||||
use crate::events::OnModeSwitch;
|
||||
@ -47,32 +49,53 @@ pub(super) fn register_hooks(handlers: &Handlers) {
|
||||
|
||||
send_blocking(
|
||||
&tx,
|
||||
PullDiagnosticsEvent {
|
||||
PullDiagnosticsForLanguageServersEvent {
|
||||
language_server_ids,
|
||||
},
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
const TIMEOUT: u64 = 120;
|
||||
let tx = handlers.pull_diagnostics_document.clone();
|
||||
register_hook!(move |event: &mut DocumentDidOpen| {
|
||||
send_blocking(
|
||||
&tx,
|
||||
PullDiagnosticsForDocumentsEvent {
|
||||
document_id: event.doc,
|
||||
},
|
||||
);
|
||||
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct PullDiagnosticsHandler {
|
||||
language_server_ids: Vec<LanguageServerId>,
|
||||
language_server_ids: HashSet<LanguageServerId>,
|
||||
}
|
||||
|
||||
impl PullDiagnosticsHandler {
|
||||
pub fn new() -> PullDiagnosticsHandler {
|
||||
PullDiagnosticsHandler {
|
||||
language_server_ids: vec![],
|
||||
language_server_ids: [].into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub(super) struct PullDiagnosticsForDocumentsHandler {
|
||||
document_ids: HashSet<DocumentId>,
|
||||
}
|
||||
|
||||
impl PullDiagnosticsForDocumentsHandler {
|
||||
pub fn new() -> PullDiagnosticsForDocumentsHandler {
|
||||
PullDiagnosticsForDocumentsHandler {
|
||||
document_ids: [].into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl helix_event::AsyncHook for PullDiagnosticsHandler {
|
||||
type Event = PullDiagnosticsEvent;
|
||||
type Event = PullDiagnosticsForLanguageServersEvent;
|
||||
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
@ -80,27 +103,96 @@ fn handle_event(
|
||||
_: Option<tokio::time::Instant>,
|
||||
) -> Option<tokio::time::Instant> {
|
||||
self.language_server_ids = event.language_server_ids;
|
||||
Some(Instant::now() + Duration::from_millis(TIMEOUT))
|
||||
Some(Instant::now() + Duration::from_millis(120))
|
||||
}
|
||||
|
||||
fn finish_debounce(&mut self) {
|
||||
let language_servers = self.language_server_ids.clone();
|
||||
job::dispatch_blocking(move |editor, _| {
|
||||
pull_diagnostic_for_document(
|
||||
editor,
|
||||
language_servers,
|
||||
editor.documents().map(|x| x.id()).collect(),
|
||||
)
|
||||
pull_diagnostic_for_language_servers(editor, language_servers)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn pull_diagnostic_for_document(
|
||||
impl helix_event::AsyncHook for PullDiagnosticsForDocumentsHandler {
|
||||
type Event = PullDiagnosticsForDocumentsEvent;
|
||||
|
||||
fn handle_event(
|
||||
&mut self,
|
||||
event: Self::Event,
|
||||
_: Option<tokio::time::Instant>,
|
||||
) -> Option<tokio::time::Instant> {
|
||||
self.document_ids.insert(event.document_id);
|
||||
|
||||
Some(Instant::now() + Duration::from_millis(50))
|
||||
}
|
||||
|
||||
fn finish_debounce(&mut self) {
|
||||
let document_ids = self.document_ids.clone();
|
||||
job::dispatch_blocking(move |editor, _| {
|
||||
pull_diagnostics_for_documents(editor, document_ids)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn pull_diagnostics_for_documents(editor: &mut Editor, document_ids: HashSet<DocumentId>) {
|
||||
for document_id in document_ids {
|
||||
let doc = doc_mut!(editor, &document_id);
|
||||
|
||||
let language_servers =
|
||||
doc.language_servers_with_feature(LanguageServerFeature::PullDiagnostics);
|
||||
|
||||
for language_server in language_servers {
|
||||
let Some(future) = language_server
|
||||
.text_document_diagnostic(doc.identifier(), doc.previous_diagnostic_id.clone())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(uri) = doc.uri() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let server_id = language_server.id();
|
||||
|
||||
tokio::spawn(async move {
|
||||
match future.await {
|
||||
Ok(res) => {
|
||||
job::dispatch(move |editor, _| {
|
||||
let parsed_response: Option<lsp::DocumentDiagnosticReport> =
|
||||
match serde_json::from_value(res) {
|
||||
Ok(result) => Some(result),
|
||||
Err(_) => None,
|
||||
};
|
||||
|
||||
let Some(response) = parsed_response else {
|
||||
return;
|
||||
};
|
||||
|
||||
handle_pull_diagnostics_response(
|
||||
editor,
|
||||
response,
|
||||
server_id,
|
||||
uri,
|
||||
&document_id,
|
||||
)
|
||||
})
|
||||
.await
|
||||
}
|
||||
Err(err) => log::error!("Pull diagnostic request failed: {err}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pull_diagnostic_for_language_servers(
|
||||
editor: &mut Editor,
|
||||
language_server_ids: Vec<LanguageServerId>,
|
||||
document_ids: Vec<helix_view::DocumentId>,
|
||||
language_server_ids: HashSet<LanguageServerId>,
|
||||
) {
|
||||
for document_id in document_ids.clone() {
|
||||
let document_ids: Vec<_> = editor.documents().map(|x| x.id()).collect();
|
||||
|
||||
for document_id in document_ids {
|
||||
let doc = doc_mut!(editor, &document_id);
|
||||
let language_servers = doc
|
||||
.language_servers()
|
||||
@ -123,8 +215,6 @@ fn pull_diagnostic_for_document(
|
||||
match future.await {
|
||||
Ok(res) => {
|
||||
job::dispatch(move |editor, _| {
|
||||
log::error!("{}", res);
|
||||
|
||||
let parsed_response: Option<lsp::DocumentDiagnosticReport> =
|
||||
match serde_json::from_value(res) {
|
||||
Ok(result) => Some(result),
|
||||
@ -135,18 +225,24 @@ fn pull_diagnostic_for_document(
|
||||
return;
|
||||
};
|
||||
|
||||
show_pull_diagnostics(editor, response, server_id, uri, &document_id)
|
||||
handle_pull_diagnostics_response(
|
||||
editor,
|
||||
response,
|
||||
server_id,
|
||||
uri,
|
||||
&document_id,
|
||||
)
|
||||
})
|
||||
.await
|
||||
}
|
||||
Err(err) => log::error!("signature help request failed: {err}"),
|
||||
Err(err) => log::error!("Pull diagnostic request failed: {err}"),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn show_pull_diagnostics(
|
||||
fn handle_pull_diagnostics_response(
|
||||
editor: &mut Editor,
|
||||
response: lsp::DocumentDiagnosticReport,
|
||||
server_id: LanguageServerId,
|
||||
@ -157,7 +253,7 @@ fn show_pull_diagnostics(
|
||||
match response {
|
||||
lsp::DocumentDiagnosticReport::Full(report) => {
|
||||
// Original file diagnostic
|
||||
parse_diagnostic(
|
||||
add_diagnostic(
|
||||
editor,
|
||||
uri,
|
||||
report.full_document_diagnostic_report.items,
|
||||
@ -187,7 +283,7 @@ fn show_pull_diagnostics(
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_diagnostic(
|
||||
fn add_diagnostic(
|
||||
editor: &mut Editor,
|
||||
uri: Uri,
|
||||
report: Vec<lsp::Diagnostic>,
|
||||
@ -213,7 +309,7 @@ fn handle_document_diagnostic_report_kind(
|
||||
return;
|
||||
};
|
||||
|
||||
parse_diagnostic(editor, uri, report.items, report.result_id, server_id);
|
||||
add_diagnostic(editor, uri, report.items, report.result_id, server_id);
|
||||
}
|
||||
lsp::DocumentDiagnosticReportKind::Unchanged(report) => {
|
||||
let doc = doc_mut!(editor, &document_id);
|
||||
|
@ -3,6 +3,7 @@
|
||||
document::{
|
||||
DocumentOpenError, DocumentSavedEventFuture, DocumentSavedEventResult, Mode, SavePoint,
|
||||
},
|
||||
events::DocumentDidOpen,
|
||||
graphics::{CursorKind, Rect},
|
||||
handlers::Handlers,
|
||||
info::Info,
|
||||
@ -1717,6 +1718,8 @@ pub fn open(&mut self, path: &Path, action: Action) -> Result<DocumentId, Docume
|
||||
let id = self.new_document(doc);
|
||||
self.launch_language_servers(id);
|
||||
|
||||
helix_event::dispatch(DocumentDidOpen { doc: id });
|
||||
|
||||
id
|
||||
};
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
events! {
|
||||
DocumentDidChange<'a> { doc: &'a mut Document, view: ViewId, old_text: &'a Rope }
|
||||
DocumentDidOpen { doc: DocumentId}
|
||||
SelectionDidChange<'a> { doc: &'a mut Document, view: ViewId }
|
||||
DiagnosticsDidChange<'a> { editor: &'a mut Editor, doc: DocumentId }
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ pub struct Handlers {
|
||||
pub completions: Sender<lsp::CompletionEvent>,
|
||||
pub signature_hints: Sender<lsp::SignatureHelpEvent>,
|
||||
pub auto_save: Sender<AutoSaveEvent>,
|
||||
pub pull_diagnostics: Sender<lsp::PullDiagnosticsEvent>,
|
||||
pub pull_diagnostics: Sender<lsp::PullDiagnosticsForLanguageServersEvent>,
|
||||
pub pull_diagnostics_document: Sender<lsp::PullDiagnosticsForDocumentsEvent>,
|
||||
}
|
||||
|
||||
impl Handlers {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::editor::Action;
|
||||
@ -47,8 +48,12 @@ pub enum SignatureHelpEvent {
|
||||
RequestComplete { open: bool },
|
||||
}
|
||||
|
||||
pub struct PullDiagnosticsEvent {
|
||||
pub language_server_ids: Vec<helix_lsp::LanguageServerId>,
|
||||
pub struct PullDiagnosticsForLanguageServersEvent {
|
||||
pub language_server_ids: HashSet<helix_lsp::LanguageServerId>,
|
||||
}
|
||||
|
||||
pub struct PullDiagnosticsForDocumentsEvent {
|
||||
pub document_id: DocumentId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
Loading…
Reference in New Issue
Block a user