Skip to content

Commit 0cb462a

Browse files
committed
Change explicit return type T to Promise<T>
1 parent c945beb commit 0cb462a

7 files changed

+121
-9
lines changed

src/services/codefixes/fixAwaitInSyncFunction.ts

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,42 @@ namespace ts.codefix {
99
errorCodes,
1010
getCodeActions(context) {
1111
const { sourceFile, span } = context;
12-
const node = getNodeToInsertBefore(sourceFile, span.start);
13-
if (!node) return undefined;
14-
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, node));
12+
const token = getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false);
13+
const containingFunction = getContainingFunction(token);
14+
const insertBefore = getNodeToInsertBefore(sourceFile, containingFunction);
15+
const returnType = getReturnTypeNode(containingFunction);
16+
if (!insertBefore) return undefined;
17+
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, insertBefore, returnType));
1518
return [{ description: getLocaleSpecificMessage(Diagnostics.Convert_to_async), changes, fixId }];
1619
},
1720
fixIds: [fixId],
18-
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) =>
19-
doChange(changes, context.sourceFile, getNodeToInsertBefore(diag.file, diag.start!))),
21+
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => {
22+
const token = getTokenAtPosition(diag.file, diag.start!, /*includeJsDocComment*/ false);
23+
const containingFunction = getContainingFunction(token);
24+
const insertBefore = getNodeToInsertBefore(diag.file, containingFunction);
25+
const returnType = getReturnTypeNode(containingFunction);
26+
if (insertBefore) {
27+
doChange(changes, context.sourceFile, insertBefore, returnType);
28+
}
29+
}),
2030
});
2131

22-
function getNodeToInsertBefore(sourceFile: SourceFile, pos: number): Node | undefined {
23-
const token = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
24-
const containingFunction = getContainingFunction(token);
32+
function getReturnTypeNode(containingFunction: FunctionLike): TypeNode | undefined {
33+
switch (containingFunction.kind) {
34+
case SyntaxKind.MethodDeclaration:
35+
case SyntaxKind.FunctionDeclaration:
36+
return containingFunction.type;
37+
case SyntaxKind.FunctionExpression:
38+
case SyntaxKind.ArrowFunction:
39+
if (isVariableDeclaration(containingFunction.parent) &&
40+
containingFunction.parent.type &&
41+
isFunctionTypeNode(containingFunction.parent.type)) {
42+
return containingFunction.parent.type.type;
43+
}
44+
}
45+
}
46+
47+
function getNodeToInsertBefore(sourceFile: SourceFile, containingFunction: FunctionLike): Node | undefined {
2548
switch (containingFunction.kind) {
2649
case SyntaxKind.MethodDeclaration:
2750
return containingFunction.name;
@@ -35,7 +58,13 @@ namespace ts.codefix {
3558
}
3659
}
3760

38-
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, insertBefore: Node): void {
61+
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, insertBefore: Node, returnType: TypeNode | undefined): void {
62+
if (returnType) {
63+
const entityName = getEntityNameFromTypeNode(returnType);
64+
if (!entityName || entityName.getText() !== "Promise") {
65+
changes.replaceNode(sourceFile, returnType, createTypeReferenceNode("Promise", createNodeArray([returnType])));
66+
}
67+
}
3968
changes.insertModifierBefore(sourceFile, SyntaxKind.AsyncKeyword, insertBefore);
4069
}
4170
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////const f: () => number | string = () => {
4+
//// await Promise.resolve('foo');
5+
////}
6+
7+
verify.codeFix({
8+
description: "Convert to async",
9+
newFileContent:
10+
`const f: () => Promise<number | string> = async () => {
11+
await Promise.resolve('foo');
12+
}`,
13+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////const f: string = () => {
4+
//// await Promise.resolve('foo');
5+
////}
6+
7+
// should not change type if it's incorrectly set
8+
verify.codeFix({
9+
description: "Convert to async",
10+
newFileContent:
11+
`const f: string = async () => {
12+
await Promise.resolve('foo');
13+
}`,
14+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////const f: () => Array<number | string> = function() {
4+
//// await Promise.resolve([]);
5+
////}
6+
7+
verify.codeFix({
8+
description: "Convert to async",
9+
newFileContent:
10+
`const f: () => Promise<Array<number | string>> = async function() {
11+
await Promise.resolve([]);
12+
}`,
13+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////const f: () => Promise<number | string> = () => {
4+
//// await Promise.resolve('foo');
5+
////}
6+
7+
verify.codeFix({
8+
description: "Convert to async",
9+
newFileContent:
10+
`const f: () => Promise<number | string> = async () => {
11+
await Promise.resolve('foo');
12+
}`,
13+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////function f(): number | string {
4+
//// await Promise.resolve(8);
5+
////}
6+
7+
verify.codeFix({
8+
description: "Convert to async",
9+
newFileContent:
10+
`async function f(): Promise<number | string> {
11+
await Promise.resolve(8);
12+
}`,
13+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////class Foo {
4+
//// bar(): string {
5+
//// await Promise.resolve('baz');
6+
//// }
7+
////}
8+
9+
verify.codeFix({
10+
description: "Convert to async",
11+
newFileContent:
12+
`class Foo {
13+
async bar(): Promise<string> {
14+
await Promise.resolve('baz');
15+
}
16+
}`,
17+
});

0 commit comments

Comments
 (0)