Skip to content
Closed
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
44 changes: 43 additions & 1 deletion src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ import {
isBinaryExpression,
isBindingElement,
isBindingPattern,
isBlock,
isBreakOrContinueStatement,
isCallExpression,
isCaseBlock,
Expand Down Expand Up @@ -598,6 +599,7 @@ const enum KeywordCompletionFilters {
InterfaceElementKeywords, // Keywords inside interface body
ConstructorParameterKeywords, // Keywords at constructor parameter
FunctionLikeBodyKeywords, // Keywords at function like body
ArrowFunctionExpressionBodyKeywords, // Keywords valid as expression-position completions in arrow function expression bodies
TypeAssertionKeywords,
TypeKeywords,
TypeKeyword, // Literally just `type`
Expand Down Expand Up @@ -3982,7 +3984,15 @@ function getCompletionData(
}

function getGlobalCompletions(): void {
keywordFilters = tryGetFunctionLikeBodyCompletionContainer(contextToken) ? KeywordCompletionFilters.FunctionLikeBodyKeywords : KeywordCompletionFilters.All;
if (isInArrowFunctionExpressionBody(contextToken)) {
keywordFilters = KeywordCompletionFilters.ArrowFunctionExpressionBodyKeywords;
}
else if (tryGetFunctionLikeBodyCompletionContainer(contextToken)) {
keywordFilters = KeywordCompletionFilters.FunctionLikeBodyKeywords;
}
else {
keywordFilters = KeywordCompletionFilters.All;
}

// Get all entities in the current scope.
completionKind = CompletionKind.Global;
Expand Down Expand Up @@ -4831,6 +4841,10 @@ function getCompletionData(
}
}

function isInArrowFunctionExpressionBody(contextToken: Node): boolean {
return !!findAncestor(contextToken, (node: Node) => isArrowFunctionBody(node) && !isBlock(node));
}

function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement | undefined {
if (contextToken) {
const parent = contextToken.parent;
Expand Down Expand Up @@ -5488,6 +5502,8 @@ function getTypescriptKeywordCompletions(keywordFilter: KeywordCompletionFilters
|| isTypeKeyword(kind) && kind !== SyntaxKind.UndefinedKeyword;
case KeywordCompletionFilters.FunctionLikeBodyKeywords:
return isFunctionLikeBodyKeyword(kind);
case KeywordCompletionFilters.ArrowFunctionExpressionBodyKeywords:
return isArrowFunctionExpressionBodyKeyword(kind);
case KeywordCompletionFilters.ClassElementKeywords:
return isClassMemberCompletionKeyword(kind);
case KeywordCompletionFilters.InterfaceElementKeywords:
Expand Down Expand Up @@ -5571,6 +5587,32 @@ function isFunctionLikeBodyKeyword(kind: SyntaxKind) {
|| !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind);
}

function isArrowFunctionExpressionBodyKeyword(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.AsyncKeyword:
case SyntaxKind.AwaitKeyword:
case SyntaxKind.ClassKeyword:
case SyntaxKind.DeleteKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.FunctionKeyword:
case SyntaxKind.ImportKeyword:
case SyntaxKind.InKeyword:
case SyntaxKind.InstanceOfKeyword:
case SyntaxKind.NewKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.SuperKeyword:
case SyntaxKind.ThisKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.TypeOfKeyword:
case SyntaxKind.VoidKeyword:
case SyntaxKind.AsKeyword:
case SyntaxKind.SatisfiesKeyword:
return true;
default:
return false;
}
}

function keywordForNode(node: Node): SyntaxKind {
return isIdentifier(node) ? identifierToKeywordKind(node) ?? SyntaxKind.Unknown : node.kind;
}
Expand Down
Loading