Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions internal/format/format_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package format_test

import (
"context"
"strings"
"testing"

Expand Down Expand Up @@ -58,3 +59,57 @@ func TestFormatNoTrailingNewline(t *testing.T) {
})
}
}

// Test for panic in childStartsOnTheSameLineWithElseInIfStatement
// when FindPrecedingToken returns nil (Issue: panic handling request textDocument/onTypeFormatting)
func TestFormatOnEnter_NilPrecedingToken(t *testing.T) {
t.Parallel()

// Test case where else statement is at the beginning of the file
// which can cause FindPrecedingToken to return nil
testCases := []struct {
name string
text string
position int // position where enter is pressed
}{
{
name: "else at file start - edge case",
text: "if(a){}\nelse{}",
position: 9, // After the newline, before 'else'
},
{
name: "simple if-else with enter after if block",
text: "if (true) {\n}\nelse {\n}",
position: 13, // After "}\n", before "else"
},
{
name: "if-else with enter in else block",
text: "if (true) {\n} else {\n}",
position: 21, // Inside else block
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
sourceFile := parser.ParseSourceFile(ast.SourceFileParseOptions{
FileName: "/test.ts",
Path: "/test.ts",
}, tc.text, core.ScriptKindTS)

ctx := format.WithFormatCodeSettings(context.Background(), &format.FormatCodeSettings{
EditorSettings: format.EditorSettings{
TabSize: 4,
IndentSize: 4,
NewLineCharacter: "\n",
ConvertTabsToSpaces: true,
IndentStyle: format.IndentStyleSmart,
},
}, "\n")

// This should not panic
edits := format.FormatOnEnter(ctx, sourceFile, tc.position)
_ = edits // Just ensuring no panic
})
}
}
6 changes: 6 additions & 0 deletions internal/format/indent.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,12 @@ func findFirstNonWhitespaceCharacterAndColumn(startPos int, endPos int, sourceFi
func childStartsOnTheSameLineWithElseInIfStatement(parent *ast.Node, child *ast.Node, childStartLine int, sourceFile *ast.SourceFile) bool {
if parent.Kind == ast.KindIfStatement && parent.AsIfStatement().ElseStatement == child {
elseKeyword := astnav.FindPrecedingToken(sourceFile, child.Pos())
if elseKeyword == nil {
// In edge cases, FindPrecedingToken can return nil (e.g., else at file start).
// When this happens, we can't determine if the else keyword is on the same line,
// so we return false to avoid a nil pointer dereference.
return false
}
debug.AssertIsDefined(elseKeyword)
elseKeywordStartLine, _ := getStartLineAndCharacterForNode(elseKeyword, sourceFile)
return elseKeywordStartLine == childStartLine
Expand Down