Skip to content

Commit 636141a

Browse files
authored
Update code style to match eslint-plugin-react.
Update code style to match eslint-plugin-react. Also bring test coverage to 100% and fix a minor error in the linting logic.
2 parents fc45082 + 64ad746 commit 636141a

File tree

9 files changed

+325
-111
lines changed

9 files changed

+325
-111
lines changed

.editorconfig

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false

.eslintignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/**
2+
reports/**

.eslintrc

+168
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
{
2+
"env": {
3+
"es6": true,
4+
"node": true
5+
},
6+
parserOptions: {
7+
ecmaVersion: 6,
8+
ecmaFeatures: {
9+
jsx: true
10+
}
11+
},
12+
"rules": {
13+
// Possible Errors
14+
"comma-dangle": [2, "never"],
15+
"computed-property-spacing": [2, "never"],
16+
"no-cond-assign": 2,
17+
"no-console": 2,
18+
"no-constant-condition": 2,
19+
"no-control-regex": 2,
20+
"no-debugger": 2,
21+
"no-dupe-keys": 2,
22+
"no-empty": 2,
23+
"no-empty-character-class": 2,
24+
"no-ex-assign": 2,
25+
"no-extra-boolean-cast": 2,
26+
"no-extra-parens": 0,
27+
"no-extra-semi": 2,
28+
"no-func-assign": 2,
29+
"no-inner-declarations": 2,
30+
"no-invalid-regexp": 2,
31+
"no-irregular-whitespace": 2,
32+
"no-negated-in-lhs": 2,
33+
"no-obj-calls": 2,
34+
"no-regex-spaces": 2,
35+
"no-reserved-keys": 0,
36+
"no-sparse-arrays": 2,
37+
"no-unreachable": 2,
38+
"use-isnan": 2,
39+
"valid-jsdoc": 0,
40+
"valid-typeof": 2,
41+
// Best Practices
42+
"block-scoped-var": 2,
43+
"complexity": 0,
44+
"consistent-return": 2,
45+
"curly": 2,
46+
"default-case": 2,
47+
"dot-notation": 2,
48+
"eqeqeq": 2,
49+
"guard-for-in": 2,
50+
"no-alert": 2,
51+
"no-caller": 2,
52+
"no-div-regex": 2,
53+
"no-else-return": 2,
54+
"no-eq-null": 2,
55+
"no-eval": 2,
56+
"no-extend-native": 2,
57+
"no-extra-bind": 2,
58+
"no-fallthrough": 2,
59+
"no-floating-decimal": 2,
60+
"no-implied-eval": 2,
61+
"no-iterator": 2,
62+
"no-labels": 2,
63+
"no-lone-blocks": 2,
64+
"no-loop-func": 2,
65+
"no-multi-spaces": 2,
66+
"no-multi-str": 2,
67+
"no-native-reassign": 2,
68+
"no-new": 2,
69+
"no-new-func": 2,
70+
"no-new-wrappers": 2,
71+
"no-octal": 2,
72+
"no-octal-escape": 2,
73+
"no-process-env": 2,
74+
"no-proto": 2,
75+
"no-redeclare": 2,
76+
"no-return-assign": 2,
77+
"no-script-url": 2,
78+
"no-self-compare": 2,
79+
"no-sequences": 2,
80+
"no-unused-expressions": 2,
81+
"no-void": 0,
82+
"no-warning-comments": 2,
83+
"no-with": 2,
84+
"radix": 2,
85+
"vars-on-top": 0,
86+
"wrap-iife": 2,
87+
"yoda": 2,
88+
// Strict Mode
89+
"strict": [2, "global"],
90+
// Variables
91+
"prefer-const": 2,
92+
"no-catch-shadow": 2,
93+
"no-const-assign": 2,
94+
"no-delete-var": 2,
95+
"no-label-var": 2,
96+
"no-shadow": 2,
97+
"no-shadow-restricted-names": 2,
98+
"no-undef": 2,
99+
"no-undef-init": 2,
100+
"no-undefined": 2,
101+
"no-unused-vars": 2,
102+
"no-use-before-define": 2,
103+
"no-var": 2,
104+
// Stylistic Issues
105+
"indent": [2, 2, {
106+
"SwitchCase": 1
107+
}],
108+
"brace-style": 2,
109+
"camelcase": 0,
110+
"comma-spacing": 2,
111+
"comma-style": 2,
112+
"consistent-this": 0,
113+
"eol-last": 2,
114+
"func-names": 0,
115+
"func-style": 0,
116+
"key-spacing": [2, {
117+
"beforeColon": false,
118+
"afterColon": true
119+
}],
120+
"max-nested-callbacks": 0,
121+
"new-cap": 2,
122+
"new-parens": 2,
123+
"no-array-constructor": 2,
124+
"no-inline-comments": 0,
125+
"no-lonely-if": 2,
126+
"no-mixed-spaces-and-tabs": 2,
127+
"no-nested-ternary": 2,
128+
"no-new-object": 2,
129+
"semi-spacing": [2, {
130+
"before": false,
131+
"after": true
132+
}],
133+
"no-spaced-func": 2,
134+
"no-ternary": 0,
135+
"no-trailing-spaces": 2,
136+
"no-multiple-empty-lines": 2,
137+
"no-underscore-dangle": 0,
138+
"one-var": 0,
139+
"operator-assignment": [2, "always"],
140+
"padded-blocks": [2, { "blocks": "never", "classes": "never", "switches": "never" }],
141+
"quotes": [2, "single"],
142+
"quote-props": [2, "as-needed"],
143+
"semi": [2, "always"],
144+
"sort-vars": [2, {"ignoreCase": true}],
145+
"keyword-spacing": 2,
146+
"space-before-blocks": 2,
147+
"object-curly-spacing": [2, "never"],
148+
"array-bracket-spacing": [2, "never"],
149+
"space-in-parens": 2,
150+
"space-infix-ops": 2,
151+
"space-unary-ops": 2,
152+
"spaced-comment": 2,
153+
"wrap-regex": 0,
154+
// Legacy
155+
"max-depth": 0,
156+
"max-len": [2, 120, {
157+
"ignoreStrings": true,
158+
"ignoreTemplateLiterals": true,
159+
"ignoreComments": true,
160+
}],
161+
"max-params": 0,
162+
"max-statements": 0,
163+
"no-plusplus": 0,
164+
"no-prototype-builtins": 2,
165+
"prefer-template": 2,
166+
"template-curly-spacing": [2, "never"],
167+
}
168+
}

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
node_modules
2+
reports
3+
npm-debug.log

lib/index.js

+7-9
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,18 @@
22
* @fileoverview Lint Rule for React to use functional setState
33
* @author Edwin Cromley
44
*/
5-
"use strict";
5+
'use strict';
66

7-
//------------------------------------------------------------------------------
7+
// ------------------------------------------------------------------------------
88
// Requirements
9-
//------------------------------------------------------------------------------
9+
// ------------------------------------------------------------------------------
1010

11-
var requireIndex = require("requireindex");
12-
13-
//------------------------------------------------------------------------------
11+
// ------------------------------------------------------------------------------
1412
// Plugin Definition
15-
//------------------------------------------------------------------------------
13+
// ------------------------------------------------------------------------------
1614

1715

1816
// import all rules in lib/rules
1917
module.exports.rules = {
20-
"no-this-state-props": require('./rules/no-this-state-props')
21-
}
18+
'no-this-state-props': require('./rules/no-this-state-props')
19+
};

lib/rules/no-this-state-props.js

+53-30
Original file line numberDiff line numberDiff line change
@@ -19,60 +19,83 @@ module.exports = {
1919
},
2020

2121
create: function(context) {
22-
var setStateUsages = [];
22+
const setStateUsages = [];
2323

24+
/**
25+
* Checks to see if this is a this.setState call.
26+
*
27+
* @param {Object} node AST Node.
28+
*/
2429
function isThisSetState (node) {
25-
if ( node.type === 'CallExpression' ) {
26-
var callee = node.callee;
27-
var isMatching = (
30+
if (node.type === 'CallExpression') {
31+
const callee = node.callee;
32+
const isMatching = (
2833
callee.type === 'MemberExpression' &&
2934
callee.object.type === 'ThisExpression' &&
3035
callee.property.name === 'setState'
31-
)
32-
return isMatching
36+
);
37+
return isMatching;
3338
}
39+
return false;
3440
}
3541

42+
/**
43+
* Checks whether this is `this.setState( doUpdates, CALLBACK )`.
44+
*
45+
* This is used to determine whether the secondary callback in this.setState
46+
* can allow the use of this.state and this.props.
47+
*
48+
* @param {Object} node AST Node.
49+
*/
3650
function isThisSetStateCallback (node) {
37-
if ( node.parent && node.parent.type === 'CallExpression' ) {
38-
var parent = node.parent;
39-
var isMatching = (
51+
if (node.parent && node.parent.type === 'CallExpression') {
52+
const parent = node.parent;
53+
const isMatching = (
4054
isThisSetState(parent) &&
4155
parent.arguments &&
4256
parent.arguments.length > 1 &&
4357
parent.arguments[1] === node
44-
)
45-
return isMatching
58+
);
59+
return isMatching;
4660
}
61+
return false;
4762
}
4863

64+
/**
65+
* Checks whether this is `this.state`.
66+
* @param {Object} node AST Node.
67+
*/
4968
function isThisState(node) {
50-
var isMatching = (
69+
const isMatching = (
5170
node.type === 'MemberExpression' &&
5271
node.object.type === 'ThisExpression' &&
5372
node.property.name === 'state'
54-
)
55-
return isMatching
73+
);
74+
return isMatching;
5675
}
5776

77+
/**
78+
* Checks whether this is `this.props`.
79+
* @param {Object} node AST Node.
80+
*/
5881
function isThisProps(node) {
59-
var isMatching = (
82+
const isMatching = (
6083
node.type === 'MemberExpression' &&
6184
node.object.type === 'ThisExpression' &&
6285
node.property.name === 'props'
63-
)
64-
return isMatching
86+
);
87+
return isMatching;
6588
}
6689

6790
/**
6891
* Reports usages of setState where this.props or this.state are used.
69-
* @param {Object} setStateUsages Usages of set state.
92+
* @param {Array} setStateCalls Usages of set state.
7093
*/
71-
function reportSetStateUsages(setStateUsages) {
72-
var setStateUsage;
73-
for (var i = 0, j = setStateUsages.length; i < j; i++) {
74-
setStateUsage = setStateUsages[i];
75-
if ( isThisSetState(setStateUsage) ) {
94+
function reportSetStateUsages(setStateCalls) {
95+
let setStateUsage;
96+
for (let i = 0, j = setStateCalls.length; i < j; i++) {
97+
setStateUsage = setStateCalls[i];
98+
if (isThisSetState(setStateUsage)) {
7699
context.report({
77100
node: setStateUsage,
78101
message: 'Do not access this.state or this.props in setState(), instead apply a function with signature ( state, [props] ) to setState and access state and props.'
@@ -83,17 +106,17 @@ module.exports = {
83106

84107
return {
85108
CallExpression: function(node) {
86-
var callee = node.callee;
87-
if ( ! isThisSetState(node) ) {
109+
const callee = node.callee;
110+
if (isThisSetState(node)) {
88111
setStateUsages.push(callee);
89112
}
90113
},
91114

92115
MemberExpression: function(node) {
93-
if ( isThisProps(node) || isThisState(node) ) {
94-
var ancestors = context.getAncestors()
95-
if ( ancestors.some(isThisSetState) && !ancestors.some(isThisSetStateCallback) ) {
96-
var setStateUsage = ancestors.find(isThisSetState)
116+
if (isThisProps(node) || isThisState(node)) {
117+
const ancestors = context.getAncestors();
118+
if (ancestors.some(isThisSetState) && !ancestors.some(isThisSetStateCallback)) {
119+
const setStateUsage = ancestors.find(isThisSetState);
97120
setStateUsages.push(setStateUsage);
98121
}
99122
}
@@ -102,6 +125,6 @@ module.exports = {
102125
'Program:exit': function() {
103126
reportSetStateUsages(setStateUsages);
104127
}
105-
}
128+
};
106129
}
107130
};

package.json

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "eslint-plugin-react-functional-set-state",
3-
"version": "1.0.1",
3+
"version": "1.1.0",
44
"description": "Lint rule for React, should use functional setState",
55
"repository": {
66
"type": "git",
@@ -14,13 +14,18 @@
1414
"author": "Edwin Cromley",
1515
"main": "lib/index.js",
1616
"scripts": {
17-
"test": "mocha tests --recursive"
17+
"lint": "eslint ./",
18+
"lint:fix": "eslint ./ --fix",
19+
"test": "npm run lint && npm run unit-test",
20+
"unit-test": "istanbul cover --dir reports/coverage node_modules/mocha/bin/_mocha tests/**/*.js -- --reporter dot"
1821
},
1922
"dependencies": {
2023
"requireindex": "~1.1.0"
2124
},
2225
"devDependencies": {
26+
"babel-eslint": "^7.2.3",
2327
"eslint": "^3.9.1",
28+
"istanbul": "0.4.5",
2429
"mocha": "^3.1.2"
2530
},
2631
"engines": {

0 commit comments

Comments
 (0)