Prepare for omittiong parts of completion data that need to be resolved

This commit is contained in:
Kirill Bulatov 2024-09-22 20:10:15 +03:00
parent 00037c18ed
commit 2395a4e932
10 changed files with 99 additions and 16 deletions

View file

@ -7,7 +7,7 @@
use hir::ImportPathConfig; use hir::ImportPathConfig;
use ide_db::{imports::insert_use::InsertUseConfig, SnippetCap}; use ide_db::{imports::insert_use::InsertUseConfig, SnippetCap};
use crate::snippet::Snippet; use crate::{snippet::Snippet, CompletionFieldsToResolve};
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct CompletionConfig { pub struct CompletionConfig {
@ -27,6 +27,7 @@ pub struct CompletionConfig {
pub prefer_absolute: bool, pub prefer_absolute: bool,
pub snippets: Vec<Snippet>, pub snippets: Vec<Snippet>,
pub limit: Option<usize>, pub limit: Option<usize>,
pub fields_to_resolve: CompletionFieldsToResolve,
} }
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]

View file

@ -37,6 +37,35 @@ pub use crate::{
snippet::{Snippet, SnippetScope}, snippet::{Snippet, SnippetScope},
}; };
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CompletionFieldsToResolve {
pub resolve_label_details: bool,
pub resolve_tags: bool,
pub resolve_detail: bool,
pub resolve_documentation: bool,
pub resolve_sort_text: bool,
pub resolve_filter_text: bool,
pub resolve_text_edit: bool,
// FIXME: those are always resolved
// pub resolve_additional_text_edits: bool,
pub resolve_command: bool,
}
impl CompletionFieldsToResolve {
pub const fn empty() -> Self {
Self {
resolve_label_details: false,
resolve_tags: false,
resolve_detail: false,
resolve_documentation: false,
resolve_sort_text: false,
resolve_filter_text: false,
resolve_text_edit: false,
resolve_command: false,
}
}
}
//FIXME: split the following feature into fine-grained features. //FIXME: split the following feature into fine-grained features.
// Feature: Magic Completions // Feature: Magic Completions

View file

@ -37,8 +37,8 @@ use test_fixture::ChangeFixture;
use test_utils::assert_eq_text; use test_utils::assert_eq_text;
use crate::{ use crate::{
resolve_completion_edits, CallableSnippets, CompletionConfig, CompletionItem, resolve_completion_edits, CallableSnippets, CompletionConfig, CompletionFieldsToResolve,
CompletionItemKind, CompletionItem, CompletionItemKind,
}; };
/// Lots of basic item definitions /// Lots of basic item definitions
@ -84,6 +84,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
prefer_absolute: false, prefer_absolute: false,
snippets: Vec::new(), snippets: Vec::new(),
limit: None, limit: None,
fields_to_resolve: CompletionFieldsToResolve::empty(),
}; };
pub(crate) fn completion_list(ra_fixture: &str) -> String { pub(crate) fn completion_list(ra_fixture: &str) -> String {

View file

@ -119,8 +119,8 @@ pub use ide_assists::{
Assist, AssistConfig, AssistId, AssistKind, AssistResolveStrategy, SingleResolve, Assist, AssistConfig, AssistId, AssistKind, AssistResolveStrategy, SingleResolve,
}; };
pub use ide_completion::{ pub use ide_completion::{
CallableSnippets, CompletionConfig, CompletionItem, CompletionItemKind, CompletionRelevance, CallableSnippets, CompletionConfig, CompletionFieldsToResolve, CompletionItem,
Snippet, SnippetScope, CompletionItemKind, CompletionRelevance, Snippet, SnippetScope,
}; };
pub use ide_db::{ pub use ide_db::{
base_db::{Cancelled, CrateGraph, CrateId, FileChange, SourceRoot, SourceRootId}, base_db::{Cancelled, CrateGraph, CrateId, FileChange, SourceRoot, SourceRootId},

View file

@ -12,10 +12,10 @@ use std::{
use cfg::{CfgAtom, CfgDiff}; use cfg::{CfgAtom, CfgDiff};
use hir::Symbol; use hir::Symbol;
use ide::{ use ide::{
AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode, AssistConfig, CallableSnippets, CompletionConfig, CompletionFieldsToResolve, DiagnosticsConfig,
GenericParameterHints, HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, ExprFillDefaultMode, GenericParameterHints, HighlightConfig, HighlightRelatedConfig,
InlayFieldsToResolve, InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve, InlayHintsConfig, JoinLinesConfig,
MemoryLayoutHoverRenderKind, Snippet, SnippetScope, SourceRootId, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, Snippet, SnippetScope, SourceRootId,
}; };
use ide_db::{ use ide_db::{
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind}, imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
@ -1391,6 +1391,7 @@ impl Config {
} }
pub fn completion(&self, source_root: Option<SourceRootId>) -> CompletionConfig { pub fn completion(&self, source_root: Option<SourceRootId>) -> CompletionConfig {
let client_capability_fields = self.completion_resolve_support_properties();
CompletionConfig { CompletionConfig {
enable_postfix_completions: self.completion_postfix_enable(source_root).to_owned(), enable_postfix_completions: self.completion_postfix_enable(source_root).to_owned(),
enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned() enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned()
@ -1415,6 +1416,16 @@ impl Config {
limit: self.completion_limit(source_root).to_owned(), limit: self.completion_limit(source_root).to_owned(),
enable_term_search: self.completion_termSearch_enable(source_root).to_owned(), enable_term_search: self.completion_termSearch_enable(source_root).to_owned(),
term_search_fuel: self.completion_termSearch_fuel(source_root).to_owned() as u64, term_search_fuel: self.completion_termSearch_fuel(source_root).to_owned() as u64,
fields_to_resolve: CompletionFieldsToResolve {
resolve_label_details: client_capability_fields.contains("labelDetails"),
resolve_tags: client_capability_fields.contains("tags"),
resolve_detail: client_capability_fields.contains("detail"),
resolve_documentation: client_capability_fields.contains("documentation"),
resolve_sort_text: client_capability_fields.contains("sortText"),
resolve_filter_text: client_capability_fields.contains("filterText"),
resolve_text_edit: client_capability_fields.contains("textEdit"),
resolve_command: client_capability_fields.contains("command"),
},
} }
} }

View file

@ -1019,9 +1019,11 @@ pub(crate) fn handle_completion(
let items = to_proto::completion_items( let items = to_proto::completion_items(
&snap.config, &snap.config,
&completion_config.fields_to_resolve,
&line_index, &line_index,
snap.file_version(position.file_id), snap.file_version(position.file_id),
text_document_position, text_document_position,
completion_trigger_character,
items, items,
); );

View file

@ -12,7 +12,8 @@
use hir::ChangeWithProcMacros; use hir::ChangeWithProcMacros;
use ide::{ use ide::{
AnalysisHost, CallableSnippets, CompletionConfig, DiagnosticsConfig, FilePosition, TextSize, AnalysisHost, CallableSnippets, CompletionConfig, CompletionFieldsToResolve, DiagnosticsConfig,
FilePosition, TextSize,
}; };
use ide_db::{ use ide_db::{
imports::insert_use::{ImportGranularity, InsertUseConfig}, imports::insert_use::{ImportGranularity, InsertUseConfig},
@ -168,6 +169,7 @@ fn integrated_completion_benchmark() {
snippets: Vec::new(), snippets: Vec::new(),
limit: None, limit: None,
add_semicolon_to_unit: true, add_semicolon_to_unit: true,
fields_to_resolve: CompletionFieldsToResolve::empty(),
}; };
let position = let position =
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@ -215,6 +217,7 @@ fn integrated_completion_benchmark() {
snippets: Vec::new(), snippets: Vec::new(),
limit: None, limit: None,
add_semicolon_to_unit: true, add_semicolon_to_unit: true,
fields_to_resolve: CompletionFieldsToResolve::empty(),
}; };
let position = let position =
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@ -260,6 +263,7 @@ fn integrated_completion_benchmark() {
snippets: Vec::new(), snippets: Vec::new(),
limit: None, limit: None,
add_semicolon_to_unit: true, add_semicolon_to_unit: true,
fields_to_resolve: CompletionFieldsToResolve::empty(),
}; };
let position = let position =
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };

View file

@ -458,7 +458,21 @@ impl ClientCapabilities {
.into_iter() .into_iter()
.flatten() .flatten()
.cloned() .cloned()
.collect::<FxHashSet<_>>() .collect()
}
pub fn completion_resolve_support_properties(&self) -> FxHashSet<String> {
self.0
.text_document
.as_ref()
.and_then(|text| text.completion.as_ref())
.and_then(|completion_caps| completion_caps.completion_item.as_ref())
.and_then(|completion_item_caps| completion_item_caps.resolve_support.as_ref())
.map(|resolve_support| resolve_support.properties.iter())
.into_iter()
.flatten()
.cloned()
.collect()
} }
pub fn hover_markdown_support(&self) -> bool { pub fn hover_markdown_support(&self) -> bool {

View file

@ -825,6 +825,7 @@ pub struct CompletionResolveData {
pub position: lsp_types::TextDocumentPositionParams, pub position: lsp_types::TextDocumentPositionParams,
pub imports: Vec<CompletionImport>, pub imports: Vec<CompletionImport>,
pub version: Option<i32>, pub version: Option<i32>,
pub completion_trigger_character: Option<char>,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]

View file

@ -6,9 +6,9 @@ use std::{
}; };
use ide::{ use ide::{
Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionItem, Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionFieldsToResolve,
CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit, CompletionItem, CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange,
Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel, FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel,
InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup,
NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp, NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize, SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
@ -227,9 +227,11 @@ pub(crate) fn snippet_text_edit_vec(
pub(crate) fn completion_items( pub(crate) fn completion_items(
config: &Config, config: &Config,
fields_to_resolve: &CompletionFieldsToResolve,
line_index: &LineIndex, line_index: &LineIndex,
version: Option<i32>, version: Option<i32>,
tdpp: lsp_types::TextDocumentPositionParams, tdpp: lsp_types::TextDocumentPositionParams,
completion_trigger_character: Option<char>,
mut items: Vec<CompletionItem>, mut items: Vec<CompletionItem>,
) -> Vec<lsp_types::CompletionItem> { ) -> Vec<lsp_types::CompletionItem> {
if config.completion_hide_deprecated() { if config.completion_hide_deprecated() {
@ -239,7 +241,17 @@ pub(crate) fn completion_items(
let max_relevance = items.iter().map(|it| it.relevance.score()).max().unwrap_or_default(); let max_relevance = items.iter().map(|it| it.relevance.score()).max().unwrap_or_default();
let mut res = Vec::with_capacity(items.len()); let mut res = Vec::with_capacity(items.len());
for item in items { for item in items {
completion_item(&mut res, config, line_index, version, &tdpp, max_relevance, item); completion_item(
&mut res,
config,
fields_to_resolve,
line_index,
version,
&tdpp,
max_relevance,
completion_trigger_character,
item,
);
} }
if let Some(limit) = config.completion(None).limit { if let Some(limit) = config.completion(None).limit {
@ -253,10 +265,12 @@ pub(crate) fn completion_items(
fn completion_item( fn completion_item(
acc: &mut Vec<lsp_types::CompletionItem>, acc: &mut Vec<lsp_types::CompletionItem>,
config: &Config, config: &Config,
fields_to_resolve: &CompletionFieldsToResolve,
line_index: &LineIndex, line_index: &LineIndex,
version: Option<i32>, version: Option<i32>,
tdpp: &lsp_types::TextDocumentPositionParams, tdpp: &lsp_types::TextDocumentPositionParams,
max_relevance: u32, max_relevance: u32,
completion_trigger_character: Option<char>,
item: CompletionItem, item: CompletionItem,
) { ) {
let insert_replace_support = config.insert_replace_support().then_some(tdpp.position); let insert_replace_support = config.insert_replace_support().then_some(tdpp.position);
@ -264,6 +278,7 @@ fn completion_item(
let lookup = item.lookup().to_owned(); let lookup = item.lookup().to_owned();
let mut additional_text_edits = Vec::new(); let mut additional_text_edits = Vec::new();
let mut something_to_resolve = false;
// LSP does not allow arbitrary edits in completion, so we have to do a // LSP does not allow arbitrary edits in completion, so we have to do a
// non-trivial mapping here. // non-trivial mapping here.
@ -337,7 +352,12 @@ fn completion_item(
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if !imports.is_empty() { if !imports.is_empty() {
let data = lsp_ext::CompletionResolveData { position: tdpp.clone(), imports, version }; let data = lsp_ext::CompletionResolveData {
position: tdpp.clone(),
imports,
version,
completion_trigger_character,
};
lsp_item.data = Some(to_value(data).unwrap()); lsp_item.data = Some(to_value(data).unwrap());
} }
} }