Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 9, 2025

Fixes a panic that occurred when pressing enter in an empty TypeScript file, which triggered textDocument/onTypeFormatting.

Problem

The language server would panic with invalid memory address or nil pointer dereference when:

  1. Opening an empty .ts file
  2. Pressing <enter> to insert a newline

The stack trace showed the panic occurred in getRangeOfEnclosingComment when it tried to use a nil tokenAtPosition node:

panic: runtime error: invalid memory address or nil pointer dereference
...
github.com/microsoft/typescript-go/internal/ls.getRangeOfEnclosingComment(0x140031b4588, 0x1, 0x0, 0x0)
	github.com/microsoft/typescript-go/internal/ls/format.go:147 +0x90
github.com/microsoft/typescript-go/internal/ls.isInComment(0x140031b4588, 0x1, 0x0)
	github.com/microsoft/typescript-go/internal/ls/utilities.go:185 +0x44

Root Cause

In getFormattingEditsAfterKeystroke, the call to isInComment(file, position, nil) passed nil for the tokenAtPosition parameter. This nil value was then passed to getRangeOfEnclosingComment, which attempted to use it without checking, causing nil pointer dereferences.

Solution

Fixed the caller (getFormattingEditsAfterKeystroke) to properly compute tokenAtPosition using astnav.GetTokenAtPosition(file, position) before calling isInComment. This follows the same pattern used elsewhere in the codebase (e.g., in completions.go) and respects the contract documented in the function comments: "It is the caller's responsibility to call astnav.GetTokenAtPosition to compute a default tokenAtPosition."

Testing

Added two test cases that reproduce the original panic:

  • Formatting an empty file with newline at position 0
  • Formatting a simple statement with newline at end of file

All tests pass, including the full test suite.

Fixes #1666

Original prompt

This section details on the original issue you should resolve

<issue_title>Panic Handling textDocument/onTypeFormatting</issue_title>
<issue_description>## Stack trace

panic handling request textDocument/onTypeFormatting runtime error: invalid memory address or nil pointer dereference goroutine 1314 [running]:
runtime/debug.Stack()
	runtime/debug/stack.go:26 +0x64
github.com/microsoft/typescript-go/internal/lsp.(*Server).recover(0x1400010adc0, 0x1400ae41d40)
	github.com/microsoft/typescript-go/internal/lsp/server.go:532 +0x44
panic({0x1011dd960?, 0x101aa2250?})
	runtime/panic.go:783 +0x120
github.com/microsoft/typescript-go/internal/ast.(*Node).Pos(...)
	github.com/microsoft/typescript-go/internal/ast/ast.go:240
github.com/microsoft/typescript-go/internal/scanner.GetTokenPosOfNode(0xa?, 0x140032e92a8?, 0x0?)
	github.com/microsoft/typescript-go/internal/scanner/scanner.go:2318 +0xa8
github.com/microsoft/typescript-go/internal/astnav.GetStartOfNode(...)
	github.com/microsoft/typescript-go/internal/astnav/tokens.go:380
github.com/microsoft/typescript-go/internal/ls.getRangeOfEnclosingComment(0x140031b4588, 0x1, 0x0, 0x0)
	github.com/microsoft/typescript-go/internal/ls/format.go:147 +0x90
github.com/microsoft/typescript-go/internal/ls.isInComment(0x140031b4588, 0x1, 0x0)
	github.com/microsoft/typescript-go/internal/ls/utilities.go:185 +0x44
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getFormattingEditsAfterKeystroke(0x14007775c38?, {0x1013bc710?, 0x1400669f220?}, 0x140031b4588, 0x14009dde480?, 0x1, {0x1011257b0, 0x1})
	github.com/microsoft/typescript-go/internal/ls/format.go:116 +0x60
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).ProvideFormatDocumentOnType(0x14007775c68, {0x1013bc710, 0x1400669f220}, {0x1400ae7a1c0?, 0x1?}, 0x1400ae549c0, {0x2580000?, 0x140?}, {0x1011257b0, 0x1})
	github.com/microsoft/typescript-go/internal/ls/format.go:78 +0xfc
github.com/microsoft/typescript-go/internal/lsp.(*Server).handleDocumentOnTypeFormat(0x140003521c0?, {0x1013bc710?, 0x1400669f220?}, 0x1400ae7a1c0?, 0x34?)
	github.com/microsoft/typescript-go/internal/lsp/server.go:806 +0x40
github.com/microsoft/typescript-go/internal/lsp.init.func1.registerLanguageServiceDocumentRequestHandler[...].21({0x1013bc710, 0x1400669f220}, 0x1400ae41d40)
	github.com/microsoft/typescript-go/internal/lsp/server.go:518 +0xe0
github.com/microsoft/typescript-go/internal/lsp.(*Server).handleRequestOrNotification(0x1400010adc0, {0x1013bc710, 0x1400669f220}, 0x1400ae41d40)
	github.com/microsoft/typescript-go/internal/lsp/server.go:424 +0xf4
github.com/microsoft/typescript-go/internal/lsp.(*Server).dispatchLoop.func1()
	github.com/microsoft/typescript-go/internal/lsp/server.go:329 +0x34
created by github.com/microsoft/typescript-go/internal/lsp.(*Server).dispatchLoop in goroutine 34
	github.com/microsoft/typescript-go/internal/lsp/server.go:349 +0x6f8

Steps to reproduce

  1. Create an empty directory
  2. npm init -y
  3. npm install --save @typescript/native-preview
  4. Open an empty index.ts file
  5. Press <enter> to insert a newline</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #1666


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

@Copilot Copilot AI changed the title [WIP] Fix panic handling in textDocument/onTypeFormatting Fix panic in textDocument/onTypeFormatting when tokenAtPosition is nil Oct 9, 2025
@Copilot Copilot AI requested a review from jakebailey October 9, 2025 11:40
Copilot finished work on behalf of jakebailey October 9, 2025 11:40
@jakebailey
Copy link
Member

@copilot this is a bad fix. These helpers should not have to adapt to callers passing in bad nil values. It's the callers that are wrong

Copy link
Contributor Author

Copilot AI commented Oct 9, 2025

@copilot this is a bad fix. These helpers should not have to adapt to callers passing in bad nil values. It's the callers that are wrong

Fixed in 646b07d (amending previous commits). The caller now properly computes tokenAtPosition using astnav.GetTokenAtPosition(file, position) before calling isInComment, following the same pattern used in completions.go.

Copilot finished work on behalf of jakebailey October 9, 2025 12:05
@jakebailey jakebailey marked this pull request as ready for review October 9, 2025 12:13
@Copilot Copilot AI review requested due to automatic review settings October 9, 2025 12:13
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes a panic in the language server that occurred when pressing enter in an empty TypeScript file, which triggered textDocument/onTypeFormatting. The issue was caused by passing a nil tokenAtPosition parameter to the isInComment function, which then attempted to use it without null checking.

  • Fixed getFormattingEditsAfterKeystroke to properly compute tokenAtPosition before calling isInComment
  • Added test cases to reproduce and verify the fix for the panic scenario

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
internal/ls/format.go Fixed nil pointer dereference by computing tokenAtPosition before calling isInComment
internal/ls/format_test.go Added test cases to reproduce the original panic scenario with empty files and simple statements

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Panic Handling textDocument/onTypeFormatting
2 participants