Skip to content

Commit e27d260

Browse files
committed
Fix new expression edge cases
1 parent a54ed2d commit e27d260

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed

src/services/codefixes/removeUnnecessaryAwait.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,34 @@ namespace ts.codefix {
2727
}
2828

2929
const parenthesizedExpression = tryCast(awaitExpression.parent, isParenthesizedExpression);
30-
// (await 0).toFixed() should keep its parens (or add an extra dot for 0..toFixed())
31-
if (parenthesizedExpression && isPropertyAccessExpression(parenthesizedExpression.parent) && isDecimalIntegerLiteral(awaitExpression.expression)) {
30+
const preserveParens = parenthesizedExpression && (
31+
// (await 0).toFixed() should keep its parens (or add an extra dot for 0..toFixed())
32+
isPropertyAccessExpression(parenthesizedExpression.parent) && isDecimalIntegerLiteral(awaitExpression.expression, sourceFile) ||
33+
// new (await c).Class()
34+
isPropertyAccessExpressionInNewExpression(parenthesizedExpression.parent) ||
35+
// (await new C).foo
36+
isNewExpressionWithoutParens(awaitExpression.expression)
37+
);
38+
39+
if (preserveParens) {
3240
changeTracker.replaceNode(sourceFile, awaitExpression, awaitExpression.expression);
3341
}
3442
else {
3543
changeTracker.replaceNode(sourceFile, parenthesizedExpression || awaitExpression, awaitExpression.expression);
3644
}
3745
}
46+
47+
function isPropertyAccessExpressionInNewExpression(expression: Node) {
48+
return isPropertyAccessExpression(expression) && !!findAncestor(expression, ancestor => {
49+
return isPropertyAccessExpression(ancestor)
50+
? false
51+
: isNewExpression(ancestor)
52+
? true
53+
: "quit";
54+
});
55+
}
56+
57+
function isNewExpressionWithoutParens(expression: Node) {
58+
return isNewExpression(expression) && expression.getLastToken() === expression.expression;
59+
}
3860
}

src/services/utilities.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,8 +1992,8 @@ namespace ts {
19921992
return typeIsAccessible ? res : undefined;
19931993
}
19941994

1995-
export function isDecimalIntegerLiteral(node: Node): node is NumericLiteral {
1996-
return isNumericLiteral(node) && /^\d+$/.test(node.text);
1995+
export function isDecimalIntegerLiteral(node: Node, sourceFile: SourceFile): node is NumericLiteral {
1996+
return isNumericLiteral(node) && /^\d+$/.test(node.getText(sourceFile));
19971997
}
19981998

19991999
export function syntaxUsuallyHasTrailingSemicolon(kind: SyntaxKind) {
Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,46 @@
11
/// <reference path="fourslash.ts" />
2+
////declare class C { foo(): void }
3+
////declare function getC(): { foo: { Class: C } }
24
////async function f() {
35
//// await "";
46
//// await 0;
57
//// (await "").toLowerCase();
68
//// (await 0).toFixed();
79
//// (await 3.2).toFixed();
10+
//// (await new C).foo();
11+
//// new (await getC()).foo.Class();
812
////}
913

1014
verify.codeFix({
1115
description: ts.Diagnostics.Remove_unnecessary_await.message,
1216
index: 0,
1317
newFileContent:
14-
`async function f() {
18+
`declare class C { foo(): void }
19+
declare function getC(): { foo: { Class: C } }
20+
async function f() {
1521
"";
1622
await 0;
1723
(await "").toLowerCase();
1824
(await 0).toFixed();
1925
(await 3.2).toFixed();
26+
(await new C).foo();
27+
new (await getC()).foo.Class();
2028
}`
2129
});
2230

2331
verify.codeFixAll({
2432
fixAllDescription: ts.Diagnostics.Remove_all_unnecessary_uses_of_await.message,
2533
fixId: "removeUnnecessaryAwait",
2634
newFileContent:
27-
`async function f() {
35+
`declare class C { foo(): void }
36+
declare function getC(): { foo: { Class: C } }
37+
async function f() {
2838
"";
2939
0;
3040
"".toLowerCase();
3141
(0).toFixed();
3242
3.2.toFixed();
43+
(new C).foo();
44+
new (getC()).foo.Class();
3345
}`
3446
});

0 commit comments

Comments
 (0)