Skip to content

Commit 0a918b1

Browse files
Radek Benkelbenmosher
Radek Benkel
authored andcommitted
Fix order's newlines-between edge cases (#339)
* Change required lines amount to minimum 1 (instead of exactly 1) to be at least one, not exactly one Before it was 1. To prevent multiple lines between imports, core `no-multiple-empty-lines` rule can be used. * Fix `order`s `newline-between` for multiline imports * Ignore unassigned imports while detecting empty lines Previously it was calculated based on `loc` property of nodes. Counting REAL empty lines is less error-prone. * Fix `require` in object properties
1 parent 5bdd443 commit 0a918b1

File tree

4 files changed

+167
-33
lines changed

4 files changed

+167
-33
lines changed

Diff for: CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
77
### Fixed
88
- `export * from 'foo'` now properly ignores a `default` export from `foo`, if any. ([#328]/[#332], thanks [@jkimbo])
99
This impacts all static analysis of imported names. ([`default`], [`named`], [`namespace`], [`export`])
10+
- Make [`order`]'s `newline-between` option handle multiline import statements ([#313], thanks [@singles])
11+
- Make [`order`]'s `newline-between` option handle not assigned import statements ([#313], thanks [@singles])
12+
- Make [`order`]'s `newline-between` option ignore `require` statements inside object literals ([#313], thanks [@singles])
1013

1114
## [1.8.0] - 2016-05-11
1215
### Added

Diff for: docs/rules/order.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ You can set the options like this:
9898
Enforces or forbids new lines between import groups:
9999

100100
- If omitted, assertion messages will be neither enforced nor forbidden.
101-
- If set to `always`, a new line between each group will be enforced, and new lines inside a group will be forbidden.
101+
- If set to `always`, at least one new line between each group will be enforced, and new lines inside a group will be forbidden. To prevent multiple lines between imports, core `no-multiple-empty-lines` rule can be used.
102102
- If set to `never`, no new lines are allowed in the entire import section.
103103

104104
With the default group setting, the following will be invalid:

Diff for: src/rules/order.js

+13-6
Original file line numberDiff line numberDiff line change
@@ -110,28 +110,33 @@ function convertGroupsToRanks(groups) {
110110
}
111111

112112
function makeNewlinesBetweenReport (context, imported, newlinesBetweenImports) {
113-
const getLineDifference = (currentImport, previousImport) => {
114-
return currentImport.node.loc.start.line - previousImport.node.loc.start.line
113+
const getNumberOfEmptyLinesBetween = (currentImport, previousImport) => {
114+
const linesBetweenImports = context.getSourceCode().lines.slice(
115+
previousImport.node.loc.end.line,
116+
currentImport.node.loc.start.line - 1
117+
)
118+
119+
return linesBetweenImports.filter((line) => !line.trim().length).length
115120
}
116121
let previousImport = imported[0]
117122

118123
imported.slice(1).forEach(function(currentImport) {
119124
if (newlinesBetweenImports === 'always') {
120125
if (currentImport.rank !== previousImport.rank
121-
&& getLineDifference(currentImport, previousImport) !== 2)
126+
&& getNumberOfEmptyLinesBetween(currentImport, previousImport) === 0)
122127
{
123128
context.report(
124-
previousImport.node, 'There should be one empty line between import groups'
129+
previousImport.node, 'There should be at least one empty line between import groups'
125130
)
126131
} else if (currentImport.rank === previousImport.rank
127-
&& getLineDifference(currentImport, previousImport) >= 2)
132+
&& getNumberOfEmptyLinesBetween(currentImport, previousImport) > 0)
128133
{
129134
context.report(
130135
previousImport.node, 'There should be no empty line within import group'
131136
)
132137
}
133138
} else {
134-
if (getLineDifference(currentImport, previousImport) > 1) {
139+
if (getNumberOfEmptyLinesBetween(currentImport, previousImport) > 0) {
135140
context.report(previousImport.node, 'There should be no empty line between import groups')
136141
}
137142
}
@@ -191,10 +196,12 @@ module.exports = function importOrderRule (context) {
191196
FunctionExpression: incrementLevel,
192197
ArrowFunctionExpression: incrementLevel,
193198
BlockStatement: incrementLevel,
199+
ObjectExpression: incrementLevel,
194200
'FunctionDeclaration:exit': decrementLevel,
195201
'FunctionExpression:exit': decrementLevel,
196202
'ArrowFunctionExpression:exit': decrementLevel,
197203
'BlockStatement:exit': decrementLevel,
204+
'ObjectExpression:exit': decrementLevel,
198205
}
199206
}
200207

Diff for: tests/src/rules/order.js

+150-26
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,11 @@ ruleTester.run('order', rule, {
167167
var index = require('./');
168168
var path = require('path');
169169
170+
171+
170172
var sibling = require('./foo');
171173
174+
172175
var relParent1 = require('../foo');
173176
var relParent3 = require('../');
174177
var async = require('async');
@@ -206,6 +209,121 @@ ruleTester.run('order', rule, {
206209
},
207210
],
208211
}),
212+
// Option newlines-between: 'always' with multiline imports #1
213+
test({
214+
code: `
215+
import path from 'path';
216+
217+
import {
218+
I,
219+
Want,
220+
Couple,
221+
Imports,
222+
Here
223+
} from 'bar';
224+
import external from 'external'
225+
`,
226+
options: [{ 'newlines-between': 'always' }]
227+
}),
228+
// Option newlines-between: 'always' with multiline imports #2
229+
test({
230+
code: `
231+
import path from 'path';
232+
import net
233+
from 'net';
234+
235+
import external from 'external'
236+
`,
237+
options: [{ 'newlines-between': 'always' }]
238+
}),
239+
// Option newlines-between: 'always' with multiline imports #3
240+
test({
241+
code: `
242+
import foo
243+
from '../../../../this/will/be/very/long/path/and/therefore/this/import/has/to/be/in/two/lines';
244+
245+
import bar
246+
from './sibling';
247+
`,
248+
options: [{ 'newlines-between': 'always' }]
249+
}),
250+
// Option newlines-between: 'always' with not assigned import #1
251+
test({
252+
code: `
253+
import path from 'path';
254+
255+
import 'loud-rejection';
256+
import 'something-else';
257+
258+
import _ from 'lodash';
259+
`,
260+
options: [{ 'newlines-between': 'always' }]
261+
}),
262+
// Option newlines-between: 'never' with not assigned import #2
263+
test({
264+
code: `
265+
import path from 'path';
266+
import 'loud-rejection';
267+
import 'something-else';
268+
import _ from 'lodash';
269+
`,
270+
options: [{ 'newlines-between': 'never' }]
271+
}),
272+
// Option newlines-between: 'always' with not assigned require #1
273+
test({
274+
code: `
275+
var path = require('path');
276+
277+
require('loud-rejection');
278+
require('something-else');
279+
280+
var _ = require('lodash');
281+
`,
282+
options: [{ 'newlines-between': 'always' }]
283+
}),
284+
// Option newlines-between: 'never' with not assigned require #2
285+
test({
286+
code: `
287+
var path = require('path');
288+
require('loud-rejection');
289+
require('something-else');
290+
var _ = require('lodash');
291+
`,
292+
options: [{ 'newlines-between': 'never' }]
293+
}),
294+
// Option newlines-between: 'never' should ignore nested require statement's #1
295+
test({
296+
code: `
297+
var some = require('asdas');
298+
var config = {
299+
port: 4444,
300+
runner: {
301+
server_path: require('runner-binary').path,
302+
303+
cli_args: {
304+
'webdriver.chrome.driver': require('browser-binary').path
305+
}
306+
}
307+
}
308+
`,
309+
options: [{ 'newlines-between': 'never' }]
310+
}),
311+
// Option newlines-between: 'always' should ignore nested require statement's #2
312+
test({
313+
code: `
314+
var some = require('asdas');
315+
var config = {
316+
port: 4444,
317+
runner: {
318+
server_path: require('runner-binary').path,
319+
cli_args: {
320+
'webdriver.chrome.driver': require('browser-binary').path
321+
}
322+
}
323+
}
324+
`,
325+
options: [{ 'newlines-between': 'always' }]
326+
}),
209327
],
210328
invalid: [
211329
// builtin before external module (require)
@@ -517,23 +635,24 @@ ruleTester.run('order', rule, {
517635
errors: [
518636
{
519637
line: 4,
520-
message: 'There should be one empty line between import groups',
638+
message: 'There should be at least one empty line between import groups',
521639
},
522640
{
523641
line: 5,
524-
message: 'There should be one empty line between import groups',
642+
message: 'There should be at least one empty line between import groups',
525643
},
526644
],
527645
}),
528-
//Option newlines-between: 'always' should report too many empty lines between import groups
646+
//Option newlines-between: 'always' should report unnecessary empty lines space between import groups
529647
test({
530648
code: `
531649
var fs = require('fs');
532-
var index = require('./');
533-
534650
651+
var path = require('path');
652+
var index = require('./');
535653
536654
var sibling = require('./foo');
655+
537656
var async = require('async');
538657
`,
539658
options: [
@@ -547,40 +666,45 @@ ruleTester.run('order', rule, {
547666
],
548667
errors: [
549668
{
550-
line: 3,
551-
message: 'There should be one empty line between import groups',
669+
line: 2,
670+
message: 'There should be no empty line within import group',
671+
},
672+
{
673+
line: 7,
674+
message: 'There should be no empty line within import group',
552675
},
553676
],
554677
}),
555-
//Option newlines-between: 'always' should report unnecessary empty lines space between import groups
678+
// Option newlines-between: 'never' should report unnecessary empty lines when using not assigned imports
556679
test({
557680
code: `
558-
var fs = require('fs');
559-
560-
var path = require('path');
561-
var index = require('./');
562-
563-
var sibling = require('./foo');
681+
import path from 'path';
682+
import 'loud-rejection';
564683
565-
var async = require('async');
684+
import 'something-else';
685+
import _ from 'lodash';
566686
`,
567-
options: [
687+
options: [{ 'newlines-between': 'never' }],
688+
errors: [
568689
{
569-
groups: [
570-
['builtin', 'index'],
571-
['sibling', 'parent', 'external']
572-
],
573-
'newlines-between': 'always',
690+
line: 2,
691+
message: 'There should be no empty line between import groups',
574692
},
575693
],
694+
}),
695+
// Option newlines-between: 'always' should report missing empty lines when using not assigned imports
696+
test({
697+
code: `
698+
import path from 'path';
699+
import 'loud-rejection';
700+
import 'something-else';
701+
import _ from 'lodash';
702+
`,
703+
options: [{ 'newlines-between': 'always' }],
576704
errors: [
577705
{
578706
line: 2,
579-
message: 'There should be no empty line within import group',
580-
},
581-
{
582-
line: 7,
583-
message: 'There should be no empty line within import group',
707+
message: 'There should be at least one empty line between import groups',
584708
},
585709
],
586710
}),

0 commit comments

Comments
 (0)