@@ -930,6 +930,16 @@ fn merge_text_and_snippet_edits(
930
930
let mut edits: Vec < SnippetTextEdit > = vec ! [ ] ;
931
931
let mut snippets = snippet_edit. into_edit_ranges ( ) . into_iter ( ) . peekable ( ) ;
932
932
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
+ } ;
933
943
934
944
for current_indel in text_edits {
935
945
let new_range = {
@@ -938,10 +948,17 @@ fn merge_text_and_snippet_edits(
938
948
TextRange :: at ( current_indel. delete . start ( ) , insert_len)
939
949
} ;
940
950
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
+
941
955
// 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
+
945
962
let snippet_range = if !stdx:: always!(
946
963
snippet_range. is_empty( ) ,
947
964
"placeholder range {:?} is before current text edit range {:?}" ,
@@ -965,11 +982,16 @@ fn merge_text_and_snippet_edits(
965
982
} )
966
983
}
967
984
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
+ } ) {
969
988
// at least one snippet edit intersects this text edit,
970
989
// so gather all of the edits that intersect this text edit
971
990
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) ) )
973
995
. collect_vec ( ) ;
974
996
975
997
// ensure all of the ranges are wholly contained inside of the new range
@@ -1010,10 +1032,16 @@ fn merge_text_and_snippet_edits(
1010
1032
// since it wasn't consumed, it's available for the next pass
1011
1033
edits. push ( snippet_text_edit ( line_index, false , current_indel) ) ;
1012
1034
}
1035
+
1036
+ // update the final source -> initial source mapping offset
1037
+ source_text_offset += offset_adjustment;
1013
1038
}
1014
1039
1015
1040
// insert any remaining tabstops
1016
1041
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
+
1017
1045
let snippet_range = if !stdx:: always!(
1018
1046
snippet_range. is_empty( ) ,
1019
1047
"found placeholder snippet {:?} without a text edit" ,
0 commit comments