@@ -735,12 +735,21 @@ func (f *FourslashTest) writeMsg(t *testing.T, msg *lsproto.Message) {
735735}
736736
737737func sendRequest [Params , Resp any ](t * testing.T , f * FourslashTest , info lsproto.RequestInfo [Params , Resp ], params Params ) Resp {
738+ t .Helper ()
739+ return sendRequestAndBaselineWorker (t , f , info , params , true )
740+ }
741+
742+ func sendRequestAndBaselineWorker [Params , Resp any ](t * testing.T , f * FourslashTest , info lsproto.RequestInfo [Params , Resp ], params Params , baselineProjects bool ) Resp {
738743 t .Helper ()
739744 prefix := f .getCurrentPositionPrefix ()
740- f .baselineState (t )
745+ if baselineProjects {
746+ f .baselineState (t )
747+ }
741748 f .baselineRequestOrNotification (t , info .Method , params )
742749 resMsg , result , resultOk := sendRequestWorker (t , f , info , params )
743- f .baselineState (t )
750+ if baselineProjects {
751+ f .baselineState (t )
752+ }
744753 switch info .Method {
745754 case lsproto .MethodTextDocumentOnTypeFormatting :
746755 if ! f .reportFormatOnTypeCrash {
@@ -764,8 +773,14 @@ func sendRequest[Params, Resp any](t *testing.T, f *FourslashTest, info lsproto.
764773
765774func sendNotification [Params any ](t * testing.T , f * FourslashTest , info lsproto.NotificationInfo [Params ], params Params ) {
766775 t .Helper ()
767- f .baselineState (t )
768- f .updateState (info .Method , params )
776+ if info .Method != lsproto .MethodTextDocumentDidChange {
777+ // This is called eg when doing typeText = which is series of edits and formatting - which becomes non deterministic "after state"
778+ // The notification can only guarantee before state and thats what it baselines, but in case of type it creates
779+ // multiple edits which results in getting different state -based on if the snapshot was updated or not at the time of formatting requests
780+ // So this is used for all the incremental edits - to baseline only request data but not project state between those edits
781+ f .baselineState (t )
782+ f .updateState (info .Method , params )
783+ }
769784 f .baselineRequestOrNotification (t , info .Method , params )
770785 sendNotificationWorker (t , f , info , params )
771786}
@@ -1665,7 +1680,6 @@ func (f *FourslashTest) VerifyImportFixAtPosition(t *testing.T, expectedTexts []
16651680 // Save the original content before any edits
16661681 script := f .getScriptInfo (f .activeFilename )
16671682 originalContent := script .content
1668-
16691683 // For each import action, apply it and check the result
16701684 actualTextArray := make ([]string , 0 , len (importActions ))
16711685 for _ , action := range importActions {
@@ -2809,19 +2823,22 @@ func roundtripThroughJson[T any](value any) (T, error) {
28092823// Insert text at the current caret position.
28102824func (f * FourslashTest ) Insert (t * testing.T , text string ) {
28112825 t .Helper ()
2826+ f .baselineState (t )
28122827 f .typeText (t , text )
28132828}
28142829
28152830// Insert text and a new line at the current caret position.
28162831func (f * FourslashTest ) InsertLine (t * testing.T , text string ) {
28172832 t .Helper ()
2833+ f .baselineState (t )
28182834 f .typeText (t , text + "\n " )
28192835}
28202836
28212837// Removes the text at the current caret position as if the user pressed backspace `count` times.
28222838func (f * FourslashTest ) Backspace (t * testing.T , count int ) {
28232839 script := f .getScriptInfo (f .activeFilename )
28242840 offset := int (f .converters .LineAndCharacterToPosition (script , f .currentCaretPosition ))
2841+ f .baselineState (t )
28252842
28262843 for range count {
28272844 offset --
@@ -2837,6 +2854,7 @@ func (f *FourslashTest) Backspace(t *testing.T, count int) {
28372854func (f * FourslashTest ) DeleteAtCaret (t * testing.T , count int ) {
28382855 script := f .getScriptInfo (f .activeFilename )
28392856 offset := int (f .converters .LineAndCharacterToPosition (script , f .currentCaretPosition ))
2857+ f .baselineState (t )
28402858
28412859 for range count {
28422860 f .editScriptAndUpdateMarkers (t , f .activeFilename , offset , offset + 1 , "" )
@@ -2848,11 +2866,12 @@ func (f *FourslashTest) DeleteAtCaret(t *testing.T, count int) {
28482866func (f * FourslashTest ) Paste (t * testing.T , text string ) {
28492867 script := f .getScriptInfo (f .activeFilename )
28502868 start := int (f .converters .LineAndCharacterToPosition (script , f .currentCaretPosition ))
2869+ f .baselineState (t )
28512870 f .editScriptAndUpdateMarkers (t , f .activeFilename , start , start , text )
28522871
28532872 // post-paste fomatting
28542873 if f .stateEnableFormatting {
2855- result := sendRequest (t , f , lsproto .TextDocumentRangeFormattingInfo , & lsproto.DocumentRangeFormattingParams {
2874+ result := sendRequestAndBaselineWorker (t , f , lsproto .TextDocumentRangeFormattingInfo , & lsproto.DocumentRangeFormattingParams {
28562875 TextDocument : lsproto.TextDocumentIdentifier {
28572876 Uri : lsconv .FileNameToDocumentURI (f .activeFilename ),
28582877 },
@@ -2861,7 +2880,7 @@ func (f *FourslashTest) Paste(t *testing.T, text string) {
28612880 End : f .converters .PositionToLineAndCharacter (script , core .TextPos (start + len (text ))),
28622881 },
28632882 Options : f .userPreferences .FormatCodeSettings .ToLSFormatOptions (),
2864- })
2883+ }, false )
28652884 if result .TextEdits != nil {
28662885 f .applyTextEdits (t , * result .TextEdits )
28672886 }
@@ -2871,6 +2890,7 @@ func (f *FourslashTest) Paste(t *testing.T, text string) {
28712890
28722891// Selects a line and replaces it with a new text.
28732892func (f * FourslashTest ) ReplaceLine (t * testing.T , lineIndex int , text string ) {
2893+ f .baselineState (t )
28742894 f .selectLine (t , lineIndex )
28752895 f .typeText (t , text )
28762896}
@@ -2944,6 +2964,12 @@ func (f *FourslashTest) applyTextEdits(t *testing.T, edits []*lsproto.TextEdit)
29442964}
29452965
29462966func (f * FourslashTest ) Replace (t * testing.T , start int , length int , text string ) {
2967+ f .baselineState (t )
2968+ f .replaceWorker (t , start , length , text )
2969+ }
2970+
2971+ func (f * FourslashTest ) replaceWorker (t * testing.T , start int , length int , text string ) {
2972+ t .Helper ()
29472973 f .editScriptAndUpdateMarkers (t , f .activeFilename , start , start + length , text )
29482974 // f.checkPostEditInvariants() // !!! do we need this?
29492975}
@@ -2958,7 +2984,7 @@ func (f *FourslashTest) typeText(t *testing.T, text string) {
29582984
29592985 script := f .getScriptInfo (f .activeFilename )
29602986 selection := f .getSelection ()
2961- f .Replace (t , selection .Pos (), selection .End ()- selection .Pos (), "" )
2987+ f .replaceWorker (t , selection .Pos (), selection .End ()- selection .Pos (), "" )
29622988
29632989 totalSize := 0
29642990
@@ -2973,14 +2999,14 @@ func (f *FourslashTest) typeText(t *testing.T, text string) {
29732999
29743000 // Handle post-keystroke formatting
29753001 if f .stateEnableFormatting {
2976- result := sendRequest (t , f , lsproto .TextDocumentOnTypeFormattingInfo , & lsproto.DocumentOnTypeFormattingParams {
3002+ result := sendRequestAndBaselineWorker (t , f , lsproto .TextDocumentOnTypeFormattingInfo , & lsproto.DocumentOnTypeFormattingParams {
29773003 TextDocument : lsproto.TextDocumentIdentifier {
29783004 Uri : lsconv .FileNameToDocumentURI (f .activeFilename ),
29793005 },
29803006 Position : f .currentCaretPosition ,
29813007 Ch : string (r ),
29823008 Options : f .userPreferences .FormatCodeSettings .ToLSFormatOptions (),
2983- })
3009+ }, false )
29843010 if result .TextEdits != nil {
29853011 offset += f .applyTextEdits (t , * result .TextEdits )
29863012 }
0 commit comments