Skip to content

Commit

Permalink
Merge pull request #1311 from RDGthree/master
Browse files Browse the repository at this point in the history
Teach sort-comp rule about getters and setters.
  • Loading branch information
ljharb committed Jul 21, 2017
2 parents ef2054b + b1c1f84 commit 067882b
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 10 deletions.
2 changes: 2 additions & 0 deletions docs/rules/sort-comp.md
Expand Up @@ -90,6 +90,8 @@ The default configuration is:
* `everything-else` is a special group that match all the methods that do not match any of the other groups.
* `render` is referring to the `render` method.
* `type-annotations`. This group is not specified by default, but can be used to enforce flow annotations to be at the top.
* `getters` This group is not specified by default, but can be used to enforce class getters positioning.
* `setters` This group is not specified by default, but can be used to enforce class setters positioning.

You can override this configuration to match your needs.

Expand Down
40 changes: 30 additions & 10 deletions lib/rules/sort-comp.js
Expand Up @@ -128,20 +128,30 @@ module.exports = {
const indexes = [];

if (method.static) {
for (i = 0, j = methodsOrder.length; i < j; i++) {
if (methodsOrder[i] === 'static-methods') {
indexes.push(i);
break;
}
const staticIndex = methodsOrder.indexOf('static-methods');
if (staticIndex >= 0) {
indexes.push(staticIndex);
}
}

if (method.getter) {
const getterIndex = methodsOrder.indexOf('getters');
if (getterIndex >= 0) {
indexes.push(getterIndex);
}
}

if (method.setter) {
const setterIndex = methodsOrder.indexOf('setters');
if (setterIndex >= 0) {
indexes.push(setterIndex);
}
}

if (method.typeAnnotation) {
for (i = 0, j = methodsOrder.length; i < j; i++) {
if (methodsOrder[i] === 'type-annotations') {
indexes.push(i);
break;
}
const annotationIndex = methodsOrder.indexOf('type-annotations');
if (annotationIndex >= 0) {
indexes.push(annotationIndex);
}
}

Expand Down Expand Up @@ -192,6 +202,14 @@ module.exports = {
return tokens[1] && tokens[1].type === 'Identifier' ? tokens[1].value : tokens[0].value;
}

if (node.kind === 'get') {
return 'getter functions';
}

if (node.kind === 'set') {
return 'setter functions';
}

return node.key.name;
}

Expand Down Expand Up @@ -363,6 +381,8 @@ module.exports = {
function checkPropsOrder(properties) {
const propertiesInfos = properties.map(node => ({
name: getPropertyName(node),
getter: node.kind === 'get',
setter: node.kind === 'set',
static: node.static,
typeAnnotation: !!node.typeAnnotation && node.value === null
}));
Expand Down
86 changes: 86 additions & 0 deletions tests/lib/rules/sort-comp.js
Expand Up @@ -268,6 +268,48 @@ ruleTester.run('sort-comp', rule, {
].join('\n'),
parser: 'babel-eslint',
parserOptions: parserOptions
}, {
// Getters should be at the top
code: [
'class Hello extends React.Component {',
' get foo() {}',
' constructor() {}',
' render() {',
' return <div>{this.props.text}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
options: [{
order: [
'getters',
'static-methods',
'lifecycle',
'everything-else',
'render'
]
}]
}, {
// Setters should be at the top
code: [
'class Hello extends React.Component {',
' set foo(bar) {}',
' constructor() {}',
' render() {',
' return <div>{this.props.text}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
options: [{
order: [
'setters',
'static-methods',
'lifecycle',
'everything-else',
'render'
]
}]
}],

invalid: [{
Expand Down Expand Up @@ -429,5 +471,49 @@ ruleTester.run('sort-comp', rule, {
'render'
]
}]
}, {
// Getters should at the top
code: [
'class Hello extends React.Component {',
' constructor() {}',
' get foo() {}',
' render() {',
' return <div>{this.props.text}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
errors: [{message: 'constructor should be placed after getter functions'}],
options: [{
order: [
'getters',
'static-methods',
'lifecycle',
'everything-else',
'render'
]
}]
}, {
// Setters should at the top
code: [
'class Hello extends React.Component {',
' constructor() {}',
' set foo(bar) {}',
' render() {',
' return <div>{this.props.text}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
errors: [{message: 'constructor should be placed after setter functions'}],
options: [{
order: [
'setters',
'static-methods',
'lifecycle',
'everything-else',
'render'
]
}]
}]
});

0 comments on commit 067882b

Please sign in to comment.