Skip to content

Commit

Permalink
lsp: make LspDiagnostics response optional
Browse files Browse the repository at this point in the history
  • Loading branch information
vitallium committed Dec 14, 2024
1 parent 029a338 commit e7fe69e
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 144 deletions.
24 changes: 14 additions & 10 deletions crates/editor/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13285,11 +13285,11 @@ pub trait DiagnosticsProvider {
buffer: &Model<Buffer>,
position: text::Anchor,
cx: &mut AppContext,
) -> Task<Result<Vec<LspDiagnostics>>>;
) -> Task<Result<Vec<Option<LspDiagnostics>>>>;

fn update_diagnostics(
&self,
diagnostics: Vec<LspDiagnostics>,
diagnostics: Vec<Option<LspDiagnostics>>,
cx: &mut AppContext,
) -> Result<()>;
}
Expand Down Expand Up @@ -13634,31 +13634,35 @@ impl DiagnosticsProvider for Model<Project> {
buffer: &Model<Buffer>,
position: text::Anchor,
cx: &mut AppContext,
) -> Task<Result<Vec<LspDiagnostics>>> {
) -> Task<Result<Vec<Option<LspDiagnostics>>>> {
self.update(cx, |project, cx| {
project.document_diagnostics(buffer, position, cx)
})
}

fn update_diagnostics(
&self,
diagnostics: Vec<LspDiagnostics>,
diagnostics: Vec<Option<LspDiagnostics>>,
cx: &mut AppContext,
) -> Result<()> {
self.update(cx, |project, cx| {
diagnostics
.into_iter()
.map(|diagnostic_set| {
project.update_diagnostics(
.iter()
.filter_map(|diagnostic_set| match diagnostic_set {
Some(diagnostic_set) => Some(project.update_diagnostics(
diagnostic_set.server_id,
lsp::PublishDiagnosticsParams {
uri: diagnostic_set.uri.unwrap(),
diagnostics: diagnostic_set.diagnostics.unwrap_or_else(Vec::new),
uri: diagnostic_set.uri.as_ref().unwrap().clone(),
diagnostics: match diagnostic_set.diagnostics.as_ref() {
Some(diagnostics) => diagnostics.clone(),
None => Vec::new(),
},
version: None,
},
&[],
cx,
)
)),
None => None,
})
.collect()
})
Expand Down
4 changes: 2 additions & 2 deletions crates/language/src/proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operati
value: message.lamport_timestamp,
},
server_id: LanguageServerId(message.server_id as usize),
diagnostics: Arc::from(deserialize_diagnostics(message.diagnostics)),
diagnostics: deserialize_diagnostics(message.diagnostics),
}
}
proto::operation::Variant::UpdateCompletionTriggers(message) => {
Expand Down Expand Up @@ -397,7 +397,7 @@ pub fn deserialize_selection(selection: proto::Selection) -> Option<Selection<An
/// Deserializes a list of diagnostics from the RPC representation.
pub fn deserialize_diagnostics(
diagnostics: Vec<proto::Diagnostic>,
) -> Vec<DiagnosticEntry<Anchor>> {
) -> Arc<[DiagnosticEntry<Anchor>]> {
diagnostics
.into_iter()
.filter_map(|diagnostic| {
Expand Down
56 changes: 34 additions & 22 deletions crates/project/src/lsp_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
lsp_store::{LocalLspStore, LspStore},
CodeAction, CoreCompletion, DocumentHighlight, Hover, HoverBlock, HoverBlockKind, InlayHint,
InlayHintLabel, InlayHintLabelPart, InlayHintLabelPartTooltip, InlayHintTooltip, Location,
LocationLink, MarkupContent, ProjectTransaction, ResolveState,
LocationLink, LspDiagnostics, MarkupContent, ProjectTransaction, ResolveState,
};
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
Expand Down Expand Up @@ -3161,7 +3161,7 @@ impl GetDocumentDiagnostics {

#[async_trait(?Send)]
impl LspCommand for GetDocumentDiagnostics {
type Response = LspDiagnostics;
type Response = Option<LspDiagnostics>;
type LspRequest = lsp::request::DocumentDiagnosticRequest;
type ProtoRequest = proto::GetDocumentDiagnostics;

Expand Down Expand Up @@ -3211,24 +3211,28 @@ impl LspCommand for GetDocumentDiagnostics {
Some(lsp::Url::from_file_path(file.abs_path(cx).clone()).unwrap())
})?;

if uri.is_none() {
return Ok(None);
}

match message {
lsp::DocumentDiagnosticReportResult::Report(report) => match report {
lsp::DocumentDiagnosticReport::Full(report) => Ok(LspDiagnostics {
lsp::DocumentDiagnosticReport::Full(report) => Ok(Some(LspDiagnostics {
server_id,
uri,
diagnostics: Some(report.full_document_diagnostic_report.items.clone()),
}),
lsp::DocumentDiagnosticReport::Unchanged(_) => Ok(LspDiagnostics {
})),
lsp::DocumentDiagnosticReport::Unchanged(_) => Ok(Some(LspDiagnostics {
server_id,
uri,
diagnostics: None,
}),
})),
},
lsp::DocumentDiagnosticReportResult::Partial(_) => Ok(LspDiagnostics {
lsp::DocumentDiagnosticReportResult::Partial(_) => Ok(Some(LspDiagnostics {
server_id,
uri,
diagnostics: None,
}),
})),
}
}

Expand Down Expand Up @@ -3268,19 +3272,27 @@ impl LspCommand for GetDocumentDiagnostics {
_: &clock::Global,
_: &mut AppContext,
) -> proto::GetDocumentDiagnosticsResponse {
let diagnostics = if let Some(diagnostics) = response.diagnostics {
diagnostics
.into_iter()
.map(GetDocumentDiagnostics::serialize_lsp_diagnostic)
.collect()
} else {
Vec::new()
};
if let Some(response) = response {
let diagnostics = if let Some(diagnostics) = response.diagnostics {
diagnostics
.into_iter()
.map(GetDocumentDiagnostics::serialize_lsp_diagnostic)
.collect()
} else {
Vec::new()
};

proto::GetDocumentDiagnosticsResponse {
server_id: LanguageServerId::to_proto(response.server_id),
uri: response.uri.unwrap().to_string(),
diagnostics,
proto::GetDocumentDiagnosticsResponse {
server_id: LanguageServerId::to_proto(response.server_id),
uri: response.uri.unwrap().to_string(),
diagnostics,
}
} else {
proto::GetDocumentDiagnosticsResponse {
server_id: 0,
uri: Default::default(),
diagnostics: Vec::new(),
}
}
}

Expand All @@ -3297,11 +3309,11 @@ impl LspCommand for GetDocumentDiagnostics {
.map(GetDocumentDiagnostics::deserialize_lsp_diagnostic)
.collect();

Ok(LspDiagnostics {
Ok(Some(LspDiagnostics {
server_id: LanguageServerId::from_proto(response.server_id),
uri: Some(lsp::Url::from_str(response.uri.as_str()).unwrap()),
diagnostics: Some(diagnostics),
})
}))
}

fn buffer_id_from_proto(message: &proto::GetDocumentDiagnostics) -> Result<BufferId> {
Expand Down
151 changes: 42 additions & 109 deletions crates/project/src/lsp_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4484,7 +4484,7 @@ impl LspStore {
buffer_handle: &Model<Buffer>,
position: Anchor,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<LspDiagnostics>>> {
) -> Task<Result<Vec<Option<LspDiagnostics>>>> {
let buffer = buffer_handle.read(cx);
let buffer_id = buffer.remote_id();

Expand Down Expand Up @@ -4920,57 +4920,6 @@ impl LspStore {
}
}

fn pull_diagnostic(
&mut self,
language_server_id: LanguageServerId,
buffer_handle: Model<Buffer>,
cx: &mut ModelContext<Self>,
) -> Option<()> {
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.clone(),
LanguageServerToQuery::Other(language_server_id),
GetDocumentDiagnostics {
language_server_id,
previous_result_id,
},
cx,
);

let snapshot =
self.buffer_snapshot_for_lsp_version(&buffer_handle, language_server_id, None, cx);

cx.spawn(move |_, mut cx| async move {
let snapshot = snapshot?;

cx.background_executor()
.timer(PULL_DIAGNOSTICS_DEBOUNCE)
.await;

let diagnostics = lsp_request_task
.await
.context("Unable to pull document diagnostic")
.unwrap_or_default();

buffer_handle.update(&mut cx, |buffer, cx| {
let set = DiagnosticSet::from_sorted_entries(diagnostics, &snapshot);
buffer.update_diagnostics(language_server_id, set, cx);
})
})
.detach();

None
}

pub fn diagnostic_summary(&self, include_ignored: bool, cx: &AppContext) -> DiagnosticSummary {
let mut summary = DiagnosticSummary::default();
for (_, _, path_summary) in self.diagnostic_summaries(include_ignored, cx) {
Expand Down Expand Up @@ -5885,6 +5834,47 @@ impl LspStore {
.collect(),
})
}
Some(proto::multi_lsp_query::Request::GetDocumentDiagnostics(
get_document_diagnostics,
)) => {
let get_document_diagnostics = GetDocumentDiagnostics::from_proto(
get_document_diagnostics,
this.clone(),
buffer.clone(),
cx.clone(),
)
.await?;

let all_diagnostics = this
.update(&mut cx, |project, cx| {
project.request_multiple_lsp_locally(
&buffer,
Some(get_document_diagnostics.position),
get_document_diagnostics,
cx,
)
})?
.await
.into_iter();

this.update(&mut cx, |project, cx| proto::MultiLspQueryResponse {
responses: all_diagnostics
.map(|lsp_diagnostic| proto::LspResponse {
response: Some(
proto::lsp_response::Response::GetDocumentDiagnosticsResponse(
GetDocumentDiagnostics::response_to_proto(
lsp_diagnostic,
project,
sender_id,
&buffer_version,
cx,
),
),
),
})
.collect(),
})
}
None => anyhow::bail!("empty multi lsp query request"),
}
}
Expand Down Expand Up @@ -7305,63 +7295,6 @@ impl LspStore {
.detach();
}

fn pull_diagnostic(
&mut self,
language_server_id: LanguageServerId,
buffer_handle: Model<Buffer>,
cx: &mut ModelContext<Self>,
) -> Option<()> {
let buffer = buffer_handle.read(cx);
let file = File::from_dyn(buffer.file())?;
let abs_path = file.as_local()?.abs_path(cx);
let uri = lsp::Url::from_file_path(abs_path).log_err()?;

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 {
language_server_id,
previous_result_id,
},
cx,
);

cx.spawn(move |this, mut cx| async move {
cx.background_executor()
.timer(PULL_DIAGNOSTICS_DEBOUNCE)
.await;

let diagnostics = lsp_request_task.await;
this.update(&mut cx, |this, cx| {
this.update_diagnostics(
language_server_id,
lsp::PublishDiagnosticsParams {
uri: uri.clone(),
diagnostics: diagnostics.unwrap(),
version: None,
},
&[],
cx,
)
.log_err()
})
.ok();
})
.detach();

None
}

pub fn update_diagnostics(
&mut self,
language_server_id: LanguageServerId,
Expand Down
14 changes: 13 additions & 1 deletion crates/project/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3042,12 +3042,24 @@ impl Project {
buffer_handle: &Model<Buffer>,
position: Anchor,
cx: &mut ModelContext<Self>,
) -> Task<Result<Vec<LspDiagnostics>>> {
) -> Task<Result<Vec<Option<LspDiagnostics>>>> {
self.lsp_store.update(cx, |lsp_store, cx| {
lsp_store.document_diagnostic(buffer_handle, position, cx)
})
}

pub fn update_diagnostics(
&mut self,
language_server_id: LanguageServerId,
params: lsp::PublishDiagnosticsParams,
disk_based_sources: &[String],
cx: &mut ModelContext<Self>,
) -> Result<(), anyhow::Error> {
self.lsp_store.update(cx, |lsp_store, cx| {
lsp_store.update_diagnostics(language_server_id, params, disk_based_sources, cx)
})
}

pub fn search(
&mut self,
query: SearchQuery,
Expand Down

0 comments on commit e7fe69e

Please sign in to comment.