Eagerly attempt to resolve missing completion documentation
This commit is contained in:
parent
d23bb3b05d
commit
c4fc9f7ed8
1 changed files with 191 additions and 73 deletions
|
@ -25,7 +25,7 @@ use ::git::diff::DiffHunk;
|
||||||
use aho_corasick::AhoCorasick;
|
use aho_corasick::AhoCorasick;
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use blink_manager::BlinkManager;
|
use blink_manager::BlinkManager;
|
||||||
use client::{ClickhouseEvent, Collaborator, ParticipantIndex, TelemetrySettings};
|
use client::{ClickhouseEvent, Client, Collaborator, ParticipantIndex, TelemetrySettings};
|
||||||
use clock::{Global, ReplicaId};
|
use clock::{Global, ReplicaId};
|
||||||
use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
|
use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
|
@ -62,8 +62,8 @@ use language::{
|
||||||
language_settings::{self, all_language_settings, InlayHintSettings},
|
language_settings::{self, all_language_settings, InlayHintSettings},
|
||||||
markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel,
|
markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel,
|
||||||
Completion, CursorShape, Diagnostic, DiagnosticSeverity, Documentation, File, IndentKind,
|
Completion, CursorShape, Diagnostic, DiagnosticSeverity, Documentation, File, IndentKind,
|
||||||
IndentSize, Language, LanguageServerName, OffsetRangeExt, OffsetUtf16, Point, Selection,
|
IndentSize, Language, LanguageRegistry, LanguageServerName, OffsetRangeExt, OffsetUtf16, Point,
|
||||||
SelectionGoal, TransactionId,
|
Selection, SelectionGoal, TransactionId,
|
||||||
};
|
};
|
||||||
use link_go_to_definition::{
|
use link_go_to_definition::{
|
||||||
hide_link_definition, show_link_definition, GoToDefinitionLink, InlayHighlight,
|
hide_link_definition, show_link_definition, GoToDefinitionLink, InlayHighlight,
|
||||||
|
@ -954,7 +954,7 @@ impl CompletionsMenu {
|
||||||
) {
|
) {
|
||||||
self.selected_item = 0;
|
self.selected_item = 0;
|
||||||
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
|
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
|
||||||
self.attempt_resolve_selected_completion(project, cx);
|
self.attempt_resolve_selected_completion_documentation(project, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -967,7 +967,7 @@ impl CompletionsMenu {
|
||||||
self.selected_item -= 1;
|
self.selected_item -= 1;
|
||||||
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
|
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
|
||||||
}
|
}
|
||||||
self.attempt_resolve_selected_completion(project, cx);
|
self.attempt_resolve_selected_completion_documentation(project, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,7 +980,7 @@ impl CompletionsMenu {
|
||||||
self.selected_item += 1;
|
self.selected_item += 1;
|
||||||
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
|
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
|
||||||
}
|
}
|
||||||
self.attempt_resolve_selected_completion(project, cx);
|
self.attempt_resolve_selected_completion_documentation(project, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,16 +991,99 @@ impl CompletionsMenu {
|
||||||
) {
|
) {
|
||||||
self.selected_item = self.matches.len() - 1;
|
self.selected_item = self.matches.len() - 1;
|
||||||
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
|
self.list.scroll_to(ScrollTarget::Show(self.selected_item));
|
||||||
self.attempt_resolve_selected_completion(project, cx);
|
self.attempt_resolve_selected_completion_documentation(project, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attempt_resolve_selected_completion(
|
fn pre_resolve_completion_documentation(
|
||||||
|
&self,
|
||||||
|
project: Option<ModelHandle<Project>>,
|
||||||
|
cx: &mut ViewContext<Editor>,
|
||||||
|
) {
|
||||||
|
let Some(project) = project else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let client = project.read(cx).client();
|
||||||
|
let language_registry = project.read(cx).languages().clone();
|
||||||
|
|
||||||
|
let is_remote = project.read(cx).is_remote();
|
||||||
|
let project_id = project.read(cx).remote_id();
|
||||||
|
|
||||||
|
let completions = self.completions.clone();
|
||||||
|
let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
|
||||||
|
|
||||||
|
cx.spawn(move |this, mut cx| async move {
|
||||||
|
if is_remote {
|
||||||
|
let Some(project_id) = project_id else {
|
||||||
|
log::error!("Remote project without remote_id");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
for completion_index in completion_indices {
|
||||||
|
let completions_guard = completions.read();
|
||||||
|
let completion = &completions_guard[completion_index];
|
||||||
|
if completion.documentation.is_some() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let server_id = completion.server_id;
|
||||||
|
let completion = completion.lsp_completion.clone();
|
||||||
|
drop(completions_guard);
|
||||||
|
|
||||||
|
Self::resolve_completion_documentation_remote(
|
||||||
|
project_id,
|
||||||
|
server_id,
|
||||||
|
completions.clone(),
|
||||||
|
completion_index,
|
||||||
|
completion,
|
||||||
|
client.clone(),
|
||||||
|
language_registry.clone(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
_ = this.update(&mut cx, |_, cx| cx.notify());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for completion_index in completion_indices {
|
||||||
|
let completions_guard = completions.read();
|
||||||
|
let completion = &completions_guard[completion_index];
|
||||||
|
if completion.documentation.is_some() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let server_id = completion.server_id;
|
||||||
|
let completion = completion.lsp_completion.clone();
|
||||||
|
drop(completions_guard);
|
||||||
|
|
||||||
|
let server = project.read_with(&mut cx, |project, _| {
|
||||||
|
project.language_server_for_id(server_id)
|
||||||
|
});
|
||||||
|
let Some(server) = server else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::resolve_completion_documentation_local(
|
||||||
|
server,
|
||||||
|
completions.clone(),
|
||||||
|
completion_index,
|
||||||
|
completion,
|
||||||
|
language_registry.clone(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
_ = this.update(&mut cx, |_, cx| cx.notify());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn attempt_resolve_selected_completion_documentation(
|
||||||
&mut self,
|
&mut self,
|
||||||
project: Option<&ModelHandle<Project>>,
|
project: Option<&ModelHandle<Project>>,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) {
|
) {
|
||||||
let index = self.matches[self.selected_item].candidate_id;
|
let completion_index = self.matches[self.selected_item].candidate_id;
|
||||||
let Some(project) = project else {
|
let Some(project) = project else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -1008,7 +1091,7 @@ impl CompletionsMenu {
|
||||||
|
|
||||||
let completions = self.completions.clone();
|
let completions = self.completions.clone();
|
||||||
let completions_guard = completions.read();
|
let completions_guard = completions.read();
|
||||||
let completion = &completions_guard[index];
|
let completion = &completions_guard[completion_index];
|
||||||
if completion.documentation.is_some() {
|
if completion.documentation.is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1024,13 +1107,58 @@ impl CompletionsMenu {
|
||||||
};
|
};
|
||||||
|
|
||||||
let client = project.read(cx).client();
|
let client = project.read(cx).client();
|
||||||
|
|
||||||
|
cx.spawn(move |this, mut cx| async move {
|
||||||
|
Self::resolve_completion_documentation_remote(
|
||||||
|
project_id,
|
||||||
|
server_id,
|
||||||
|
completions.clone(),
|
||||||
|
completion_index,
|
||||||
|
completion,
|
||||||
|
client,
|
||||||
|
language_registry.clone(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
_ = this.update(&mut cx, |_, cx| cx.notify());
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
} else {
|
||||||
|
let Some(server) = project.read(cx).language_server_for_id(server_id) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
cx.spawn(move |this, mut cx| async move {
|
||||||
|
Self::resolve_completion_documentation_local(
|
||||||
|
server,
|
||||||
|
completions,
|
||||||
|
completion_index,
|
||||||
|
completion,
|
||||||
|
language_registry,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
_ = this.update(&mut cx, |_, cx| cx.notify());
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn resolve_completion_documentation_remote(
|
||||||
|
project_id: u64,
|
||||||
|
server_id: LanguageServerId,
|
||||||
|
completions: Arc<RwLock<Box<[Completion]>>>,
|
||||||
|
completion_index: usize,
|
||||||
|
completion: lsp::CompletionItem,
|
||||||
|
client: Arc<Client>,
|
||||||
|
language_registry: Arc<LanguageRegistry>,
|
||||||
|
) {
|
||||||
let request = proto::ResolveCompletionDocumentation {
|
let request = proto::ResolveCompletionDocumentation {
|
||||||
project_id,
|
project_id,
|
||||||
language_server_id: server_id.0 as u64,
|
language_server_id: server_id.0 as u64,
|
||||||
lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
|
lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.spawn(|this, mut cx| async move {
|
|
||||||
let Some(response) = client
|
let Some(response) = client
|
||||||
.request(request)
|
.request(request)
|
||||||
.await
|
.await
|
||||||
|
@ -1042,7 +1170,7 @@ impl CompletionsMenu {
|
||||||
|
|
||||||
if response.text.is_empty() {
|
if response.text.is_empty() {
|
||||||
let mut completions = completions.write();
|
let mut completions = completions.write();
|
||||||
let completion = &mut completions[index];
|
let completion = &mut completions[completion_index];
|
||||||
completion.documentation = Some(Documentation::Undocumented);
|
completion.documentation = Some(Documentation::Undocumented);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1057,21 +1185,17 @@ impl CompletionsMenu {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut completions = completions.write();
|
let mut completions = completions.write();
|
||||||
let completion = &mut completions[index];
|
let completion = &mut completions[completion_index];
|
||||||
completion.documentation = Some(documentation);
|
completion.documentation = Some(documentation);
|
||||||
drop(completions);
|
|
||||||
|
|
||||||
_ = this.update(&mut cx, |_, cx| cx.notify());
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(server) = project.read(cx).language_server_for_id(server_id) else {
|
async fn resolve_completion_documentation_local(
|
||||||
return;
|
server: Arc<lsp::LanguageServer>,
|
||||||
};
|
completions: Arc<RwLock<Box<[Completion]>>>,
|
||||||
|
completion_index: usize,
|
||||||
|
completion: lsp::CompletionItem,
|
||||||
|
language_registry: Arc<LanguageRegistry>,
|
||||||
|
) {
|
||||||
let can_resolve = server
|
let can_resolve = server
|
||||||
.capabilities()
|
.capabilities()
|
||||||
.completion_provider
|
.completion_provider
|
||||||
|
@ -1082,7 +1206,6 @@ impl CompletionsMenu {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.spawn(|this, mut cx| async move {
|
|
||||||
let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
|
let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
|
||||||
let Some(completion_item) = request.await.log_err() else {
|
let Some(completion_item) = request.await.log_err() else {
|
||||||
return;
|
return;
|
||||||
|
@ -1097,18 +1220,13 @@ impl CompletionsMenu {
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let mut completions = completions.write();
|
let mut completions = completions.write();
|
||||||
let completion = &mut completions[index];
|
let completion = &mut completions[completion_index];
|
||||||
completion.documentation = Some(documentation);
|
completion.documentation = Some(documentation);
|
||||||
drop(completions);
|
|
||||||
|
|
||||||
_ = this.update(&mut cx, |_, cx| cx.notify());
|
|
||||||
} else {
|
} else {
|
||||||
let mut completions = completions.write();
|
let mut completions = completions.write();
|
||||||
let completion = &mut completions[index];
|
let completion = &mut completions[completion_index];
|
||||||
completion.documentation = Some(Documentation::Undocumented);
|
completion.documentation = Some(Documentation::Undocumented);
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visible(&self) -> bool {
|
fn visible(&self) -> bool {
|
||||||
|
@ -3450,7 +3568,7 @@ impl Editor {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
_ = this.update(&mut cx, |editor, cx| {
|
_ = this.update(&mut cx, |editor, cx| {
|
||||||
menu.attempt_resolve_selected_completion(editor.project.as_ref(), cx);
|
menu.pre_resolve_completion_documentation(editor.project.clone(), cx);
|
||||||
});
|
});
|
||||||
Some(menu)
|
Some(menu)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue