diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 42d737a9e5..fbaf0178d2 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -451,7 +451,11 @@ namespace ts.codefix { } return shouldReturn ? refactoredStmts.map(s => getSynthesizedDeepClone(s)) : - removeReturns(refactoredStmts, prevArgName!.identifier, transformer, seenReturnStatement); + removeReturns( + refactoredStmts, + prevArgName === undefined ? undefined : prevArgName.identifier, + transformer, + seenReturnStatement); } else { const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody)); @@ -491,14 +495,19 @@ namespace ts.codefix { } - function removeReturns(stmts: ReadonlyArray, prevArgName: Identifier, transformer: Transformer, seenReturnStatement: boolean): ReadonlyArray { + function removeReturns(stmts: ReadonlyArray, prevArgName: Identifier | undefined, transformer: Transformer, seenReturnStatement: boolean): ReadonlyArray { const ret: Statement[] = []; for (const stmt of stmts) { if (isReturnStatement(stmt)) { if (stmt.expression) { const possiblyAwaitedExpression = isPromiseReturningExpression(stmt.expression, transformer.checker) ? createAwait(stmt.expression) : stmt.expression; - ret.push(createVariableStatement(/*modifiers*/ undefined, - (createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, possiblyAwaitedExpression)], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers))))); + if (prevArgName === undefined) { + ret.push(createExpressionStatement(possiblyAwaitedExpression)); + } + else { + ret.push(createVariableStatement(/*modifiers*/ undefined, + (createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, possiblyAwaitedExpression)], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers))))); + } } } else { @@ -507,7 +516,7 @@ namespace ts.codefix { } // if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables - if (!seenReturnStatement) { + if (!seenReturnStatement && prevArgName !== undefined) { ret.push(createVariableStatement(/*modifiers*/ undefined, (createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers))))); } diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index c1a08b3319..162b357847 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -1241,6 +1241,19 @@ _testConvertToAsyncFunction("convertToAsyncFunction_nestedPromises", ` function [#|f|]() { return fetch('https://typescriptlang.org').then(x => Promise.resolve(3).then(y => Promise.resolve(x.statusText.length + y))); } +`); +_testConvertToAsyncFunction("convertToAsyncFunction_noArgs", ` +function delay(millis: number): Promise { + throw "no" +} + +function [#|main2|]() { + console.log("Please wait. Loading."); + return delay(500) + .then(() => { console.log("."); return delay(500); }) + .then(() => { console.log("."); return delay(500); }) + .then(() => { console.log("."); return delay(500); }) +} `); }); @@ -1251,4 +1264,4 @@ function [#|f|]() { function _testConvertToAsyncFunctionFailed(caption: string, text: string) { testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", /*includeLib*/ true, /*expectFailure*/ true); } -} \ No newline at end of file +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_noArgs.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_noArgs.js new file mode 100644 index 0000000000..8cda2c9dc9 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_noArgs.js @@ -0,0 +1,30 @@ +// ==ORIGINAL== + +function delay(millis) { + throw "no" +} + +function /*[#|*/main2/*|]*/() { + console.log("Please wait. Loading."); + return delay(500) + .then(() => { console.log("."); return delay(500); }) + .then(() => { console.log("."); return delay(500); }) + .then(() => { console.log("."); return delay(500); }) +} + +// ==ASYNC FUNCTION::Convert to async function== + +function delay(millis) { + throw "no" +} + +async function main2() { + console.log("Please wait. Loading."); + await delay(500); + console.log("."); + await delay(500); + console.log("."); + await delay(500); + console.log("."); + return delay(500); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_noArgs.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_noArgs.ts new file mode 100644 index 0000000000..088bf9f828 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_noArgs.ts @@ -0,0 +1,30 @@ +// ==ORIGINAL== + +function delay(millis: number): Promise { + throw "no" +} + +function /*[#|*/main2/*|]*/() { + console.log("Please wait. Loading."); + return delay(500) + .then(() => { console.log("."); return delay(500); }) + .then(() => { console.log("."); return delay(500); }) + .then(() => { console.log("."); return delay(500); }) +} + +// ==ASYNC FUNCTION::Convert to async function== + +function delay(millis: number): Promise { + throw "no" +} + +async function main2() { + console.log("Please wait. Loading."); + await delay(500); + console.log("."); + await delay(500); + console.log("."); + await delay(500); + console.log("."); + return delay(500); +}