Skip to content

Commit e0fe727

Browse files
not-an-aardvarknzakas
authored andcommitted
Update: add fixer for brace-style (fixes #7074) (#7347)
1 parent cbbe420 commit e0fe727

File tree

3 files changed

+431
-106
lines changed

3 files changed

+431
-106
lines changed

docs/rules/brace-style.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Require Brace Style (brace-style)
22

3+
(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixes problems reported by this rule.
4+
35
Brace style is closely related to [indent style](http://en.wikipedia.org/wiki/Indent_style) in programming and describes the placement of braces relative to their control statement and body. There are probably a dozen, if not more, brace styles in the world.
46

57
The *one true brace style* is one of the most common brace styles in JavaScript, in which the opening brace of a block is placed on the same line as its corresponding statement or declaration. For example:

lib/rules/brace-style.js

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ module.exports = {
3030
},
3131
additionalProperties: false
3232
}
33-
]
33+
],
34+
35+
fixable: "whitespace"
3436
},
3537

3638
create(context) {
@@ -69,6 +71,28 @@ module.exports = {
6971
return token.value === "{" || token.value === "}";
7072
}
7173

74+
/**
75+
* Reports a place where a newline unexpectedly appears
76+
* @param {ASTNode} node The node to report
77+
* @param {string} message The message to report
78+
* @param {Token} firstToken The token before the unexpected newline
79+
* @returns {void}
80+
*/
81+
function reportExtraNewline(node, message, firstToken) {
82+
context.report({
83+
node,
84+
message,
85+
fix(fixer) {
86+
const secondToken = sourceCode.getTokenAfter(firstToken);
87+
const textBetween = sourceCode.getText().slice(firstToken.range[1], secondToken.range[0]);
88+
const NEWLINE_REGEX = /\r\n|\r|\n|\u2028|\u2029/g;
89+
90+
// Don't do a fix if there is a comment between the tokens.
91+
return textBetween.trim() ? null : fixer.replaceTextRange([firstToken.range[1], secondToken.range[0]], textBetween.replace(NEWLINE_REGEX, ""));
92+
}
93+
});
94+
}
95+
7296
/**
7397
* Binds a list of properties to a function that verifies that the opening
7498
* curly brace is on the same line as its controlling statement of a given
@@ -98,21 +122,33 @@ module.exports = {
98122
}
99123

100124
if (style !== "allman" && previousToken.loc.start.line !== curlyToken.loc.start.line) {
101-
context.report(node, OPEN_MESSAGE);
125+
reportExtraNewline(node, OPEN_MESSAGE, previousToken);
102126
} else if (style === "allman" && previousToken.loc.start.line === curlyToken.loc.start.line) {
103-
context.report(node, OPEN_MESSAGE_ALLMAN);
127+
context.report({
128+
node,
129+
message: OPEN_MESSAGE_ALLMAN,
130+
fix: fixer => fixer.insertTextBefore(curlyToken, "\n")
131+
});
104132
}
105133

106134
if (!block.body.length) {
107135
return;
108136
}
109137

110138
if (curlyToken.loc.start.line === block.body[0].loc.start.line) {
111-
context.report(block.body[0], BODY_MESSAGE);
139+
context.report({
140+
node: block.body[0],
141+
message: BODY_MESSAGE,
142+
fix: fixer => fixer.insertTextAfter(curlyToken, "\n")
143+
});
112144
}
113145

114146
if (curlyTokenEnd.loc.start.line === block.body[block.body.length - 1].loc.start.line) {
115-
context.report(block.body[block.body.length - 1], CLOSE_MESSAGE_SINGLE);
147+
context.report({
148+
node: block.body[block.body.length - 1],
149+
message: CLOSE_MESSAGE_SINGLE,
150+
fix: fixer => fixer.insertTextBefore(curlyTokenEnd, "\n")
151+
});
116152
}
117153
});
118154
};
@@ -135,10 +171,14 @@ module.exports = {
135171
if (tokens[0].loc.start.line !== tokens[1].loc.start.line &&
136172
node.consequent.type === "BlockStatement" &&
137173
isCurlyPunctuator(tokens[0])) {
138-
context.report(node.alternate, CLOSE_MESSAGE);
174+
reportExtraNewline(node.alternate, CLOSE_MESSAGE, tokens[0]);
139175
}
140176
} else if (tokens[0].loc.start.line === tokens[1].loc.start.line) {
141-
context.report(node.alternate, CLOSE_MESSAGE_STROUSTRUP_ALLMAN);
177+
context.report({
178+
node: node.alternate,
179+
message: CLOSE_MESSAGE_STROUSTRUP_ALLMAN,
180+
fix: fixer => fixer.insertTextAfter(tokens[0], "\n")
181+
});
142182
}
143183

144184
}
@@ -158,10 +198,14 @@ module.exports = {
158198

159199
if (style === "1tbs") {
160200
if (tokens[0].loc.start.line !== tokens[1].loc.start.line) {
161-
context.report(node.finalizer, CLOSE_MESSAGE);
201+
reportExtraNewline(node.finalizer, CLOSE_MESSAGE, tokens[0]);
162202
}
163203
} else if (tokens[0].loc.start.line === tokens[1].loc.start.line) {
164-
context.report(node.finalizer, CLOSE_MESSAGE_STROUSTRUP_ALLMAN);
204+
context.report({
205+
node: node.finalizer,
206+
message: CLOSE_MESSAGE_STROUSTRUP_ALLMAN,
207+
fix: fixer => fixer.insertTextAfter(tokens[0], "\n")
208+
});
165209
}
166210
}
167211
}
@@ -181,11 +225,15 @@ module.exports = {
181225
if (isBlock(node.body)) {
182226
if (style === "1tbs") {
183227
if (previousToken.loc.start.line !== firstToken.loc.start.line) {
184-
context.report(node, CLOSE_MESSAGE);
228+
reportExtraNewline(node, CLOSE_MESSAGE, previousToken);
185229
}
186230
} else {
187231
if (previousToken.loc.start.line === firstToken.loc.start.line) {
188-
context.report(node, CLOSE_MESSAGE_STROUSTRUP_ALLMAN);
232+
context.report({
233+
node,
234+
message: CLOSE_MESSAGE_STROUSTRUP_ALLMAN,
235+
fix: fixer => fixer.insertTextAfter(previousToken, "\n")
236+
});
189237
}
190238
}
191239
}
@@ -207,9 +255,13 @@ module.exports = {
207255
}
208256

209257
if (style !== "allman" && tokens[0].loc.start.line !== tokens[1].loc.start.line) {
210-
context.report(node, OPEN_MESSAGE);
258+
reportExtraNewline(node, OPEN_MESSAGE, tokens[0]);
211259
} else if (style === "allman" && tokens[0].loc.start.line === tokens[1].loc.start.line) {
212-
context.report(node, OPEN_MESSAGE_ALLMAN);
260+
context.report({
261+
node,
262+
message: OPEN_MESSAGE_ALLMAN,
263+
fix: fixer => fixer.insertTextBefore(tokens[1], "\n")
264+
});
213265
}
214266
}
215267

0 commit comments

Comments
 (0)