Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e07e2e0

Browse filesBrowse files
authored
Merge pull request microsoft#23423 from Kingwl/add-braces
add support for add or remove braces to arrow function
2 parents 7df8131 + 0d730c0 commit e07e2e0
Copy full SHA for e07e2e0

31 files changed

+408-16Lines changed: 408 additions & 16 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/diagnosticMessages.json‎

Copy file name to clipboardExpand all lines: src/compiler/diagnosticMessages.json
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4402,5 +4402,17 @@
44024402
"Convert named imports to namespace import": {
44034403
"category": "Message",
44044404
"code": 95057
4405+
},
4406+
"Add or remove braces in an arrow function": {
4407+
"category": "Message",
4408+
"code": 95058
4409+
},
4410+
"Add braces to arrow function": {
4411+
"category": "Message",
4412+
"code": 95059
4413+
},
4414+
"Remove braces from arrow function": {
4415+
"category": "Message",
4416+
"code": 95060
44054417
}
44064418
}
Collapse file

‎src/harness/tsconfig.json‎

Copy file name to clipboardExpand all lines: src/harness/tsconfig.json
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@
125125
"../services/refactors/extractSymbol.ts",
126126
"../services/refactors/generateGetAccessorAndSetAccessor.ts",
127127
"../services/refactors/moveToNewFile.ts",
128+
"../services/refactors/addOrRemoveBracesToArrowFunction.ts",
128129
"../services/sourcemaps.ts",
129130
"../services/services.ts",
130131
"../services/breakpoints.ts",
Collapse file

‎src/server/tsconfig.json‎

Copy file name to clipboardExpand all lines: src/server/tsconfig.json
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
"../services/refactors/extractSymbol.ts",
121121
"../services/refactors/generateGetAccessorAndSetAccessor.ts",
122122
"../services/refactors/moveToNewFile.ts",
123+
"../services/refactors/addOrRemoveBracesToArrowFunction.ts",
123124
"../services/sourcemaps.ts",
124125
"../services/services.ts",
125126
"../services/breakpoints.ts",
Collapse file

‎src/server/tsconfig.library.json‎

Copy file name to clipboardExpand all lines: src/server/tsconfig.library.json
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
"../services/refactors/extractSymbol.ts",
127127
"../services/refactors/generateGetAccessorAndSetAccessor.ts",
128128
"../services/refactors/moveToNewFile.ts",
129+
"../services/refactors/addOrRemoveBracesToArrowFunction.ts",
129130
"../services/sourcemaps.ts",
130131
"../services/services.ts",
131132
"../services/breakpoints.ts",
Collapse file

‎src/services/codefixes/convertFunctionToEs6Class.ts‎

Copy file name to clipboardExpand all lines: src/services/codefixes/convertFunctionToEs6Class.ts
-16Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -202,22 +202,6 @@ namespace ts.codefix {
202202
}
203203
}
204204

205-
function copyComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile) {
206-
forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, (pos, end, kind, htnl) => {
207-
if (kind === SyntaxKind.MultiLineCommentTrivia) {
208-
// Remove leading /*
209-
pos += 2;
210-
// Remove trailing */
211-
end -= 2;
212-
}
213-
else {
214-
// Remove leading //
215-
pos += 2;
216-
}
217-
addSyntheticLeadingComment(targetNode, kind, sourceFile.text.slice(pos, end), htnl);
218-
});
219-
}
220-
221205
function getModifierKindFromSource(source: Node, kind: SyntaxKind): ReadonlyArray<Modifier> | undefined {
222206
return filter(source.modifiers, modifier => modifier.kind === kind);
223207
}
Collapse file
+96Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/* @internal */
2+
namespace ts.refactor.addOrRemoveBracesToArrowFunction {
3+
const refactorName = "Add or remove braces in an arrow function";
4+
const refactorDescription = Diagnostics.Add_or_remove_braces_in_an_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+
func: ArrowFunction;
13+
expression: Expression | undefined;
14+
returnStatement?: ReturnStatement;
15+
addBraces: boolean;
16+
}
17+
18+
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
19+
const { file, startPosition } = context;
20+
const info = getConvertibleArrowFunctionAtPosition(file, startPosition);
21+
if (!info) return undefined;
22+
23+
return [{
24+
name: refactorName,
25+
description: refactorDescription,
26+
actions: [
27+
info.addBraces ?
28+
{
29+
name: addBracesActionName,
30+
description: addBracesActionDescription
31+
} : {
32+
name: removeBracesActionName,
33+
description: removeBracesActionDescription
34+
}
35+
]
36+
}];
37+
}
38+
39+
function getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined {
40+
const { file, startPosition } = context;
41+
const info = getConvertibleArrowFunctionAtPosition(file, startPosition);
42+
if (!info) return undefined;
43+
44+
const { expression, returnStatement, func } = info;
45+
46+
let body: ConciseBody;
47+
if (actionName === addBracesActionName) {
48+
const returnStatement = createReturn(expression);
49+
body = createBlock([returnStatement], /* multiLine */ true);
50+
suppressLeadingAndTrailingTrivia(body);
51+
copyComments(expression!, returnStatement, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ true);
52+
}
53+
else if (actionName === removeBracesActionName && returnStatement) {
54+
const actualExpression = expression || createVoidZero();
55+
body = needsParentheses(actualExpression) ? createParen(actualExpression) : actualExpression;
56+
suppressLeadingAndTrailingTrivia(body);
57+
copyComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false);
58+
}
59+
else {
60+
Debug.fail("invalid action");
61+
}
62+
63+
const edits = textChanges.ChangeTracker.with(context, t => t.replaceNode(file, func.body, body));
64+
return { renameFilename: undefined, renameLocation: undefined, edits };
65+
}
66+
67+
function needsParentheses(expression: Expression) {
68+
return isBinaryExpression(expression) && expression.operatorToken.kind === SyntaxKind.CommaToken || isObjectLiteralExpression(expression);
69+
}
70+
71+
function getConvertibleArrowFunctionAtPosition(file: SourceFile, startPosition: number): Info | undefined {
72+
const node = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false);
73+
const func = getContainingFunction(node);
74+
if (!func || !isArrowFunction(func) || (!rangeContainsRange(func, node) || rangeContainsRange(func.body, node))) return undefined;
75+
76+
if (isExpression(func.body)) {
77+
return {
78+
func,
79+
addBraces: true,
80+
expression: func.body
81+
};
82+
}
83+
else if (func.body.statements.length === 1) {
84+
const firstStatement = first(func.body.statements);
85+
if (isReturnStatement(firstStatement)) {
86+
return {
87+
func,
88+
addBraces: false,
89+
expression: firstStatement.expression,
90+
returnStatement: firstStatement
91+
};
92+
}
93+
}
94+
return undefined;
95+
}
96+
}
Collapse file

‎src/services/tsconfig.json‎

Copy file name to clipboardExpand all lines: src/services/tsconfig.json
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
"refactors/extractSymbol.ts",
118118
"refactors/generateGetAccessorAndSetAccessor.ts",
119119
"refactors/moveToNewFile.ts",
120+
"refactors/addOrRemoveBracesToArrowFunction.ts",
120121
"sourcemaps.ts",
121122
"services.ts",
122123
"breakpoints.ts",
Collapse file

‎src/services/utilities.ts‎

Copy file name to clipboardExpand all lines: src/services/utilities.ts
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,6 +1720,22 @@ namespace ts {
17201720
return lastPos;
17211721
}
17221722

1723+
export function copyComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) {
1724+
forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, (pos, end, kind, htnl) => {
1725+
if (kind === SyntaxKind.MultiLineCommentTrivia) {
1726+
// Remove leading /*
1727+
pos += 2;
1728+
// Remove trailing */
1729+
end -= 2;
1730+
}
1731+
else {
1732+
// Remove leading //
1733+
pos += 2;
1734+
}
1735+
addSyntheticLeadingComment(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl);
1736+
});
1737+
}
1738+
17231739
function indexInTextChange(change: string, name: string): number {
17241740
if (startsWith(change, name)) return 0;
17251741
// Add a " " to avoid references inside words
Collapse file
+13Lines 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 foo = /*a*/a/*b*/ => a + 1;
4+
5+
goTo.select("a", "b");
6+
edit.applyRefactor({
7+
refactorName: "Add or remove braces in an arrow function",
8+
actionName: "Add braces to arrow function",
9+
actionDescription: "Add braces to arrow function",
10+
newContent: `const foo = a => {
11+
return a + 1;
12+
};`,
13+
});
Collapse file
+11Lines 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, 2, 3); };
4+
5+
goTo.select("a", "b");
6+
edit.applyRefactor({
7+
refactorName: "Add or remove braces in an arrow function",
8+
actionName: "Remove braces from arrow function",
9+
actionDescription: "Remove braces from arrow function",
10+
newContent: `const foo = a => (1, 2, 3);`,
11+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.