Skip to content

Commit

Permalink
lsp: store and use previous result of document diagnostics
Browse files Browse the repository at this point in the history
  • Loading branch information
vitallium committed Oct 17, 2024
1 parent 7dfbe51 commit 3ab5b2c
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 28 deletions.
8 changes: 0 additions & 8 deletions crates/language/src/language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ pub struct CachedLspAdapter {
pub name: LanguageServerName,
pub disk_based_diagnostic_sources: Vec<String>,
pub disk_based_diagnostics_progress_token: Option<String>,
pub previous_document_diagnostic_result_id: Option<String>,
language_ids: HashMap<String, String>,
pub adapter: Arc<dyn LspAdapter>,
pub reinstall_attempt_count: AtomicU64,
Expand Down Expand Up @@ -232,14 +231,11 @@ impl CachedLspAdapter {
let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources();
let disk_based_diagnostics_progress_token = adapter.disk_based_diagnostics_progress_token();
let language_ids = adapter.language_ids();
let previous_document_diagnostic_result_id =
adapter.previous_document_diagnostic_result_id();

Arc::new(CachedLspAdapter {
name,
disk_based_diagnostic_sources,
disk_based_diagnostics_progress_token,
previous_document_diagnostic_result_id,
language_ids,
adapter,
cached_binary: Default::default(),
Expand Down Expand Up @@ -533,10 +529,6 @@ pub trait LspAdapter: 'static + Send + Sync {
fn language_ids(&self) -> HashMap<String, String> {
Default::default()
}

fn previous_document_diagnostic_result_id(&self) -> Option<String> {
None
}
}

async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>(
Expand Down
74 changes: 56 additions & 18 deletions crates/project/src/lsp_command.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
mod signature_help;

use crate::{
lsp_store::LspStore, CodeAction, CoreCompletion, DocumentHighlight, Hover, HoverBlock,
HoverBlockKind, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayHintLabelPartTooltip,
InlayHintTooltip, Location, LocationLink, MarkupContent, ProjectTransaction, ResolveState,
lsp_store::{LanguageServerState, LspStore},
CodeAction, CoreCompletion, DocumentHighlight, Hover, HoverBlock, HoverBlockKind, InlayHint,
InlayHintLabel, InlayHintLabelPart, InlayHintLabelPartTooltip, InlayHintTooltip, Location,
LocationLink, MarkupContent, ProjectTransaction, ResolveState,
};
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
Expand Down Expand Up @@ -183,7 +184,8 @@ pub(crate) struct LinkedEditingRange {

#[derive(Debug)]
pub(crate) struct GetDocumentDiagnostics {
// pub previous_result_id: Option<String>,
pub language_server_id: LanguageServerId,
pub previous_result_id: Option<String>,
}

#[async_trait(?Send)]
Expand Down Expand Up @@ -3059,7 +3061,7 @@ impl LspCommand for GetDocumentDiagnostics {
uri: lsp::Url::from_file_path(path).unwrap(),
},
identifier,
previous_result_id: None,
previous_result_id: self.previous_result_id.clone(),
partial_result_params: Default::default(),
work_done_progress_params: Default::default(),
}
Expand All @@ -3068,24 +3070,36 @@ impl LspCommand for GetDocumentDiagnostics {
async fn response_from_lsp(
self,
message: lsp::DocumentDiagnosticReportResult,
_: Model<LspStore>,
lsp_store: Model<LspStore>,
_: Model<Buffer>,
_server_id: LanguageServerId,
_: AsyncAppContext,
language_server_id: LanguageServerId,
mut cx: AsyncAppContext,
) -> Result<Vec<Diagnostic>> {
match message {
lsp::DocumentDiagnosticReportResult::Report(report) => match report {
lsp::DocumentDiagnosticReport::Full(report) => {
// TODO: Handle related_documents in the report
// TODO: Store the result in the adapter?
let previous_result_id =
report.full_document_diagnostic_report.result_id.clone();
lsp_store.update(&mut cx, |store, _| {
if let Some(LanguageServerState::Running {
previous_document_diagnostic_result_id,
..
}) = store.as_local_mut().and_then(|local_store| {
local_store.language_servers.get_mut(&language_server_id)
}) {
*previous_document_diagnostic_result_id = previous_result_id;
}
})?;

Ok(report.full_document_diagnostic_report.items.clone())
}
lsp::DocumentDiagnosticReport::Unchanged(_) => {
panic!("unexpected unchanged report");
todo!("Not implemented yet.")
}
},
lsp::DocumentDiagnosticReportResult::Partial(_) => {
panic!("unexpected partial report");
todo!("Not implemented yet.")
}
}
}
Expand All @@ -3094,18 +3108,42 @@ impl LspCommand for GetDocumentDiagnostics {
proto::GetDocumentDiagnostics {
project_id,
buffer_id: buffer.remote_id().into(),
language_server_id: self.language_server_id.to_proto(),
version: serialize_version(&buffer.version()),
}
}

async fn from_proto(
_: proto::GetDocumentDiagnostics,
_: Model<LspStore>,
_: Model<Buffer>,
_: AsyncAppContext,
message: proto::GetDocumentDiagnostics,
lsp_store: Model<LspStore>,
buffer: Model<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {
let language_server_id = LanguageServerId::from_proto(message.language_server_id);
let previous_result_id = lsp_store
.update(&mut cx, |lsp_store, _| {
match lsp_store
.as_local()
.and_then(|local_store| local_store.language_servers.get(&language_server_id))
{
Some(LanguageServerState::Running {
previous_document_diagnostic_result_id,
..
}) => previous_document_diagnostic_result_id.clone(),
_ => None,
}
})
.expect("Failed to retrieve previous_result_id");

buffer
.update(&mut cx, |buffer, _| {
buffer.wait_for_version(deserialize_version(&message.version))
})?
.await?;

Ok(Self {
// previous_result_id: None,
language_server_id,
previous_result_id,
})
}

Expand All @@ -3116,7 +3154,7 @@ impl LspCommand for GetDocumentDiagnostics {
_: &clock::Global,
_: &mut AppContext,
) -> proto::GetDocumentDiagnosticsResponse {
panic!()
todo!("Not implemented yet.")
// let diagnostics = response
// .into_iter()
// .map(|diagnostic| language::proto::serialize_diagnostics(diagnostic))
Expand All @@ -3131,7 +3169,7 @@ impl LspCommand for GetDocumentDiagnostics {
_: Model<Buffer>,
_: AsyncAppContext,
) -> Result<Vec<Diagnostic>> {
panic!()
todo!("Not implemented yet.")
// language::proto::deserialize_diagnostics(message.diagnostics)
}

Expand Down
15 changes: 14 additions & 1 deletion crates/project/src/lsp_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3044,10 +3044,21 @@ impl LspStore {

const PULL_DIAGNOSTICS_DEBOUNCE: Duration = Duration::from_millis(125);

let previous_result_id = match self.as_local()?.language_servers.get(&language_server_id) {
Some(LanguageServerState::Running {
previous_document_diagnostic_result_id,
..
}) => previous_document_diagnostic_result_id.clone(),
_ => None,
};

let lsp_request_task = self.request_lsp(
buffer_handle,
LanguageServerToQuery::Other(language_server_id),
GetDocumentDiagnostics {},
GetDocumentDiagnostics {
language_server_id,
previous_result_id,
},
cx,
);

Expand Down Expand Up @@ -6513,6 +6524,7 @@ impl LspStore {
language: language.clone(),
server: language_server.clone(),
simulate_disk_based_diagnostics_completion: None,
previous_document_diagnostic_result_id: None,
},
);
}
Expand Down Expand Up @@ -7513,6 +7525,7 @@ pub enum LanguageServerState {
adapter: Arc<CachedLspAdapter>,
server: Arc<LanguageServer>,
simulate_disk_based_diagnostics_completion: Option<Task<()>>,
previous_document_diagnostic_result_id: Option<String>,
},
}

Expand Down
3 changes: 2 additions & 1 deletion crates/proto/proto/zed.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2528,7 +2528,8 @@ message GetPermalinkToLineResponse {
message GetDocumentDiagnostics {
uint64 project_id = 1;
uint64 buffer_id = 2;
repeated VectorClockEntry version = 3;
uint64 language_server_id = 3;
repeated VectorClockEntry version = 4;
}

message GetDocumentDiagnosticsResponse {
Expand Down

0 comments on commit 3ab5b2c

Please sign in to comment.