Skip to content

Commit c7dd755

Browse files
authored
Merge pull request #1470 from RDGthree/master
Add instance-methods and instance-variables to sort-comp.
2 parents e632628 + 7efe31a commit c7dd755

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

docs/rules/sort-comp.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,11 @@ The default configuration is:
8989
* `lifecycle` is referring to the `lifecycle` group defined in `groups`.
9090
* `everything-else` is a special group that match all the methods that do not match any of the other groups.
9191
* `render` is referring to the `render` method.
92-
* `type-annotations`. This group is not specified by default, but can be used to enforce flow annotations to be at the top.
92+
* `type-annotations`. This group is not specified by default, but can be used to enforce flow annotations positioning.
9393
* `getters` This group is not specified by default, but can be used to enforce class getters positioning.
9494
* `setters` This group is not specified by default, but can be used to enforce class setters positioning.
95+
* `instance-variables` This group is not specified by default, but can be used to enforce all other instance variables positioning.
96+
* `instance-methods` This group is not specified by default, but can be used to enforce all other instance methods positioning.
9597

9698
You can override this configuration to match your needs.
9799

lib/rules/sort-comp.js

+24
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,20 @@ module.exports = {
172172
}
173173
}
174174

175+
if (indexes.length === 0 && method.instanceVariable) {
176+
const annotationIndex = methodsOrder.indexOf('instance-variables');
177+
if (annotationIndex >= 0) {
178+
indexes.push(annotationIndex);
179+
}
180+
}
181+
182+
if (indexes.length === 0 && method.instanceMethod) {
183+
const annotationIndex = methodsOrder.indexOf('instance-methods');
184+
if (annotationIndex >= 0) {
185+
indexes.push(annotationIndex);
186+
}
187+
}
188+
175189
// No matching pattern, return 'everything-else' index
176190
if (indexes.length === 0) {
177191
for (i = 0, j = methodsOrder.length; i < j; i++) {
@@ -361,6 +375,16 @@ module.exports = {
361375
getter: node.kind === 'get',
362376
setter: node.kind === 'set',
363377
static: node.static,
378+
instanceVariable: !node.static &&
379+
node.type === 'ClassProperty' &&
380+
node.value &&
381+
node.value.type !== 'ArrowFunctionExpression' &&
382+
node.value.type !== 'FunctionExpression',
383+
instanceMethod: !node.static &&
384+
node.type === 'ClassProperty' &&
385+
node.value &&
386+
(node.value.type === 'ArrowFunctionExpression' ||
387+
node.value.type === 'FunctionExpression'),
364388
typeAnnotation: !!node.typeAnnotation && node.value === null
365389
}));
366390

tests/lib/rules/sort-comp.js

+90
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,50 @@ ruleTester.run('sort-comp', rule, {
310310
'render'
311311
]
312312
}]
313+
}, {
314+
// Instance methods should be at the top
315+
code: [
316+
'class Hello extends React.Component {',
317+
' foo = () => {}',
318+
' constructor() {}',
319+
' classMethod() {}',
320+
' static bar = () => {}',
321+
' render() {',
322+
' return <div>{this.props.text}</div>;',
323+
' }',
324+
'}'
325+
].join('\n'),
326+
parser: 'babel-eslint',
327+
options: [{
328+
order: [
329+
'instance-methods',
330+
'lifecycle',
331+
'everything-else',
332+
'render'
333+
]
334+
}]
335+
}, {
336+
// Instance variables should be at the top
337+
code: [
338+
'class Hello extends React.Component {',
339+
' foo = \'bar\'',
340+
' constructor() {}',
341+
' state = {}',
342+
' static bar = \'foo\'',
343+
' render() {',
344+
' return <div>{this.props.text}</div>;',
345+
' }',
346+
'}'
347+
].join('\n'),
348+
parser: 'babel-eslint',
349+
options: [{
350+
order: [
351+
'instance-variables',
352+
'lifecycle',
353+
'everything-else',
354+
'render'
355+
]
356+
}]
313357
}],
314358

315359
invalid: [{
@@ -515,5 +559,51 @@ ruleTester.run('sort-comp', rule, {
515559
'render'
516560
]
517561
}]
562+
}, {
563+
// Instance methods should not be at the top
564+
code: [
565+
'class Hello extends React.Component {',
566+
' constructor() {}',
567+
' static bar = () => {}',
568+
' classMethod() {}',
569+
' foo = function() {}',
570+
' render() {',
571+
' return <div>{this.props.text}</div>;',
572+
' }',
573+
'}'
574+
].join('\n'),
575+
parser: 'babel-eslint',
576+
errors: [{message: 'foo should be placed before constructor'}],
577+
options: [{
578+
order: [
579+
'instance-methods',
580+
'lifecycle',
581+
'everything-else',
582+
'render'
583+
]
584+
}]
585+
}, {
586+
// Instance variables should not be at the top
587+
code: [
588+
'class Hello extends React.Component {',
589+
' constructor() {}',
590+
' state = {}',
591+
' static bar = {}',
592+
' foo = {}',
593+
' render() {',
594+
' return <div>{this.props.text}</div>;',
595+
' }',
596+
'}'
597+
].join('\n'),
598+
parser: 'babel-eslint',
599+
errors: [{message: 'foo should be placed before constructor'}],
600+
options: [{
601+
order: [
602+
'instance-variables',
603+
'lifecycle',
604+
'everything-else',
605+
'render'
606+
]
607+
}]
518608
}]
519609
});

0 commit comments

Comments
 (0)