Skip to content

Commit

Permalink
Fixed a crash in completions on functionlike types (#56257)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist authored and DanielRosenwasser committed Nov 16, 2023
1 parent 9684ba6 commit 477dc07
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 11 deletions.
35 changes: 24 additions & 11 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ import {
isCallChain,
isCallExpression,
isCallLikeExpression,
isCallLikeOrFunctionLikeExpression,
isCallOrNewExpression,
isCallSignatureDeclaration,
isCatchClause,
Expand Down Expand Up @@ -1837,23 +1838,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
};

function runWithoutResolvedSignatureCaching<T>(node: Node | undefined, fn: () => T): T {
const cachedSignatures = [];
while (node) {
if (isCallLikeExpression(node)) {
node = findAncestor(node, isCallLikeOrFunctionLikeExpression);
if (node) {
const cachedResolvedSignatures = [];
const cachedTypes = [];
while (node) {
const nodeLinks = getNodeLinks(node);
const resolvedSignature = nodeLinks.resolvedSignature;
cachedSignatures.push([nodeLinks, resolvedSignature] as const);
cachedResolvedSignatures.push([nodeLinks, nodeLinks.resolvedSignature] as const);
nodeLinks.resolvedSignature = undefined;
if (isFunctionExpressionOrArrowFunction(node)) {
const symbolLinks = getSymbolLinks(getSymbolOfDeclaration(node));
const type = symbolLinks.type;
cachedTypes.push([symbolLinks, type] as const);
symbolLinks.type = undefined;
}
node = findAncestor(node.parent, isCallLikeOrFunctionLikeExpression);
}
node = node.parent;
}
const result = fn();
for (const [nodeLinks, resolvedSignature] of cachedSignatures) {
nodeLinks.resolvedSignature = resolvedSignature;
const result = fn();
for (const [nodeLinks, resolvedSignature] of cachedResolvedSignatures) {
nodeLinks.resolvedSignature = resolvedSignature;
}
for (const [symbolLinks, type] of cachedTypes) {
symbolLinks.type = type;
}
return result;
}
return result;
return fn();
}


function runWithInferenceBlockedFromSourceNode<T>(node: Node | undefined, fn: () => T): T {
const containingCall = findAncestor(node, isCallLikeExpression);
if (containingCall) {
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/utilitiesPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ArrayBindingElement,
ArrayBindingOrAssignmentElement,
ArrayBindingOrAssignmentPattern,
ArrowFunction,
AssertionExpression,
AssertionKey,
AssignmentDeclarationKind,
Expand Down Expand Up @@ -65,6 +66,7 @@ import {
ForInitializer,
ForInOrOfStatement,
FunctionBody,
FunctionExpression,
FunctionLikeDeclaration,
FunctionTypeNode,
GeneratedIdentifier,
Expand Down Expand Up @@ -116,6 +118,7 @@ import {
isExportSpecifier,
isFunctionBlock,
isFunctionExpression,
isFunctionExpressionOrArrowFunction,
isFunctionTypeNode,
isIdentifier,
isImportSpecifier,
Expand Down Expand Up @@ -1917,6 +1920,11 @@ export function isPropertyAccessOrQualifiedName(node: Node): node is PropertyAcc
|| kind === SyntaxKind.QualifiedName;
}

/** @internal */
export function isCallLikeOrFunctionLikeExpression(node: Node): node is CallLikeExpression | FunctionExpression | ArrowFunction {
return isCallLikeExpression(node) || isFunctionExpressionOrArrowFunction(node);
}

export function isCallLikeExpression(node: Node): node is CallLikeExpression {
switch (node.kind) {
case SyntaxKind.JsxOpeningElement:
Expand Down
13 changes: 13 additions & 0 deletions tests/cases/fourslash/jsDocFunctionTypeCompletionsNoCrash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
///<reference path="fourslash.ts" />

//// /**
//// * @returns {function/**/(): string}
//// */
//// function updateCalendarEvent() {
//// return "";
//// }

verify.completions({
marker: "",
exact: completion.globalTypes
});

0 comments on commit 477dc07

Please sign in to comment.