From 781bfff5409399009c7fe8c9305b45f1ec03818b Mon Sep 17 00:00:00 2001 From: Veda Date: Wed, 11 Sep 2019 20:57:10 +0530 Subject: [PATCH] [new] `sort-comp`: add `static-variables` grouping Fixes #2405 --- docs/rules/sort-comp.md | 2 +- lib/rules/sort-comp.js | 14 ++- tests/lib/rules/sort-comp.js | 184 +++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 3 deletions(-) diff --git a/docs/rules/sort-comp.md b/docs/rules/sort-comp.md index 1e03d12ed1..d0b26486c6 100644 --- a/docs/rules/sort-comp.md +++ b/docs/rules/sort-comp.md @@ -90,7 +90,7 @@ The default configuration is: } } ``` - +* `static-variables` This group is not specified by default, but can be used to enforce class static variable positioning. * `static-methods` is a special keyword that refers to static class methods. * `lifecycle` refers to the `lifecycle` group defined in `groups`. * `everything-else` is a special group that matches all of the methods that do not match any of the other groups. diff --git a/lib/rules/sort-comp.js b/lib/rules/sort-comp.js index 293b830f8f..752a53bd38 100644 --- a/lib/rules/sort-comp.js +++ b/lib/rules/sort-comp.js @@ -148,8 +148,12 @@ module.exports = { if (method.typeAnnotation) { methodGroupIndexes.push(groupIndex); } + } else if (currentGroup === 'static-variables') { + if (method.staticVariable) { + methodGroupIndexes.push(groupIndex); + } } else if (currentGroup === 'static-methods') { - if (method.static) { + if (method.staticMethod) { methodGroupIndexes.push(groupIndex); } } else if (currentGroup === 'instance-variables') { @@ -380,7 +384,13 @@ module.exports = { name: getPropertyName(node), getter: node.kind === 'get', setter: node.kind === 'set', - static: node.static, + staticVariable: node.static && + node.type === 'ClassProperty' && + (!node.value || !astUtil.isFunctionLikeExpression(node.value)), + staticMethod: node.static && + (node.type === 'ClassProperty' || node.type === 'MethodDefinition') && + node.value && + (astUtil.isFunctionLikeExpression(node.value)), instanceVariable: !node.static && node.type === 'ClassProperty' && (!node.value || !astUtil.isFunctionLikeExpression(node.value)), diff --git a/tests/lib/rules/sort-comp.js b/tests/lib/rules/sort-comp.js index 7c67bcb4a8..d30bb25f48 100644 --- a/tests/lib/rules/sort-comp.js +++ b/tests/lib/rules/sort-comp.js @@ -506,6 +506,129 @@ ruleTester.run('sort-comp', rule, { 'everything-else' ] }] + }, { + code: ` + class MyComponent extends React.Component { + static foo; + static getDerivedStateFromProps() {} + + render() { + return null; + } + } + `, + parser: parsers.BABEL_ESLINT, + options: [{ + order: [ + 'static-variables', + 'static-methods' + ] + }] + }, { + code: ` + class MyComponent extends React.Component { + static getDerivedStateFromProps() {} + static foo = 'some-str'; + + render() { + return null; + } + } + `, + parser: parsers.BABEL_ESLINT, + options: [{ + order: [ + 'static-methods', + 'static-variables' + ] + }] + }, { + code: ` + class MyComponent extends React.Component { + foo = {}; + static bar = 0; + static getDerivedStateFromProps() {} + + render() { + return null; + } + } + `, + parser: parsers.BABEL_ESLINT, + options: [{ + order: [ + 'instance-variables', + 'static-variables', + 'static-methods' + ] + }] + }, { + code: ` + class MyComponent extends React.Component { + static bar = 1; + foo = {}; + static getDerivedStateFromProps() {} + + render() { + return null; + } + } + `, + parser: parsers.BABEL_ESLINT, + options: [{ + order: [ + 'static-variables', + 'instance-variables', + 'static-methods' + ] + }] + }, { + code: ` + class MyComponent extends React.Component { + static getDerivedStateFromProps() {} + render() { + return null; + } + static bar; + foo = {}; + } + `, + parser: parsers.BABEL_ESLINT, + options: [{ + order: [ + 'static-methods', + 'render', + 'static-variables', + 'instance-variables' + ] + }] + }, { + code: ` + class MyComponent extends React.Component { + static foo = 1; + bar; + + constructor() { + super(props); + + this.state = {}; + } + + render() { + return null; + } + } + `, + parser: parsers.BABEL_ESLINT, + options: [{ + order: [ + 'static-variables', + 'instance-variables', + 'constructor', + 'everything-else', + 'render' + ] + }] }], invalid: [{ @@ -790,5 +913,66 @@ ruleTester.run('sort-comp', rule, { 'render' ] }] + }, { + code: ` + class MyComponent extends React.Component { + static getDerivedStateFromProps() {} + static foo; + + render() { + return null; + } + } + `, + errors: [{message: 'getDerivedStateFromProps should be placed after foo'}], + parser: parsers.BABEL_ESLINT, + options: [{ + order: [ + 'static-variables', + 'static-methods' + ] + }] + }, { + code: ` + class MyComponent extends React.Component { + static foo; + bar = 'some-str' + static getDerivedStateFromProps() {} + + render() { + return null; + } + } + `, + errors: [{message: 'foo should be placed after bar'}], + parser: parsers.BABEL_ESLINT, + options: [{ + order: [ + 'instance-variables', + 'static-variables', + 'static-methods' + ] + }] + }, { + code: ` + class MyComponent extends React.Component { + static getDerivedStateFromProps() {} + static bar; + render() { + return null; + } + foo = {}; + } + `, + parser: parsers.BABEL_ESLINT, + errors: [{message: 'bar should be placed after render'}], + options: [{ + order: [ + 'static-methods', + 'render', + 'static-variables', + 'instance-variables' + ] + }] }] });