5
5
use std:: {
6
6
io:: Write as _,
7
7
process:: { self , Stdio } ,
8
- sync:: Arc ,
9
8
} ;
10
9
11
10
use ide:: {
12
- FileId , FilePosition , FileRange , HoverAction , HoverGotoTypeData , ImportToAdd , LineIndex ,
13
- NavigationTarget , Query , RangeInfo , Runnable , RunnableKind , SearchScope , TextEdit ,
11
+ FileId , FilePosition , FileRange , HoverAction , HoverGotoTypeData , NavigationTarget , Query ,
12
+ RangeInfo , Runnable , RunnableKind , SearchScope , TextEdit ,
14
13
} ;
15
- use ide_db:: helpers:: { insert_use, mod_path_to_ast} ;
16
14
use itertools:: Itertools ;
17
15
use lsp_server:: ErrorCode ;
18
16
use lsp_types:: {
@@ -36,10 +34,10 @@ use crate::{
36
34
cargo_target_spec:: CargoTargetSpec ,
37
35
config:: RustfmtConfig ,
38
36
from_json, from_proto,
39
- global_state:: { GlobalState , GlobalStateSnapshot } ,
40
- line_endings:: LineEndings ,
37
+ global_state:: { CompletionResolveData , GlobalState , GlobalStateSnapshot } ,
41
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
43
pub ( crate ) fn handle_analyzer_status (
@@ -538,12 +536,6 @@ pub(crate) fn handle_runnables(
538
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
539
pub ( crate ) fn handle_completion (
548
540
global_state : & mut GlobalState ,
549
541
params : lsp_types:: CompletionParams ,
@@ -579,38 +571,31 @@ pub(crate) fn handle_completion(
579
571
} ;
580
572
let line_index = snap. analysis . file_line_index ( position. file_id ) ?;
581
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
576
let items: Vec < CompletionItem > = items
585
577
. into_iter ( )
586
578
. enumerate ( )
587
579
. flat_map ( |( item_index, item) | {
588
- let resolve_completion_data = ResolveCompletionData {
589
- completion_id : item_index,
590
- completion_file_id : position. file_id . 0 ,
591
- } ;
592
- let import_to_add = item. import_to_add ( ) . cloned ( ) ;
593
- let mut new_completion_items =
594
- to_proto:: completion_item ( & line_index, line_endings, item) ;
595
-
596
- if let Some ( import_to_add) = import_to_add {
597
- for new_item in & mut new_completion_items {
598
- match serde_json:: to_value ( & resolve_completion_data) {
599
- Ok ( resolve_value) => {
600
- new_item. data = Some ( resolve_value) ;
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
- }
580
+ let mut new_completion_items = to_proto:: completion_item (
581
+ & line_index,
582
+ line_endings,
583
+ item. clone ( ) ,
584
+ & snap. config . completion . resolve_capabilities ,
585
+ ) ;
586
+
587
+ let item_id = serde_json:: to_value ( & item_index)
588
+ . expect ( & format ! ( "Should be able to serialize usize value {}" , item_index) ) ;
589
+ completion_resolve_data
590
+ . insert ( item_index, CompletionResolveData { file_id : position. file_id , item } ) ;
591
+ for new_item in & mut new_completion_items {
592
+ new_item. data = Some ( item_id. clone ( ) ) ;
608
593
}
609
594
new_completion_items
610
595
} )
611
596
. collect ( ) ;
612
597
613
- global_state. additional_imports = additional_imports ;
598
+ global_state. completion_resolve_data = completion_resolve_data ;
614
599
615
600
let completion_list = lsp_types:: CompletionList { is_incomplete : true , items } ;
616
601
Ok ( Some ( completion_list. into ( ) ) )
@@ -622,71 +607,38 @@ pub(crate) fn handle_resolve_completion(
622
607
) -> Result < lsp_types:: CompletionItem > {
623
608
let _p = profile:: span ( "handle_resolve_completion" ) ;
624
609
625
- match original_completion. data . as_ref ( ) {
626
- Some ( completion_data) => {
627
- match serde_json:: from_value :: < ResolveCompletionData > ( completion_data. clone ( ) ) {
628
- Ok ( resolve_completion_data) => {
629
- if let Some ( import_to_add) =
630
- global_state. additional_imports . get ( & resolve_completion_data. completion_id )
631
- {
632
- let snap = global_state. snapshot ( ) ;
633
- let file_id = FileId ( resolve_completion_data. completion_file_id ) ;
634
- let line_index = snap. analysis . file_line_index ( file_id) ?;
635
- let line_endings = snap. file_line_endings ( file_id) ;
636
-
637
- let resolved_edits =
638
- resolve_additional_edits ( import_to_add, line_index, line_endings) ;
639
-
640
- original_completion. additional_text_edits =
641
- match original_completion. additional_text_edits {
642
- Some ( mut original_additional_edits) => {
643
- if let Some ( mut new_edits) = resolved_edits {
644
- original_additional_edits. extend ( new_edits. drain ( ..) )
645
- }
646
- Some ( original_additional_edits)
647
- }
648
- None => resolved_edits,
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
- }
610
+ let server_completion_data = match original_completion
611
+ . data
612
+ . as_ref ( )
613
+ . map ( |data| serde_json:: from_value :: < usize > ( data. clone ( ) ) )
614
+ . transpose ( ) ?
615
+ . and_then ( |server_completion_id| {
616
+ global_state. completion_resolve_data . get ( & server_completion_id)
617
+ } ) {
618
+ Some ( data) => data,
619
+ None => return Ok ( original_completion) ,
620
+ } ;
621
+
622
+ let snap = & global_state. snapshot ( ) ;
623
+ for supported_completion_resolve_cap in & snap. config . completion . resolve_capabilities {
624
+ match supported_completion_resolve_cap {
625
+ ide:: CompletionResolveCapability :: AdditionalTextEdits => {
626
+ // TODO kb actually add all additional edits here?
627
+ if let Some ( import_to_add) = server_completion_data. item . import_to_add ( ) {
628
+ append_import_edits (
629
+ & mut original_completion,
630
+ import_to_add,
631
+ snap. analysis . file_line_index ( server_completion_data. file_id ) ?. as_ref ( ) ,
632
+ snap. file_line_endings ( server_completion_data. file_id ) ,
633
+ ) ;
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?
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
- )
641
+ Ok ( original_completion)
690
642
}
691
643
692
644
pub ( crate ) fn handle_folding_range (
0 commit comments