@@ -934,16 +934,18 @@ pub(crate) fn handle_related_tests(
934934
935935pub ( crate ) fn handle_completion (
936936 snap : GlobalStateSnapshot ,
937- params : lsp_types:: CompletionParams ,
937+ lsp_types :: CompletionParams { text_document_position , context , .. } : lsp_types:: CompletionParams ,
938938) -> anyhow:: Result < Option < lsp_types:: CompletionResponse > > {
939939 let _p = tracing:: span!( tracing:: Level :: INFO , "handle_completion" ) . entered ( ) ;
940- let text_document_position = params . text_document_position . clone ( ) ;
941- let position = from_proto :: file_position ( & snap, params . text_document_position ) ?;
940+ let mut position = from_proto :: file_position ( & snap , text_document_position. clone ( ) ) ? ;
941+ let line_index = snap. file_line_index ( position . file_id ) ?;
942942 let completion_trigger_character =
943- params . context . and_then ( |ctx| ctx. trigger_character ) . and_then ( |s| s. chars ( ) . next ( ) ) ;
943+ context. and_then ( |ctx| ctx. trigger_character ) . and_then ( |s| s. chars ( ) . next ( ) ) ;
944944
945945 let source_root = snap. analysis . source_root ( position. file_id ) ?;
946946 let completion_config = & snap. config . completion ( Some ( source_root) ) ;
947+ // FIXME: We should fix up the position when retrying the cancelled request instead
948+ position. offset = position. offset . min ( line_index. index . len ( ) ) ;
947949 let items = match snap. analysis . completions (
948950 completion_config,
949951 position,
@@ -952,10 +954,14 @@ pub(crate) fn handle_completion(
952954 None => return Ok ( None ) ,
953955 Some ( items) => items,
954956 } ;
955- let line_index = snap. file_line_index ( position. file_id ) ?;
956957
957- let items =
958- to_proto:: completion_items ( & snap. config , & line_index, text_document_position, items) ;
958+ let items = to_proto:: completion_items (
959+ & snap. config ,
960+ & line_index,
961+ snap. file_version ( position. file_id ) ,
962+ text_document_position,
963+ items,
964+ ) ;
959965
960966 let completion_list = lsp_types:: CompletionList { is_incomplete : true , items } ;
961967 Ok ( Some ( completion_list. into ( ) ) )
@@ -974,16 +980,16 @@ pub(crate) fn handle_completion_resolve(
974980 . into ( ) ) ;
975981 }
976982
977- let data = match original_completion. data . take ( ) {
978- Some ( it) => it,
979- None => return Ok ( original_completion) ,
980- } ;
983+ let Some ( data) = original_completion. data . take ( ) else { return Ok ( original_completion) } ;
981984
982985 let resolve_data: lsp_ext:: CompletionResolveData = serde_json:: from_value ( data) ?;
983986
984987 let file_id = from_proto:: file_id ( & snap, & resolve_data. position . text_document . uri ) ?;
985988 let line_index = snap. file_line_index ( file_id) ?;
986- let offset = from_proto:: offset ( & line_index, resolve_data. position . position ) ?;
989+ // FIXME: We should fix up the position when retrying the cancelled request instead
990+ let Ok ( offset) = from_proto:: offset ( & line_index, resolve_data. position . position ) else {
991+ return Ok ( original_completion) ;
992+ } ;
987993 let source_root = snap. analysis . source_root ( file_id) ?;
988994
989995 let additional_edits = snap
@@ -1240,8 +1246,11 @@ pub(crate) fn handle_code_action(
12401246 frange,
12411247 ) ?;
12421248 for ( index, assist) in assists. into_iter ( ) . enumerate ( ) {
1243- let resolve_data =
1244- if code_action_resolve_cap { Some ( ( index, params. clone ( ) ) ) } else { None } ;
1249+ let resolve_data = if code_action_resolve_cap {
1250+ Some ( ( index, params. clone ( ) , snap. file_version ( file_id) ) )
1251+ } else {
1252+ None
1253+ } ;
12451254 let code_action = to_proto:: code_action ( & snap, assist, resolve_data) ?;
12461255
12471256 // Check if the client supports the necessary `ResourceOperation`s.
@@ -1280,12 +1289,14 @@ pub(crate) fn handle_code_action_resolve(
12801289 mut code_action : lsp_ext:: CodeAction ,
12811290) -> anyhow:: Result < lsp_ext:: CodeAction > {
12821291 let _p = tracing:: span!( tracing:: Level :: INFO , "handle_code_action_resolve" ) . entered ( ) ;
1283- let params = match code_action. data . take ( ) {
1284- Some ( it) => it,
1285- None => return Err ( invalid_params_error ( "code action without data" . to_owned ( ) ) . into ( ) ) ,
1292+ let Some ( params) = code_action. data . take ( ) else {
1293+ return Err ( invalid_params_error ( "code action without data" . to_owned ( ) ) . into ( ) ) ;
12861294 } ;
12871295
12881296 let file_id = from_proto:: file_id ( & snap, & params. code_action_params . text_document . uri ) ?;
1297+ if snap. file_version ( file_id) != params. version {
1298+ return Err ( invalid_params_error ( "stale code action" . to_owned ( ) ) . into ( ) ) ;
1299+ }
12891300 let line_index = snap. file_line_index ( file_id) ?;
12901301 let range = from_proto:: text_range ( & line_index, params. code_action_params . range ) ?;
12911302 let frange = FileRange { file_id, range } ;
@@ -1411,12 +1422,11 @@ pub(crate) fn handle_code_lens(
14111422
14121423pub ( crate ) fn handle_code_lens_resolve (
14131424 snap : GlobalStateSnapshot ,
1414- code_lens : CodeLens ,
1425+ mut code_lens : CodeLens ,
14151426) -> anyhow:: Result < CodeLens > {
1416- if code_lens. data . is_none ( ) {
1417- return Ok ( code_lens) ;
1418- }
1419- let Some ( annotation) = from_proto:: annotation ( & snap, code_lens. clone ( ) ) ? else {
1427+ let Some ( data) = code_lens. data . take ( ) else { return Ok ( code_lens) } ;
1428+ let resolve = serde_json:: from_value :: < lsp_ext:: CodeLensResolveData > ( data) ?;
1429+ let Some ( annotation) = from_proto:: annotation ( & snap, code_lens. range , resolve) ? else {
14201430 return Ok ( code_lens) ;
14211431 } ;
14221432 let annotation = snap. analysis . resolve_annotation ( annotation) ?;
@@ -1495,6 +1505,10 @@ pub(crate) fn handle_inlay_hints(
14951505 ) ?;
14961506 let line_index = snap. file_line_index ( file_id) ?;
14971507 let source_root = snap. analysis . source_root ( file_id) ?;
1508+ let range = TextRange :: new (
1509+ range. start ( ) . min ( line_index. index . len ( ) ) ,
1510+ range. end ( ) . min ( line_index. index . len ( ) ) ,
1511+ ) ;
14981512
14991513 let inlay_hints_config = snap. config . inlay_hints ( Some ( source_root) ) ;
15001514 Ok ( Some (
@@ -1522,8 +1536,12 @@ pub(crate) fn handle_inlay_hints_resolve(
15221536
15231537 let Some ( data) = original_hint. data . take ( ) else { return Ok ( original_hint) } ;
15241538 let resolve_data: lsp_ext:: InlayHintResolveData = serde_json:: from_value ( data) ?;
1525- let Some ( hash) = resolve_data. hash . parse ( ) . ok ( ) else { return Ok ( original_hint) } ;
15261539 let file_id = FileId :: from_raw ( resolve_data. file_id ) ;
1540+ if resolve_data. version != snap. file_version ( file_id) {
1541+ tracing:: warn!( "Inlay hint resolve data is outdated" ) ;
1542+ return Ok ( original_hint) ;
1543+ }
1544+ let Some ( hash) = resolve_data. hash . parse ( ) . ok ( ) else { return Ok ( original_hint) } ;
15271545 anyhow:: ensure!( snap. file_exists( file_id) , "Invalid LSP resolve data" ) ;
15281546
15291547 let line_index = snap. file_line_index ( file_id) ?;
0 commit comments