Skip to content

Commit fc8547f

Browse files
author
cookieranger
committed
Teach sort-comp to put static methods at the top
The Airbnb JavaScript style guide was recently updated to sort static methods to the tops of classes [0]. Since this codemod is designed to follow the constraints of the Airbnb style guide, I figured it would be good to update this as well. [0]: airbnb/javascript#715
1 parent b6f0b37 commit fc8547f

File tree

4 files changed

+39
-13
lines changed

4 files changed

+39
-13
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Reorders React component methods to match the [ESLint](http://eslint.org/)
9595
[react/sort-comp
9696
rule](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md),
9797
specifically with the [tighter constraints of the Airbnb style
98-
guide](https://github.com/airbnb/javascript/blob/6c89f958/packages/eslint-config-airbnb/rules/react.js#L47-L57).
98+
guide](https://github.com/airbnb/javascript/blob/7684892951ef663e1c4e62ad57d662e9b2748b9e/packages/eslint-config-airbnb/rules/react.js#L122-L134).
9999

100100
```sh
101101
jscodeshift -t react-codemod/transforms/sort-comp.js <file>

test/sort-comp-test2.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ class MyComponent extends React.Component {
1515
componentDidMount() {
1616
}
1717

18+
static someStaticThing() {
19+
// should come first
20+
}
21+
1822
renderFoo() {
1923
// other render* function
2024
}

test/sort-comp-test2.output.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ const propTypes = {};
44

55
// comment above class
66
class MyComponent extends React.Component {
7+
static someStaticThing() {
8+
// should come first
9+
}
10+
711
// comment on componentDidMount
812
componentDidMount() {
913
}

transforms/sort-comp.js

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
/**
22
* Reorders React component methods to match the [ESLint](http://eslint.org/)
33
* [react/sort-comp rule](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md),
4-
* specifically with the [tighter constraints of the Airbnb style guide](https://github.com/airbnb/javascript/blob/6c89f9587f96688bf0d4d536adb8eb4ed9bf0002/packages/eslint-config-airbnb/rules/react.js#L47-L57),
4+
* specifically with the [tighter constraints of the Airbnb style guide](https://github.com/airbnb/javascript/blob/7684892951ef663e1c4e62ad57d662e9b2748b9e/packages/eslint-config-airbnb/rules/react.js#L122-L134),
55
*
66
* 'react/sort-comp': [2, {
77
* 'order': [
8+
* 'static-methods',
89
* 'lifecycle',
910
* '/^on.+$/',
1011
* '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/',
@@ -28,8 +29,8 @@ module.exports = function(fileInfo, api, options) {
2829
const nameA = a.key.name;
2930
const nameB = b.key.name;
3031

31-
const indexA = getRefPropIndexes(nameA);
32-
const indexB = getRefPropIndexes(nameB);
32+
const indexA = getRefPropIndexes(a);
33+
const indexB = getRefPropIndexes(b);
3334

3435
const sameLocation = indexA.length == 1 && indexB.length == 1 && indexA[0] == indexB[0];
3536

@@ -86,6 +87,7 @@ module.exports = function(fileInfo, api, options) {
8687

8788
// Hard-coded for Airbnb style
8889
const methodsOrder = [
90+
'static-methods',
8991
'displayName',
9092
'propTypes',
9193
'contextTypes',
@@ -119,24 +121,40 @@ const regExpRegExp = /\/(.*)\/([g|y|i|m]*)/;
119121

120122
/**
121123
* Get indexes of the matching patterns in methods order configuration
122-
* @param {String} method - Method name.
124+
* @param {Object} method
123125
* @returns {Array} The matching patterns indexes. Return [Infinity] if there is no match.
124126
*/
125127
function getRefPropIndexes(method) {
128+
var methodName = method.key.name;
126129
var isRegExp;
127130
var matching;
128131
var i;
129132
var j;
130133
var indexes = [];
131-
for (i = 0, j = methodsOrder.length; i < j; i++) {
132-
isRegExp = methodsOrder[i].match(regExpRegExp);
133-
if (isRegExp) {
134-
matching = new RegExp(isRegExp[1], isRegExp[2]).test(method);
135-
} else {
136-
matching = methodsOrder[i] === method;
134+
// Check for static methods
135+
if (indexes.length === 0) {
136+
if (method.static) {
137+
for (i = 0, j = methodsOrder.length; i < j; i++) {
138+
if (methodsOrder[i] === 'static-methods') {
139+
indexes.push(i);
140+
}
141+
}
137142
}
138-
if (matching) {
139-
indexes.push(i);
143+
}
144+
145+
// This is not a staic method, so we try to determine where it should go based
146+
// on method name.
147+
if (indexes.length === 0) {
148+
for (i = 0, j = methodsOrder.length; i < j; i++) {
149+
isRegExp = methodsOrder[i].match(regExpRegExp);
150+
if (isRegExp) {
151+
matching = new RegExp(isRegExp[1], isRegExp[2]).test(methodName);
152+
} else {
153+
matching = methodsOrder[i] === methodName;
154+
}
155+
if (matching) {
156+
indexes.push(i);
157+
}
140158
}
141159
}
142160

0 commit comments

Comments
 (0)