Skip to content

Commit 906fbae

Browse files
author
Benjamin Lichtman
committed
Handle promise handler block bodies with no return and other cleanup
1 parent 9079df1 commit 906fbae

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

src/services/codefixes/convertToAsyncFunction.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ namespace ts.codefix {
8282
}
8383

8484
for (const statement of returnStatements) {
85-
forEachChild(statement, function visit(node: Node) {
85+
forEachChild(statement, function visit(node) {
8686
if (isCallExpression(node)) {
8787
startTransformation(node, statement);
8888
}
@@ -179,7 +179,7 @@ namespace ts.codefix {
179179
// Note - the choice of the last call signature is arbitrary
180180
if (lastCallSignature && lastCallSignature.parameters.length && !synthNamesMap.has(symbolIdString)) {
181181
const name = lastCallSignature.parameters[0].name;
182-
const synthName = getNewNameIfConflict(createIdentifier(lastCallSignature.parameters[0].name), allVarNames);
182+
const synthName = getNewNameIfConflict(createIdentifier(name), allVarNames);
183183
synthNamesMap.set(symbolIdString, synthName);
184184
allVarNames.push({ identifier: synthName.identifier, symbol, originalName: name });
185185
}
@@ -404,8 +404,13 @@ namespace ts.codefix {
404404
// Arrow functions with block bodies { } will enter this control flow
405405
if (isFunctionLikeDeclaration(func) && func.body && isBlock(func.body) && func.body.statements) {
406406
let refactoredStmts: Statement[] = [];
407+
let seenReturnStatement = false;
407408

408409
for (const statement of func.body.statements) {
410+
if (isReturnStatement(statement)) {
411+
seenReturnStatement = true;
412+
}
413+
409414
if (getReturnStatementsWithPromiseHandlers(statement).length) {
410415
refactoredStmts = refactoredStmts.concat(getInnerTransformationBody(transformer, [statement], prevArgName));
411416
}
@@ -415,7 +420,7 @@ namespace ts.codefix {
415420
}
416421

417422
return shouldReturn ? getSynthesizedDeepClones(createNodeArray(refactoredStmts)) :
418-
removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer.constIdentifiers);
423+
removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer.constIdentifiers, seenReturnStatement);
419424
}
420425
else {
421426
const funcBody = (<ArrowFunction>func).body;
@@ -443,12 +448,12 @@ namespace ts.codefix {
443448
}
444449

445450
function getLastCallSignature(type: Type, checker: TypeChecker): Signature | undefined {
446-
const callSignatures = type && checker.getSignaturesOfType(type, SignatureKind.Call);
451+
const callSignatures = checker.getSignaturesOfType(type, SignatureKind.Call);
447452
return callSignatures && callSignatures[callSignatures.length - 1];
448453
}
449454

450455

451-
function removeReturns(stmts: NodeArray<Statement>, prevArgName: Identifier, constIdentifiers: Identifier[]): NodeArray<Statement> {
456+
function removeReturns(stmts: NodeArray<Statement>, prevArgName: Identifier, constIdentifiers: Identifier[], seenReturnStatement: boolean): NodeArray<Statement> {
452457
const ret: Statement[] = [];
453458
for (const stmt of stmts) {
454459
if (isReturnStatement(stmt)) {
@@ -462,6 +467,12 @@ namespace ts.codefix {
462467
}
463468
}
464469

470+
// if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables
471+
if (!seenReturnStatement) {
472+
ret.push(createVariableStatement(/*modifiers*/ undefined,
473+
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, constIdentifiers)))));
474+
}
475+
465476
return createNodeArray(ret);
466477
}
467478

0 commit comments

Comments
 (0)