diff options
-rw-r--r-- | crates/completion/src/item.rs | 1 | ||||
-rw-r--r-- | crates/completion/src/test_utils.rs | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 11 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 142 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 70 |
5 files changed, 120 insertions, 105 deletions
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs index 0e59f73cb..dc67df075 100644 --- a/crates/completion/src/item.rs +++ b/crates/completion/src/item.rs | |||
@@ -12,6 +12,7 @@ use crate::config::SnippetCap; | |||
12 | /// `CompletionItem` describes a single completion variant in the editor pop-up. | 12 | /// `CompletionItem` describes a single completion variant in the editor pop-up. |
13 | /// It is basically a POD with various properties. To construct a | 13 | /// It is basically a POD with various properties. To construct a |
14 | /// `CompletionItem`, use `new` method and the `Builder` struct. | 14 | /// `CompletionItem`, use `new` method and the `Builder` struct. |
15 | #[derive(Clone)] | ||
15 | pub struct CompletionItem { | 16 | pub struct CompletionItem { |
16 | /// Used only internally in tests, to check only specific kind of | 17 | /// Used only internally in tests, to check only specific kind of |
17 | /// completion (postfix, keyword, reference, etc). | 18 | /// completion (postfix, keyword, reference, etc). |
diff --git a/crates/completion/src/test_utils.rs b/crates/completion/src/test_utils.rs index 4c1b1a839..516a63b4d 100644 --- a/crates/completion/src/test_utils.rs +++ b/crates/completion/src/test_utils.rs | |||
@@ -97,6 +97,7 @@ pub(crate) fn check_edit_with_config( | |||
97 | .unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions)); | 97 | .unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions)); |
98 | let mut actual = db.file_text(position.file_id).to_string(); | 98 | let mut actual = db.file_text(position.file_id).to_string(); |
99 | completion.text_edit().apply(&mut actual); | 99 | completion.text_edit().apply(&mut actual); |
100 | // TODO kb how to apply imports now? | ||
100 | assert_eq_text!(&ra_fixture_after, &actual) | 101 | assert_eq_text!(&ra_fixture_after, &actual) |
101 | } | 102 | } |
102 | 103 | ||
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index ba4bf2eeb..e12651937 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -7,7 +7,7 @@ use std::{sync::Arc, time::Instant}; | |||
7 | 7 | ||
8 | use crossbeam_channel::{unbounded, Receiver, Sender}; | 8 | use crossbeam_channel::{unbounded, Receiver, Sender}; |
9 | use flycheck::FlycheckHandle; | 9 | use flycheck::FlycheckHandle; |
10 | use ide::{Analysis, AnalysisHost, Change, FileId, ImportToAdd}; | 10 | use ide::{Analysis, AnalysisHost, Change, CompletionItem, FileId}; |
11 | use ide_db::base_db::{CrateId, VfsPath}; | 11 | use ide_db::base_db::{CrateId, VfsPath}; |
12 | use lsp_types::{SemanticTokens, Url}; | 12 | use lsp_types::{SemanticTokens, Url}; |
13 | use parking_lot::{Mutex, RwLock}; | 13 | use parking_lot::{Mutex, RwLock}; |
@@ -51,6 +51,11 @@ pub(crate) struct Handle<H, C> { | |||
51 | pub(crate) type ReqHandler = fn(&mut GlobalState, lsp_server::Response); | 51 | pub(crate) type ReqHandler = fn(&mut GlobalState, lsp_server::Response); |
52 | pub(crate) type ReqQueue = lsp_server::ReqQueue<(String, Instant), ReqHandler>; | 52 | pub(crate) type ReqQueue = lsp_server::ReqQueue<(String, Instant), ReqHandler>; |
53 | 53 | ||
54 | pub(crate) struct CompletionResolveData { | ||
55 | pub(crate) file_id: FileId, | ||
56 | pub(crate) item: CompletionItem, | ||
57 | } | ||
58 | |||
54 | /// `GlobalState` is the primary mutable state of the language server | 59 | /// `GlobalState` is the primary mutable state of the language server |
55 | /// | 60 | /// |
56 | /// The most interesting components are `vfs`, which stores a consistent | 61 | /// The most interesting components are `vfs`, which stores a consistent |
@@ -69,7 +74,7 @@ pub(crate) struct GlobalState { | |||
69 | pub(crate) config: Config, | 74 | pub(crate) config: Config, |
70 | pub(crate) analysis_host: AnalysisHost, | 75 | pub(crate) analysis_host: AnalysisHost, |
71 | pub(crate) diagnostics: DiagnosticCollection, | 76 | pub(crate) diagnostics: DiagnosticCollection, |
72 | pub(crate) additional_imports: FxHashMap<usize, ImportToAdd>, | 77 | pub(crate) completion_resolve_data: FxHashMap<usize, CompletionResolveData>, |
73 | pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>, | 78 | pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>, |
74 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, | 79 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, |
75 | pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, | 80 | pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, |
@@ -122,7 +127,7 @@ impl GlobalState { | |||
122 | config, | 127 | config, |
123 | analysis_host, | 128 | analysis_host, |
124 | diagnostics: Default::default(), | 129 | diagnostics: Default::default(), |
125 | additional_imports: FxHashMap::default(), | 130 | completion_resolve_data: FxHashMap::default(), |
126 | mem_docs: FxHashMap::default(), | 131 | mem_docs: FxHashMap::default(), |
127 | semantic_tokens_cache: Arc::new(Default::default()), | 132 | semantic_tokens_cache: Arc::new(Default::default()), |
128 | vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))), | 133 | vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))), |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index d9fdf0434..a186d2e5d 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -5,14 +5,12 @@ | |||
5 | use std::{ | 5 | use std::{ |
6 | io::Write as _, | 6 | io::Write as _, |
7 | process::{self, Stdio}, | 7 | process::{self, Stdio}, |
8 | sync::Arc, | ||
9 | }; | 8 | }; |
10 | 9 | ||
11 | use ide::{ | 10 | use ide::{ |
12 | FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, ImportToAdd, LineIndex, | 11 | FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query, |
13 | NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit, | 12 | RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit, |
14 | }; | 13 | }; |
15 | use ide_db::helpers::{insert_use, mod_path_to_ast}; | ||
16 | use itertools::Itertools; | 14 | use itertools::Itertools; |
17 | use lsp_server::ErrorCode; | 15 | use lsp_server::ErrorCode; |
18 | use lsp_types::{ | 16 | use lsp_types::{ |
@@ -36,10 +34,10 @@ use crate::{ | |||
36 | cargo_target_spec::CargoTargetSpec, | 34 | cargo_target_spec::CargoTargetSpec, |
37 | config::RustfmtConfig, | 35 | config::RustfmtConfig, |
38 | from_json, from_proto, | 36 | from_json, from_proto, |
39 | global_state::{GlobalState, GlobalStateSnapshot}, | 37 | global_state::{CompletionResolveData, GlobalState, GlobalStateSnapshot}, |
40 | line_endings::LineEndings, | ||
41 | lsp_ext::{self, InlayHint, InlayHintsParams}, | 38 | lsp_ext::{self, InlayHint, InlayHintsParams}, |
42 | to_proto, LspError, Result, | 39 | to_proto::{self, append_import_edits}, |
40 | LspError, Result, | ||
43 | }; | 41 | }; |
44 | 42 | ||
45 | pub(crate) fn handle_analyzer_status( | 43 | pub(crate) fn handle_analyzer_status( |
@@ -538,12 +536,6 @@ pub(crate) fn handle_runnables( | |||
538 | Ok(res) | 536 | Ok(res) |
539 | } | 537 | } |
540 | 538 | ||
541 | #[derive(Debug, Copy, Clone, Serialize, Deserialize)] | ||
542 | pub(crate) struct ResolveCompletionData { | ||
543 | completion_id: usize, | ||
544 | completion_file_id: u32, | ||
545 | } | ||
546 | |||
547 | pub(crate) fn handle_completion( | 539 | pub(crate) fn handle_completion( |
548 | global_state: &mut GlobalState, | 540 | global_state: &mut GlobalState, |
549 | params: lsp_types::CompletionParams, | 541 | params: lsp_types::CompletionParams, |
@@ -579,38 +571,31 @@ pub(crate) fn handle_completion( | |||
579 | }; | 571 | }; |
580 | let line_index = snap.analysis.file_line_index(position.file_id)?; | 572 | let line_index = snap.analysis.file_line_index(position.file_id)?; |
581 | let line_endings = snap.file_line_endings(position.file_id); | 573 | let line_endings = snap.file_line_endings(position.file_id); |
582 | let mut additional_imports = FxHashMap::default(); | 574 | let mut completion_resolve_data = FxHashMap::default(); |
583 | 575 | ||
584 | let items: Vec<CompletionItem> = items | 576 | let items: Vec<CompletionItem> = items |
585 | .into_iter() | 577 | .into_iter() |
586 | .enumerate() | 578 | .enumerate() |
587 | .flat_map(|(item_index, item)| { | 579 | .flat_map(|(item_index, item)| { |
588 | let resolve_completion_data = ResolveCompletionData { | 580 | let mut new_completion_items = to_proto::completion_item( |
589 | completion_id: item_index, | 581 | &line_index, |
590 | completion_file_id: position.file_id.0, | 582 | line_endings, |
591 | }; | 583 | item.clone(), |
592 | let import_to_add = item.import_to_add().cloned(); | 584 | &snap.config.completion.resolve_capabilities, |
593 | let mut new_completion_items = | 585 | ); |
594 | to_proto::completion_item(&line_index, line_endings, item); | 586 | |
595 | 587 | let item_id = serde_json::to_value(&item_index) | |
596 | if let Some(import_to_add) = import_to_add { | 588 | .expect(&format!("Should be able to serialize usize value {}", item_index)); |
597 | for new_item in &mut new_completion_items { | 589 | completion_resolve_data |
598 | match serde_json::to_value(&resolve_completion_data) { | 590 | .insert(item_index, CompletionResolveData { file_id: position.file_id, item }); |
599 | Ok(resolve_value) => { | 591 | for new_item in &mut new_completion_items { |
600 | new_item.data = Some(resolve_value); | 592 | new_item.data = Some(item_id.clone()); |
601 | additional_imports.insert(item_index, import_to_add.clone()); | ||
602 | } | ||
603 | Err(e) => { | ||
604 | log::error!("Failed to serialize completion resolve metadata: {}", e) | ||
605 | } | ||
606 | } | ||
607 | } | ||
608 | } | 593 | } |
609 | new_completion_items | 594 | new_completion_items |
610 | }) | 595 | }) |
611 | .collect(); | 596 | .collect(); |
612 | 597 | ||
613 | global_state.additional_imports = additional_imports; | 598 | global_state.completion_resolve_data = completion_resolve_data; |
614 | 599 | ||
615 | let completion_list = lsp_types::CompletionList { is_incomplete: true, items }; | 600 | let completion_list = lsp_types::CompletionList { is_incomplete: true, items }; |
616 | Ok(Some(completion_list.into())) | 601 | Ok(Some(completion_list.into())) |
@@ -622,71 +607,38 @@ pub(crate) fn handle_resolve_completion( | |||
622 | ) -> Result<lsp_types::CompletionItem> { | 607 | ) -> Result<lsp_types::CompletionItem> { |
623 | let _p = profile::span("handle_resolve_completion"); | 608 | let _p = profile::span("handle_resolve_completion"); |
624 | 609 | ||
625 | match original_completion.data.as_ref() { | 610 | let server_completion_data = match original_completion |
626 | Some(completion_data) => { | 611 | .data |
627 | match serde_json::from_value::<ResolveCompletionData>(completion_data.clone()) { | 612 | .as_ref() |
628 | Ok(resolve_completion_data) => { | 613 | .map(|data| serde_json::from_value::<usize>(data.clone())) |
629 | if let Some(import_to_add) = | 614 | .transpose()? |
630 | global_state.additional_imports.get(&resolve_completion_data.completion_id) | 615 | .and_then(|server_completion_id| { |
631 | { | 616 | global_state.completion_resolve_data.get(&server_completion_id) |
632 | let snap = global_state.snapshot(); | 617 | }) { |
633 | let file_id = FileId(resolve_completion_data.completion_file_id); | 618 | Some(data) => data, |
634 | let line_index = snap.analysis.file_line_index(file_id)?; | 619 | None => return Ok(original_completion), |
635 | let line_endings = snap.file_line_endings(file_id); | 620 | }; |
636 | 621 | ||
637 | let resolved_edits = | 622 | let snap = &global_state.snapshot(); |
638 | resolve_additional_edits(import_to_add, line_index, line_endings); | 623 | for supported_completion_resolve_cap in &snap.config.completion.resolve_capabilities { |
639 | 624 | match supported_completion_resolve_cap { | |
640 | original_completion.additional_text_edits = | 625 | ide::CompletionResolveCapability::AdditionalTextEdits => { |
641 | match original_completion.additional_text_edits { | 626 | // TODO kb actually add all additional edits here? |
642 | Some(mut original_additional_edits) => { | 627 | if let Some(import_to_add) = server_completion_data.item.import_to_add() { |
643 | if let Some(mut new_edits) = resolved_edits { | 628 | append_import_edits( |
644 | original_additional_edits.extend(new_edits.drain(..)) | 629 | &mut original_completion, |
645 | } | 630 | import_to_add, |
646 | Some(original_additional_edits) | 631 | snap.analysis.file_line_index(server_completion_data.file_id)?.as_ref(), |
647 | } | 632 | snap.file_line_endings(server_completion_data.file_id), |
648 | None => resolved_edits, | 633 | ); |
649 | }; | ||
650 | } else { | ||
651 | log::error!( | ||
652 | "Got no import data for completion with label {}, id {}", | ||
653 | original_completion.label, | ||
654 | resolve_completion_data.completion_id | ||
655 | ) | ||
656 | } | ||
657 | } | 634 | } |
658 | Err(e) => log::error!("Failed to deserialize completion resolve metadata: {}", e), | ||
659 | } | 635 | } |
636 | // TODO kb calculate the rest also? | ||
637 | _ => {} | ||
660 | } | 638 | } |
661 | None => (), | ||
662 | } | 639 | } |
663 | Ok(original_completion) | ||
664 | } | ||
665 | 640 | ||
666 | // TODO kb what to do when no resolve is available on the client? | 641 | Ok(original_completion) |
667 | fn resolve_additional_edits( | ||
668 | import_to_add: &ImportToAdd, | ||
669 | line_index: Arc<LineIndex>, | ||
670 | line_endings: LineEndings, | ||
671 | ) -> Option<Vec<lsp_types::TextEdit>> { | ||
672 | let _p = profile::span("resolve_additional_edits"); | ||
673 | |||
674 | let rewriter = insert_use::insert_use( | ||
675 | &import_to_add.import_scope, | ||
676 | mod_path_to_ast(&import_to_add.import_path), | ||
677 | import_to_add.merge_behaviour, | ||
678 | ); | ||
679 | let old_ast = rewriter.rewrite_root()?; | ||
680 | let mut import_insert = TextEdit::builder(); | ||
681 | algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert); | ||
682 | let text_edit = import_insert.finish(); | ||
683 | |||
684 | Some( | ||
685 | text_edit | ||
686 | .into_iter() | ||
687 | .map(|indel| to_proto::text_edit(&line_index, line_endings, indel)) | ||
688 | .collect_vec(), | ||
689 | ) | ||
690 | } | 642 | } |
691 | 643 | ||
692 | pub(crate) fn handle_folding_range( | 644 | pub(crate) fn handle_folding_range( |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 01eabe852..aa542f5d1 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -5,14 +5,19 @@ use std::{ | |||
5 | }; | 5 | }; |
6 | 6 | ||
7 | use ide::{ | 7 | use ide::{ |
8 | Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, | 8 | Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, CompletionResolveCapability, |
9 | FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, HighlightedRange, | 9 | Documentation, FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, |
10 | Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget, | 10 | HighlightedRange, ImportToAdd, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, |
11 | ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit, | 11 | Markup, NavigationTarget, ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, |
12 | SourceFileEdit, TextEdit, | ||
13 | }; | ||
14 | use ide_db::{ | ||
15 | base_db::{FileId, FileRange}, | ||
16 | helpers::{insert_use, mod_path_to_ast}, | ||
12 | }; | 17 | }; |
13 | use ide_db::base_db::{FileId, FileRange}; | ||
14 | use itertools::Itertools; | 18 | use itertools::Itertools; |
15 | use syntax::{SyntaxKind, TextRange, TextSize}; | 19 | use rustc_hash::FxHashSet; |
20 | use syntax::{algo, SyntaxKind, TextRange, TextSize}; | ||
16 | 21 | ||
17 | use crate::{ | 22 | use crate::{ |
18 | cargo_target_spec::CargoTargetSpec, global_state::GlobalStateSnapshot, | 23 | cargo_target_spec::CargoTargetSpec, global_state::GlobalStateSnapshot, |
@@ -158,6 +163,7 @@ pub(crate) fn completion_item( | |||
158 | line_index: &LineIndex, | 163 | line_index: &LineIndex, |
159 | line_endings: LineEndings, | 164 | line_endings: LineEndings, |
160 | completion_item: CompletionItem, | 165 | completion_item: CompletionItem, |
166 | resolve_capabilities: &FxHashSet<CompletionResolveCapability>, | ||
161 | ) -> Vec<lsp_types::CompletionItem> { | 167 | ) -> Vec<lsp_types::CompletionItem> { |
162 | fn set_score(res: &mut lsp_types::CompletionItem, label: &str) { | 168 | fn set_score(res: &mut lsp_types::CompletionItem, label: &str) { |
163 | res.preselect = Some(true); | 169 | res.preselect = Some(true); |
@@ -231,9 +237,17 @@ pub(crate) fn completion_item( | |||
231 | None => vec![res], | 237 | None => vec![res], |
232 | }; | 238 | }; |
233 | 239 | ||
240 | let unapplied_import_data = completion_item.import_to_add().filter(|_| { | ||
241 | !resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits) | ||
242 | }); | ||
243 | |||
234 | for mut r in all_results.iter_mut() { | 244 | for mut r in all_results.iter_mut() { |
235 | r.insert_text_format = Some(insert_text_format(completion_item.insert_text_format())); | 245 | r.insert_text_format = Some(insert_text_format(completion_item.insert_text_format())); |
246 | if let Some(unapplied_import_data) = unapplied_import_data { | ||
247 | append_import_edits(r, unapplied_import_data, line_index, line_endings); | ||
248 | } | ||
236 | } | 249 | } |
250 | |||
237 | all_results | 251 | all_results |
238 | } | 252 | } |
239 | 253 | ||
@@ -817,6 +831,47 @@ pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent { | |||
817 | lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value } | 831 | lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value } |
818 | } | 832 | } |
819 | 833 | ||
834 | pub(crate) fn import_into_edits( | ||
835 | import_to_add: &ImportToAdd, | ||
836 | line_index: &LineIndex, | ||
837 | line_endings: LineEndings, | ||
838 | ) -> Option<Vec<lsp_types::TextEdit>> { | ||
839 | let _p = profile::span("add_import_edits"); | ||
840 | |||
841 | let rewriter = insert_use::insert_use( | ||
842 | &import_to_add.import_scope, | ||
843 | mod_path_to_ast(&import_to_add.import_path), | ||
844 | import_to_add.merge_behaviour, | ||
845 | ); | ||
846 | let old_ast = rewriter.rewrite_root()?; | ||
847 | let mut import_insert = TextEdit::builder(); | ||
848 | algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert); | ||
849 | let import_edit = import_insert.finish(); | ||
850 | |||
851 | Some( | ||
852 | import_edit | ||
853 | .into_iter() | ||
854 | .map(|indel| text_edit(line_index, line_endings, indel)) | ||
855 | .collect_vec(), | ||
856 | ) | ||
857 | } | ||
858 | |||
859 | pub(crate) fn append_import_edits( | ||
860 | completion: &mut lsp_types::CompletionItem, | ||
861 | import_to_add: &ImportToAdd, | ||
862 | line_index: &LineIndex, | ||
863 | line_endings: LineEndings, | ||
864 | ) { | ||
865 | let new_edits = import_into_edits(import_to_add, line_index, line_endings); | ||
866 | if let Some(original_additional_edits) = completion.additional_text_edits.as_mut() { | ||
867 | if let Some(mut new_edits) = new_edits { | ||
868 | original_additional_edits.extend(new_edits.drain(..)) | ||
869 | } | ||
870 | } else { | ||
871 | completion.additional_text_edits = new_edits; | ||
872 | } | ||
873 | } | ||
874 | |||
820 | #[cfg(test)] | 875 | #[cfg(test)] |
821 | mod tests { | 876 | mod tests { |
822 | use ide::Analysis; | 877 | use ide::Analysis; |
@@ -836,6 +891,7 @@ mod tests { | |||
836 | let (offset, text) = test_utils::extract_offset(fixture); | 891 | let (offset, text) = test_utils::extract_offset(fixture); |
837 | let line_index = LineIndex::new(&text); | 892 | let line_index = LineIndex::new(&text); |
838 | let (analysis, file_id) = Analysis::from_single_file(text); | 893 | let (analysis, file_id) = Analysis::from_single_file(text); |
894 | let resolve_caps = FxHashSet::default(); | ||
839 | let completions: Vec<(String, Option<String>)> = analysis | 895 | let completions: Vec<(String, Option<String>)> = analysis |
840 | .completions( | 896 | .completions( |
841 | &ide::CompletionConfig::default(), | 897 | &ide::CompletionConfig::default(), |
@@ -845,7 +901,7 @@ mod tests { | |||
845 | .unwrap() | 901 | .unwrap() |
846 | .into_iter() | 902 | .into_iter() |
847 | .filter(|c| c.label().ends_with("arg")) | 903 | .filter(|c| c.label().ends_with("arg")) |
848 | .map(|c| completion_item(&line_index, LineEndings::Unix, c)) | 904 | .map(|c| completion_item(&line_index, LineEndings::Unix, c, &resolve_caps)) |
849 | .flat_map(|comps| comps.into_iter().map(|c| (c.label, c.sort_text))) | 905 | .flat_map(|comps| comps.into_iter().map(|c| (c.label, c.sort_text))) |
850 | .collect(); | 906 | .collect(); |
851 | expect_test::expect![[r#" | 907 | expect_test::expect![[r#" |