Skip to content

Narrow keyword completions for concise arrow expression bodies#3935

Open
DhineshPonnarasan wants to merge 1 commit into
microsoft:mainfrom
DhineshPonnarasan:fix-arrow-expression-body-keyword-completions
Open

Narrow keyword completions for concise arrow expression bodies#3935
DhineshPonnarasan wants to merge 1 commit into
microsoft:mainfrom
DhineshPonnarasan:fix-arrow-expression-body-keyword-completions

Conversation

@DhineshPonnarasan
Copy link
Copy Markdown

Description

This PR ports the arrow expression body keyword filtering fix from microsoft/TypeScript#63485 to the Go implementation.

Problem

The default keyword (and other statement keywords) were incorrectly offered in completions within concise arrow function expression bodies, where only expression keywords are valid.

Example:
\\ ypescript
const arrow = () => /default/ 42; // incorrect - 'default' is a statement keyword
\\

Solution

  • Added \KeywordCompletionFiltersArrowFunctionExpressionBodyKeywords\ enum variant
  • Implemented \isArrowFunctionExpressionBody()\ to detect non-block arrow bodies
  • Defined \isArrowFunctionExpressionBodyKeyword()\ with 23 allowed expression keywords
  • Updated \getTypescriptKeywordCompletions()\ to filter appropriately
  • Prioritized arrow expression check in \getGlobalCompletions()\

Keywords Filtered Out

Statement keywords: return, break, continue, default, etc.
Declaration keywords: var, let, const, function, class (at statement level), etc.

Keywords Still Available

Expression keywords: class (expr), function (expr), new, import, delete, typeof, await, as, satisfies, etc.

Block-body arrow functions preserve full statement keyword availability.

Testing

Go build validates the implementation compiles without errors.

References


Transparency Notice: I used AI assistance while preparing this implementation (investigation, code generation, and validation support), and I reviewed and validated the resulting changes and test runs locally.

- Add KeywordCompletionFiltersArrowFunctionExpressionBodyKeywords filter
- Implement isArrowFunctionExpressionBody() to detect non-block arrow bodies
- Define isArrowFunctionExpressionBodyKeyword() with 23 allowed keywords
- Update getTypescriptKeywordCompletions() to handle new filter
- Wire arrow expression check into getGlobalCompletions() with priority
- Port of JS implementation from microsoft/TypeScript#63485

This prevents statement keywords (return, break, etc.) from being offered
in concise arrow function expression bodies, where only expression keywords
are valid (class, new, function, etc.).

For transparency: I used AI assistance while preparing this draft (investigation, wording, and implementation support), and I reviewed/validated the resulting changes and test runs locally.
Copilot AI review requested due to automatic review settings May 16, 2026 23:35
Copy link
Copy Markdown
Contributor

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

Ports the keyword-completion narrowing from microsoft/TypeScript#63485 so that, inside a concise (non-block) arrow function expression body, only keywords valid in expression position are suggested.

Changes:

  • Adds KeywordCompletionFiltersArrowFunctionExpressionBodyKeywords and wires it into getTypescriptKeywordCompletions.
  • Adds isArrowFunctionExpressionBodyKeyword listing the allowed expression keywords.
  • Adds isArrowFunctionExpressionBody detection and checks it before the function-like-body filter in getGlobalCompletions.

Comment on lines +3449 to +3469
func isArrowFunctionExpressionBody(contextToken *ast.Node) bool {
if contextToken == nil {
return false
}

var prev *ast.Node
result := ast.FindAncestorOrQuit(contextToken, func(node *ast.Node) ast.FindAncestorResult {
// Only arrow functions with non-block bodies
if node.Kind == ast.KindArrowFunction {
arrow := node.AsArrowFunction()
body := arrow.Body
// If body is not a block, and prev is the body (not part of parameters), we're in expression body
if body != nil && body.Kind != ast.KindBlock && prev == body {
return ast.FindAncestorTrue
}
}
prev = node
return ast.FindAncestorFalse
})
return result != nil
}
Comment on lines +3454 to +3468
var prev *ast.Node
result := ast.FindAncestorOrQuit(contextToken, func(node *ast.Node) ast.FindAncestorResult {
// Only arrow functions with non-block bodies
if node.Kind == ast.KindArrowFunction {
arrow := node.AsArrowFunction()
body := arrow.Body
// If body is not a block, and prev is the body (not part of parameters), we're in expression body
if body != nil && body.Kind != ast.KindBlock && prev == body {
return ast.FindAncestorTrue
}
}
prev = node
return ast.FindAncestorFalse
})
return result != nil
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.

2 participants