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