Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit b4cff9d

Browse files
fatfisznzakas
authored andcommitted
Fix: Incorrect object-property-newline behavior (fixes eslint#6207) (eslint#6213)
Syntax that wasn't handled correctly / caused errors to be thrown: - computed keys spanning multiple lines - experimental object spread
1 parent 35b4656 commit b4cff9d

File tree

2 files changed

+159
-10
lines changed

2 files changed

+159
-10
lines changed

lib/rules/object-property-newline.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ module.exports = {
4040

4141
return {
4242
ObjectExpression: function(node) {
43-
var lastTokenOfPreviousValue, firstTokenOfCurrentKey;
43+
var lastTokenOfPreviousProperty, firstTokenOfCurrentProperty;
4444

4545
if (allowSameLine) {
4646
if (node.properties.length > 1) {
47-
var firstToken = sourceCode.getFirstToken(node.properties[0].key);
48-
var lastToken = sourceCode.getLastToken(node.properties[node.properties.length - 1].value);
47+
var firstTokenOfFirstProperty = sourceCode.getFirstToken(node.properties[0]);
48+
var lastTokenOfLastProperty = sourceCode.getLastToken(node.properties[node.properties.length - 1]);
4949

50-
if (firstToken.loc.end.line === lastToken.loc.start.line) {
50+
if (firstTokenOfFirstProperty.loc.end.line === lastTokenOfLastProperty.loc.start.line) {
5151

5252
// All keys and values are on the same line
5353
return;
@@ -56,13 +56,13 @@ module.exports = {
5656
}
5757

5858
for (var i = 1; i < node.properties.length; i++) {
59-
lastTokenOfPreviousValue = sourceCode.getLastToken(node.properties[i - 1].value);
60-
firstTokenOfCurrentKey = sourceCode.getFirstToken(node.properties[i].key);
59+
lastTokenOfPreviousProperty = sourceCode.getLastToken(node.properties[i - 1]);
60+
firstTokenOfCurrentProperty = sourceCode.getFirstToken(node.properties[i]);
6161

62-
if (lastTokenOfPreviousValue.loc.end.line === firstTokenOfCurrentKey.loc.start.line) {
62+
if (lastTokenOfPreviousProperty.loc.end.line === firstTokenOfCurrentProperty.loc.start.line) {
6363
context.report({
6464
node: node,
65-
loc: firstTokenOfCurrentKey.loc.start,
65+
loc: firstTokenOfCurrentProperty.loc.start,
6666
message: errorMessage
6767
});
6868
}

tests/lib/rules/object-property-newline.js

Lines changed: 151 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,35 @@ ruleTester.run("object-property-newline", rule, {
2828
{ code: "var obj = { k1: 'val1' };" },
2929
{ code: "var obj = {\nk1: 'val1'\n};" },
3030
{ code: "var obj = {};" },
31+
{ code: "var obj = {\n[bar]: 'baz',\nbaz\n};", parserOptions: { ecmaVersion: 6 } },
32+
{ code: "var obj = {\nk1: 'val1',\nk2: 'val2',\n...{}\n};", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } },
33+
{ code: "var obj = { k1: 'val1',\nk2: 'val2',\n...{} };", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } },
34+
{ code: "var obj = { ...{} };", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } },
3135
{ code: "foo({ k1: 'val1',\nk2: 'val2' });" },
3236
{ code: "foo({\nk1: 'val1',\nk2: 'val2'\n});" },
3337
{ code: "foo({\na,\nb\n});", parserOptions: { ecmaVersion: 6 } },
3438
{ code: "foo({\na,\nb,\n});", parserOptions: { ecmaVersion: 6 } },
3539
{ code: "foo({\nbar() {},\nbaz\n});", parserOptions: { ecmaVersion: 6 } },
3640
{ code: "foo({\n[bar]: 'baz',\nbaz \n})", parserOptions: { ecmaVersion: 6 } },
41+
{ code: "foo({\nk1: 'val1',\nk2: 'val2',\n...{}\n});", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } },
42+
{ code: "foo({ k1: 'val1',\nk2: 'val2',\n...{} });", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } },
43+
{ code: "foo({ ...{} });", parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } },
3744

3845
// allowMultiplePropertiesPerLine: true
3946
{ code: "var obj = { k1: 'val1', k2: 'val2', k3: 'val3' };", options: [{ allowMultiplePropertiesPerLine: true }] },
4047
{ code: "var obj = {\nk1: 'val1', k2: 'val2', k3: 'val3'\n};", options: [{ allowMultiplePropertiesPerLine: true }] },
4148
{ code: "var obj = { k1: 'val1' };", options: [{ allowMultiplePropertiesPerLine: true }] },
4249
{ code: "var obj = {\nk1: 'val1'\n};", options: [{ allowMultiplePropertiesPerLine: true }] },
4350
{ code: "var obj = {};", options: [{ allowMultiplePropertiesPerLine: true }] },
51+
{ code: "var obj = { 'k1': 'val1', k2: 'val2', ...{} };", options: [{ allowMultiplePropertiesPerLine: true }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } },
52+
{ code: "var obj = {\n'k1': 'val1', k2: 'val2', ...{}\n};", options: [{ allowMultiplePropertiesPerLine: true }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } },
4453
{ code: "foo({ k1: 'val1', k2: 'val2' });", options: [{ allowMultiplePropertiesPerLine: true }] },
4554
{ code: "foo({\nk1: 'val1', k2: 'val2'\n});", options: [{ allowMultiplePropertiesPerLine: true }] },
4655
{ code: "foo({ a, b });", options: [{ allowMultiplePropertiesPerLine: true }], parserOptions: { ecmaVersion: 6 } },
4756
{ code: "foo({ bar() {}, baz });", options: [{ allowMultiplePropertiesPerLine: true }], parserOptions: { ecmaVersion: 6 } },
48-
{ code: "foo({ [bar]: 'baz', baz })", options: [{ allowMultiplePropertiesPerLine: true }], parserOptions: { ecmaVersion: 6 } }
57+
{ code: "foo({ [bar]: 'baz', baz })", options: [{ allowMultiplePropertiesPerLine: true }], parserOptions: { ecmaVersion: 6 } },
58+
{ code: "foo({ 'k1': 'val1', k2: 'val2', ...{} });", options: [{ allowMultiplePropertiesPerLine: true }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } },
59+
{ code: "foo({\n'k1': 'val1', k2: 'val2', ...{}\n});", options: [{ allowMultiplePropertiesPerLine: true }], parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }
4960
],
5061

5162
invalid: [
@@ -96,6 +107,42 @@ ruleTester.run("object-property-newline", rule, {
96107
}
97108
]
98109
},
110+
{
111+
code: "var obj = { k1: 'val1', [\nk2]: 'val2' };",
112+
parserOptions: { ecmaVersion: 6 },
113+
errors: [
114+
{
115+
message: "Object properties must go on a new line",
116+
type: "ObjectExpression",
117+
line: 1,
118+
column: 25
119+
}
120+
]
121+
},
122+
{
123+
code: "var obj = { k1: 'val1', ...{} };",
124+
parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } },
125+
errors: [
126+
{
127+
message: "Object properties must go on a new line",
128+
type: "ObjectExpression",
129+
line: 1,
130+
column: 25
131+
}
132+
]
133+
},
134+
{
135+
code: "var obj = {\nk1: 'val1', ...{}\n};",
136+
parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } },
137+
errors: [
138+
{
139+
message: "Object properties must go on a new line",
140+
type: "ObjectExpression",
141+
line: 2,
142+
column: 13
143+
}
144+
]
145+
},
99146
{
100147
code: "foo({ k1: 'val1', k2: 'val2' });",
101148
errors: [
@@ -166,6 +213,42 @@ ruleTester.run("object-property-newline", rule, {
166213
}
167214
]
168215
},
216+
{
217+
code: "foo({ k1: 'val1', [\nk2]: 'val2' })",
218+
parserOptions: { ecmaVersion: 6 },
219+
errors: [
220+
{
221+
message: "Object properties must go on a new line",
222+
type: "ObjectExpression",
223+
line: 1,
224+
column: 19
225+
}
226+
]
227+
},
228+
{
229+
code: "foo({ k1: 'val1', ...{} })",
230+
parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } },
231+
errors: [
232+
{
233+
message: "Object properties must go on a new line",
234+
type: "ObjectExpression",
235+
line: 1,
236+
column: 19
237+
}
238+
]
239+
},
240+
{
241+
code: "foo({\nk1: 'val1', ...{}\n})",
242+
parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } },
243+
errors: [
244+
{
245+
message: "Object properties must go on a new line",
246+
type: "ObjectExpression",
247+
line: 2,
248+
column: 13
249+
}
250+
]
251+
},
169252
{
170253
code: "var obj = {\na: {\nb: 1,\nc: 2\n}, d: 2\n};",
171254
errors: [
@@ -192,8 +275,74 @@ ruleTester.run("object-property-newline", rule, {
192275
]
193276
},
194277
{
195-
code: "var obj = {\nk1: 'val1',\nk2: 'val2', k3: 'val3'\n};",
278+
code: "var obj = { [\nk1]: 'val1', k2: 'val2' };",
279+
options: [{ allowMultiplePropertiesPerLine: true }],
280+
parserOptions: { ecmaVersion: 6 },
281+
errors: [
282+
{
283+
message: "Object properties must go on a new line if they aren't all on the same line",
284+
type: "ObjectExpression",
285+
line: 2,
286+
column: 14
287+
}
288+
]
289+
},
290+
{
291+
code: "var obj = {\nk1: 'val1',\nk2: 'val2', ...{}\n};",
292+
options: [{ allowMultiplePropertiesPerLine: true }],
293+
parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } },
294+
errors: [
295+
{
296+
message: "Object properties must go on a new line if they aren't all on the same line",
297+
type: "ObjectExpression",
298+
line: 3,
299+
column: 13
300+
}
301+
]
302+
},
303+
{
304+
code: "var obj = {\n...{},\nk1: 'val1', k2: 'val2'\n};",
305+
options: [{ allowMultiplePropertiesPerLine: true }],
306+
parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } },
307+
errors: [
308+
{
309+
message: "Object properties must go on a new line if they aren't all on the same line",
310+
type: "ObjectExpression",
311+
line: 3,
312+
column: 13
313+
}
314+
]
315+
},
316+
{
317+
code: "foo({ [\nk1]: 'val1', k2: 'val2' })",
318+
options: [{ allowMultiplePropertiesPerLine: true }],
319+
parserOptions: { ecmaVersion: 6 },
320+
errors: [
321+
{
322+
message: "Object properties must go on a new line if they aren't all on the same line",
323+
type: "ObjectExpression",
324+
line: 2,
325+
column: 14
326+
}
327+
]
328+
},
329+
{
330+
code: "foo({\nk1: 'val1',\nk2: 'val2', ...{}\n})",
331+
options: [{ allowMultiplePropertiesPerLine: true }],
332+
parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } },
333+
errors: [
334+
{
335+
message: "Object properties must go on a new line if they aren't all on the same line",
336+
type: "ObjectExpression",
337+
line: 3,
338+
column: 13
339+
}
340+
]
341+
},
342+
{
343+
code: "foo({\n...{},\nk1: 'val1', k2: 'val2'\n})",
196344
options: [{ allowMultiplePropertiesPerLine: true }],
345+
parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } },
197346
errors: [
198347
{
199348
message: "Object properties must go on a new line if they aren't all on the same line",

0 commit comments

Comments
 (0)