Skip to content

Commit e1b1d2b

Browse files
committed
add support for add or remove braces to arrow function
1 parent 40fd6ae commit e1b1d2b

14 files changed

+187
-0
lines changed

src/compiler/diagnosticMessages.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4165,5 +4165,17 @@
41654165
"Generate 'get' and 'set' accessors": {
41664166
"category": "Message",
41674167
"code": 95046
4168+
},
4169+
"Convert arrow function": {
4170+
"category": "Message",
4171+
"code": 95047
4172+
},
4173+
"Add braces to arrow function": {
4174+
"category": "Message",
4175+
"code": 95048
4176+
},
4177+
"Remove braces from arrow function": {
4178+
"category": "Message",
4179+
"code": 95049
41684180
}
41694181
}

src/harness/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
"../services/codefixes/useDefaultImport.ts",
115115
"../services/refactors/extractSymbol.ts",
116116
"../services/refactors/generateGetAccessorAndSetAccessor.ts",
117+
"../services/refactors/convertArrowFunction.ts",
117118
"../services/sourcemaps.ts",
118119
"../services/services.ts",
119120
"../services/breakpoints.ts",

src/server/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
"../services/codefixes/useDefaultImport.ts",
111111
"../services/refactors/extractSymbol.ts",
112112
"../services/refactors/generateGetAccessorAndSetAccessor.ts",
113+
"../services/refactors/convertArrowFunction.ts",
113114
"../services/sourcemaps.ts",
114115
"../services/services.ts",
115116
"../services/breakpoints.ts",

src/server/tsconfig.library.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
"../services/codefixes/useDefaultImport.ts",
117117
"../services/refactors/extractSymbol.ts",
118118
"../services/refactors/generateGetAccessorAndSetAccessor.ts",
119+
"../services/refactors/convertArrowFunction.ts",
119120
"../services/sourcemaps.ts",
120121
"../services/services.ts",
121122
"../services/breakpoints.ts",
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/* @internal */
2+
namespace ts.refactor.convertArrowFunction {
3+
const refactorName = "Convert arrow function";
4+
const refactorDescription = Diagnostics.Convert_arrow_function.message;
5+
const addBracesActionName = "Add braces to arrow function";
6+
const removeBracesActionName = "Remove braces from arrow function";
7+
const addBracesActionDescription = Diagnostics.Add_braces_to_arrow_function.message;
8+
const removeBracesActionDescription = Diagnostics.Remove_braces_from_arrow_function.message;
9+
registerRefactor(refactorName, { getEditsForAction, getAvailableActions });
10+
11+
interface Info {
12+
container: ArrowFunction;
13+
expression: Expression;
14+
addBraces: boolean;
15+
}
16+
17+
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
18+
const { file, startPosition } = context;
19+
const info = getConvertibleArrowFunctionAtPosition(file, startPosition);
20+
if (!info) return undefined;
21+
22+
const actions: RefactorActionInfo[] = [
23+
info.addBraces ?
24+
{
25+
name: addBracesActionName,
26+
description: addBracesActionDescription
27+
} : {
28+
name: removeBracesActionName,
29+
description: removeBracesActionDescription
30+
}
31+
];
32+
33+
return [{
34+
name: refactorName,
35+
description: refactorDescription,
36+
actions
37+
}];
38+
}
39+
40+
function getEditsForAction(context: RefactorContext, _actionName: string): RefactorEditInfo | undefined {
41+
const { file, startPosition } = context;
42+
const info = getConvertibleArrowFunctionAtPosition(file, startPosition);
43+
if (!info) return undefined;
44+
45+
const { addBraces, expression, container } = info;
46+
const changeTracker = textChanges.ChangeTracker.fromContext(context);
47+
updateBraces(changeTracker, file, container, expression, addBraces);
48+
49+
return {
50+
renameFilename: undefined,
51+
renameLocation: undefined,
52+
edits: changeTracker.getChanges()
53+
};
54+
}
55+
56+
function updateBraces(changeTracker: textChanges.ChangeTracker, file: SourceFile, container: ArrowFunction, expression: Expression, addBraces: boolean) {
57+
const body = addBraces ? createBlock([createReturn(expression)]) : expression;
58+
59+
const arrowFunction = updateArrowFunction(
60+
container,
61+
container.modifiers,
62+
container.typeParameters,
63+
container.parameters,
64+
container.type,
65+
body);
66+
changeTracker.replaceNode(file, container, arrowFunction);
67+
}
68+
69+
function getConvertibleArrowFunctionAtPosition(file: SourceFile, startPosition: number): Info | undefined {
70+
const node = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false);
71+
const container = getContainingFunction(node);
72+
if (!container || !isArrowFunction(container)) return undefined;
73+
74+
if (isExpression(container.body)) {
75+
return {
76+
container,
77+
addBraces: true,
78+
expression: container.body
79+
};
80+
}
81+
else if (container.body.statements.length === 1 && isReturnStatement(first(container.body.statements))) {
82+
return {
83+
container,
84+
addBraces: false,
85+
expression: (<ReturnStatement>first(container.body.statements)).expression
86+
};
87+
}
88+
return undefined;
89+
}
90+
}

src/services/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
"codefixes/useDefaultImport.ts",
108108
"refactors/extractSymbol.ts",
109109
"refactors/generateGetAccessorAndSetAccessor.ts",
110+
"refactors/convertArrowFunction.ts",
110111
"sourcemaps.ts",
111112
"services.ts",
112113
"breakpoints.ts",
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const foo = /*a*/a/*b*/ => a + 1;
4+
5+
goTo.select("a", "b");
6+
edit.applyRefactor({
7+
refactorName: "Convert arrow function",
8+
actionName: "Add braces to arrow function",
9+
actionDescription: "Add braces to arrow function",
10+
newContent: `const foo = a => { return a + 1; };`,
11+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const foo = /*a*/a/*b*/ => ({ a: 1 });
4+
5+
goTo.select("a", "b");
6+
edit.applyRefactor({
7+
refactorName: "Convert arrow function",
8+
actionName: "Add braces to arrow function",
9+
actionDescription: "Add braces to arrow function",
10+
newContent: `const foo = a => { return ({ a: 1 }); };`,
11+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const foo = /*a*/a/*b*/ => 1;
4+
5+
goTo.select("a", "b");
6+
edit.applyRefactor({
7+
refactorName: "Convert arrow function",
8+
actionName: "Add braces to arrow function",
9+
actionDescription: "Add braces to arrow function",
10+
newContent: `const foo = a => { return 1; };`,
11+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const foo = /*a*/a/*b*/ => { return a + 1; };
4+
5+
goTo.select("a", "b");
6+
edit.applyRefactor({
7+
refactorName: "Convert arrow function",
8+
actionName: "Remove braces from arrow function",
9+
actionDescription: "Remove braces from arrow function",
10+
newContent: `const foo = a => a + 1;`,
11+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const foo = /*a*/a/*b*/ => { return { a: 1 }; };
4+
5+
goTo.select("a", "b");
6+
edit.applyRefactor({
7+
refactorName: "Convert arrow function",
8+
actionName: "Remove braces from arrow function",
9+
actionDescription: "Remove braces from arrow function",
10+
newContent: `const foo = a => ({ a: 1 });`,
11+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const foo = /*a*/a/*b*/ => { return 1; };
4+
5+
goTo.select("a", "b");
6+
edit.applyRefactor({
7+
refactorName: "Convert arrow function",
8+
actionName: "Remove braces from arrow function",
9+
actionDescription: "Remove braces from arrow function",
10+
newContent: `const foo = a => 1;`,
11+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const foo = /*a*/a/*b*/ => { };
4+
5+
goTo.select("a", "b");
6+
verify.not.refactorAvailable("Convert arrow function");
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const foo = /*a*/a/*b*/ => {
4+
//// const b = 1;
5+
//// return a + b;
6+
//// };
7+
8+
goTo.select("a", "b");
9+
verify.not.refactorAvailable("Convert arrow function");

0 commit comments

Comments
 (0)