• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts {
2    const libFile: TestFSWithWatch.File = {
3        path: "/a/lib/lib.d.ts",
4        content: `/// <reference no-default-lib="true"/>
5interface Boolean {}
6interface Function {}
7interface IArguments {}
8interface Number { toExponential: any; }
9interface Object {}
10declare function fetch(input?, init?): Promise<Response>;
11interface Response extends Body {
12    readonly headers: Headers;
13    readonly ok: boolean;
14    readonly redirected: boolean;
15    readonly status: number;
16    readonly statusText: string;
17    readonly trailer: Promise<Headers>;
18    readonly type: ResponseType;
19    readonly url: string;
20    clone(): Response;
21}
22interface Body {
23    readonly body: ReadableStream | null;
24    readonly bodyUsed: boolean;
25    arrayBuffer(): Promise<ArrayBuffer>;
26    blob(): Promise<Blob>;
27    formData(): Promise<FormData>;
28    json(): Promise<any>;
29    text(): Promise<string>;
30}
31declare type PromiseConstructorLike = new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) => PromiseLike<T>;
32interface PromiseLike<T> {
33    /**
34     * Attaches callbacks for the resolution and/or rejection of the Promise.
35     * @param onfulfilled The callback to execute when the Promise is resolved.
36     * @param onrejected The callback to execute when the Promise is rejected.
37     * @returns A Promise for the completion of which ever callback is executed.
38     */
39    then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
40}
41interface Promise<T> {
42    /**
43     * Attaches callbacks for the resolution and/or rejection of the Promise.
44     * @param onfulfilled The callback to execute when the Promise is resolved.
45     * @param onrejected The callback to execute when the Promise is rejected.
46     * @returns A Promise for the completion of which ever callback is executed.
47     */
48    then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
49
50    /**
51     * Attaches a callback for only the rejection of the Promise.
52     * @param onrejected The callback to execute when the Promise is rejected.
53     * @returns A Promise for the completion of the callback.
54     */
55    catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
56}
57interface PromiseConstructor {
58    /**
59     * A reference to the prototype.
60     */
61    readonly prototype: Promise<any>;
62
63    /**
64     * Creates a new Promise.
65     * @param executor A callback used to initialize the promise. This callback is passed two arguments:
66     * a resolve callback used resolve the promise with a value or the result of another promise,
67     * and a reject callback used to reject the promise with a provided reason or error.
68     */
69    new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
70
71    /**
72     * Creates a Promise that is resolved with an array of results when all of the provided Promises
73     * resolve, or rejected when any Promise is rejected.
74     * @param values An array of Promises.
75     * @returns A new Promise.
76     */
77    all<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>;
78
79    /**
80     * Creates a Promise that is resolved with an array of results when all of the provided Promises
81     * resolve, or rejected when any Promise is rejected.
82     * @param values An array of Promises.
83     * @returns A new Promise.
84     */
85    all<T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>;
86
87    /**
88     * Creates a Promise that is resolved with an array of results when all of the provided Promises
89     * resolve, or rejected when any Promise is rejected.
90     * @param values An array of Promises.
91     * @returns A new Promise.
92     */
93    all<T1, T2, T3, T4, T5, T6, T7, T8>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>;
94
95    /**
96     * Creates a Promise that is resolved with an array of results when all of the provided Promises
97     * resolve, or rejected when any Promise is rejected.
98     * @param values An array of Promises.
99     * @returns A new Promise.
100     */
101    all<T1, T2, T3, T4, T5, T6, T7>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>;
102
103    /**
104     * Creates a Promise that is resolved with an array of results when all of the provided Promises
105     * resolve, or rejected when any Promise is rejected.
106     * @param values An array of Promises.
107     * @returns A new Promise.
108     */
109    all<T1, T2, T3, T4, T5, T6>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>;
110
111    /**
112     * Creates a Promise that is resolved with an array of results when all of the provided Promises
113     * resolve, or rejected when any Promise is rejected.
114     * @param values An array of Promises.
115     * @returns A new Promise.
116     */
117    all<T1, T2, T3, T4, T5>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>]): Promise<[T1, T2, T3, T4, T5]>;
118
119    /**
120     * Creates a Promise that is resolved with an array of results when all of the provided Promises
121     * resolve, or rejected when any Promise is rejected.
122     * @param values An array of Promises.
123     * @returns A new Promise.
124     */
125    all<T1, T2, T3, T4>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>]): Promise<[T1, T2, T3, T4]>;
126
127    /**
128     * Creates a Promise that is resolved with an array of results when all of the provided Promises
129     * resolve, or rejected when any Promise is rejected.
130     * @param values An array of Promises.
131     * @returns A new Promise.
132     */
133    all<T1, T2, T3>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>;
134
135    /**
136     * Creates a Promise that is resolved with an array of results when all of the provided Promises
137     * resolve, or rejected when any Promise is rejected.
138     * @param values An array of Promises.
139     * @returns A new Promise.
140     */
141    all<T1, T2>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;
142
143    /**
144     * Creates a Promise that is resolved with an array of results when all of the provided Promises
145     * resolve, or rejected when any Promise is rejected.
146     * @param values An array of Promises.
147     * @returns A new Promise.
148     */
149    all<T>(values: (T | PromiseLike<T>)[]): Promise<T[]>;
150
151    /**
152     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
153     * or rejected.
154     * @param values An array of Promises.
155     * @returns A new Promise.
156     */
157    race<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10>;
158
159    /**
160     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
161     * or rejected.
162     * @param values An array of Promises.
163     * @returns A new Promise.
164     */
165    race<T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9>;
166
167    /**
168     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
169     * or rejected.
170     * @param values An array of Promises.
171     * @returns A new Promise.
172     */
173    race<T1, T2, T3, T4, T5, T6, T7, T8>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8>;
174
175    /**
176     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
177     * or rejected.
178     * @param values An array of Promises.
179     * @returns A new Promise.
180     */
181    race<T1, T2, T3, T4, T5, T6, T7>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<T1 | T2 | T3 | T4 | T5 | T6 | T7>;
182
183    /**
184     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
185     * or rejected.
186     * @param values An array of Promises.
187     * @returns A new Promise.
188     */
189    race<T1, T2, T3, T4, T5, T6>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<T1 | T2 | T3 | T4 | T5 | T6>;
190
191    /**
192     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
193     * or rejected.
194     * @param values An array of Promises.
195     * @returns A new Promise.
196     */
197    race<T1, T2, T3, T4, T5>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>]): Promise<T1 | T2 | T3 | T4 | T5>;
198
199    /**
200     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
201     * or rejected.
202     * @param values An array of Promises.
203     * @returns A new Promise.
204     */
205    race<T1, T2, T3, T4>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<T1 | T2 | T3 | T4>;
206
207    /**
208     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
209     * or rejected.
210     * @param values An array of Promises.
211     * @returns A new Promise.
212     */
213    race<T1, T2, T3>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<T1 | T2 | T3>;
214
215    /**
216     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
217     * or rejected.
218     * @param values An array of Promises.
219     * @returns A new Promise.
220     */
221    race<T1, T2>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<T1 | T2>;
222
223    /**
224     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
225     * or rejected.
226     * @param values An array of Promises.
227     * @returns A new Promise.
228     */
229    race<T>(values: (T | PromiseLike<T>)[]): Promise<T>;
230
231    /**
232     * Creates a new rejected promise for the provided reason.
233     * @param reason The reason the promise was rejected.
234     * @returns A new rejected Promise.
235     */
236    reject<T = never>(reason?: any): Promise<T>;
237
238    /**
239     * Creates a new resolved promise for the provided value.
240     * @param value A promise.
241     * @returns A promise whose internal state matches the provided promise.
242     */
243    resolve<T>(value: T | PromiseLike<T>): Promise<T>;
244
245    /**
246     * Creates a new resolved promise .
247     * @returns A resolved promise.
248     */
249    resolve(): Promise<void>;
250}
251
252declare var Promise: PromiseConstructor;
253interface RegExp {}
254interface String { charAt: any; }
255interface Array<T> {}`
256    };
257
258    const moduleFile: TestFSWithWatch.File = {
259        path: "/module.ts",
260        content:
261`export function fn(res: any): any {
262    return res;
263}`
264    };
265
266    type WithSkipAndOnly<T extends any[]> = ((...args: T) => void) & {
267        skip: (...args: T) => void;
268        only: (...args: T) => void;
269    };
270
271    function createTestWrapper<T extends any[]>(fn: (it: Mocha.PendingTestFunction, ...args: T) => void): WithSkipAndOnly<T> {
272        wrapped.skip = (...args: T) => fn(it.skip, ...args);
273        wrapped.only = (...args: T) => fn(it.only, ...args);
274        return wrapped;
275        function wrapped(...args: T) {
276            return fn(it, ...args);
277        }
278    }
279
280    function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: string, text: string, baselineFolder: string, includeLib?: boolean, includeModule?: boolean, expectFailure = false, onlyProvideAction = false) {
281        const t = extractTest(text);
282        const selectionRange = t.ranges.get("selection")!;
283        if (!selectionRange) {
284            throw new Error(`Test ${caption} does not specify selection range`);
285        }
286
287        const extensions = expectFailure ? [Extension.Ts] : [Extension.Ts, Extension.Js];
288
289        extensions.forEach(extension =>
290            it(`${caption} [${extension}]`, () => runBaseline(extension)));
291
292        function runBaseline(extension: Extension) {
293            const path = "/a" + extension;
294            const languageService = makeLanguageService({ path, content: t.source }, includeLib, includeModule);
295            const program = languageService.getProgram()!;
296
297            if (hasSyntacticDiagnostics(program)) {
298                // Don't bother generating JS baselines for inputs that aren't valid JS.
299                assert.equal(Extension.Js, extension, "Syntactic diagnostics found in non-JS file");
300                return;
301            }
302
303            const f = {
304                path,
305                content: t.source
306            };
307
308            const sourceFile = program.getSourceFile(path)!;
309            const context: CodeFixContext = {
310                errorCode: 80006,
311                span: { start: selectionRange.pos, length: selectionRange.end - selectionRange.pos },
312                sourceFile,
313                program,
314                cancellationToken: { throwIfCancellationRequested: noop, isCancellationRequested: returnFalse },
315                preferences: emptyOptions,
316                host: notImplementedHost,
317                formatContext: formatting.getFormatContext(testFormatSettings, notImplementedHost)
318            };
319
320            const diagnostics = languageService.getSuggestionDiagnostics(f.path);
321            const diagnostic = find(diagnostics, diagnostic => diagnostic.messageText === Diagnostics.This_may_be_converted_to_an_async_function.message &&
322                diagnostic.start === context.span.start && diagnostic.length === context.span.length);
323            if (expectFailure) {
324                assert.isUndefined(diagnostic);
325            }
326            else {
327                assert.exists(diagnostic);
328            }
329
330            const actions = codefix.getFixes(context);
331            const action = find(actions, action => action.description === Diagnostics.Convert_to_async_function.message);
332            if (expectFailure && !onlyProvideAction) {
333                assert.isNotTrue(action && action.changes.length > 0);
334                return;
335            }
336
337            assert.isTrue(action && action.changes.length > 0);
338
339            const data: string[] = [];
340            data.push(`// ==ORIGINAL==`);
341            data.push(text.replace("[#|", "/*[#|*/").replace("|]", "/*|]*/"));
342            const changes = action!.changes;
343            assert.lengthOf(changes, 1);
344
345            data.push(`// ==ASYNC FUNCTION::${action!.description}==`);
346            const newText = textChanges.applyChanges(sourceFile.text, changes[0].textChanges);
347            data.push(newText);
348
349            const diagProgram = makeLanguageService({ path, content: newText }, includeLib, includeModule).getProgram()!;
350            assert.isFalse(hasSyntacticDiagnostics(diagProgram));
351            Harness.Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, data.join(newLineCharacter));
352        }
353
354        function makeLanguageService(file: TestFSWithWatch.File, includeLib?: boolean, includeModule?: boolean) {
355            const files = [file];
356            if (includeLib) {
357                files.push(libFile); // libFile is expensive to parse repeatedly - only test when required
358            }
359            if (includeModule) {
360                files.push(moduleFile);
361            }
362            const host = projectSystem.createServerHost(files);
363            const projectService = projectSystem.createProjectService(host);
364            projectService.openClientFile(file.path);
365            return first(projectService.inferredProjects).getLanguageService();
366        }
367
368        function hasSyntacticDiagnostics(program: Program) {
369            const diags = program.getSyntacticDiagnostics();
370            return length(diags) > 0;
371        }
372    }
373
374    const _testConvertToAsyncFunction = createTestWrapper((it, caption: string, text: string) => {
375        testConvertToAsyncFunction(it, caption, text, "convertToAsyncFunction", /*includeLib*/ true);
376    });
377
378    const _testConvertToAsyncFunctionFailed = createTestWrapper((it, caption: string, text: string) => {
379        testConvertToAsyncFunction(it, caption, text, "convertToAsyncFunction", /*includeLib*/ true, /*includeModule*/ false, /*expectFailure*/ true);
380    });
381
382    const _testConvertToAsyncFunctionFailedSuggestion = createTestWrapper((it, caption: string, text: string) => {
383        testConvertToAsyncFunction(it, caption, text, "convertToAsyncFunction", /*includeLib*/ true, /*includeModule*/ false, /*expectFailure*/ true, /*onlyProvideAction*/ true);
384    });
385
386    const _testConvertToAsyncFunctionWithModule = createTestWrapper((it, caption: string, text: string) => {
387        testConvertToAsyncFunction(it, caption, text, "convertToAsyncFunction", /*includeLib*/ true, /*includeModule*/ true);
388    });
389
390    describe("unittests:: services:: convertToAsyncFunction", () => {
391        _testConvertToAsyncFunction("convertToAsyncFunction_basic", `
392function [#|f|](): Promise<void>{
393    return fetch('https://typescriptlang.org').then(result => { console.log(result) });
394}`);
395        _testConvertToAsyncFunction("convertToAsyncFunction_arrayBindingPattern", `
396function [#|f|](): Promise<void>{
397    return fetch('https://typescriptlang.org').then(([result]) => { console.log(result) });
398}`);
399        _testConvertToAsyncFunction("convertToAsyncFunction_objectBindingPattern", `
400function [#|f|](): Promise<void>{
401    return fetch('https://typescriptlang.org').then(({ result }) => { console.log(result) });
402}`);
403        _testConvertToAsyncFunction("convertToAsyncFunction_arrayBindingPatternRename", `
404function [#|f|](): Promise<void>{
405    const result = getResult();
406    return fetch('https://typescriptlang.org').then(([result]) => { console.log(result) });
407}`);
408        _testConvertToAsyncFunction("convertToAsyncFunction_objectBindingPatternRename", `
409function [#|f|](): Promise<void>{
410    const result = getResult();
411    return fetch('https://typescriptlang.org').then(({ result }) => { console.log(result) });
412}`);
413        _testConvertToAsyncFunction("convertToAsyncFunction_basicNoReturnTypeAnnotation", `
414function [#|f|]() {
415    return fetch('https://typescriptlang.org').then(result => { console.log(result) });
416}`);
417        _testConvertToAsyncFunction("convertToAsyncFunction_basicWithComments", `
418function [#|f|](): Promise<void>{
419    /* Note - some of these comments are removed during the refactor. This is not ideal. */
420
421    // a
422    /*b*/ return /*c*/ fetch( /*d*/ 'https://typescriptlang.org' /*e*/).then( /*f*/ result /*g*/ => { /*h*/ console.log(/*i*/ result /*j*/) /*k*/}/*l*/);
423    // m
424}`);
425
426        _testConvertToAsyncFunction("convertToAsyncFunction_ArrowFunction", `
427[#|():Promise<void> => {|]
428    return fetch('https://typescriptlang.org').then(result => console.log(result));
429}`);
430        _testConvertToAsyncFunction("convertToAsyncFunction_ArrowFunctionNoAnnotation", `
431[#|() => {|]
432    return fetch('https://typescriptlang.org').then(result => console.log(result));
433}`);
434        _testConvertToAsyncFunction("convertToAsyncFunction_Catch", `
435function [#|f|]():Promise<void> {
436    return fetch('https://typescriptlang.org').then(result => { console.log(result); }).catch(err => { console.log(err); });
437}`);
438        _testConvertToAsyncFunction("convertToAsyncFunction_CatchAndRej", `
439function [#|f|]():Promise<void> {
440    return fetch('https://typescriptlang.org').then(result => { console.log(result); }, rejection => { console.log("rejected:", rejection); }).catch(err => { console.log(err) });
441}`);
442        _testConvertToAsyncFunction("convertToAsyncFunction_CatchAndRejRef", `
443function [#|f|]():Promise<void> {
444    return fetch('https://typescriptlang.org').then(res, rej).catch(catch_err)
445}
446function res(result){
447    console.log(result);
448}
449function rej(rejection){
450    return rejection.ok;
451}
452function catch_err(err){
453    console.log(err);
454}`);
455        _testConvertToAsyncFunction("convertToAsyncFunction_CatchRef", `
456function [#|f|]():Promise<void> {
457    return fetch('https://typescriptlang.org').then(res).catch(catch_err)
458}
459function res(result){
460    console.log(result);
461}
462function catch_err(err){
463    console.log(err);
464}
465`);
466        _testConvertToAsyncFunction("convertToAsyncFunction_CatchNoBrackets", `
467function [#|f|]():Promise<void> {
468    return fetch('https://typescriptlang.org').then(result => console.log(result)).catch(err => console.log(err));
469}`
470        );
471        _testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs1", `
472function [#|f|](): Promise<void> {
473    return fetch('https://typescriptlang.org').then( _ => { console.log("done"); });
474}`
475        );
476        _testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs2", `
477function [#|f|](): Promise<void> {
478    return fetch('https://typescriptlang.org').then( () => console.log("done") );
479}`
480        );
481        _testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs3", `
482function [#|f|](): Promise<void> {
483    return fetch('https://typescriptlang.org').then( () => console.log("almost done") ).then( () => console.log("done") );
484}`
485        );
486        _testConvertToAsyncFunction("convertToAsyncFunction_IgnoreArgs4", `
487function [#|f|]() {
488    return fetch('https://typescriptlang.org').then(res);
489}
490function res(){
491    console.log("done");
492}`
493        );
494
495        _testConvertToAsyncFunction("convertToAsyncFunction_Method", `
496class Parser {
497    [#|f|]():Promise<void> {
498        return fetch('https://typescriptlang.org').then(result => console.log(result));
499    }
500}`
501        );
502        _testConvertToAsyncFunction("convertToAsyncFunction_MultipleCatches", `
503function [#|f|](): Promise<void> {
504    return fetch('https://typescriptlang.org').then(res => console.log(res)).catch(err => console.log("err", err)).catch(err2 => console.log("err2", err2));
505}`
506        );
507        _testConvertToAsyncFunction("convertToAsyncFunction_MultipleThens", `
508function [#|f|]():Promise<void> {
509    return fetch('https://typescriptlang.org').then(res).then(res2);
510}
511function res(result){
512    return result.ok;
513}
514function res2(result2){
515    console.log(result2);
516}`
517        );
518        _testConvertToAsyncFunction("convertToAsyncFunction_MultipleThensSameVarName", `
519function [#|f|]():Promise<void> {
520    return fetch('https://typescriptlang.org').then(res).then(res2);
521}
522function res(result){
523    return result.ok;
524}
525function res2(result){
526    return result.bodyUsed;
527}
528`
529        );
530        _testConvertToAsyncFunction("convertToAsyncFunction_NoRes", `
531function [#|f|]():Promise<void | Response> {
532    return fetch('https://typescriptlang.org').then(null, rejection => console.log("rejected:", rejection));
533}
534`
535        );
536        _testConvertToAsyncFunction("convertToAsyncFunction_NoRes2", `
537function [#|f|]():Promise<void | Response> {
538    return fetch('https://typescriptlang.org').then(undefined).catch(rej => console.log(rej));
539}
540`
541        );
542
543        _testConvertToAsyncFunction("convertToAsyncFunction_NoRes3", `
544function [#|f|]():Promise<void | Response> {
545    return fetch('https://typescriptlang.org').catch(rej => console.log(rej));
546}
547`
548        );
549        _testConvertToAsyncFunction("convertToAsyncFunction_NoRes4", `
550function [#|f|]() {
551    return fetch('https://typescriptlang.org').then(undefined, rejection => console.log("rejected:", rejection));
552}
553`
554        );
555        _testConvertToAsyncFunction("convertToAsyncFunction_NoCatchHandler", `
556function [#|f|]() {
557    return fetch('https://typescriptlang.org').then(x => x.statusText).catch(undefined);
558}
559`
560        );
561        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestion", `
562function [#|f|]():Promise<Response> {
563    return fetch('https://typescriptlang.org');
564}
565`
566        );
567        _testConvertToAsyncFunction("convertToAsyncFunction_PromiseDotAll", `
568function [#|f|]():Promise<void>{
569    return Promise.all([fetch('https://typescriptlang.org'), fetch('https://microsoft.com'), fetch('https://youtube.com')]).then(function(vals){
570        vals.forEach(console.log);
571    });
572}
573`
574        );
575        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestionNoPromise", `
576function [#|f|]():void{
577}
578`
579        );
580        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Rej", `
581function [#|f|]():Promise<void> {
582    return fetch('https://typescriptlang.org').then(result => { console.log(result); }, rejection => { console.log("rejected:", rejection); });
583}
584`
585        );
586        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_RejRef", `
587function [#|f|]():Promise<void> {
588    return fetch('https://typescriptlang.org').then(res, rej);
589}
590function res(result){
591    console.log(result);
592}
593function rej(err){
594    console.log(err);
595}
596`
597        );
598        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_RejNoBrackets", `
599function [#|f|]():Promise<void> {
600    return fetch('https://typescriptlang.org').then(result => console.log(result), rejection => console.log("rejected:", rejection));
601}
602`
603        );
604
605        _testConvertToAsyncFunction("convertToAsyncFunction_ResRef", `
606function [#|f|]():Promise<boolean> {
607    return fetch('https://typescriptlang.org').then(res);
608}
609function res(result){
610    return result.ok;
611}
612`
613        );
614
615        _testConvertToAsyncFunction("convertToAsyncFunction_ResRef1", `
616class Foo {
617    public [#|method|](): Promise<boolean> {
618        return fetch('a').then(this.foo);
619    }
620
621    private foo(res) {
622        return res.ok;
623    }
624}
625        `);
626
627        _testConvertToAsyncFunction("convertToAsyncFunction_ResRef2", `
628class Foo {
629    public [#|method|](): Promise<Response> {
630        return fetch('a').then(this.foo);
631    }
632
633    private foo = res => res;
634}
635        `);
636
637        _testConvertToAsyncFunction("convertToAsyncFunction_ResRef3", `
638const res = (result) => {
639    return result.ok;
640}
641function [#|f|](): Promise<boolean> {
642    return fetch('https://typescriptlang.org').then(res);
643}
644        `
645        );
646
647        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestionResRef1", `
648const res = 1;
649function [#|f|]() {
650    return fetch('https://typescriptlang.org').then(res);
651}
652`
653        );
654
655        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestionResRef2", `
656class Foo {
657    private foo = 1;
658    public [#|method|](): Promise<boolean> {
659        return fetch('a').then(this.foo);
660    }
661}
662`
663        );
664
665        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestionResRef3", `
666const res = undefined;
667function [#|f|]() {
668    return fetch('https://typescriptlang.org').then(res);
669}
670`
671        );
672
673        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestionResRef4", `
674class Foo {
675    private foo = undefined;
676    public [#|method|](): Promise<boolean> {
677        return fetch('a').then(this.foo);
678    }
679}
680`
681        );
682
683        _testConvertToAsyncFunction("convertToAsyncFunction_ResRefNoReturnVal", `
684function [#|f|]():Promise<void> {
685    return fetch('https://typescriptlang.org').then(res);
686}
687function res(result){
688    console.log(result);
689}
690`
691        );
692
693        _testConvertToAsyncFunction("convertToAsyncFunction_ResRefNoReturnVal1", `
694class Foo {
695    public [#|method|](): Promise<void> {
696        return fetch('a').then(this.foo);
697    }
698
699    private foo(res) {
700        console.log(res);
701    }
702}
703        `);
704
705        _testConvertToAsyncFunction("convertToAsyncFunction_NoBrackets", `
706function [#|f|]():Promise<void> {
707    return fetch('https://typescriptlang.org').then(result => console.log(result));
708}
709`
710        );
711        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Finally1", `
712function [#|finallyTest|](): Promise<void> {
713    return fetch("https://typescriptlang.org").then(res => console.log(res)).catch(rej => console.log("error", rej)).finally(console.log("finally!"));
714}
715`
716        );
717
718        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Finally2", `
719function [#|finallyTest|](): Promise<void> {
720    return fetch("https://typescriptlang.org").then(res => console.log(res)).finally(console.log("finally!"));
721}
722`
723        );
724
725        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Finally3", `
726function [#|finallyTest|](): Promise<void> {
727    return fetch("https://typescriptlang.org").finally(console.log("finally!"));
728}
729`
730        );
731        _testConvertToAsyncFunction("convertToAsyncFunction_InnerPromise", `
732function [#|innerPromise|](): Promise<string> {
733    return fetch("https://typescriptlang.org").then(resp => {
734        var blob2 = resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
735        return blob2;
736    }).then(blob => {
737        return blob.toString();
738    });
739}
740`
741        );
742        _testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRet", `
743function [#|innerPromise|](): Promise<string> {
744    return fetch("https://typescriptlang.org").then(resp => {
745        return resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
746    }).then(blob => {
747        return blob.toString();
748    });
749}
750`
751        );
752
753        _testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding1", `
754function [#|innerPromise|](): Promise<string> {
755    return fetch("https://typescriptlang.org").then(resp => {
756        return resp.blob().then(({ blob }) => blob.byteOffset).catch(({ message }) => 'Error ' + message);
757    }).then(blob => {
758        return blob.toString();
759    });
760}
761`
762        );
763
764        _testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding2", `
765function [#|innerPromise|](): Promise<string> {
766    return fetch("https://typescriptlang.org").then(resp => {
767        return resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
768    }).then(({ x }) => {
769        return x.toString();
770    });
771}
772`
773        );
774
775        _testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding3", `
776function [#|innerPromise|](): Promise<string> {
777    return fetch("https://typescriptlang.org").then(resp => {
778        return resp.blob().then(({ blob }) => blob.byteOffset).catch(({ message }) => 'Error ' + message);
779    }).then(([x, y]) => {
780        return (x || y).toString();
781    });
782}
783`
784        );
785
786        _testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseRetBinding4", `
787function [#|innerPromise|](): Promise<string> {
788    return fetch("https://typescriptlang.org").then(resp => {
789        return resp.blob().then(({ blob }: { blob: { byteOffset: number } }) => [0, blob.byteOffset]).catch(({ message }: Error) => ['Error ', message]);
790    }).then(([x, y]) => {
791        return (x || y).toString();
792    });
793}
794`
795        );
796
797        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn01", `
798function [#|f|]() {
799    let blob = fetch("https://typescriptlang.org").then(resp => console.log(resp));
800    return blob;
801}
802`
803        );
804        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn02", `
805function [#|f|]() {
806    let blob = fetch("https://typescriptlang.org");
807    blob.then(resp => console.log(resp));
808    return blob;
809}
810`
811        );
812        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn03", `
813function [#|f|]() {
814    let blob = fetch("https://typescriptlang.org")
815    let blob2 = blob.then(resp => console.log(resp));
816    blob2.catch(err);
817    return blob;
818}
819
820function err (rej) {
821    console.log(rej)
822}
823`
824        );
825        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn04", `
826function [#|f|]() {
827    var blob = fetch("https://typescriptlang.org").then(res => console.log(res)), blob2 = fetch("https://microsoft.com").then(res => res.ok).catch(err);
828    return blob;
829}
830function err (rej) {
831    console.log(rej)
832}
833`
834        );
835
836        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn05", `
837function [#|f|]() {
838    var blob = fetch("https://typescriptlang.org").then(res => console.log(res));
839    blob.then(x => x);
840    return blob;
841}
842`
843        );
844
845        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn06", `
846function [#|f|]() {
847    var blob = fetch("https://typescriptlang.org");
848    return blob;
849}
850`
851        );
852
853        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn07", `
854function [#|f|]() {
855    let blob = fetch("https://typescriptlang.org");
856    let blob2 = fetch("https://microsoft.com");
857    blob2.then(res => console.log("res:", res));
858    blob.then(resp => console.log(resp));
859    return blob;
860}
861`
862        );
863
864        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn08", `
865function [#|f|]() {
866    let blob = fetch("https://typescriptlang.org");
867    if (!blob.ok){
868        return blob;
869    }
870    blob.then(resp => console.log(resp));
871    return blob;
872}
873`
874        );
875
876        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn09", `
877function [#|f|]() {
878    let blob3;
879    let blob = fetch("https://typescriptlang.org");
880    let blob2 = fetch("https://microsoft.com");
881    blob2.then(res => console.log("res:", res));
882    blob.then(resp => console.log(resp));
883    blob3 = blob2.catch(rej => rej.ok);
884    return blob;
885}
886`
887        );
888
889
890        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn10", `
891function [#|f|]() {
892    let blob3;
893    let blob = fetch("https://typescriptlang.org");
894    let blob2 = fetch("https://microsoft.com");
895    blob2.then(res => console.log("res:", res));
896    blob.then(resp => console.log(resp));
897    blob3 = fetch("test.com");
898    blob3 = blob2;
899    return blob;
900}
901`
902        );
903
904        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn11", `
905function [#|f|]() {
906    let blob;
907    return blob;
908}
909`
910        );
911
912
913
914        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Param1", `
915function [#|f|]() {
916    return my_print(fetch("https://typescriptlang.org").then(res => console.log(res)));
917}
918function my_print (resp) {
919    if (resp.ok) {
920        console.log(resp.buffer);
921    }
922    return resp;
923}
924
925`
926        );
927
928        _testConvertToAsyncFunction("convertToAsyncFunction_Param2", `
929function [#|f|]() {
930    return my_print(fetch("https://typescriptlang.org").then(res => console.log(res))).catch(err => console.log("Error!", err));
931}
932function my_print (resp): Promise<void> {
933    if (resp.ok) {
934        console.log(resp.buffer);
935    }
936    return resp;
937}
938
939
940`
941        );
942
943        _testConvertToAsyncFunction("convertToAsyncFunction_MultipleReturns1", `
944function [#|f|](): Promise<void> {
945    let x = fetch("https://microsoft.com").then(res => console.log("Microsoft:", res));
946    if (x.ok) {
947        return fetch("https://typescriptlang.org").then(res => console.log(res));
948    }
949    return x.then(resp => {
950        var blob = resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
951    });
952}
953`
954        );
955
956        _testConvertToAsyncFunction("convertToAsyncFunction_MultipleReturns2", `
957function [#|f|](): Promise<void> {
958    let x = fetch("https://microsoft.com").then(res => console.log("Microsoft:", res));
959    if (x.ok) {
960        return fetch("https://typescriptlang.org").then(res => console.log(res));
961    }
962    return x.then(resp => {
963        var blob = resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
964        return fetch("https://microsoft.com").then(res => console.log("Another one!"));
965    });
966}
967`
968        );
969
970
971        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_SeperateLines", `
972function [#|f|](): Promise<string> {
973    var blob = fetch("https://typescriptlang.org")
974    blob.then(resp => {
975        var blob = resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
976    });
977    blob.then(blob => {
978        return blob.toString();
979    });
980
981    return blob;
982}
983`
984        );
985
986
987        _testConvertToAsyncFunction("convertToAsyncFunction_InnerVarNameConflict", `
988function [#|f|](): Promise<string> {
989    return fetch("https://typescriptlang.org").then(resp => {
990        var blob = resp.blob().then(blob => blob.byteOffset).catch(err => 'Error');
991    }).then(blob => {
992        return blob.toString();
993    });
994}
995`
996        );
997        _testConvertToAsyncFunction("convertToAsyncFunction_InnerPromiseSimple", `
998function [#|f|](): Promise<string> {
999    return fetch("https://typescriptlang.org").then(resp => {
1000        return resp.blob().then(blob => blob.byteOffset);
1001    }).then(blob => {
1002        return blob.toString();
1003    });
1004}
1005`
1006        );
1007        _testConvertToAsyncFunction("convertToAsyncFunction_PromiseAllAndThen1", `
1008function [#|f|]() {
1009    return Promise.resolve().then(function () {
1010        return Promise.all([fetch("https://typescriptlang.org"), fetch("https://microsoft.com"), Promise.resolve().then(function () {
1011                return fetch("https://github.com");
1012              }).then(res => res.toString())]);
1013    });
1014}
1015`
1016        );
1017
1018        _testConvertToAsyncFunction("convertToAsyncFunction_PromiseAllAndThen2", `
1019function [#|f|]() {
1020    return Promise.resolve().then(function () {
1021        return Promise.all([fetch("https://typescriptlang.org"), fetch("https://microsoft.com"), Promise.resolve().then(function () {
1022                return fetch("https://github.com");
1023              })]).then(res => res.toString());
1024    });
1025}
1026`
1027        );
1028
1029        _testConvertToAsyncFunction("convertToAsyncFunction_PromiseAllAndThen3", `
1030function [#|f|]() {
1031    return Promise.resolve().then(() =>
1032        Promise.all([fetch("https://typescriptlang.org"), fetch("https://microsoft.com"), Promise.resolve().then(function () {
1033            return fetch("https://github.com");
1034        }).then(res => res.toString())]));
1035}
1036`
1037        );
1038
1039        _testConvertToAsyncFunction("convertToAsyncFunction_PromiseAllAndThen4", `
1040function [#|f|]() {
1041    return Promise.resolve().then(() =>
1042        Promise.all([fetch("https://typescriptlang.org"), fetch("https://microsoft.com"), Promise.resolve().then(function () {
1043            return fetch("https://github.com");
1044        })]).then(res => res.toString()));
1045}
1046`
1047        );
1048        _testConvertToAsyncFunction("convertToAsyncFunction_Scope1", `
1049function [#|f|]() {
1050    var var1: Response, var2;
1051    return fetch('https://typescriptlang.org').then( _ =>
1052      Promise.resolve().then( res => {
1053        var2 = "test";
1054        return fetch("https://microsoft.com");
1055      }).then(res =>
1056         var1 === res
1057      )
1058    ).then(res);
1059  }
1060  function res(response){
1061      console.log(response);
1062  }
1063`);
1064
1065        _testConvertToAsyncFunction("convertToAsyncFunction_Conditionals", `
1066function [#|f|](){
1067    return fetch("https://typescriptlang.org").then(res => {
1068      if (res.ok) {
1069        return fetch("https://microsoft.com");
1070      }
1071      else {
1072        if (res.buffer.length > 5) {
1073          return res;
1074        }
1075        else {
1076            return fetch("https://github.com");
1077        }
1078      }
1079    });
1080}
1081`
1082        );
1083
1084        _testConvertToAsyncFunction("convertToAsyncFunction_CatchFollowedByThen", `
1085function [#|f|](){
1086    return fetch("https://typescriptlang.org").then(res).catch(rej).then(res);
1087}
1088
1089function res(result){
1090    return result;
1091}
1092
1093function rej(reject){
1094    return reject;
1095}
1096`
1097        );
1098
1099        _testConvertToAsyncFunction("convertToAsyncFunction_CatchFollowedByThenMatchingTypes01", `
1100function [#|f|](){
1101    return fetch("https://typescriptlang.org").then(res).catch(rej).then(res);
1102}
1103
1104function res(result): number {
1105    return 5;
1106}
1107
1108function rej(reject): number {
1109    return 3;
1110}
1111`
1112        );
1113
1114        _testConvertToAsyncFunction("convertToAsyncFunction_CatchFollowedByThenMatchingTypes01NoAnnotations", `
1115function [#|f|](){
1116    return fetch("https://typescriptlang.org").then(res).catch(rej).then(res);
1117}
1118
1119function res(result){
1120    return 5;
1121}
1122
1123function rej(reject){
1124    return 3;
1125}
1126`
1127        );
1128
1129
1130        _testConvertToAsyncFunction("convertToAsyncFunction_CatchFollowedByThenMatchingTypes02", `
1131function [#|f|](){
1132    return fetch("https://typescriptlang.org").then(res => 0).catch(rej => 1).then(res);
1133}
1134
1135function res(result): number {
1136    return 5;
1137}
1138`
1139        );
1140
1141        _testConvertToAsyncFunction("convertToAsyncFunction_CatchFollowedByThenMatchingTypes02NoAnnotations", `
1142function [#|f|](){
1143    return fetch("https://typescriptlang.org").then(res => 0).catch(rej => 1).then(res);
1144}
1145
1146function res(result){
1147    return 5;
1148}
1149`
1150        );
1151
1152        _testConvertToAsyncFunction("convertToAsyncFunction_CatchFollowedByThenMismatchTypes01", `
1153function [#|f|](){
1154    return fetch("https://typescriptlang.org").then(res).catch(rej).then(res);
1155}
1156
1157function res(result){
1158    return 5;
1159}
1160
1161function rej(reject){
1162    return "Error";
1163}
1164`
1165        );
1166
1167        _testConvertToAsyncFunction("convertToAsyncFunction_CatchFollowedByThenMismatchTypes02", `
1168function [#|f|](){
1169    return fetch("https://typescriptlang.org").then(res).catch(rej).then(res);
1170}
1171
1172function res(result){
1173    return 5;
1174}
1175
1176function rej(reject): Response{
1177    return reject;
1178}
1179`
1180        );
1181
1182        _testConvertToAsyncFunction("convertToAsyncFunction_CatchFollowedByThenMismatchTypes02NoAnnotations", `
1183function [#|f|](){
1184    return fetch("https://typescriptlang.org").then(res).catch(rej).then(res);
1185}
1186
1187function res(result){
1188    return 5;
1189}
1190
1191function rej(reject){
1192    return reject;
1193}
1194`
1195        );
1196
1197
1198        _testConvertToAsyncFunction("convertToAsyncFunction_CatchFollowedByThenMismatchTypes03", `
1199function [#|f|](){
1200    return fetch("https://typescriptlang.org").then(res).catch(rej).then(res);
1201}
1202
1203function res(result){
1204    return 5;
1205}
1206
1207function rej(reject){
1208    return Promise.resolve(1);
1209}
1210`
1211        );
1212
1213        _testConvertToAsyncFunction("convertToAsyncFunction_CatchFollowedByThenMismatchTypes04", `
1214interface a {
1215    name: string;
1216    age: number;
1217}
1218
1219interface b extends a {
1220    color: string;
1221}
1222
1223
1224function [#|f|](){
1225    return fetch("https://typescriptlang.org").then(res).catch(rej).then(res);
1226}
1227
1228function res(result): b{
1229    return {name: "myName", age: 22, color: "red"};
1230}
1231
1232function rej(reject): a{
1233    return {name: "myName", age: 27};
1234}
1235`
1236        );
1237
1238        _testConvertToAsyncFunction("convertToAsyncFunction_ParameterNameCollision", `
1239async function foo<T>(x: T): Promise<T> {
1240    return x;
1241}
1242
1243function [#|bar|]<T>(x: T): Promise<T> {
1244    return foo(x).then(foo)
1245}
1246`
1247        );
1248
1249        _testConvertToAsyncFunction("convertToAsyncFunction_Return1", `
1250function [#|f|](p: Promise<unknown>) {
1251    return p.catch((error: Error) => {
1252        return Promise.reject(error);
1253    });
1254}`
1255        );
1256
1257        _testConvertToAsyncFunction("convertToAsyncFunction_Return2", `
1258function [#|f|](p: Promise<unknown>) {
1259    return p.catch((error: Error) => Promise.reject(error));
1260}`
1261        );
1262
1263        _testConvertToAsyncFunction("convertToAsyncFunction_Return3", `
1264function [#|f|](p: Promise<unknown>) {
1265    return p.catch(function (error: Error) {
1266        return Promise.reject(error);
1267    });
1268}`
1269        );
1270
1271        _testConvertToAsyncFunction("convertToAsyncFunction_LocalReturn", `
1272function [#|f|]() {
1273    let x = fetch("https://typescriptlang.org").then(res => console.log(res));
1274    return x.catch(err => console.log("Error!", err));
1275}
1276
1277`);
1278        _testConvertToAsyncFunction("convertToAsyncFunction_PromiseCallInner", `
1279function [#|f|]() {
1280    return fetch(Promise.resolve(1).then(res => "https://typescriptlang.org")).catch(err => console.log(err));
1281}
1282
1283`);
1284        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_CatchFollowedByCall", `
1285function [#|f|](){
1286    return fetch("https://typescriptlang.org").then(res).catch(rej).toString();
1287}
1288
1289function res(result){
1290    return result;
1291}
1292
1293function rej(reject){
1294    return reject;
1295}
1296`
1297        );
1298
1299        _testConvertToAsyncFunction("convertToAsyncFunction_Scope2", `
1300function [#|f|](){
1301    var i:number;
1302    return fetch("https://typescriptlang.org").then(i => i.ok).then(res => i+1).catch(err => i-1)
1303}
1304`
1305        );
1306
1307        _testConvertToAsyncFunction("convertToAsyncFunction_Loop", `
1308function [#|f|](){
1309    return fetch("https://typescriptlang.org").then(res => { for(let i=0; i<10; i++){
1310        console.log(res);
1311    }})
1312}
1313`
1314        );
1315
1316        _testConvertToAsyncFunction("convertToAsyncFunction_Conditional2", `
1317function [#|f|](){
1318    var res = 100;
1319    if (res > 50) {
1320        return fetch("https://typescriptlang.org").then(res => console.log(res));
1321    }
1322    else {
1323        return fetch("https://typescriptlang.org").then(res_func);
1324    }
1325}
1326
1327function res_func(result){
1328    console.log(result);
1329}
1330`
1331        );
1332
1333        _testConvertToAsyncFunction("convertToAsyncFunction_Scope3", `
1334function [#|f|]() {
1335  var obj;
1336  return fetch("https://typescriptlang.org").then(function (res) {
1337    obj = {
1338      func: function f() {
1339        console.log(res);
1340      }
1341    };
1342  });
1343}
1344`
1345        );
1346
1347        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NestedFunctionWrongLocation", `
1348function [#|f|]() {
1349    function fn2(){
1350        function fn3(){
1351            return fetch("https://typescriptlang.org").then(res => console.log(res));
1352        }
1353        return fn3();
1354    }
1355    return fn2();
1356}
1357`);
1358
1359        _testConvertToAsyncFunction("convertToAsyncFunction_NestedFunctionRightLocation", `
1360function f() {
1361    function fn2(){
1362        function [#|fn3|](){
1363            return fetch("https://typescriptlang.org").then(res => console.log(res));
1364        }
1365        return fn3();
1366    }
1367    return fn2();
1368}
1369`);
1370
1371        _testConvertToAsyncFunction("convertToAsyncFunction_UntypedFunction", `
1372function [#|f|]() {
1373    return Promise.resolve().then(res => console.log(res));
1374}
1375`);
1376
1377        _testConvertToAsyncFunction("convertToAsyncFunction_TernaryConditional", `
1378function [#|f|]() {
1379    let i;
1380    return Promise.resolve().then(res => res ? i = res : i = 100);
1381}
1382`);
1383
1384        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_ResRejNoArgsArrow", `
1385    function [#|f|]() {
1386        return Promise.resolve().then(() => 1, () => "a");
1387    }
1388`);
1389
1390        _testConvertToAsyncFunction("convertToAsyncFunction_simpleFunctionExpression", `
1391const [#|foo|] = function () {
1392    return fetch('https://typescriptlang.org').then(result => { console.log(result) });
1393}
1394`);
1395
1396        _testConvertToAsyncFunction("convertToAsyncFunction_simpleFunctionExpressionWithName", `
1397const foo = function [#|f|]() {
1398    return fetch('https://typescriptlang.org').then(result => { console.log(result) });
1399}
1400`);
1401
1402        _testConvertToAsyncFunction("convertToAsyncFunction_simpleFunctionExpressionAssignedToBindingPattern", `
1403const { length } = [#|function|] () {
1404    return fetch('https://typescriptlang.org').then(result => { console.log(result) });
1405}
1406`);
1407
1408        _testConvertToAsyncFunction("convertToAsyncFunction_catchBlockUniqueParams", `
1409function [#|f|]() {
1410    return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x);
1411}
1412`);
1413
1414        _testConvertToAsyncFunction("convertToAsyncFunction_catchBlockUniqueParamsBindingPattern", `
1415function [#|f|]() {
1416    return Promise.resolve().then(() => ({ x: 3 })).catch(() => ({ x: "a" })).then(({ x }) => !!x);
1417}
1418`);
1419
1420        _testConvertToAsyncFunction("convertToAsyncFunction_bindingPattern", `
1421function [#|f|]() {
1422    return fetch('https://typescriptlang.org').then(res);
1423}
1424function res({ status, trailer }){
1425    console.log(status);
1426}
1427`);
1428
1429        _testConvertToAsyncFunction("convertToAsyncFunction_bindingPatternNameCollision", `
1430function [#|f|]() {
1431    const result = 'https://typescriptlang.org';
1432    return fetch(result).then(res);
1433}
1434function res({ status, trailer }){
1435    console.log(status);
1436}
1437`);
1438
1439        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_thenArgumentNotFunction", `
1440function [#|f|]() {
1441    return Promise.resolve().then(f ? (x => x) : (y => y));
1442}
1443`);
1444
1445        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_thenArgumentNotFunctionNotLastInChain", `
1446function [#|f|]() {
1447    return Promise.resolve().then(f ? (x => x) : (y => y)).then(q => q);
1448}
1449`);
1450
1451        _testConvertToAsyncFunction("convertToAsyncFunction_runEffectfulContinuation", `
1452function [#|f|]() {
1453    return fetch('https://typescriptlang.org').then(res).then(_ => console.log("done"));
1454}
1455function res(result) {
1456    return Promise.resolve().then(x => console.log(result));
1457}
1458`);
1459
1460        _testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromise", `
1461function [#|f|]() {
1462    return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length)).then(x => console.log(x + 5));
1463}
1464`);
1465
1466        _testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromiseInBlock", `
1467function [#|f|]() {
1468    return fetch('https://typescriptlang.org').then(s => { return Promise.resolve(s.statusText.length) }).then(x => x + 5);
1469}
1470`);
1471
1472        _testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsFixablePromise", `
1473function [#|f|]() {
1474    return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText).then(st => st.length)).then(x => console.log(x + 5));
1475}
1476`);
1477
1478        _testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsPromiseLastInChain", `
1479function [#|f|]() {
1480    return fetch('https://typescriptlang.org').then(s => Promise.resolve(s.statusText.length));
1481}
1482`);
1483
1484        _testConvertToAsyncFunction("convertToAsyncFunction_callbackReturnsRejectedPromiseInTryBlock", `
1485function [#|f|]() {
1486    return Promise.resolve(1)
1487        .then(x => Promise.reject(x))
1488        .catch(err => console.log(err));
1489}
1490`);
1491
1492        _testConvertToAsyncFunction("convertToAsyncFunction_nestedPromises", `
1493function [#|f|]() {
1494    return fetch('https://typescriptlang.org').then(x => Promise.resolve(3).then(y => Promise.resolve(x.statusText.length + y)));
1495}
1496`);
1497
1498        _testConvertToAsyncFunction("convertToAsyncFunction_noArgs1", `
1499function delay(millis: number): Promise<void> {
1500    throw "no"
1501}
1502
1503function [#|main2|]() {
1504    console.log("Please wait. Loading.");
1505    return delay(500)
1506        .then(() => { console.log("."); return delay(500); })
1507        .then(() => { console.log("."); return delay(500); })
1508        .then(() => { console.log("."); return delay(500); })
1509}
1510        `);
1511
1512        _testConvertToAsyncFunction("convertToAsyncFunction_noArgs2", `
1513function delay(millis: number): Promise<void> {
1514    throw "no"
1515}
1516
1517function [#|main2|]() {
1518    console.log("Please wait. Loading.");
1519    return delay(500)
1520        .then(() => delay(500))
1521        .then(() => delay(500))
1522        .then(() => delay(500))
1523}
1524        `);
1525
1526        _testConvertToAsyncFunction("convertToAsyncFunction_exportModifier", `
1527export function [#|foo|]() {
1528    return fetch('https://typescriptlang.org').then(s => console.log(s));
1529}
1530`);
1531
1532        _testConvertToAsyncFunction("convertToAsyncFunction_OutermostOnlySuccess", `
1533function [#|foo|]() {
1534    return fetch('a').then(() => {
1535        return fetch('b').then(() => 'c');
1536    })
1537}
1538`);
1539        _testConvertToAsyncFunction("convertToAsyncFunction_decoratedMethod", `
1540function decorator() {
1541    return (target: any, key: any, descriptor: PropertyDescriptor) => descriptor;
1542}
1543class Foo {
1544    @decorator()
1545    [#|method|]() {
1546        return fetch('a').then(x => x);
1547    }
1548}
1549`);
1550
1551        _testConvertToAsyncFunction("convertToAsyncFunction_decoratedMethodWithSingleLineComment", `
1552function decorator() {
1553    return (target: any, key: any, descriptor: PropertyDescriptor) => descriptor;
1554}
1555class Foo {
1556    @decorator()
1557    // comment
1558    [#|method|]() {
1559        return fetch('a').then(x => x);
1560    }
1561}
1562`);
1563
1564        _testConvertToAsyncFunction("convertToAsyncFunction_decoratedMethodWithMultipleLineComment", `
1565function decorator() {
1566    return (target: any, key: any, descriptor: PropertyDescriptor) => descriptor;
1567}
1568class Foo {
1569    @decorator()
1570    /**
1571     * comment
1572     */
1573    [#|method|]() {
1574        return fetch('a').then(x => x);
1575    }
1576}
1577`);
1578
1579        _testConvertToAsyncFunction("convertToAsyncFunction_decoratedMethodWithModifier", `
1580function decorator() {
1581    return (target: any, key: any, descriptor: PropertyDescriptor) => descriptor;
1582}
1583class Foo {
1584    @decorator()
1585    public [#|method|]() {
1586        return fetch('a').then(x => x);
1587    }
1588}
1589`);
1590
1591        _testConvertToAsyncFunctionFailedSuggestion("convertToAsyncFunction_OutermostOnlyFailure", `
1592function foo() {
1593    return fetch('a').then([#|() => {|]
1594        return fetch('b').then(() => 'c');
1595    })
1596}
1597`);
1598
1599        _testConvertToAsyncFunction("convertToAsyncFunction_thenTypeArgument1", `
1600type APIResponse<T> = { success: true, data: T } | { success: false };
1601
1602function wrapResponse<T>(response: T): APIResponse<T> {
1603    return { success: true, data: response };
1604}
1605
1606function [#|get|]() {
1607    return Promise.resolve(undefined!).then<APIResponse<{ email: string }>>(wrapResponse);
1608}
1609`);
1610
1611        _testConvertToAsyncFunction("convertToAsyncFunction_thenTypeArgument2", `
1612type APIResponse<T> = { success: true, data: T } | { success: false };
1613
1614function wrapResponse<T>(response: T): APIResponse<T> {
1615    return { success: true, data: response };
1616}
1617
1618function [#|get|]() {
1619    return Promise.resolve(undefined!).then<APIResponse<{ email: string }>>(d => wrapResponse(d));
1620}
1621`);
1622
1623        _testConvertToAsyncFunction("convertToAsyncFunction_thenTypeArgument3", `
1624type APIResponse<T> = { success: true, data: T } | { success: false };
1625
1626function wrapResponse<T>(response: T): APIResponse<T> {
1627    return { success: true, data: response };
1628}
1629
1630function [#|get|]() {
1631    return Promise.resolve(undefined!).then<APIResponse<{ email: string }>>(d => {
1632        console.log(d);
1633        return wrapResponse(d);
1634    });
1635}
1636`);
1637
1638        _testConvertToAsyncFunction("convertToAsyncFunction_catchTypeArgument1", `
1639type APIResponse<T> = { success: true, data: T } | { success: false };
1640
1641function [#|get|]() {
1642    return Promise
1643        .resolve<APIResponse<{ email: string }>>({ success: true, data: { email: "" } })
1644        .catch<APIResponse<{ email: string }>>(() => ({ success: false }));
1645}
1646`);
1647
1648        _testConvertToAsyncFunctionFailed("convertToAsyncFunction_threeArguments", `
1649function [#|f|]() {
1650    return Promise.resolve().then(undefined, undefined, () => 1);
1651}`);
1652
1653        _testConvertToAsyncFunction("convertToAsyncFunction_callbackArgument", `
1654function foo(props: any): void {
1655    return props;
1656}
1657
1658const fn = (): Promise<(message: string) => void> =>
1659    new Promise(resolve => resolve((message: string) => foo(message)));
1660
1661function [#|f|]() {
1662    return fn().then(res => res("test"));
1663}
1664`);
1665
1666        _testConvertToAsyncFunction("convertToAsyncFunction_emptyCatch1", `
1667function [#|f|]() {
1668    return Promise.resolve().catch();
1669}
1670`);
1671
1672        _testConvertToAsyncFunction("convertToAsyncFunction_emptyCatch2", `
1673function [#|f|]() {
1674    return Promise.resolve(0).then(x => x).catch();
1675}
1676`);
1677
1678        _testConvertToAsyncFunctionWithModule("convertToAsyncFunction_importedFunction", `
1679import { fn } from "./module";
1680function [#|f|]() {
1681    return Promise.resolve(0).then(fn);
1682}
1683`);
1684
1685    });
1686}
1687