diff options
author | Kirill Bulatov <[email protected]> | 2020-12-03 13:58:18 +0000 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2020-12-07 21:41:08 +0000 |
commit | 74c3bbacc9b352057f2fc7ab69bd13e53022beb0 (patch) | |
tree | 32f3407cfb6851539e7ebf6b1c4d77a78c364efa /crates | |
parent | f6d2540df09bc0dcd8a748ec0ed7cb33ac76d9f2 (diff) |
Make completion resolve async
Diffstat (limited to 'crates')
-rw-r--r-- | crates/completion/src/item.rs | 29 | ||||
-rw-r--r-- | crates/completion/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ide_db/src/helpers/insert_use.rs | 32 | ||||
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 13 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 84 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 4 |
7 files changed, 116 insertions, 53 deletions
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs index 4e56f28f3..dd25ca75c 100644 --- a/crates/completion/src/item.rs +++ b/crates/completion/src/item.rs | |||
@@ -4,10 +4,10 @@ use std::fmt; | |||
4 | 4 | ||
5 | use hir::{Documentation, ModPath, Mutability}; | 5 | use hir::{Documentation, ModPath, Mutability}; |
6 | use ide_db::helpers::{ | 6 | use ide_db::helpers::{ |
7 | insert_use::{self, ImportScope, MergeBehaviour}, | 7 | insert_use::{self, ImportScope, ImportScopePtr, MergeBehaviour}, |
8 | mod_path_to_ast, | 8 | mod_path_to_ast, |
9 | }; | 9 | }; |
10 | use syntax::{algo, TextRange}; | 10 | use syntax::{algo, SyntaxNode, TextRange}; |
11 | use text_edit::TextEdit; | 11 | use text_edit::TextEdit; |
12 | 12 | ||
13 | use crate::config::SnippetCap; | 13 | use crate::config::SnippetCap; |
@@ -275,7 +275,32 @@ pub struct ImportEdit { | |||
275 | pub merge_behaviour: Option<MergeBehaviour>, | 275 | pub merge_behaviour: Option<MergeBehaviour>, |
276 | } | 276 | } |
277 | 277 | ||
278 | #[derive(Debug, Clone)] | ||
279 | pub struct ImportEditPtr { | ||
280 | pub import_path: ModPath, | ||
281 | pub import_scope: ImportScopePtr, | ||
282 | pub merge_behaviour: Option<MergeBehaviour>, | ||
283 | } | ||
284 | |||
285 | impl ImportEditPtr { | ||
286 | pub fn into_import_edit(self, root: &SyntaxNode) -> Option<ImportEdit> { | ||
287 | Some(ImportEdit { | ||
288 | import_path: self.import_path, | ||
289 | import_scope: self.import_scope.into_scope(root)?, | ||
290 | merge_behaviour: self.merge_behaviour, | ||
291 | }) | ||
292 | } | ||
293 | } | ||
294 | |||
278 | impl ImportEdit { | 295 | impl ImportEdit { |
296 | pub fn get_edit_ptr(&self) -> ImportEditPtr { | ||
297 | ImportEditPtr { | ||
298 | import_path: self.import_path.clone(), | ||
299 | import_scope: self.import_scope.get_ptr(), | ||
300 | merge_behaviour: self.merge_behaviour, | ||
301 | } | ||
302 | } | ||
303 | |||
279 | /// Attempts to insert the import to the given scope, producing a text edit. | 304 | /// Attempts to insert the import to the given scope, producing a text edit. |
280 | /// May return no edit in edge cases, such as scope already containing the import. | 305 | /// May return no edit in edge cases, such as scope already containing the import. |
281 | pub fn to_text_edit(&self) -> Option<TextEdit> { | 306 | pub fn to_text_edit(&self) -> Option<TextEdit> { |
diff --git a/crates/completion/src/lib.rs b/crates/completion/src/lib.rs index c57203c80..c277cd466 100644 --- a/crates/completion/src/lib.rs +++ b/crates/completion/src/lib.rs | |||
@@ -18,7 +18,10 @@ use crate::{completions::Completions, context::CompletionContext, item::Completi | |||
18 | 18 | ||
19 | pub use crate::{ | 19 | pub use crate::{ |
20 | config::{CompletionConfig, CompletionResolveCapability}, | 20 | config::{CompletionConfig, CompletionResolveCapability}, |
21 | item::{CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, InsertTextFormat}, | 21 | item::{ |
22 | CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, ImportEditPtr, | ||
23 | InsertTextFormat, | ||
24 | }, | ||
22 | }; | 25 | }; |
23 | 26 | ||
24 | //FIXME: split the following feature into fine-grained features. | 27 | //FIXME: split the following feature into fine-grained features. |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 9e38d6506..c52e53d27 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -81,7 +81,7 @@ pub use crate::{ | |||
81 | }; | 81 | }; |
82 | pub use completion::{ | 82 | pub use completion::{ |
83 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionResolveCapability, | 83 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionResolveCapability, |
84 | CompletionScore, ImportEdit, InsertTextFormat, | 84 | CompletionScore, ImportEdit, ImportEditPtr, InsertTextFormat, |
85 | }; | 85 | }; |
86 | pub use ide_db::{ | 86 | pub use ide_db::{ |
87 | call_info::CallInfo, | 87 | call_info::CallInfo, |
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs index 040843990..0dae9a541 100644 --- a/crates/ide_db/src/helpers/insert_use.rs +++ b/crates/ide_db/src/helpers/insert_use.rs | |||
@@ -11,7 +11,7 @@ use syntax::{ | |||
11 | edit::{AstNodeEdit, IndentLevel}, | 11 | edit::{AstNodeEdit, IndentLevel}, |
12 | make, AstNode, PathSegmentKind, VisibilityOwner, | 12 | make, AstNode, PathSegmentKind, VisibilityOwner, |
13 | }, | 13 | }, |
14 | AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken, | 14 | AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken, |
15 | }; | 15 | }; |
16 | use test_utils::mark; | 16 | use test_utils::mark; |
17 | 17 | ||
@@ -22,6 +22,36 @@ pub enum ImportScope { | |||
22 | } | 22 | } |
23 | 23 | ||
24 | impl ImportScope { | 24 | impl ImportScope { |
25 | pub fn get_ptr(&self) -> ImportScopePtr { | ||
26 | match self { | ||
27 | ImportScope::File(file) => ImportScopePtr::File(SyntaxNodePtr::new(file.syntax())), | ||
28 | ImportScope::Module(module) => { | ||
29 | ImportScopePtr::Module(SyntaxNodePtr::new(module.syntax())) | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | } | ||
34 | |||
35 | #[derive(Debug, Clone)] | ||
36 | pub enum ImportScopePtr { | ||
37 | File(SyntaxNodePtr), | ||
38 | Module(SyntaxNodePtr), | ||
39 | } | ||
40 | |||
41 | impl ImportScopePtr { | ||
42 | pub fn into_scope(self, root: &SyntaxNode) -> Option<ImportScope> { | ||
43 | Some(match self { | ||
44 | ImportScopePtr::File(file_ptr) => { | ||
45 | ImportScope::File(ast::SourceFile::cast(file_ptr.to_node(root))?) | ||
46 | } | ||
47 | ImportScopePtr::Module(module_ptr) => { | ||
48 | ImportScope::File(ast::SourceFile::cast(module_ptr.to_node(root))?) | ||
49 | } | ||
50 | }) | ||
51 | } | ||
52 | } | ||
53 | |||
54 | impl ImportScope { | ||
25 | pub fn from(syntax: SyntaxNode) -> Option<Self> { | 55 | pub fn from(syntax: SyntaxNode) -> Option<Self> { |
26 | if let Some(module) = ast::Module::cast(syntax.clone()) { | 56 | if let Some(module) = ast::Module::cast(syntax.clone()) { |
27 | module.item_list().map(ImportScope::Module) | 57 | module.item_list().map(ImportScope::Module) |
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index a35abe86d..0fe69b996 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, ImportEdit}; | 10 | use ide::{Analysis, AnalysisHost, Change, FileId, ImportEditPtr}; |
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,11 +51,6 @@ 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) import_edit: ImportEdit, | ||
57 | } | ||
58 | |||
59 | /// `GlobalState` is the primary mutable state of the language server | 54 | /// `GlobalState` is the primary mutable state of the language server |
60 | /// | 55 | /// |
61 | /// The most interesting components are `vfs`, which stores a consistent | 56 | /// The most interesting components are `vfs`, which stores a consistent |
@@ -74,7 +69,7 @@ pub(crate) struct GlobalState { | |||
74 | pub(crate) config: Config, | 69 | pub(crate) config: Config, |
75 | pub(crate) analysis_host: AnalysisHost, | 70 | pub(crate) analysis_host: AnalysisHost, |
76 | pub(crate) diagnostics: DiagnosticCollection, | 71 | pub(crate) diagnostics: DiagnosticCollection, |
77 | pub(crate) completion_resolve_data: FxHashMap<usize, CompletionResolveData>, | 72 | pub(crate) completion_resolve_data: Arc<FxHashMap<usize, ImportEditPtr>>, |
78 | pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>, | 73 | pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>, |
79 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, | 74 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, |
80 | pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, | 75 | pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, |
@@ -96,6 +91,7 @@ pub(crate) struct GlobalStateSnapshot { | |||
96 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, | 91 | pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>, |
97 | vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, | 92 | vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>, |
98 | pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, | 93 | pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>, |
94 | pub(crate) completion_resolve_data: Arc<FxHashMap<usize, ImportEditPtr>>, | ||
99 | } | 95 | } |
100 | 96 | ||
101 | impl GlobalState { | 97 | impl GlobalState { |
@@ -127,7 +123,7 @@ impl GlobalState { | |||
127 | config, | 123 | config, |
128 | analysis_host, | 124 | analysis_host, |
129 | diagnostics: Default::default(), | 125 | diagnostics: Default::default(), |
130 | completion_resolve_data: FxHashMap::default(), | 126 | completion_resolve_data: Arc::new(FxHashMap::default()), |
131 | mem_docs: FxHashMap::default(), | 127 | mem_docs: FxHashMap::default(), |
132 | semantic_tokens_cache: Arc::new(Default::default()), | 128 | semantic_tokens_cache: Arc::new(Default::default()), |
133 | vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))), | 129 | vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))), |
@@ -198,6 +194,7 @@ impl GlobalState { | |||
198 | check_fixes: Arc::clone(&self.diagnostics.check_fixes), | 194 | check_fixes: Arc::clone(&self.diagnostics.check_fixes), |
199 | mem_docs: self.mem_docs.clone(), | 195 | mem_docs: self.mem_docs.clone(), |
200 | semantic_tokens_cache: Arc::clone(&self.semantic_tokens_cache), | 196 | semantic_tokens_cache: Arc::clone(&self.semantic_tokens_cache), |
197 | completion_resolve_data: Arc::clone(&self.completion_resolve_data), | ||
201 | } | 198 | } |
202 | } | 199 | } |
203 | 200 | ||
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 3eb5f26bc..1ea1e1f43 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -5,11 +5,13 @@ | |||
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, | ||
8 | }; | 9 | }; |
9 | 10 | ||
10 | use ide::{ | 11 | use ide::{ |
11 | FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, ImportEdit, LineIndex, | 12 | CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, |
12 | NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit, | 13 | ImportEdit, LineIndex, NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, |
14 | TextEdit, | ||
13 | }; | 15 | }; |
14 | use itertools::Itertools; | 16 | use itertools::Itertools; |
15 | use lsp_server::ErrorCode; | 17 | use lsp_server::ErrorCode; |
@@ -34,7 +36,7 @@ use crate::{ | |||
34 | cargo_target_spec::CargoTargetSpec, | 36 | cargo_target_spec::CargoTargetSpec, |
35 | config::RustfmtConfig, | 37 | config::RustfmtConfig, |
36 | from_json, from_proto, | 38 | from_json, from_proto, |
37 | global_state::{CompletionResolveData, GlobalState, GlobalStateSnapshot}, | 39 | global_state::{GlobalState, GlobalStateSnapshot}, |
38 | line_endings::LineEndings, | 40 | line_endings::LineEndings, |
39 | lsp_ext::{self, InlayHint, InlayHintsParams}, | 41 | lsp_ext::{self, InlayHint, InlayHintsParams}, |
40 | to_proto, LspError, Result, | 42 | to_proto, LspError, Result, |
@@ -542,6 +544,7 @@ pub(crate) fn handle_completion( | |||
542 | ) -> Result<Option<lsp_types::CompletionResponse>> { | 544 | ) -> Result<Option<lsp_types::CompletionResponse>> { |
543 | let _p = profile::span("handle_completion"); | 545 | let _p = profile::span("handle_completion"); |
544 | let snap = global_state.snapshot(); | 546 | let snap = global_state.snapshot(); |
547 | let text_document_url = params.text_document_position.text_document.uri.clone(); | ||
545 | let position = from_proto::file_position(&snap, params.text_document_position)?; | 548 | let position = from_proto::file_position(&snap, params.text_document_position)?; |
546 | let completion_triggered_after_single_colon = { | 549 | let completion_triggered_after_single_colon = { |
547 | let mut res = false; | 550 | let mut res = false; |
@@ -582,18 +585,15 @@ pub(crate) fn handle_completion( | |||
582 | 585 | ||
583 | if snap.config.completion.resolve_additional_edits_lazily() { | 586 | if snap.config.completion.resolve_additional_edits_lazily() { |
584 | if let Some(import_edit) = item.import_to_add() { | 587 | if let Some(import_edit) = item.import_to_add() { |
585 | completion_resolve_data.insert( | 588 | completion_resolve_data.insert(item_index, import_edit.get_edit_ptr()); |
586 | item_index, | 589 | |
587 | CompletionResolveData { | 590 | let data = serde_json::to_value(&CompletionData { |
588 | file_id: position.file_id, | 591 | document_url: text_document_url.clone(), |
589 | import_edit: import_edit.clone(), | 592 | import_id: item_index, |
590 | }, | 593 | }) |
591 | ); | 594 | .expect(&format!("Should be able to serialize usize value {}", item_index)); |
592 | |||
593 | let item_id = serde_json::to_value(&item_index) | ||
594 | .expect(&format!("Should be able to serialize usize value {}", item_index)); | ||
595 | for new_item in &mut new_completion_items { | 595 | for new_item in &mut new_completion_items { |
596 | new_item.data = Some(item_id.clone()); | 596 | new_item.data = Some(data.clone()); |
597 | } | 597 | } |
598 | } | 598 | } |
599 | } | 599 | } |
@@ -602,50 +602,54 @@ pub(crate) fn handle_completion( | |||
602 | }) | 602 | }) |
603 | .collect(); | 603 | .collect(); |
604 | 604 | ||
605 | global_state.completion_resolve_data = completion_resolve_data; | 605 | global_state.completion_resolve_data = Arc::new(completion_resolve_data); |
606 | 606 | ||
607 | let completion_list = lsp_types::CompletionList { is_incomplete: true, items }; | 607 | let completion_list = lsp_types::CompletionList { is_incomplete: true, items }; |
608 | Ok(Some(completion_list.into())) | 608 | Ok(Some(completion_list.into())) |
609 | } | 609 | } |
610 | 610 | ||
611 | pub(crate) fn handle_completion_resolve( | 611 | pub(crate) fn handle_completion_resolve( |
612 | global_state: &mut GlobalState, | 612 | snap: GlobalStateSnapshot, |
613 | mut original_completion: lsp_types::CompletionItem, | 613 | mut original_completion: lsp_types::CompletionItem, |
614 | ) -> Result<lsp_types::CompletionItem> { | 614 | ) -> Result<lsp_types::CompletionItem> { |
615 | let _p = profile::span("handle_resolve_completion"); | 615 | let _p = profile::span("handle_resolve_completion"); |
616 | 616 | ||
617 | let active_resolve_caps = &global_state.config.completion.active_resolve_capabilities; | 617 | // FIXME resolve the other capabilities also? |
618 | if active_resolve_caps.is_empty() { | 618 | if !snap |
619 | .config | ||
620 | .completion | ||
621 | .active_resolve_capabilities | ||
622 | .contains(&CompletionResolveCapability::AdditionalTextEdits) | ||
623 | { | ||
619 | return Ok(original_completion); | 624 | return Ok(original_completion); |
620 | } | 625 | } |
621 | 626 | ||
622 | let server_completion_data = match original_completion | 627 | let (import_edit_ptr, document_url) = match original_completion |
623 | .data | 628 | .data |
624 | .as_ref() | 629 | .as_ref() |
625 | .map(|data| serde_json::from_value::<usize>(data.clone())) | 630 | .map(|data| serde_json::from_value::<CompletionData>(data.clone())) |
626 | .transpose()? | 631 | .transpose()? |
627 | .and_then(|server_completion_id| { | 632 | .and_then(|data| { |
628 | global_state.completion_resolve_data.get(&server_completion_id) | 633 | let import_edit_ptr = snap.completion_resolve_data.get(&data.import_id).cloned(); |
634 | Some((import_edit_ptr, data.document_url)) | ||
629 | }) { | 635 | }) { |
630 | Some(data) => data, | 636 | Some(data) => data, |
631 | None => return Ok(original_completion), | 637 | None => return Ok(original_completion), |
632 | }; | 638 | }; |
633 | 639 | ||
634 | let snap = &global_state.snapshot(); | 640 | let file_id = from_proto::file_id(&snap, &document_url)?; |
635 | for supported_completion_resolve_cap in active_resolve_caps { | 641 | let root = snap.analysis.parse(file_id)?; |
636 | match supported_completion_resolve_cap { | 642 | |
637 | // FIXME actually add all additional edits here? see `to_proto::completion_item` for more | 643 | if let Some(import_to_add) = |
638 | ide::CompletionResolveCapability::AdditionalTextEdits => { | 644 | import_edit_ptr.and_then(|import_edit| import_edit.into_import_edit(root.syntax())) |
639 | append_import_edits( | 645 | { |
640 | &mut original_completion, | 646 | // FIXME actually add all additional edits here? see `to_proto::completion_item` for more |
641 | &server_completion_data.import_edit, | 647 | append_import_edits( |
642 | snap.analysis.file_line_index(server_completion_data.file_id)?.as_ref(), | 648 | &mut original_completion, |
643 | snap.file_line_endings(server_completion_data.file_id), | 649 | &import_to_add, |
644 | ); | 650 | snap.analysis.file_line_index(file_id)?.as_ref(), |
645 | } | 651 | snap.file_line_endings(file_id), |
646 | // FIXME resolve the other capabilities also? | 652 | ); |
647 | _ => {} | ||
648 | } | ||
649 | } | 653 | } |
650 | 654 | ||
651 | Ok(original_completion) | 655 | Ok(original_completion) |
@@ -1609,6 +1613,12 @@ fn should_skip_target(runnable: &Runnable, cargo_spec: Option<&CargoTargetSpec>) | |||
1609 | } | 1613 | } |
1610 | } | 1614 | } |
1611 | 1615 | ||
1616 | #[derive(Debug, Serialize, Deserialize)] | ||
1617 | struct CompletionData { | ||
1618 | document_url: Url, | ||
1619 | import_id: usize, | ||
1620 | } | ||
1621 | |||
1612 | fn append_import_edits( | 1622 | fn append_import_edits( |
1613 | completion: &mut lsp_types::CompletionItem, | 1623 | completion: &mut lsp_types::CompletionItem, |
1614 | import_to_add: &ImportEdit, | 1624 | import_to_add: &ImportEdit, |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index db30b3dce..aad37fde1 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -437,9 +437,7 @@ impl GlobalState { | |||
437 | })? | 437 | })? |
438 | .on_sync::<lsp_ext::MemoryUsage>(|s, p| handlers::handle_memory_usage(s, p))? | 438 | .on_sync::<lsp_ext::MemoryUsage>(|s, p| handlers::handle_memory_usage(s, p))? |
439 | .on_sync::<lsp_types::request::Completion>(handlers::handle_completion)? | 439 | .on_sync::<lsp_types::request::Completion>(handlers::handle_completion)? |
440 | .on_sync::<lsp_types::request::ResolveCompletionItem>( | 440 | .on::<lsp_types::request::ResolveCompletionItem>(handlers::handle_completion_resolve) |
441 | handlers::handle_completion_resolve, | ||
442 | )? | ||
443 | .on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status) | 441 | .on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status) |
444 | .on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree) | 442 | .on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree) |
445 | .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro) | 443 | .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro) |