@@ -8,16 +8,16 @@ use std::{
8
8
} ;
9
9
10
10
use ide:: {
11
- AnnotationConfig , FileId , FilePosition , FileRange , HoverAction , HoverGotoTypeData , Query ,
12
- RangeInfo , Runnable , RunnableKind , SearchScope , SourceChange , TextEdit ,
11
+ AnnotationConfig , AssistKind , FileId , FilePosition , FileRange , HoverAction , HoverGotoTypeData ,
12
+ Query , RangeInfo , Runnable , RunnableKind , SearchScope , SourceChange , TextEdit ,
13
13
} ;
14
14
use ide_db:: SymbolKind ;
15
15
use itertools:: Itertools ;
16
16
use lsp_server:: ErrorCode ;
17
17
use lsp_types:: {
18
18
CallHierarchyIncomingCall , CallHierarchyIncomingCallsParams , CallHierarchyItem ,
19
19
CallHierarchyOutgoingCall , CallHierarchyOutgoingCallsParams , CallHierarchyPrepareParams ,
20
- CodeActionKind , CodeLens , CompletionItem , Diagnostic , DiagnosticTag , DocumentFormattingParams ,
20
+ CodeLens , CompletionItem , Diagnostic , DiagnosticTag , DocumentFormattingParams ,
21
21
DocumentHighlight , FoldingRange , FoldingRangeParams , HoverContents , Location , NumberOrString ,
22
22
Position , PrepareRenameResponse , Range , RenameParams , SemanticTokensDeltaParams ,
23
23
SemanticTokensFullDeltaResult , SemanticTokensParams , SemanticTokensRangeParams ,
@@ -36,7 +36,7 @@ use crate::{
36
36
diff:: diff,
37
37
from_proto,
38
38
global_state:: { GlobalState , GlobalStateSnapshot } ,
39
- line_index:: { LineEndings , LineIndex } ,
39
+ line_index:: LineEndings ,
40
40
lsp_ext:: { self , InlayHint , InlayHintsParams } ,
41
41
lsp_utils:: all_edits_are_disjoint,
42
42
to_proto, LspError , Result ,
@@ -982,86 +982,66 @@ pub(crate) fn handle_code_action(
982
982
params : lsp_types:: CodeActionParams ,
983
983
) -> Result < Option < Vec < lsp_ext:: CodeAction > > > {
984
984
let _p = profile:: span ( "handle_code_action" ) ;
985
- // We intentionally don't support command-based actions, as those either
986
- // requires custom client-code anyway, or requires server-initiated edits.
987
- // Server initiated edits break causality, so we avoid those as well.
985
+
988
986
if !snap. config . code_action_literals ( ) {
987
+ // We intentionally don't support command-based actions, as those either
988
+ // require either custom client-code or server-initiated edits. Server
989
+ // initiated edits break causality, so we avoid those.
989
990
return Ok ( None ) ;
990
991
}
991
992
992
- let file_id = from_proto:: file_id ( & snap, & params. text_document . uri ) ?;
993
- let line_index = snap. file_line_index ( file_id) ?;
994
- let range = from_proto:: text_range ( & line_index, params. range ) ;
995
- let frange = FileRange { file_id, range } ;
993
+ let line_index =
994
+ snap. file_line_index ( from_proto:: file_id ( & snap, & params. text_document . uri ) ?) ?;
995
+ let frange = from_proto:: file_range ( & snap, params. text_document . clone ( ) , params. range ) ?;
996
996
997
997
let mut assists_config = snap. config . assist ( ) ;
998
998
assists_config. allowed = params
999
- . clone ( )
1000
999
. context
1001
1000
. only
1001
+ . clone ( )
1002
1002
. map ( |it| it. into_iter ( ) . filter_map ( from_proto:: assist_kind) . collect ( ) ) ;
1003
1003
1004
1004
let mut res: Vec < lsp_ext:: CodeAction > = Vec :: new ( ) ;
1005
1005
1006
- let include_quick_fixes = match & params. context . only {
1007
- Some ( v) => v. iter ( ) . any ( |it| {
1008
- it == & lsp_types:: CodeActionKind :: EMPTY || it == & lsp_types:: CodeActionKind :: QUICKFIX
1009
- } ) ,
1006
+ let include_quick_fixes = match & assists_config. allowed {
1007
+ Some ( v) => v. iter ( ) . any ( |it| it == & AssistKind :: None || it == & AssistKind :: QuickFix ) ,
1010
1008
None => true ,
1011
1009
} ;
1012
- if include_quick_fixes {
1013
- add_quick_fixes ( & snap, frange, & line_index, & mut res) ?;
1014
- }
1015
-
1016
- if snap. config . code_action_resolve ( ) {
1017
- for ( index, assist) in
1018
- snap. analysis . assists ( & assists_config, false , frange) ?. into_iter ( ) . enumerate ( )
1019
- {
1020
- res. push ( to_proto:: unresolved_code_action ( & snap, params. clone ( ) , assist, index) ?) ;
1021
- }
1022
- } else {
1023
- for assist in snap. analysis . assists ( & assists_config, true , frange) ?. into_iter ( ) {
1024
- res. push ( to_proto:: resolved_code_action ( & snap, assist) ?) ;
1025
- }
1026
- }
1010
+ let code_action_resolve_cap = snap. config . code_action_resolve ( ) ;
1027
1011
1028
- Ok ( Some ( res) )
1029
- }
1012
+ let mut assists = Vec :: new ( ) ;
1030
1013
1031
- fn add_quick_fixes (
1032
- snap : & GlobalStateSnapshot ,
1033
- frange : FileRange ,
1034
- line_index : & LineIndex ,
1035
- acc : & mut Vec < lsp_ext:: CodeAction > ,
1036
- ) -> Result < ( ) > {
1037
- let diagnostics = snap. analysis . diagnostics ( & snap. config . diagnostics ( ) , frange. file_id ) ?;
1014
+ // Fixes from native diagnostics.
1015
+ if include_quick_fixes {
1016
+ let diagnostics = snap. analysis . diagnostics ( & snap. config . diagnostics ( ) , frange. file_id ) ?;
1017
+ assists. extend (
1018
+ diagnostics
1019
+ . into_iter ( )
1020
+ . filter_map ( |d| d. fix )
1021
+ . filter ( |fix| fix. target . intersect ( frange. range ) . is_some ( ) ) ,
1022
+ )
1023
+ }
1038
1024
1039
- for fix in diagnostics
1040
- . into_iter ( )
1041
- . filter_map ( |d| d. fix )
1042
- . filter ( |fix| fix. target . intersect ( frange. range ) . is_some ( ) )
1043
- {
1044
- if let Some ( source_change) = fix. source_change {
1045
- let edit = to_proto:: snippet_workspace_edit ( & snap, source_change) ?;
1046
- let action = lsp_ext:: CodeAction {
1047
- title : fix. label . to_string ( ) ,
1048
- group : None ,
1049
- kind : Some ( CodeActionKind :: QUICKFIX ) ,
1050
- edit : Some ( edit) ,
1051
- is_preferred : Some ( false ) ,
1052
- data : None ,
1053
- } ;
1054
- acc. push ( action) ;
1055
- }
1025
+ // Assists proper.
1026
+ assists. extend ( snap. analysis . assists ( & assists_config, !code_action_resolve_cap, frange) ?) ;
1027
+ for ( index, assist) in assists. into_iter ( ) . enumerate ( ) {
1028
+ let resolve_data =
1029
+ if code_action_resolve_cap { Some ( ( index, params. clone ( ) ) ) } else { None } ;
1030
+ let code_action = to_proto:: code_action ( & snap, assist, resolve_data) ?;
1031
+ res. push ( code_action)
1056
1032
}
1057
1033
1034
+ // Fixes from `cargo check`.
1058
1035
for fix in snap. check_fixes . get ( & frange. file_id ) . into_iter ( ) . flatten ( ) {
1036
+ // FIXME: this mapping is awkward and shouldn't exist. Refactor
1037
+ // `snap.check_fixes` to not convert to LSP prematurely.
1059
1038
let fix_range = from_proto:: text_range ( & line_index, fix. range ) ;
1060
1039
if fix_range. intersect ( frange. range ) . is_some ( ) {
1061
- acc . push ( fix. action . clone ( ) ) ;
1040
+ res . push ( fix. action . clone ( ) ) ;
1062
1041
}
1063
1042
}
1064
- Ok ( ( ) )
1043
+
1044
+ Ok ( Some ( res) )
1065
1045
}
1066
1046
1067
1047
pub ( crate ) fn handle_code_action_resolve (
@@ -1091,7 +1071,7 @@ pub(crate) fn handle_code_action_resolve(
1091
1071
let index = index. parse :: < usize > ( ) . unwrap ( ) ;
1092
1072
let assist = & assists[ index] ;
1093
1073
assert ! ( assist. id. 0 == id) ;
1094
- let edit = to_proto:: resolved_code_action ( & snap, assist. clone ( ) ) ?. edit ;
1074
+ let edit = to_proto:: code_action ( & snap, assist. clone ( ) , None ) ?. edit ;
1095
1075
code_action. edit = edit;
1096
1076
Ok ( code_action)
1097
1077
}
0 commit comments