Skip to content

Commit fe297df

Browse files
authored
fix(42034): allow convert async function with empty catch (microsoft#42123)
1 parent e4c4292 commit fe297df

File tree

6 files changed

+73
-12
lines changed

6 files changed

+73
-12
lines changed

src/services/codefixes/convertToAsyncFunction.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ namespace ts.codefix {
235235
return transformThen(node, transformer, prevArgName);
236236
}
237237
if (isPromiseReturningCallExpression(node, transformer.checker, "catch")) {
238-
if (node.arguments.length === 0) return silentFail();
239238
return transformCatch(node, transformer, prevArgName);
240239
}
241240
if (isPropertyAccessExpression(node)) {
@@ -252,15 +251,13 @@ namespace ts.codefix {
252251
}
253252

254253
function transformCatch(node: CallExpression, transformer: Transformer, prevArgName?: SynthBindingName): readonly Statement[] {
255-
const func = node.arguments[0];
256-
const argName = getArgBindingName(func, transformer);
254+
const func = singleOrUndefined(node.arguments);
255+
const argName = func ? getArgBindingName(func, transformer) : undefined;
257256
let possibleNameForVarDecl: SynthIdentifier | undefined;
258257

259-
/*
260-
If there is another call in the chain after the .catch() we are transforming, we will need to save the result of both paths (try block and catch block)
261-
To do this, we will need to synthesize a variable that we were not aware of while we were adding identifiers to the synthNamesMap
262-
We will use the prevArgName and then update the synthNamesMap with a new variable name for the next transformation step
263-
*/
258+
// If there is another call in the chain after the .catch() we are transforming, we will need to save the result of both paths (try block and catch block)
259+
// To do this, we will need to synthesize a variable that we were not aware of while we were adding identifiers to the synthNamesMap
260+
// We will use the prevArgName and then update the synthNamesMap with a new variable name for the next transformation step
264261
if (prevArgName && !shouldReturn(node, transformer)) {
265262
if (isSynthIdentifier(prevArgName)) {
266263
possibleNameForVarDecl = prevArgName;
@@ -282,14 +279,12 @@ namespace ts.codefix {
282279
}
283280

284281
const tryBlock = factory.createBlock(transformExpression(node.expression, transformer, possibleNameForVarDecl));
285-
const transformationBody = getTransformationBody(func, possibleNameForVarDecl, argName, node, transformer);
282+
const transformationBody = func ? getTransformationBody(func, possibleNameForVarDecl, argName, node, transformer) : emptyArray;
286283
const catchArg = argName ? isSynthIdentifier(argName) ? argName.identifier.text : argName.bindingPattern : "e";
287284
const catchVariableDeclaration = factory.createVariableDeclaration(catchArg);
288285
const catchClause = factory.createCatchClause(catchVariableDeclaration, factory.createBlock(transformationBody));
289286

290-
/*
291-
In order to avoid an implicit any, we will synthesize a type for the declaration using the unions of the types of both paths (try block and catch block)
292-
*/
287+
// In order to avoid an implicit any, we will synthesize a type for the declaration using the unions of the types of both paths (try block and catch block)
293288
let varDeclList: VariableStatement | undefined;
294289
let varDeclIdentifier: Identifier | undefined;
295290
if (possibleNameForVarDecl && !shouldReturn(node, transformer)) {

src/testRunner/unittests/services/convertToAsyncFunction.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,6 +1577,18 @@ const fn = (): Promise<(message: string) => void> =>
15771577
function [#|f|]() {
15781578
return fn().then(res => res("test"));
15791579
}
1580+
`);
1581+
1582+
_testConvertToAsyncFunction("convertToAsyncFunction_emptyCatch1", `
1583+
function [#|f|]() {
1584+
return Promise.resolve().catch();
1585+
}
1586+
`);
1587+
1588+
_testConvertToAsyncFunction("convertToAsyncFunction_emptyCatch2", `
1589+
function [#|f|]() {
1590+
return Promise.resolve(0).then(x => x).catch();
1591+
}
15801592
`);
15811593

15821594
_testConvertToAsyncFunctionWithModule("convertToAsyncFunction_importedFunction", `
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// ==ORIGINAL==
2+
3+
function /*[#|*/f/*|]*/() {
4+
return Promise.resolve().catch();
5+
}
6+
7+
// ==ASYNC FUNCTION::Convert to async function==
8+
9+
async function f() {
10+
try {
11+
return Promise.resolve();
12+
} catch (e) { }
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// ==ORIGINAL==
2+
3+
function /*[#|*/f/*|]*/() {
4+
return Promise.resolve().catch();
5+
}
6+
7+
// ==ASYNC FUNCTION::Convert to async function==
8+
9+
async function f() {
10+
try {
11+
return Promise.resolve();
12+
} catch (e) { }
13+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// ==ORIGINAL==
2+
3+
function /*[#|*/f/*|]*/() {
4+
return Promise.resolve(0).then(x => x).catch();
5+
}
6+
7+
// ==ASYNC FUNCTION::Convert to async function==
8+
9+
async function f() {
10+
try {
11+
const x = await Promise.resolve(0);
12+
return x;
13+
} catch (e) { }
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// ==ORIGINAL==
2+
3+
function /*[#|*/f/*|]*/() {
4+
return Promise.resolve(0).then(x => x).catch();
5+
}
6+
7+
// ==ASYNC FUNCTION::Convert to async function==
8+
9+
async function f() {
10+
try {
11+
const x = await Promise.resolve(0);
12+
return x;
13+
} catch (e) { }
14+
}

0 commit comments

Comments
 (0)