@@ -884,7 +884,7 @@ fn outside_workspace_annotation_id() -> String {
884
884
String :: from ( "OutsideWorkspace" )
885
885
}
886
886
887
- fn merge_text_and_snippet_edit (
887
+ fn merge_text_and_snippet_edits (
888
888
line_index : & LineIndex ,
889
889
edit : TextEdit ,
890
890
snippet_edit : Option < SnippetEdit > ,
@@ -905,34 +905,33 @@ fn merge_text_and_snippet_edit(
905
905
} ;
906
906
907
907
// insert any snippets before the text edit
908
- let first_snippet_in_or_after_edit = loop {
909
- let Some ( ( snippet_index, snippet_range) ) = snippets. peek ( ) else { break None } ;
910
-
911
- // check if we're entirely before the range
912
- // only possible for tabstops
913
- if snippet_range. end ( ) < new_range. start ( )
914
- && stdx:: always!(
915
- snippet_range. is_empty( ) ,
916
- "placeholder range is before any text edits"
917
- )
918
- {
919
- let range = range ( & line_index, * snippet_range) ;
920
- let new_text = format ! ( "${snippet_index}" ) ;
921
-
922
- edits. push ( SnippetTextEdit {
923
- range,
924
- new_text,
925
- insert_text_format : Some ( lsp_types:: InsertTextFormat :: SNIPPET ) ,
926
- annotation_id : None ,
927
- } )
908
+ for ( snippet_index, snippet_range) in
909
+ snippets. take_while_ref ( |( _, range) | range. end ( ) < new_range. start ( ) )
910
+ {
911
+ let snippet_range = if stdx:: never!(
912
+ !snippet_range. is_empty( ) ,
913
+ "placeholder range {:?} is before current text edit range {:?}" ,
914
+ snippet_range,
915
+ new_range
916
+ ) {
917
+ // only possible for tabstops, so make sure it's an empty/insert range
918
+ TextRange :: empty ( snippet_range. start ( ) )
928
919
} else {
929
- break Some ( ( snippet_index, snippet_range) ) ;
930
- }
931
- } ;
920
+ snippet_range
921
+ } ;
932
922
933
- if first_snippet_in_or_after_edit
934
- . is_some_and ( |( _, range) | new_range. intersect ( * range) . is_some ( ) )
935
- {
923
+ let range = range ( & line_index, snippet_range) ;
924
+ let new_text = format ! ( "${snippet_index}" ) ;
925
+
926
+ edits. push ( SnippetTextEdit {
927
+ range,
928
+ new_text,
929
+ insert_text_format : Some ( lsp_types:: InsertTextFormat :: SNIPPET ) ,
930
+ annotation_id : None ,
931
+ } )
932
+ }
933
+
934
+ if snippets. peek ( ) . is_some_and ( |( _, range) | new_range. intersect ( * range) . is_some ( ) ) {
936
935
// at least one snippet edit intersects this text edit,
937
936
// so gather all of the edits that intersect this text edit
938
937
let mut all_snippets = snippets
@@ -984,11 +983,15 @@ fn merge_text_and_snippet_edit(
984
983
// so it's either a tail of text edits or tabstops
985
984
edits. extend ( text_edits. map ( |indel| snippet_text_edit ( line_index, false , indel) ) ) ;
986
985
edits. extend ( snippets. map ( |( snippet_index, snippet_range) | {
987
- stdx:: always !(
988
- snippet_range. is_empty( ) ,
986
+ let snippet_range = if stdx:: never !(
987
+ ! snippet_range. is_empty( ) ,
989
988
"found placeholder snippet {:?} without a text edit" ,
990
989
snippet_range
991
- ) ;
990
+ ) {
991
+ TextRange :: empty ( snippet_range. start ( ) )
992
+ } else {
993
+ snippet_range
994
+ } ;
992
995
993
996
let range = range ( & line_index, snippet_range) ;
994
997
let new_text = format ! ( "${snippet_index}" ) ;
@@ -1012,7 +1015,7 @@ pub(crate) fn snippet_text_document_edit(
1012
1015
) -> Cancellable < lsp_ext:: SnippetTextDocumentEdit > {
1013
1016
let text_document = optional_versioned_text_document_identifier ( snap, file_id) ;
1014
1017
let line_index = snap. file_line_index ( file_id) ?;
1015
- let mut edits = merge_text_and_snippet_edit ( & line_index, edit, snippet_edit) ;
1018
+ let mut edits = merge_text_and_snippet_edits ( & line_index, edit, snippet_edit) ;
1016
1019
1017
1020
if snap. analysis . is_library_file ( file_id) ? && snap. config . change_annotation_support ( ) {
1018
1021
for edit in & mut edits {
0 commit comments