Skip to content

Commit 6608349

Browse files
authored
Merge pull request microsoft#31008 from andrewbranch/bug/29358
Support binding patterns in Promise -> async/await refactor
2 parents e2310f2 + 95fb694 commit 6608349

15 files changed

+403
-60
lines changed

src/services/codefixes/convertToAsyncFunction.ts

Lines changed: 130 additions & 54 deletions
Large diffs are not rendered by default.

src/services/utilities.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1717,7 +1717,19 @@ namespace ts {
17171717

17181718
export function getSynthesizedDeepCloneWithRenames<T extends Node>(node: T, includeTrivia = true, renameMap?: Map<Identifier>, checker?: TypeChecker, callback?: (originalNode: Node, clone: Node) => any): T {
17191719
let clone;
1720-
if (isIdentifier(node) && renameMap && checker) {
1720+
if (renameMap && checker && isBindingElement(node) && isIdentifier(node.name) && isObjectBindingPattern(node.parent)) {
1721+
const symbol = checker.getSymbolAtLocation(node.name);
1722+
const renameInfo = symbol && renameMap.get(String(getSymbolId(symbol)));
1723+
1724+
if (renameInfo && renameInfo.text !== (node.name || node.propertyName).getText()) {
1725+
clone = createBindingElement(
1726+
node.dotDotDotToken,
1727+
node.propertyName || node.name,
1728+
renameInfo,
1729+
node.initializer);
1730+
}
1731+
}
1732+
else if (renameMap && checker && isIdentifier(node)) {
17211733
const symbol = checker.getSymbolAtLocation(node);
17221734
const renameInfo = symbol && renameMap.get(String(getSymbolId(symbol)));
17231735

src/testRunner/unittests/services/convertToAsyncFunction.ts

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,24 @@ interface Array<T> {}`
347347
_testConvertToAsyncFunction("convertToAsyncFunction_basic", `
348348
function [#|f|](): Promise<void>{
349349
return fetch('https://typescriptlang.org').then(result => { console.log(result) });
350+
}`);
351+
_testConvertToAsyncFunction("convertToAsyncFunction_arrayBindingPattern", `
352+
function [#|f|](): Promise<void>{
353+
return fetch('https://typescriptlang.org').then(([result]) => { console.log(result) });
354+
}`);
355+
_testConvertToAsyncFunction("convertToAsyncFunction_objectBindingPattern", `
356+
function [#|f|](): Promise<void>{
357+
return fetch('https://typescriptlang.org').then(({ result }) => { console.log(result) });
358+
}`);
359+
_testConvertToAsyncFunction("convertToAsyncFunction_arrayBindingPatternRename", `
360+
function [#|f|](): Promise<void>{
361+
const result = getResult();
362+
return fetch('https://typescriptlang.org').then(([result]) => { console.log(result) });
363+
}`);
364+
_testConvertToAsyncFunction("convertToAsyncFunction_objectBindingPatternRename", `
365+
function [#|f|](): Promise<void>{
366+
const result = getResult();
367+
return fetch('https://typescriptlang.org').then(({ result }) => { console.log(result) });
350368
}`);
351369
_testConvertToAsyncFunction("convertToAsyncFunction_basicNoReturnTypeAnnotation", `
352370
function [#|f|]() {
@@ -604,6 +622,50 @@ function [#|innerPromise|](): Promise<string> {
604622
`
605623
);
606624

625+
_testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding1", `
626+
function [#|innerPromise|](): Promise<string> {
627+
return fetch("https://typescriptlang.org").then(resp => {
628+
return resp.blob().then(({ blob }) => blob.byteOffset).catch(({ message }) => 'Error ' + message);
629+
}).then(blob => {
630+
return blob.toString();
631+
});
632+
}
633+
`
634+
);
635+
636+
_testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding2", `
637+
function [#|innerPromise|](): Promise<string> {
638+
return fetch("https://typescriptlang.org").then(resp => {
639+
return resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
640+
}).then(({ x }) => {
641+
return x.toString();
642+
});
643+
}
644+
`
645+
);
646+
647+
_testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding3", `
648+
function [#|innerPromise|](): Promise<string> {
649+
return fetch("https://typescriptlang.org").then(resp => {
650+
return resp.blob().then(({ blob }) => blob.byteOffset).catch(({ message }) => 'Error ' + message);
651+
}).then(([x, y]) => {
652+
return (x || y).toString();
653+
});
654+
}
655+
`
656+
);
657+
658+
_testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding4", `
659+
function [#|innerPromise|](): Promise<string> {
660+
return fetch("https://typescriptlang.org").then(resp => {
661+
return resp.blob().then(({ blob }: { blob: { byteOffset: number } }) => [0, blob.byteOffset]).catch(({ message }: Error) => ['Error ', message]);
662+
}).then(([x, y]) => {
663+
return (x || y).toString();
664+
});
665+
}
666+
`
667+
);
668+
607669
_testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn01", `
608670
function [#|f|]() {
609671
let blob = fetch("https://typescriptlang.org").then(resp => console.log(resp));
@@ -1168,7 +1230,13 @@ const { length } = [#|function|] () {
11681230

11691231
_testConvertToAsyncFunction("convertToAsyncFunction_catchBlockUniqueParams", `
11701232
function [#|f|]() {
1171-
return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x);
1233+
return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x);
1234+
}
1235+
`);
1236+
1237+
_testConvertToAsyncFunction("convertToAsyncFunction_catchBlockUniqueParamsBindingPattern", `
1238+
function [#|f|]() {
1239+
return Promise.resolve().then(() => ({ x: 3 })).catch(() => ({ x: "a" })).then(({ x }) => !!x);
11721240
}
11731241
`);
11741242

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// ==ORIGINAL==
2+
3+
function /*[#|*/innerPromise/*|]*/(): Promise<string> {
4+
return fetch("https://typescriptlang.org").then(resp => {
5+
return resp.blob().then(({ blob }) => blob.byteOffset).catch(({ message }) => 'Error ' + message);
6+
}).then(blob => {
7+
return blob.toString();
8+
});
9+
}
10+
11+
// ==ASYNC FUNCTION::Convert to async function==
12+
13+
async function innerPromise(): Promise<string> {
14+
const resp = await fetch("https://typescriptlang.org");
15+
let blob: any;
16+
try {
17+
const { blob } = await resp.blob();
18+
blob = blob.byteOffset;
19+
}
20+
catch ({ message }) {
21+
blob = 'Error ' + message;
22+
}
23+
return blob.toString();
24+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// ==ORIGINAL==
2+
3+
function /*[#|*/innerPromise/*|]*/(): Promise<string> {
4+
return fetch("https://typescriptlang.org").then(resp => {
5+
return resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
6+
}).then(({ x }) => {
7+
return x.toString();
8+
});
9+
}
10+
11+
// ==ASYNC FUNCTION::Convert to async function==
12+
13+
async function innerPromise(): Promise<string> {
14+
const resp = await fetch("https://typescriptlang.org");
15+
let result: any;
16+
try {
17+
const blob = await resp.blob();
18+
result = blob.byteOffset;
19+
}
20+
catch (err) {
21+
result = 'Error';
22+
}
23+
const { x } = result;
24+
return x.toString();
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// ==ORIGINAL==
2+
3+
function /*[#|*/innerPromise/*|]*/(): Promise<string> {
4+
return fetch("https://typescriptlang.org").then(resp => {
5+
return resp.blob().then(({ blob }) => blob.byteOffset).catch(({ message }) => 'Error ' + message);
6+
}).then(([x, y]) => {
7+
return (x || y).toString();
8+
});
9+
}
10+
11+
// ==ASYNC FUNCTION::Convert to async function==
12+
13+
async function innerPromise(): Promise<string> {
14+
const resp = await fetch("https://typescriptlang.org");
15+
let result: any;
16+
try {
17+
const { blob } = await resp.blob();
18+
result = blob.byteOffset;
19+
}
20+
catch ({ message }) {
21+
result = 'Error ' + message;
22+
}
23+
const [x, y] = result;
24+
return (x || y).toString();
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// ==ORIGINAL==
2+
3+
function /*[#|*/innerPromise/*|]*/(): Promise<string> {
4+
return fetch("https://typescriptlang.org").then(resp => {
5+
return resp.blob().then(({ blob }: { blob: { byteOffset: number } }) => [0, blob.byteOffset]).catch(({ message }: Error) => ['Error ', message]);
6+
}).then(([x, y]) => {
7+
return (x || y).toString();
8+
});
9+
}
10+
11+
// ==ASYNC FUNCTION::Convert to async function==
12+
13+
async function innerPromise(): Promise<string> {
14+
const resp = await fetch("https://typescriptlang.org");
15+
let result: any[];
16+
try {
17+
const { blob } = await resp.blob();
18+
result = [0, blob.byteOffset];
19+
}
20+
catch ({ message }) {
21+
result = ['Error ', message];
22+
}
23+
const [x, y] = result;
24+
return (x || y).toString();
25+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// ==ORIGINAL==
2+
3+
function /*[#|*/f/*|]*/(): Promise<void>{
4+
return fetch('https://typescriptlang.org').then(([result]) => { console.log(result) });
5+
}
6+
// ==ASYNC FUNCTION::Convert to async function==
7+
8+
async function f(): Promise<void>{
9+
const [result] = await fetch('https://typescriptlang.org');
10+
console.log(result);
11+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// ==ORIGINAL==
2+
3+
function /*[#|*/f/*|]*/(): Promise<void>{
4+
const result = getResult();
5+
return fetch('https://typescriptlang.org').then(([result]) => { console.log(result) });
6+
}
7+
// ==ASYNC FUNCTION::Convert to async function==
8+
9+
async function f(): Promise<void>{
10+
const result = getResult();
11+
const [result_1] = await fetch('https://typescriptlang.org');
12+
console.log(result_1);
13+
}

tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_catchBlockUniqueParams.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// ==ORIGINAL==
22

33
function /*[#|*/f/*|]*/() {
4-
return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x);
4+
return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x);
55
}
66

77
// ==ASYNC FUNCTION::Convert to async function==
88

99
async function f() {
10-
let x_2;
10+
let x_2;
1111
try {
1212
const x = await Promise.resolve();
1313
x_2 = 1;

0 commit comments

Comments
 (0)