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
60 changes: 60 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,62 @@ func TestFormatNoTrailingNewline(t *testing.T) {
})
}
}

// Test for panic handling request textDocument/onTypeFormatting (issue #2042)
// The panic occurs when nodes in a list can be nil, causing deriveActualIndentationFromList
// to panic when accessing node properties
func TestFormatOnEnter_NilNodesInList(t *testing.T) {
t.Parallel()

// Test cases that can produce nil nodes in AST lists
testCases := []struct {
name string
text string
position int // position where enter is pressed
}{
{
name: "empty file",
text: "",
position: 0,
},
{
name: "simple statement",
text: "const x = 1;",
position: 12,
},
{
name: "incomplete code",
text: "if (",
position: 4,
},
{
name: "malformed syntax",
text: "function f() { return }",
position: 21,
},
}

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 even with nil nodes in lists
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 @@ -177,13 +177,19 @@ func deriveActualIndentationFromList(list *ast.NodeList, index int, sourceFile *
debug.Assert(list != nil && index >= 0 && index < len(list.Nodes))

node := list.Nodes[index]
if node == nil {
return -1
}

// walk toward the start of the list starting from current node and check if the line is the same for all items.
// if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i]

line, char := getStartLineAndCharacterForNode(node, sourceFile)

for i := index; i >= 0; i-- {
if list.Nodes[i] == nil {
continue
}
if list.Nodes[i].Kind == ast.KindCommaToken {
continue
}
Expand Down