@@ -930,6 +930,16 @@ fn merge_text_and_snippet_edits(
930930 let mut edits: Vec < SnippetTextEdit > = vec ! [ ] ;
931931 let mut snippets = snippet_edit. into_edit_ranges ( ) . into_iter ( ) . peekable ( ) ;
932932 let text_edits = edit. into_iter ( ) ;
933+ // offset to go from the final source location to the original source location
934+ let mut source_text_offset = 0i32 ;
935+
936+ let offset_range = |range : TextRange , offset : i32 | -> TextRange {
937+ // map the snippet range from the target location into the original source location
938+ let start = u32:: from ( range. start ( ) ) . checked_add_signed ( offset) . unwrap_or ( 0 ) ;
939+ let end = u32:: from ( range. end ( ) ) . checked_add_signed ( offset) . unwrap_or ( 0 ) ;
940+
941+ TextRange :: new ( start. into ( ) , end. into ( ) )
942+ } ;
933943
934944 for current_indel in text_edits {
935945 let new_range = {
@@ -938,10 +948,17 @@ fn merge_text_and_snippet_edits(
938948 TextRange :: at ( current_indel. delete . start ( ) , insert_len)
939949 } ;
940950
951+ // figure out how much this Indel will shift future ranges from the initial source
952+ let offset_adjustment =
953+ u32:: from ( current_indel. delete . len ( ) ) as i32 - u32:: from ( new_range. len ( ) ) as i32 ;
954+
941955 // insert any snippets before the text edit
942- for ( snippet_index, snippet_range) in
943- snippets. take_while_ref ( |( _, range) | range. end ( ) < new_range. start ( ) )
944- {
956+ for ( snippet_index, snippet_range) in snippets. peeking_take_while ( |( _, range) | {
957+ offset_range ( * range, source_text_offset) . end ( ) < new_range. start ( )
958+ } ) {
959+ // adjust the snippet range into the corresponding initial source location
960+ let snippet_range = offset_range ( snippet_range, source_text_offset) ;
961+
945962 let snippet_range = if !stdx:: always!(
946963 snippet_range. is_empty( ) ,
947964 "placeholder range {:?} is before current text edit range {:?}" ,
@@ -965,11 +982,16 @@ fn merge_text_and_snippet_edits(
965982 } )
966983 }
967984
968- if snippets. peek ( ) . is_some_and ( |( _, range) | new_range. intersect ( * range) . is_some ( ) ) {
985+ if snippets. peek ( ) . is_some_and ( |( _, range) | {
986+ new_range. intersect ( offset_range ( * range, source_text_offset) ) . is_some ( )
987+ } ) {
969988 // at least one snippet edit intersects this text edit,
970989 // so gather all of the edits that intersect this text edit
971990 let mut all_snippets = snippets
972- . take_while_ref ( |( _, range) | new_range. intersect ( * range) . is_some ( ) )
991+ . peeking_take_while ( |( _, range) | {
992+ new_range. intersect ( offset_range ( * range, source_text_offset) ) . is_some ( )
993+ } )
994+ . map ( |( tabstop, range) | ( tabstop, offset_range ( range, source_text_offset) ) )
973995 . collect_vec ( ) ;
974996
975997 // ensure all of the ranges are wholly contained inside of the new range
@@ -1010,10 +1032,16 @@ fn merge_text_and_snippet_edits(
10101032 // since it wasn't consumed, it's available for the next pass
10111033 edits. push ( snippet_text_edit ( line_index, false , current_indel) ) ;
10121034 }
1035+
1036+ // update the final source -> initial source mapping offset
1037+ source_text_offset += offset_adjustment;
10131038 }
10141039
10151040 // insert any remaining tabstops
10161041 edits. extend ( snippets. map ( |( snippet_index, snippet_range) | {
1042+ // adjust the snippet range into the corresponding initial source location
1043+ let snippet_range = offset_range ( snippet_range, source_text_offset) ;
1044+
10171045 let snippet_range = if !stdx:: always!(
10181046 snippet_range. is_empty( ) ,
10191047 "found placeholder snippet {:?} without a text edit" ,
0 commit comments