Skip to content

Commit

Permalink
Merge pull request #31008 from andrewbranch/bug/29358
Browse files Browse the repository at this point in the history
Support binding patterns in Promise -> async/await refactor
  • Loading branch information
andrewbranch committed Apr 24, 2019
2 parents e2310f2 + 95fb694 commit 6608349
Show file tree
Hide file tree
Showing 15 changed files with 403 additions and 60 deletions.
184 changes: 130 additions & 54 deletions src/services/codefixes/convertToAsyncFunction.ts

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion src/services/utilities.ts
Expand Up @@ -1717,7 +1717,19 @@ namespace ts {

export function getSynthesizedDeepCloneWithRenames<T extends Node>(node: T, includeTrivia = true, renameMap?: Map<Identifier>, checker?: TypeChecker, callback?: (originalNode: Node, clone: Node) => any): T {
let clone;
if (isIdentifier(node) && renameMap && checker) {
if (renameMap && checker && isBindingElement(node) && isIdentifier(node.name) && isObjectBindingPattern(node.parent)) {
const symbol = checker.getSymbolAtLocation(node.name);
const renameInfo = symbol && renameMap.get(String(getSymbolId(symbol)));

if (renameInfo && renameInfo.text !== (node.name || node.propertyName).getText()) {
clone = createBindingElement(
node.dotDotDotToken,
node.propertyName || node.name,
renameInfo,
node.initializer);
}
}
else if (renameMap && checker && isIdentifier(node)) {
const symbol = checker.getSymbolAtLocation(node);
const renameInfo = symbol && renameMap.get(String(getSymbolId(symbol)));

Expand Down
70 changes: 69 additions & 1 deletion src/testRunner/unittests/services/convertToAsyncFunction.ts
Expand Up @@ -347,6 +347,24 @@ interface Array<T> {}`
_testConvertToAsyncFunction("convertToAsyncFunction_basic", `
function [#|f|](): Promise<void>{
return fetch('https://typescriptlang.org').then(result => { console.log(result) });
}`);
_testConvertToAsyncFunction("convertToAsyncFunction_arrayBindingPattern", `
function [#|f|](): Promise<void>{
return fetch('https://typescriptlang.org').then(([result]) => { console.log(result) });
}`);
_testConvertToAsyncFunction("convertToAsyncFunction_objectBindingPattern", `
function [#|f|](): Promise<void>{
return fetch('https://typescriptlang.org').then(({ result }) => { console.log(result) });
}`);
_testConvertToAsyncFunction("convertToAsyncFunction_arrayBindingPatternRename", `
function [#|f|](): Promise<void>{
const result = getResult();
return fetch('https://typescriptlang.org').then(([result]) => { console.log(result) });
}`);
_testConvertToAsyncFunction("convertToAsyncFunction_objectBindingPatternRename", `
function [#|f|](): Promise<void>{
const result = getResult();
return fetch('https://typescriptlang.org').then(({ result }) => { console.log(result) });
}`);
_testConvertToAsyncFunction("convertToAsyncFunction_basicNoReturnTypeAnnotation", `
function [#|f|]() {
Expand Down Expand Up @@ -604,6 +622,50 @@ function [#|innerPromise|](): Promise<string> {
`
);

_testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding1", `
function [#|innerPromise|](): Promise<string> {
return fetch("https://typescriptlang.org").then(resp => {
return resp.blob().then(({ blob }) => blob.byteOffset).catch(({ message }) => 'Error ' + message);
}).then(blob => {
return blob.toString();
});
}
`
);

_testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding2", `
function [#|innerPromise|](): Promise<string> {
return fetch("https://typescriptlang.org").then(resp => {
return resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
}).then(({ x }) => {
return x.toString();
});
}
`
);

_testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding3", `
function [#|innerPromise|](): Promise<string> {
return fetch("https://typescriptlang.org").then(resp => {
return resp.blob().then(({ blob }) => blob.byteOffset).catch(({ message }) => 'Error ' + message);
}).then(([x, y]) => {
return (x || y).toString();
});
}
`
);

_testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding4", `
function [#|innerPromise|](): Promise<string> {
return fetch("https://typescriptlang.org").then(resp => {
return resp.blob().then(({ blob }: { blob: { byteOffset: number } }) => [0, blob.byteOffset]).catch(({ message }: Error) => ['Error ', message]);
}).then(([x, y]) => {
return (x || y).toString();
});
}
`
);

_testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn01", `
function [#|f|]() {
let blob = fetch("https://typescriptlang.org").then(resp => console.log(resp));
Expand Down Expand Up @@ -1168,7 +1230,13 @@ const { length } = [#|function|] () {

_testConvertToAsyncFunction("convertToAsyncFunction_catchBlockUniqueParams", `
function [#|f|]() {
return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x);
return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x);
}
`);

_testConvertToAsyncFunction("convertToAsyncFunction_catchBlockUniqueParamsBindingPattern", `
function [#|f|]() {
return Promise.resolve().then(() => ({ x: 3 })).catch(() => ({ x: "a" })).then(({ x }) => !!x);
}
`);

Expand Down
@@ -0,0 +1,24 @@
// ==ORIGINAL==

function /*[#|*/innerPromise/*|]*/(): Promise<string> {
return fetch("https://typescriptlang.org").then(resp => {
return resp.blob().then(({ blob }) => blob.byteOffset).catch(({ message }) => 'Error ' + message);
}).then(blob => {
return blob.toString();
});
}

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

async function innerPromise(): Promise<string> {
const resp = await fetch("https://typescriptlang.org");
let blob: any;
try {
const { blob } = await resp.blob();
blob = blob.byteOffset;
}
catch ({ message }) {
blob = 'Error ' + message;
}
return blob.toString();
}
@@ -0,0 +1,25 @@
// ==ORIGINAL==

function /*[#|*/innerPromise/*|]*/(): Promise<string> {
return fetch("https://typescriptlang.org").then(resp => {
return resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
}).then(({ x }) => {
return x.toString();
});
}

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

async function innerPromise(): Promise<string> {
const resp = await fetch("https://typescriptlang.org");
let result: any;
try {
const blob = await resp.blob();
result = blob.byteOffset;
}
catch (err) {
result = 'Error';
}
const { x } = result;
return x.toString();
}
@@ -0,0 +1,25 @@
// ==ORIGINAL==

function /*[#|*/innerPromise/*|]*/(): Promise<string> {
return fetch("https://typescriptlang.org").then(resp => {
return resp.blob().then(({ blob }) => blob.byteOffset).catch(({ message }) => 'Error ' + message);
}).then(([x, y]) => {
return (x || y).toString();
});
}

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

async function innerPromise(): Promise<string> {
const resp = await fetch("https://typescriptlang.org");
let result: any;
try {
const { blob } = await resp.blob();
result = blob.byteOffset;
}
catch ({ message }) {
result = 'Error ' + message;
}
const [x, y] = result;
return (x || y).toString();
}
@@ -0,0 +1,25 @@
// ==ORIGINAL==

function /*[#|*/innerPromise/*|]*/(): Promise<string> {
return fetch("https://typescriptlang.org").then(resp => {
return resp.blob().then(({ blob }: { blob: { byteOffset: number } }) => [0, blob.byteOffset]).catch(({ message }: Error) => ['Error ', message]);
}).then(([x, y]) => {
return (x || y).toString();
});
}

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

async function innerPromise(): Promise<string> {
const resp = await fetch("https://typescriptlang.org");
let result: any[];
try {
const { blob } = await resp.blob();
result = [0, blob.byteOffset];
}
catch ({ message }) {
result = ['Error ', message];
}
const [x, y] = result;
return (x || y).toString();
}
@@ -0,0 +1,11 @@
// ==ORIGINAL==

function /*[#|*/f/*|]*/(): Promise<void>{
return fetch('https://typescriptlang.org').then(([result]) => { console.log(result) });
}
// ==ASYNC FUNCTION::Convert to async function==

async function f(): Promise<void>{
const [result] = await fetch('https://typescriptlang.org');
console.log(result);
}
@@ -0,0 +1,13 @@
// ==ORIGINAL==

function /*[#|*/f/*|]*/(): Promise<void>{
const result = getResult();
return fetch('https://typescriptlang.org').then(([result]) => { console.log(result) });
}
// ==ASYNC FUNCTION::Convert to async function==

async function f(): Promise<void>{
const result = getResult();
const [result_1] = await fetch('https://typescriptlang.org');
console.log(result_1);
}
@@ -1,13 +1,13 @@
// ==ORIGINAL==

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

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

async function f() {
let x_2;
let x_2;
try {
const x = await Promise.resolve();
x_2 = 1;
Expand Down
@@ -1,13 +1,13 @@
// ==ORIGINAL==

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

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

async function f() {
let x_2: string | number;
let x_2: string | number;
try {
const x = await Promise.resolve();
x_2 = 1;
Expand Down
@@ -0,0 +1,20 @@
// ==ORIGINAL==

function /*[#|*/f/*|]*/() {
return Promise.resolve().then(() => ({ x: 3 })).catch(() => ({ x: "a" })).then(({ x }) => !!x);
}

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

async function f() {
let result;
try {
await Promise.resolve();
result = ({ x: 3 });
}
catch (e) {
result = ({ x: "a" });
}
const { x } = result;
return !!x;
}
@@ -0,0 +1,20 @@
// ==ORIGINAL==

function /*[#|*/f/*|]*/() {
return Promise.resolve().then(() => ({ x: 3 })).catch(() => ({ x: "a" })).then(({ x }) => !!x);
}

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

async function f() {
let result: { x: number; } | { x: string; };
try {
await Promise.resolve();
result = ({ x: 3 });
}
catch (e) {
result = ({ x: "a" });
}
const { x } = result;
return !!x;
}
@@ -0,0 +1,11 @@
// ==ORIGINAL==

function /*[#|*/f/*|]*/(): Promise<void>{
return fetch('https://typescriptlang.org').then(({ result }) => { console.log(result) });
}
// ==ASYNC FUNCTION::Convert to async function==

async function f(): Promise<void>{
const { result } = await fetch('https://typescriptlang.org');
console.log(result);
}
@@ -0,0 +1,13 @@
// ==ORIGINAL==

function /*[#|*/f/*|]*/(): Promise<void>{
const result = getResult();
return fetch('https://typescriptlang.org').then(({ result }) => { console.log(result) });
}
// ==ASYNC FUNCTION::Convert to async function==

async function f(): Promise<void>{
const result = getResult();
const { result: result_1 } = await fetch('https://typescriptlang.org');
console.log(result_1);
}

0 comments on commit 6608349

Please sign in to comment.