Upload folder using huggingface_hub (part 2)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- node_modules/eslint-plugin-react/lib/rules/no-unsafe.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/no-unsafe.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/no-unsafe.js +151 -0
- node_modules/eslint-plugin-react/lib/rules/no-unstable-nested-components.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/no-unstable-nested-components.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/no-unstable-nested-components.js +491 -0
- node_modules/eslint-plugin-react/lib/rules/no-unused-class-component-methods.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/no-unused-class-component-methods.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/no-unused-class-component-methods.js +258 -0
- node_modules/eslint-plugin-react/lib/rules/no-unused-prop-types.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/no-unused-prop-types.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/no-unused-prop-types.js +171 -0
- node_modules/eslint-plugin-react/lib/rules/no-unused-state.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/no-unused-state.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/no-unused-state.js +529 -0
- node_modules/eslint-plugin-react/lib/rules/no-will-update-set-state.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/no-will-update-set-state.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/no-will-update-set-state.js +15 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-es6-class.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-es6-class.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-es6-class.js +58 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-exact-props.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-exact-props.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-exact-props.js +162 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-read-only-props.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-read-only-props.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-read-only-props.js +117 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-stateless-function.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-stateless-function.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/prefer-stateless-function.js +397 -0
- node_modules/eslint-plugin-react/lib/rules/prop-types.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/prop-types.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/prop-types.js +225 -0
- node_modules/eslint-plugin-react/lib/rules/react-in-jsx-scope.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/react-in-jsx-scope.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/react-in-jsx-scope.js +56 -0
- node_modules/eslint-plugin-react/lib/rules/require-default-props.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/require-default-props.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/require-default-props.js +209 -0
- node_modules/eslint-plugin-react/lib/rules/require-optimization.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/require-optimization.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/require-optimization.js +240 -0
- node_modules/eslint-plugin-react/lib/rules/require-render-return.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/require-render-return.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/require-render-return.js +106 -0
- node_modules/eslint-plugin-react/lib/rules/self-closing-comp.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/self-closing-comp.d.ts.map +1 -0
- node_modules/eslint-plugin-react/lib/rules/self-closing-comp.js +104 -0
- node_modules/eslint-plugin-react/lib/rules/sort-comp.d.ts +3 -0
- node_modules/eslint-plugin-react/lib/rules/sort-comp.d.ts.map +1 -0
node_modules/eslint-plugin-react/lib/rules/no-unsafe.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=no-unsafe.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/no-unsafe.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"no-unsafe.d.ts","sourceRoot":"","sources":["no-unsafe.js"],"names":[],"mappings":"wBAqBW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/no-unsafe.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Prevent usage of unsafe lifecycle methods
|
| 3 |
+
* @author Sergei Startsev
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const astUtil = require('../util/ast');
|
| 9 |
+
const componentUtil = require('../util/componentUtil');
|
| 10 |
+
const docsUrl = require('../util/docsUrl');
|
| 11 |
+
const testReactVersion = require('../util/version').testReactVersion;
|
| 12 |
+
const report = require('../util/report');
|
| 13 |
+
|
| 14 |
+
// ------------------------------------------------------------------------------
|
| 15 |
+
// Rule Definition
|
| 16 |
+
// ------------------------------------------------------------------------------
|
| 17 |
+
|
| 18 |
+
const messages = {
|
| 19 |
+
unsafeMethod: '{{method}} is unsafe for use in async rendering. Update the component to use {{newMethod}} instead. {{details}}',
|
| 20 |
+
};
|
| 21 |
+
|
| 22 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 23 |
+
module.exports = {
|
| 24 |
+
meta: {
|
| 25 |
+
docs: {
|
| 26 |
+
description: 'Disallow usage of unsafe lifecycle methods',
|
| 27 |
+
category: 'Best Practices',
|
| 28 |
+
recommended: false,
|
| 29 |
+
url: docsUrl('no-unsafe'),
|
| 30 |
+
},
|
| 31 |
+
|
| 32 |
+
messages,
|
| 33 |
+
|
| 34 |
+
schema: [
|
| 35 |
+
{
|
| 36 |
+
type: 'object',
|
| 37 |
+
properties: {
|
| 38 |
+
checkAliases: {
|
| 39 |
+
default: false,
|
| 40 |
+
type: 'boolean',
|
| 41 |
+
},
|
| 42 |
+
},
|
| 43 |
+
additionalProperties: false,
|
| 44 |
+
},
|
| 45 |
+
],
|
| 46 |
+
},
|
| 47 |
+
|
| 48 |
+
create(context) {
|
| 49 |
+
const config = context.options[0] || {};
|
| 50 |
+
const checkAliases = config.checkAliases || false;
|
| 51 |
+
|
| 52 |
+
const isApplicable = testReactVersion(context, '>= 16.3.0');
|
| 53 |
+
if (!isApplicable) {
|
| 54 |
+
return {};
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
const unsafe = {
|
| 58 |
+
UNSAFE_componentWillMount: {
|
| 59 |
+
newMethod: 'componentDidMount',
|
| 60 |
+
details: 'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.',
|
| 61 |
+
},
|
| 62 |
+
UNSAFE_componentWillReceiveProps: {
|
| 63 |
+
newMethod: 'getDerivedStateFromProps',
|
| 64 |
+
details: 'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.',
|
| 65 |
+
},
|
| 66 |
+
UNSAFE_componentWillUpdate: {
|
| 67 |
+
newMethod: 'componentDidUpdate',
|
| 68 |
+
details: 'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.',
|
| 69 |
+
},
|
| 70 |
+
};
|
| 71 |
+
if (checkAliases) {
|
| 72 |
+
unsafe.componentWillMount = unsafe.UNSAFE_componentWillMount;
|
| 73 |
+
unsafe.componentWillReceiveProps = unsafe.UNSAFE_componentWillReceiveProps;
|
| 74 |
+
unsafe.componentWillUpdate = unsafe.UNSAFE_componentWillUpdate;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
/**
|
| 78 |
+
* Returns a list of unsafe methods
|
| 79 |
+
* @returns {Array} A list of unsafe methods
|
| 80 |
+
*/
|
| 81 |
+
function getUnsafeMethods() {
|
| 82 |
+
return Object.keys(unsafe);
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
/**
|
| 86 |
+
* Checks if a passed method is unsafe
|
| 87 |
+
* @param {string} method Life cycle method
|
| 88 |
+
* @returns {boolean} Returns true for unsafe methods, otherwise returns false
|
| 89 |
+
*/
|
| 90 |
+
function isUnsafe(method) {
|
| 91 |
+
const unsafeMethods = getUnsafeMethods();
|
| 92 |
+
return unsafeMethods.indexOf(method) !== -1;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
/**
|
| 96 |
+
* Reports the error for an unsafe method
|
| 97 |
+
* @param {ASTNode} node The AST node being checked
|
| 98 |
+
* @param {string} method Life cycle method
|
| 99 |
+
*/
|
| 100 |
+
function checkUnsafe(node, method) {
|
| 101 |
+
if (!isUnsafe(method)) {
|
| 102 |
+
return;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
const meta = unsafe[method];
|
| 106 |
+
const newMethod = meta.newMethod;
|
| 107 |
+
const details = meta.details;
|
| 108 |
+
|
| 109 |
+
const propertyNode = astUtil.getComponentProperties(node)
|
| 110 |
+
.find((property) => astUtil.getPropertyName(property) === method);
|
| 111 |
+
|
| 112 |
+
report(context, messages.unsafeMethod, 'unsafeMethod', {
|
| 113 |
+
node: propertyNode,
|
| 114 |
+
data: {
|
| 115 |
+
method,
|
| 116 |
+
newMethod,
|
| 117 |
+
details,
|
| 118 |
+
},
|
| 119 |
+
});
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
/**
|
| 123 |
+
* Returns life cycle methods if available
|
| 124 |
+
* @param {ASTNode} node The AST node being checked.
|
| 125 |
+
* @returns {Array} The array of methods.
|
| 126 |
+
*/
|
| 127 |
+
function getLifeCycleMethods(node) {
|
| 128 |
+
const properties = astUtil.getComponentProperties(node);
|
| 129 |
+
return properties.map((property) => astUtil.getPropertyName(property));
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
/**
|
| 133 |
+
* Checks life cycle methods
|
| 134 |
+
* @param {ASTNode} node The AST node being checked.
|
| 135 |
+
*/
|
| 136 |
+
function checkLifeCycleMethods(node) {
|
| 137 |
+
if (componentUtil.isES5Component(node, context) || componentUtil.isES6Component(node, context)) {
|
| 138 |
+
const methods = getLifeCycleMethods(node);
|
| 139 |
+
methods
|
| 140 |
+
.sort((a, b) => a.localeCompare(b))
|
| 141 |
+
.forEach((method) => checkUnsafe(node, method));
|
| 142 |
+
}
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
return {
|
| 146 |
+
ClassDeclaration: checkLifeCycleMethods,
|
| 147 |
+
ClassExpression: checkLifeCycleMethods,
|
| 148 |
+
ObjectExpression: checkLifeCycleMethods,
|
| 149 |
+
};
|
| 150 |
+
},
|
| 151 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/no-unstable-nested-components.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=no-unstable-nested-components.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/no-unstable-nested-components.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"no-unstable-nested-components.d.ts","sourceRoot":"","sources":["no-unstable-nested-components.js"],"names":[],"mappings":"wBAsQW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/no-unstable-nested-components.js
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Prevent creating unstable components inside components
|
| 3 |
+
* @author Ari Perkkiö
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const minimatch = require('minimatch');
|
| 9 |
+
const Components = require('../util/Components');
|
| 10 |
+
const docsUrl = require('../util/docsUrl');
|
| 11 |
+
const astUtil = require('../util/ast');
|
| 12 |
+
const isCreateElement = require('../util/isCreateElement');
|
| 13 |
+
const report = require('../util/report');
|
| 14 |
+
|
| 15 |
+
// ------------------------------------------------------------------------------
|
| 16 |
+
// Constants
|
| 17 |
+
// ------------------------------------------------------------------------------
|
| 18 |
+
|
| 19 |
+
const COMPONENT_AS_PROPS_INFO = ' If you want to allow component creation in props, set allowAsProps option to true.';
|
| 20 |
+
const HOOK_REGEXP = /^use[A-Z0-9].*$/;
|
| 21 |
+
|
| 22 |
+
// ------------------------------------------------------------------------------
|
| 23 |
+
// Helpers
|
| 24 |
+
// ------------------------------------------------------------------------------
|
| 25 |
+
|
| 26 |
+
/**
|
| 27 |
+
* Generate error message with given parent component name
|
| 28 |
+
* @param {string} parentName Name of the parent component, if known
|
| 29 |
+
* @returns {string} Error message with parent component name
|
| 30 |
+
*/
|
| 31 |
+
function generateErrorMessageWithParentName(parentName) {
|
| 32 |
+
return `Do not define components during render. React will see a new component type on every render and destroy the entire subtree’s DOM nodes and state (https://reactjs.org/docs/reconciliation.html#elements-of-different-types). Instead, move this component definition out of the parent component${parentName ? ` “${parentName}” ` : ' '}and pass data as props.`;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
/**
|
| 36 |
+
* Check whether given text matches the pattern passed in.
|
| 37 |
+
* @param {string} text Text to validate
|
| 38 |
+
* @param {string} pattern Pattern to match against
|
| 39 |
+
* @returns {boolean}
|
| 40 |
+
*/
|
| 41 |
+
function propMatchesRenderPropPattern(text, pattern) {
|
| 42 |
+
return typeof text === 'string' && minimatch(text, pattern);
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
/**
|
| 46 |
+
* Get closest parent matching given matcher
|
| 47 |
+
* @param {ASTNode} node The AST node
|
| 48 |
+
* @param {Context} context eslint context
|
| 49 |
+
* @param {Function} matcher Method used to match the parent
|
| 50 |
+
* @returns {ASTNode} The matching parent node, if any
|
| 51 |
+
*/
|
| 52 |
+
function getClosestMatchingParent(node, context, matcher) {
|
| 53 |
+
if (!node || !node.parent || node.parent.type === 'Program') {
|
| 54 |
+
return;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
if (matcher(node.parent, context)) {
|
| 58 |
+
return node.parent;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
return getClosestMatchingParent(node.parent, context, matcher);
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
/**
|
| 65 |
+
* Matcher used to check whether given node is a `createElement` call
|
| 66 |
+
* @param {ASTNode} node The AST node
|
| 67 |
+
* @param {Context} context eslint context
|
| 68 |
+
* @returns {boolean} True if node is a `createElement` call, false if not
|
| 69 |
+
*/
|
| 70 |
+
function isCreateElementMatcher(node, context) {
|
| 71 |
+
return (
|
| 72 |
+
astUtil.isCallExpression(node)
|
| 73 |
+
&& isCreateElement(context, node)
|
| 74 |
+
);
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
/**
|
| 78 |
+
* Matcher used to check whether given node is a `ObjectExpression`
|
| 79 |
+
* @param {ASTNode} node The AST node
|
| 80 |
+
* @returns {boolean} True if node is a `ObjectExpression`, false if not
|
| 81 |
+
*/
|
| 82 |
+
function isObjectExpressionMatcher(node) {
|
| 83 |
+
return node && node.type === 'ObjectExpression';
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
/**
|
| 87 |
+
* Matcher used to check whether given node is a `JSXExpressionContainer`
|
| 88 |
+
* @param {ASTNode} node The AST node
|
| 89 |
+
* @returns {boolean} True if node is a `JSXExpressionContainer`, false if not
|
| 90 |
+
*/
|
| 91 |
+
function isJSXExpressionContainerMatcher(node) {
|
| 92 |
+
return node && node.type === 'JSXExpressionContainer';
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
/**
|
| 96 |
+
* Matcher used to check whether given node is a `JSXAttribute` of `JSXExpressionContainer`
|
| 97 |
+
* @param {ASTNode} node The AST node
|
| 98 |
+
* @returns {boolean} True if node is a `JSXAttribute` of `JSXExpressionContainer`, false if not
|
| 99 |
+
*/
|
| 100 |
+
function isJSXAttributeOfExpressionContainerMatcher(node) {
|
| 101 |
+
return (
|
| 102 |
+
node
|
| 103 |
+
&& node.type === 'JSXAttribute'
|
| 104 |
+
&& node.value
|
| 105 |
+
&& node.value.type === 'JSXExpressionContainer'
|
| 106 |
+
);
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
/**
|
| 110 |
+
* Matcher used to check whether given node is an object `Property`
|
| 111 |
+
* @param {ASTNode} node The AST node
|
| 112 |
+
* @returns {boolean} True if node is a `Property`, false if not
|
| 113 |
+
*/
|
| 114 |
+
function isPropertyOfObjectExpressionMatcher(node) {
|
| 115 |
+
return (
|
| 116 |
+
node
|
| 117 |
+
&& node.parent
|
| 118 |
+
&& node.parent.type === 'Property'
|
| 119 |
+
);
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
/**
|
| 123 |
+
* Check whether given node or its parent is directly inside `map` call
|
| 124 |
+
* ```jsx
|
| 125 |
+
* {items.map(item => <li />)}
|
| 126 |
+
* ```
|
| 127 |
+
* @param {ASTNode} node The AST node
|
| 128 |
+
* @returns {boolean} True if node is directly inside `map` call, false if not
|
| 129 |
+
*/
|
| 130 |
+
function isMapCall(node) {
|
| 131 |
+
return (
|
| 132 |
+
node
|
| 133 |
+
&& node.callee
|
| 134 |
+
&& node.callee.property
|
| 135 |
+
&& node.callee.property.name === 'map'
|
| 136 |
+
);
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
/**
|
| 140 |
+
* Check whether given node is `ReturnStatement` of a React hook
|
| 141 |
+
* @param {ASTNode} node The AST node
|
| 142 |
+
* @param {Context} context eslint context
|
| 143 |
+
* @returns {boolean} True if node is a `ReturnStatement` of a React hook, false if not
|
| 144 |
+
*/
|
| 145 |
+
function isReturnStatementOfHook(node, context) {
|
| 146 |
+
if (
|
| 147 |
+
!node
|
| 148 |
+
|| !node.parent
|
| 149 |
+
|| node.parent.type !== 'ReturnStatement'
|
| 150 |
+
) {
|
| 151 |
+
return false;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
const callExpression = getClosestMatchingParent(node, context, astUtil.isCallExpression);
|
| 155 |
+
return (
|
| 156 |
+
callExpression
|
| 157 |
+
&& callExpression.callee
|
| 158 |
+
&& HOOK_REGEXP.test(callExpression.callee.name)
|
| 159 |
+
);
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
/**
|
| 163 |
+
* Check whether given node is declared inside a render prop
|
| 164 |
+
* ```jsx
|
| 165 |
+
* <Component renderFooter={() => <div />} />
|
| 166 |
+
* <Component>{() => <div />}</Component>
|
| 167 |
+
* ```
|
| 168 |
+
* @param {ASTNode} node The AST node
|
| 169 |
+
* @param {Context} context eslint context
|
| 170 |
+
* @param {string} propNamePattern a pattern to match render props against
|
| 171 |
+
* @returns {boolean} True if component is declared inside a render prop, false if not
|
| 172 |
+
*/
|
| 173 |
+
function isComponentInRenderProp(node, context, propNamePattern) {
|
| 174 |
+
if (
|
| 175 |
+
node
|
| 176 |
+
&& node.parent
|
| 177 |
+
&& node.parent.type === 'Property'
|
| 178 |
+
&& node.parent.key
|
| 179 |
+
&& propMatchesRenderPropPattern(node.parent.key.name, propNamePattern)
|
| 180 |
+
) {
|
| 181 |
+
return true;
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
// Check whether component is a render prop used as direct children, e.g. <Component>{() => <div />}</Component>
|
| 185 |
+
if (
|
| 186 |
+
node
|
| 187 |
+
&& node.parent
|
| 188 |
+
&& node.parent.type === 'JSXExpressionContainer'
|
| 189 |
+
&& node.parent.parent
|
| 190 |
+
&& node.parent.parent.type === 'JSXElement'
|
| 191 |
+
) {
|
| 192 |
+
return true;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
const jsxExpressionContainer = getClosestMatchingParent(node, context, isJSXExpressionContainerMatcher);
|
| 196 |
+
|
| 197 |
+
// Check whether prop name indicates accepted patterns
|
| 198 |
+
if (
|
| 199 |
+
jsxExpressionContainer
|
| 200 |
+
&& jsxExpressionContainer.parent
|
| 201 |
+
&& jsxExpressionContainer.parent.type === 'JSXAttribute'
|
| 202 |
+
&& jsxExpressionContainer.parent.name
|
| 203 |
+
&& jsxExpressionContainer.parent.name.type === 'JSXIdentifier'
|
| 204 |
+
) {
|
| 205 |
+
const propName = jsxExpressionContainer.parent.name.name;
|
| 206 |
+
|
| 207 |
+
// Starts with render, e.g. <Component renderFooter={() => <div />} />
|
| 208 |
+
if (propMatchesRenderPropPattern(propName, propNamePattern)) {
|
| 209 |
+
return true;
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
// Uses children prop explicitly, e.g. <Component children={() => <div />} />
|
| 213 |
+
if (propName === 'children') {
|
| 214 |
+
return true;
|
| 215 |
+
}
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
return false;
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
/**
|
| 222 |
+
* Check whether given node is declared directly inside a render property
|
| 223 |
+
* ```jsx
|
| 224 |
+
* const rows = { render: () => <div /> }
|
| 225 |
+
* <Component rows={ [{ render: () => <div /> }] } />
|
| 226 |
+
* ```
|
| 227 |
+
* @param {ASTNode} node The AST node
|
| 228 |
+
* @param {string} propNamePattern The pattern to match render props against
|
| 229 |
+
* @returns {boolean} True if component is declared inside a render property, false if not
|
| 230 |
+
*/
|
| 231 |
+
function isDirectValueOfRenderProperty(node, propNamePattern) {
|
| 232 |
+
return (
|
| 233 |
+
node
|
| 234 |
+
&& node.parent
|
| 235 |
+
&& node.parent.type === 'Property'
|
| 236 |
+
&& node.parent.key
|
| 237 |
+
&& node.parent.key.type === 'Identifier'
|
| 238 |
+
&& propMatchesRenderPropPattern(node.parent.key.name, propNamePattern)
|
| 239 |
+
);
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
/**
|
| 243 |
+
* Resolve the component name of given node
|
| 244 |
+
* @param {ASTNode} node The AST node of the component
|
| 245 |
+
* @returns {string} Name of the component, if any
|
| 246 |
+
*/
|
| 247 |
+
function resolveComponentName(node) {
|
| 248 |
+
const parentName = node.id && node.id.name;
|
| 249 |
+
if (parentName) return parentName;
|
| 250 |
+
|
| 251 |
+
return (
|
| 252 |
+
node.type === 'ArrowFunctionExpression'
|
| 253 |
+
&& node.parent
|
| 254 |
+
&& node.parent.id
|
| 255 |
+
&& node.parent.id.name
|
| 256 |
+
);
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
// ------------------------------------------------------------------------------
|
| 260 |
+
// Rule Definition
|
| 261 |
+
// ------------------------------------------------------------------------------
|
| 262 |
+
|
| 263 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 264 |
+
module.exports = {
|
| 265 |
+
meta: {
|
| 266 |
+
docs: {
|
| 267 |
+
description: 'Disallow creating unstable components inside components',
|
| 268 |
+
category: 'Possible Errors',
|
| 269 |
+
recommended: false,
|
| 270 |
+
url: docsUrl('no-unstable-nested-components'),
|
| 271 |
+
},
|
| 272 |
+
schema: [{
|
| 273 |
+
type: 'object',
|
| 274 |
+
properties: {
|
| 275 |
+
customValidators: {
|
| 276 |
+
type: 'array',
|
| 277 |
+
items: {
|
| 278 |
+
type: 'string',
|
| 279 |
+
},
|
| 280 |
+
},
|
| 281 |
+
allowAsProps: {
|
| 282 |
+
type: 'boolean',
|
| 283 |
+
},
|
| 284 |
+
propNamePattern: {
|
| 285 |
+
type: 'string',
|
| 286 |
+
},
|
| 287 |
+
},
|
| 288 |
+
additionalProperties: false,
|
| 289 |
+
}],
|
| 290 |
+
},
|
| 291 |
+
|
| 292 |
+
create: Components.detect((context, components, utils) => {
|
| 293 |
+
const allowAsProps = context.options.some((option) => option && option.allowAsProps);
|
| 294 |
+
const propNamePattern = (context.options[0] || {}).propNamePattern || 'render*';
|
| 295 |
+
|
| 296 |
+
/**
|
| 297 |
+
* Check whether given node is declared inside class component's render block
|
| 298 |
+
* ```jsx
|
| 299 |
+
* class Component extends React.Component {
|
| 300 |
+
* render() {
|
| 301 |
+
* class NestedClassComponent extends React.Component {
|
| 302 |
+
* ...
|
| 303 |
+
* ```
|
| 304 |
+
* @param {ASTNode} node The AST node being checked
|
| 305 |
+
* @returns {boolean} True if node is inside class component's render block, false if not
|
| 306 |
+
*/
|
| 307 |
+
function isInsideRenderMethod(node) {
|
| 308 |
+
const parentComponent = utils.getParentComponent(node);
|
| 309 |
+
|
| 310 |
+
if (!parentComponent || parentComponent.type !== 'ClassDeclaration') {
|
| 311 |
+
return false;
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
return (
|
| 315 |
+
node
|
| 316 |
+
&& node.parent
|
| 317 |
+
&& node.parent.type === 'MethodDefinition'
|
| 318 |
+
&& node.parent.key
|
| 319 |
+
&& node.parent.key.name === 'render'
|
| 320 |
+
);
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
/**
|
| 324 |
+
* Check whether given node is a function component declared inside class component.
|
| 325 |
+
* Util's component detection fails to detect function components inside class components.
|
| 326 |
+
* ```jsx
|
| 327 |
+
* class Component extends React.Component {
|
| 328 |
+
* render() {
|
| 329 |
+
* const NestedComponent = () => <div />;
|
| 330 |
+
* ...
|
| 331 |
+
* ```
|
| 332 |
+
* @param {ASTNode} node The AST node being checked
|
| 333 |
+
* @returns {boolean} True if given node a function component declared inside class component, false if not
|
| 334 |
+
*/
|
| 335 |
+
function isFunctionComponentInsideClassComponent(node) {
|
| 336 |
+
const parentComponent = utils.getParentComponent(node);
|
| 337 |
+
const parentStatelessComponent = utils.getParentStatelessComponent(node);
|
| 338 |
+
|
| 339 |
+
return (
|
| 340 |
+
parentComponent
|
| 341 |
+
&& parentStatelessComponent
|
| 342 |
+
&& parentComponent.type === 'ClassDeclaration'
|
| 343 |
+
&& utils.getStatelessComponent(parentStatelessComponent)
|
| 344 |
+
&& utils.isReturningJSX(node)
|
| 345 |
+
);
|
| 346 |
+
}
|
| 347 |
+
|
| 348 |
+
/**
|
| 349 |
+
* Check whether given node is declared inside `createElement` call's props
|
| 350 |
+
* ```js
|
| 351 |
+
* React.createElement(Component, {
|
| 352 |
+
* footer: () => React.createElement("div", null)
|
| 353 |
+
* })
|
| 354 |
+
* ```
|
| 355 |
+
* @param {ASTNode} node The AST node
|
| 356 |
+
* @returns {boolean} True if node is declare inside `createElement` call's props, false if not
|
| 357 |
+
*/
|
| 358 |
+
function isComponentInsideCreateElementsProp(node) {
|
| 359 |
+
if (!components.get(node)) {
|
| 360 |
+
return false;
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
const createElementParent = getClosestMatchingParent(node, context, isCreateElementMatcher);
|
| 364 |
+
|
| 365 |
+
return (
|
| 366 |
+
createElementParent
|
| 367 |
+
&& createElementParent.arguments
|
| 368 |
+
&& createElementParent.arguments[1] === getClosestMatchingParent(node, context, isObjectExpressionMatcher)
|
| 369 |
+
);
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
/**
|
| 373 |
+
* Check whether given node is declared inside a component/object prop.
|
| 374 |
+
* ```jsx
|
| 375 |
+
* <Component footer={() => <div />} />
|
| 376 |
+
* { footer: () => <div /> }
|
| 377 |
+
* ```
|
| 378 |
+
* @param {ASTNode} node The AST node being checked
|
| 379 |
+
* @returns {boolean} True if node is a component declared inside prop, false if not
|
| 380 |
+
*/
|
| 381 |
+
function isComponentInProp(node) {
|
| 382 |
+
if (isPropertyOfObjectExpressionMatcher(node)) {
|
| 383 |
+
return utils.isReturningJSX(node);
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
const jsxAttribute = getClosestMatchingParent(node, context, isJSXAttributeOfExpressionContainerMatcher);
|
| 387 |
+
|
| 388 |
+
if (!jsxAttribute) {
|
| 389 |
+
return isComponentInsideCreateElementsProp(node);
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
return utils.isReturningJSX(node);
|
| 393 |
+
}
|
| 394 |
+
|
| 395 |
+
/**
|
| 396 |
+
* Check whether given node is a stateless component returning non-JSX
|
| 397 |
+
* ```jsx
|
| 398 |
+
* {{ a: () => null }}
|
| 399 |
+
* ```
|
| 400 |
+
* @param {ASTNode} node The AST node being checked
|
| 401 |
+
* @returns {boolean} True if node is a stateless component returning non-JSX, false if not
|
| 402 |
+
*/
|
| 403 |
+
function isStatelessComponentReturningNull(node) {
|
| 404 |
+
const component = utils.getStatelessComponent(node);
|
| 405 |
+
|
| 406 |
+
return component && !utils.isReturningJSX(component);
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
/**
|
| 410 |
+
* Check whether given node is a unstable nested component
|
| 411 |
+
* @param {ASTNode} node The AST node being checked
|
| 412 |
+
*/
|
| 413 |
+
function validate(node) {
|
| 414 |
+
if (!node || !node.parent) {
|
| 415 |
+
return;
|
| 416 |
+
}
|
| 417 |
+
|
| 418 |
+
const isDeclaredInsideProps = isComponentInProp(node);
|
| 419 |
+
|
| 420 |
+
if (
|
| 421 |
+
!components.get(node)
|
| 422 |
+
&& !isFunctionComponentInsideClassComponent(node)
|
| 423 |
+
&& !isDeclaredInsideProps) {
|
| 424 |
+
return;
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
if (
|
| 428 |
+
// Support allowAsProps option
|
| 429 |
+
(isDeclaredInsideProps && (allowAsProps || isComponentInRenderProp(node, context, propNamePattern)))
|
| 430 |
+
|
| 431 |
+
// Prevent reporting components created inside Array.map calls
|
| 432 |
+
|| isMapCall(node)
|
| 433 |
+
|| isMapCall(node.parent)
|
| 434 |
+
|
| 435 |
+
// Do not mark components declared inside hooks (or falsy '() => null' clean-up methods)
|
| 436 |
+
|| isReturnStatementOfHook(node, context)
|
| 437 |
+
|
| 438 |
+
// Do not mark objects containing render methods
|
| 439 |
+
|| isDirectValueOfRenderProperty(node, propNamePattern)
|
| 440 |
+
|
| 441 |
+
// Prevent reporting nested class components twice
|
| 442 |
+
|| isInsideRenderMethod(node)
|
| 443 |
+
|
| 444 |
+
// Prevent falsely reporting detected "components" which do not return JSX
|
| 445 |
+
|| isStatelessComponentReturningNull(node)
|
| 446 |
+
) {
|
| 447 |
+
return;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
// Get the closest parent component
|
| 451 |
+
const parentComponent = getClosestMatchingParent(
|
| 452 |
+
node,
|
| 453 |
+
context,
|
| 454 |
+
(nodeToMatch) => components.get(nodeToMatch)
|
| 455 |
+
);
|
| 456 |
+
|
| 457 |
+
if (parentComponent) {
|
| 458 |
+
const parentName = resolveComponentName(parentComponent);
|
| 459 |
+
|
| 460 |
+
// Exclude lowercase parents, e.g. function createTestComponent()
|
| 461 |
+
// React-dom prevents creating lowercase components
|
| 462 |
+
if (parentName && parentName[0] === parentName[0].toLowerCase()) {
|
| 463 |
+
return;
|
| 464 |
+
}
|
| 465 |
+
|
| 466 |
+
let message = generateErrorMessageWithParentName(parentName);
|
| 467 |
+
|
| 468 |
+
// Add information about allowAsProps option when component is declared inside prop
|
| 469 |
+
if (isDeclaredInsideProps && !allowAsProps) {
|
| 470 |
+
message += COMPONENT_AS_PROPS_INFO;
|
| 471 |
+
}
|
| 472 |
+
|
| 473 |
+
report(context, message, null, {
|
| 474 |
+
node,
|
| 475 |
+
});
|
| 476 |
+
}
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
// --------------------------------------------------------------------------
|
| 480 |
+
// Public
|
| 481 |
+
// --------------------------------------------------------------------------
|
| 482 |
+
|
| 483 |
+
return {
|
| 484 |
+
FunctionDeclaration(node) { validate(node); },
|
| 485 |
+
ArrowFunctionExpression(node) { validate(node); },
|
| 486 |
+
FunctionExpression(node) { validate(node); },
|
| 487 |
+
ClassDeclaration(node) { validate(node); },
|
| 488 |
+
CallExpression(node) { validate(node); },
|
| 489 |
+
};
|
| 490 |
+
}),
|
| 491 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/no-unused-class-component-methods.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=no-unused-class-component-methods.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/no-unused-class-component-methods.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"no-unused-class-component-methods.d.ts","sourceRoot":"","sources":["no-unused-class-component-methods.js"],"names":[],"mappings":"wBAoGW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/no-unused-class-component-methods.js
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Prevent declaring unused methods and properties of component class
|
| 3 |
+
* @author Paweł Nowak, Berton Zhu
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const docsUrl = require('../util/docsUrl');
|
| 9 |
+
const componentUtil = require('../util/componentUtil');
|
| 10 |
+
const report = require('../util/report');
|
| 11 |
+
|
| 12 |
+
// ------------------------------------------------------------------------------
|
| 13 |
+
// Rule Definition
|
| 14 |
+
// ------------------------------------------------------------------------------
|
| 15 |
+
|
| 16 |
+
const LIFECYCLE_METHODS = new Set([
|
| 17 |
+
'constructor',
|
| 18 |
+
'componentDidCatch',
|
| 19 |
+
'componentDidMount',
|
| 20 |
+
'componentDidUpdate',
|
| 21 |
+
'componentWillMount',
|
| 22 |
+
'componentWillReceiveProps',
|
| 23 |
+
'componentWillUnmount',
|
| 24 |
+
'componentWillUpdate',
|
| 25 |
+
'getChildContext',
|
| 26 |
+
'getSnapshotBeforeUpdate',
|
| 27 |
+
'render',
|
| 28 |
+
'shouldComponentUpdate',
|
| 29 |
+
'UNSAFE_componentWillMount',
|
| 30 |
+
'UNSAFE_componentWillReceiveProps',
|
| 31 |
+
'UNSAFE_componentWillUpdate',
|
| 32 |
+
]);
|
| 33 |
+
|
| 34 |
+
const ES6_LIFECYCLE = new Set([
|
| 35 |
+
'state',
|
| 36 |
+
]);
|
| 37 |
+
|
| 38 |
+
const ES5_LIFECYCLE = new Set([
|
| 39 |
+
'getInitialState',
|
| 40 |
+
'getDefaultProps',
|
| 41 |
+
'mixins',
|
| 42 |
+
]);
|
| 43 |
+
|
| 44 |
+
function isKeyLiteralLike(node, property) {
|
| 45 |
+
return property.type === 'Literal'
|
| 46 |
+
|| (property.type === 'TemplateLiteral' && property.expressions.length === 0)
|
| 47 |
+
|| (node.computed === false && property.type === 'Identifier');
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
// Descend through all wrapping TypeCastExpressions and return the expression
|
| 51 |
+
// that was cast.
|
| 52 |
+
function uncast(node) {
|
| 53 |
+
while (node.type === 'TypeCastExpression') {
|
| 54 |
+
node = node.expression;
|
| 55 |
+
}
|
| 56 |
+
return node;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
// Return the name of an identifier or the string value of a literal. Useful
|
| 60 |
+
// anywhere that a literal may be used as a key (e.g., member expressions,
|
| 61 |
+
// method definitions, ObjectExpression property keys).
|
| 62 |
+
function getName(node) {
|
| 63 |
+
node = uncast(node);
|
| 64 |
+
const type = node.type;
|
| 65 |
+
|
| 66 |
+
if (type === 'Identifier') {
|
| 67 |
+
return node.name;
|
| 68 |
+
}
|
| 69 |
+
if (type === 'Literal') {
|
| 70 |
+
return String(node.value);
|
| 71 |
+
}
|
| 72 |
+
if (type === 'TemplateLiteral' && node.expressions.length === 0) {
|
| 73 |
+
return node.quasis[0].value.raw;
|
| 74 |
+
}
|
| 75 |
+
return null;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
function isThisExpression(node) {
|
| 79 |
+
return uncast(node).type === 'ThisExpression';
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
function getInitialClassInfo(node, isClass) {
|
| 83 |
+
return {
|
| 84 |
+
classNode: node,
|
| 85 |
+
isClass,
|
| 86 |
+
// Set of nodes where properties were defined.
|
| 87 |
+
properties: new Set(),
|
| 88 |
+
|
| 89 |
+
// Set of names of properties that we've seen used.
|
| 90 |
+
usedProperties: new Set(),
|
| 91 |
+
|
| 92 |
+
inStatic: false,
|
| 93 |
+
};
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
const messages = {
|
| 97 |
+
unused: 'Unused method or property "{{name}}"',
|
| 98 |
+
unusedWithClass: 'Unused method or property "{{name}}" of class "{{className}}"',
|
| 99 |
+
};
|
| 100 |
+
|
| 101 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 102 |
+
module.exports = {
|
| 103 |
+
meta: {
|
| 104 |
+
docs: {
|
| 105 |
+
description: 'Disallow declaring unused methods of component class',
|
| 106 |
+
category: 'Best Practices',
|
| 107 |
+
recommended: false,
|
| 108 |
+
url: docsUrl('no-unused-class-component-methods'),
|
| 109 |
+
},
|
| 110 |
+
messages,
|
| 111 |
+
schema: [],
|
| 112 |
+
},
|
| 113 |
+
|
| 114 |
+
create: ((context) => {
|
| 115 |
+
let classInfo = null;
|
| 116 |
+
|
| 117 |
+
// Takes an ObjectExpression node and adds all named Property nodes to the
|
| 118 |
+
// current set of properties.
|
| 119 |
+
function addProperty(node) {
|
| 120 |
+
classInfo.properties.add(node);
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
// Adds the name of the given node as a used property if the node is an
|
| 124 |
+
// Identifier or a Literal. Other node types are ignored.
|
| 125 |
+
function addUsedProperty(node) {
|
| 126 |
+
const name = getName(node);
|
| 127 |
+
if (name) {
|
| 128 |
+
classInfo.usedProperties.add(name);
|
| 129 |
+
}
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
function reportUnusedProperties() {
|
| 133 |
+
// Report all unused properties.
|
| 134 |
+
for (const node of classInfo.properties) { // eslint-disable-line no-restricted-syntax
|
| 135 |
+
const name = getName(node);
|
| 136 |
+
if (
|
| 137 |
+
!classInfo.usedProperties.has(name)
|
| 138 |
+
&& !LIFECYCLE_METHODS.has(name)
|
| 139 |
+
&& (classInfo.isClass ? !ES6_LIFECYCLE.has(name) : !ES5_LIFECYCLE.has(name))
|
| 140 |
+
) {
|
| 141 |
+
const className = (classInfo.classNode.id && classInfo.classNode.id.name) || '';
|
| 142 |
+
|
| 143 |
+
const messageID = className ? 'unusedWithClass' : 'unused';
|
| 144 |
+
report(
|
| 145 |
+
context,
|
| 146 |
+
messages[messageID],
|
| 147 |
+
messageID,
|
| 148 |
+
{
|
| 149 |
+
node,
|
| 150 |
+
data: {
|
| 151 |
+
name,
|
| 152 |
+
className,
|
| 153 |
+
},
|
| 154 |
+
}
|
| 155 |
+
);
|
| 156 |
+
}
|
| 157 |
+
}
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
function exitMethod() {
|
| 161 |
+
if (!classInfo || !classInfo.inStatic) {
|
| 162 |
+
return;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
classInfo.inStatic = false;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
return {
|
| 169 |
+
ClassDeclaration(node) {
|
| 170 |
+
if (componentUtil.isES6Component(node, context)) {
|
| 171 |
+
classInfo = getInitialClassInfo(node, true);
|
| 172 |
+
}
|
| 173 |
+
},
|
| 174 |
+
|
| 175 |
+
ObjectExpression(node) {
|
| 176 |
+
if (componentUtil.isES5Component(node, context)) {
|
| 177 |
+
classInfo = getInitialClassInfo(node, false);
|
| 178 |
+
}
|
| 179 |
+
},
|
| 180 |
+
|
| 181 |
+
'ClassDeclaration:exit'() {
|
| 182 |
+
if (!classInfo) {
|
| 183 |
+
return;
|
| 184 |
+
}
|
| 185 |
+
reportUnusedProperties();
|
| 186 |
+
classInfo = null;
|
| 187 |
+
},
|
| 188 |
+
|
| 189 |
+
'ObjectExpression:exit'(node) {
|
| 190 |
+
if (!classInfo || classInfo.classNode !== node) {
|
| 191 |
+
return;
|
| 192 |
+
}
|
| 193 |
+
reportUnusedProperties();
|
| 194 |
+
classInfo = null;
|
| 195 |
+
},
|
| 196 |
+
|
| 197 |
+
Property(node) {
|
| 198 |
+
if (!classInfo || classInfo.classNode !== node.parent) {
|
| 199 |
+
return;
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
if (isKeyLiteralLike(node, node.key)) {
|
| 203 |
+
addProperty(node.key);
|
| 204 |
+
}
|
| 205 |
+
},
|
| 206 |
+
|
| 207 |
+
'ClassProperty, MethodDefinition, PropertyDefinition'(node) {
|
| 208 |
+
if (!classInfo) {
|
| 209 |
+
return;
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
if (node.static) {
|
| 213 |
+
classInfo.inStatic = true;
|
| 214 |
+
return;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
if (isKeyLiteralLike(node, node.key)) {
|
| 218 |
+
addProperty(node.key);
|
| 219 |
+
}
|
| 220 |
+
},
|
| 221 |
+
|
| 222 |
+
'ClassProperty:exit': exitMethod,
|
| 223 |
+
'MethodDefinition:exit': exitMethod,
|
| 224 |
+
'PropertyDefinition:exit': exitMethod,
|
| 225 |
+
|
| 226 |
+
MemberExpression(node) {
|
| 227 |
+
if (!classInfo || classInfo.inStatic) {
|
| 228 |
+
return;
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
if (isThisExpression(node.object) && isKeyLiteralLike(node, node.property)) {
|
| 232 |
+
if (node.parent.type === 'AssignmentExpression' && node.parent.left === node) {
|
| 233 |
+
// detect `this.property = xxx`
|
| 234 |
+
addProperty(node.property);
|
| 235 |
+
} else {
|
| 236 |
+
// detect `this.property()`, `x = this.property`, etc.
|
| 237 |
+
addUsedProperty(node.property);
|
| 238 |
+
}
|
| 239 |
+
}
|
| 240 |
+
},
|
| 241 |
+
|
| 242 |
+
VariableDeclarator(node) {
|
| 243 |
+
if (!classInfo || classInfo.inStatic) {
|
| 244 |
+
return;
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
// detect `{ foo, bar: baz } = this`
|
| 248 |
+
if (node.init && isThisExpression(node.init) && node.id.type === 'ObjectPattern') {
|
| 249 |
+
node.id.properties
|
| 250 |
+
.filter((prop) => prop.type === 'Property' && isKeyLiteralLike(prop, prop.key))
|
| 251 |
+
.forEach((prop) => {
|
| 252 |
+
addUsedProperty('key' in prop ? prop.key : undefined);
|
| 253 |
+
});
|
| 254 |
+
}
|
| 255 |
+
},
|
| 256 |
+
};
|
| 257 |
+
}),
|
| 258 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/no-unused-prop-types.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=no-unused-prop-types.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/no-unused-prop-types.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"no-unused-prop-types.d.ts","sourceRoot":"","sources":["no-unused-prop-types.js"],"names":[],"mappings":"wBAiCW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/no-unused-prop-types.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Prevent definitions of unused prop types
|
| 3 |
+
* @author Evgueni Naverniouk
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const values = require('object.values');
|
| 9 |
+
|
| 10 |
+
// As for exceptions for props.children or props.className (and alike) look at
|
| 11 |
+
// https://github.com/jsx-eslint/eslint-plugin-react/issues/7
|
| 12 |
+
|
| 13 |
+
const Components = require('../util/Components');
|
| 14 |
+
const docsUrl = require('../util/docsUrl');
|
| 15 |
+
const report = require('../util/report');
|
| 16 |
+
|
| 17 |
+
/**
|
| 18 |
+
* Checks if the component must be validated
|
| 19 |
+
* @param {Object} component The component to process
|
| 20 |
+
* @returns {boolean} True if the component must be validated, false if not.
|
| 21 |
+
*/
|
| 22 |
+
function mustBeValidated(component) {
|
| 23 |
+
return !!component && !component.ignoreUnusedPropTypesValidation;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
// ------------------------------------------------------------------------------
|
| 27 |
+
// Rule Definition
|
| 28 |
+
// ------------------------------------------------------------------------------
|
| 29 |
+
|
| 30 |
+
const messages = {
|
| 31 |
+
unusedPropType: '\'{{name}}\' PropType is defined but prop is never used',
|
| 32 |
+
};
|
| 33 |
+
|
| 34 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 35 |
+
module.exports = {
|
| 36 |
+
meta: {
|
| 37 |
+
docs: {
|
| 38 |
+
description: 'Disallow definitions of unused propTypes',
|
| 39 |
+
category: 'Best Practices',
|
| 40 |
+
recommended: false,
|
| 41 |
+
url: docsUrl('no-unused-prop-types'),
|
| 42 |
+
},
|
| 43 |
+
|
| 44 |
+
messages,
|
| 45 |
+
|
| 46 |
+
schema: [{
|
| 47 |
+
type: 'object',
|
| 48 |
+
properties: {
|
| 49 |
+
ignore: {
|
| 50 |
+
type: 'array',
|
| 51 |
+
items: {
|
| 52 |
+
type: 'string',
|
| 53 |
+
},
|
| 54 |
+
uniqueItems: true,
|
| 55 |
+
},
|
| 56 |
+
customValidators: {
|
| 57 |
+
type: 'array',
|
| 58 |
+
items: {
|
| 59 |
+
type: 'string',
|
| 60 |
+
},
|
| 61 |
+
},
|
| 62 |
+
skipShapeProps: {
|
| 63 |
+
type: 'boolean',
|
| 64 |
+
},
|
| 65 |
+
},
|
| 66 |
+
additionalProperties: false,
|
| 67 |
+
}],
|
| 68 |
+
},
|
| 69 |
+
|
| 70 |
+
create: Components.detect((context, components) => {
|
| 71 |
+
const defaults = { skipShapeProps: true, customValidators: [], ignore: [] };
|
| 72 |
+
const configuration = Object.assign({}, defaults, context.options[0] || {});
|
| 73 |
+
|
| 74 |
+
/**
|
| 75 |
+
* Checks if the prop is ignored
|
| 76 |
+
* @param {string} name Name of the prop to check.
|
| 77 |
+
* @returns {boolean} True if the prop is ignored, false if not.
|
| 78 |
+
*/
|
| 79 |
+
function isIgnored(name) {
|
| 80 |
+
return configuration.ignore.indexOf(name) !== -1;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
/**
|
| 84 |
+
* Checks if a prop is used
|
| 85 |
+
* @param {ASTNode} node The AST node being checked.
|
| 86 |
+
* @param {Object} prop Declared prop object
|
| 87 |
+
* @returns {boolean} True if the prop is used, false if not.
|
| 88 |
+
*/
|
| 89 |
+
function isPropUsed(node, prop) {
|
| 90 |
+
const usedPropTypes = node.usedPropTypes || [];
|
| 91 |
+
for (let i = 0, l = usedPropTypes.length; i < l; i++) {
|
| 92 |
+
const usedProp = usedPropTypes[i];
|
| 93 |
+
if (
|
| 94 |
+
prop.type === 'shape'
|
| 95 |
+
|| prop.type === 'exact'
|
| 96 |
+
|| prop.name === '__ANY_KEY__'
|
| 97 |
+
|| usedProp.name === prop.name
|
| 98 |
+
) {
|
| 99 |
+
return true;
|
| 100 |
+
}
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
return false;
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
/**
|
| 107 |
+
* Used to recursively loop through each declared prop type
|
| 108 |
+
* @param {Object} component The component to process
|
| 109 |
+
* @param {ASTNode[]|true} props List of props to validate
|
| 110 |
+
*/
|
| 111 |
+
function reportUnusedPropType(component, props) {
|
| 112 |
+
// Skip props that check instances
|
| 113 |
+
if (props === true) {
|
| 114 |
+
return;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
Object.keys(props || {}).forEach((key) => {
|
| 118 |
+
const prop = props[key];
|
| 119 |
+
// Skip props that check instances
|
| 120 |
+
if (prop === true) {
|
| 121 |
+
return;
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
if ((prop.type === 'shape' || prop.type === 'exact') && configuration.skipShapeProps) {
|
| 125 |
+
return;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
if (prop.node && prop.node.typeAnnotation && prop.node.typeAnnotation.typeAnnotation
|
| 129 |
+
&& prop.node.typeAnnotation.typeAnnotation.type === 'TSNeverKeyword') {
|
| 130 |
+
return;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
if (prop.node && !isIgnored(prop.fullName) && !isPropUsed(component, prop)) {
|
| 134 |
+
report(context, messages.unusedPropType, 'unusedPropType', {
|
| 135 |
+
node: prop.node.key || prop.node,
|
| 136 |
+
data: {
|
| 137 |
+
name: prop.fullName,
|
| 138 |
+
},
|
| 139 |
+
});
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
if (prop.children) {
|
| 143 |
+
reportUnusedPropType(component, prop.children);
|
| 144 |
+
}
|
| 145 |
+
});
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
/**
|
| 149 |
+
* Reports unused proptypes for a given component
|
| 150 |
+
* @param {Object} component The component to process
|
| 151 |
+
*/
|
| 152 |
+
function reportUnusedPropTypes(component) {
|
| 153 |
+
reportUnusedPropType(component, component.declaredPropTypes);
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
// --------------------------------------------------------------------------
|
| 157 |
+
// Public
|
| 158 |
+
// --------------------------------------------------------------------------
|
| 159 |
+
|
| 160 |
+
return {
|
| 161 |
+
'Program:exit'() {
|
| 162 |
+
// Report undeclared proptypes for all classes
|
| 163 |
+
values(components.list())
|
| 164 |
+
.filter((component) => mustBeValidated(component))
|
| 165 |
+
.forEach((component) => {
|
| 166 |
+
reportUnusedPropTypes(component);
|
| 167 |
+
});
|
| 168 |
+
},
|
| 169 |
+
};
|
| 170 |
+
}),
|
| 171 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/no-unused-state.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=no-unused-state.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/no-unused-state.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"no-unused-state.d.ts","sourceRoot":"","sources":["no-unused-state.js"],"names":[],"mappings":"wBAgFW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/no-unused-state.js
ADDED
|
@@ -0,0 +1,529 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Attempts to discover all state fields in a React component and
|
| 3 |
+
* warn if any of them are never read.
|
| 4 |
+
*
|
| 5 |
+
* State field definitions are collected from `this.state = {}` assignments in
|
| 6 |
+
* the constructor, objects passed to `this.setState()`, and `state = {}` class
|
| 7 |
+
* property assignments.
|
| 8 |
+
*/
|
| 9 |
+
|
| 10 |
+
'use strict';
|
| 11 |
+
|
| 12 |
+
const docsUrl = require('../util/docsUrl');
|
| 13 |
+
const astUtil = require('../util/ast');
|
| 14 |
+
const componentUtil = require('../util/componentUtil');
|
| 15 |
+
const report = require('../util/report');
|
| 16 |
+
const getScope = require('../util/eslint').getScope;
|
| 17 |
+
|
| 18 |
+
// Descend through all wrapping TypeCastExpressions and return the expression
|
| 19 |
+
// that was cast.
|
| 20 |
+
function uncast(node) {
|
| 21 |
+
while (node.type === 'TypeCastExpression') {
|
| 22 |
+
node = node.expression;
|
| 23 |
+
}
|
| 24 |
+
return node;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
// Return the name of an identifier or the string value of a literal. Useful
|
| 28 |
+
// anywhere that a literal may be used as a key (e.g., member expressions,
|
| 29 |
+
// method definitions, ObjectExpression property keys).
|
| 30 |
+
function getName(node) {
|
| 31 |
+
node = uncast(node);
|
| 32 |
+
const type = node.type;
|
| 33 |
+
|
| 34 |
+
if (type === 'Identifier') {
|
| 35 |
+
return node.name;
|
| 36 |
+
}
|
| 37 |
+
if (type === 'Literal') {
|
| 38 |
+
return String(node.value);
|
| 39 |
+
}
|
| 40 |
+
if (type === 'TemplateLiteral' && node.expressions.length === 0) {
|
| 41 |
+
return node.quasis[0].value.raw;
|
| 42 |
+
}
|
| 43 |
+
return null;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
function isThisExpression(node) {
|
| 47 |
+
return astUtil.unwrapTSAsExpression(uncast(node)).type === 'ThisExpression';
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function getInitialClassInfo() {
|
| 51 |
+
return {
|
| 52 |
+
// Set of nodes where state fields were defined.
|
| 53 |
+
stateFields: new Set(),
|
| 54 |
+
|
| 55 |
+
// Set of names of state fields that we've seen used.
|
| 56 |
+
usedStateFields: new Set(),
|
| 57 |
+
|
| 58 |
+
// Names of local variables that may be pointing to this.state. To
|
| 59 |
+
// track this properly, we would need to keep track of all locals,
|
| 60 |
+
// shadowing, assignments, etc. To keep things simple, we only
|
| 61 |
+
// maintain one set of aliases per method and accept that it will
|
| 62 |
+
// produce some false negatives.
|
| 63 |
+
aliases: null,
|
| 64 |
+
};
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
function isSetStateCall(node) {
|
| 68 |
+
const unwrappedCalleeNode = astUtil.unwrapTSAsExpression(node.callee);
|
| 69 |
+
|
| 70 |
+
return (
|
| 71 |
+
unwrappedCalleeNode.type === 'MemberExpression'
|
| 72 |
+
&& isThisExpression(unwrappedCalleeNode.object)
|
| 73 |
+
&& getName(unwrappedCalleeNode.property) === 'setState'
|
| 74 |
+
);
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
const messages = {
|
| 78 |
+
unusedStateField: 'Unused state field: \'{{name}}\'',
|
| 79 |
+
};
|
| 80 |
+
|
| 81 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 82 |
+
module.exports = {
|
| 83 |
+
meta: {
|
| 84 |
+
docs: {
|
| 85 |
+
description: 'Disallow definitions of unused state',
|
| 86 |
+
category: 'Best Practices',
|
| 87 |
+
recommended: false,
|
| 88 |
+
url: docsUrl('no-unused-state'),
|
| 89 |
+
},
|
| 90 |
+
|
| 91 |
+
messages,
|
| 92 |
+
|
| 93 |
+
schema: [],
|
| 94 |
+
},
|
| 95 |
+
|
| 96 |
+
create(context) {
|
| 97 |
+
// Non-null when we are inside a React component ClassDeclaration and we have
|
| 98 |
+
// not yet encountered any use of this.state which we have chosen not to
|
| 99 |
+
// analyze. If we encounter any such usage (like this.state being spread as
|
| 100 |
+
// JSX attributes), then this is again set to null.
|
| 101 |
+
let classInfo = null;
|
| 102 |
+
|
| 103 |
+
function isStateParameterReference(node) {
|
| 104 |
+
const classMethods = [
|
| 105 |
+
'shouldComponentUpdate',
|
| 106 |
+
'componentWillUpdate',
|
| 107 |
+
'UNSAFE_componentWillUpdate',
|
| 108 |
+
'getSnapshotBeforeUpdate',
|
| 109 |
+
'componentDidUpdate',
|
| 110 |
+
];
|
| 111 |
+
|
| 112 |
+
let scope = getScope(context, node);
|
| 113 |
+
while (scope) {
|
| 114 |
+
const parent = scope.block && scope.block.parent;
|
| 115 |
+
if (
|
| 116 |
+
parent
|
| 117 |
+
&& parent.type === 'MethodDefinition' && (
|
| 118 |
+
(parent.static && parent.key.name === 'getDerivedStateFromProps')
|
| 119 |
+
|| classMethods.indexOf(parent.key.name) !== -1
|
| 120 |
+
)
|
| 121 |
+
&& parent.value.type === 'FunctionExpression'
|
| 122 |
+
&& parent.value.params[1]
|
| 123 |
+
&& parent.value.params[1].name === node.name
|
| 124 |
+
) {
|
| 125 |
+
return true;
|
| 126 |
+
}
|
| 127 |
+
scope = scope.upper;
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
return false;
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
// Returns true if the given node is possibly a reference to `this.state` or the state parameter of
|
| 134 |
+
// a lifecycle method.
|
| 135 |
+
function isStateReference(node) {
|
| 136 |
+
node = uncast(node);
|
| 137 |
+
|
| 138 |
+
const isDirectStateReference = node.type === 'MemberExpression'
|
| 139 |
+
&& isThisExpression(node.object)
|
| 140 |
+
&& node.property.name === 'state';
|
| 141 |
+
|
| 142 |
+
const isAliasedStateReference = node.type === 'Identifier'
|
| 143 |
+
&& classInfo.aliases
|
| 144 |
+
&& classInfo.aliases.has(node.name);
|
| 145 |
+
|
| 146 |
+
return isDirectStateReference || isAliasedStateReference || isStateParameterReference(node);
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
// Takes an ObjectExpression node and adds all named Property nodes to the
|
| 150 |
+
// current set of state fields.
|
| 151 |
+
function addStateFields(node) {
|
| 152 |
+
node.properties.filter((prop) => (
|
| 153 |
+
prop.type === 'Property'
|
| 154 |
+
&& (prop.key.type === 'Literal'
|
| 155 |
+
|| (prop.key.type === 'TemplateLiteral' && prop.key.expressions.length === 0)
|
| 156 |
+
|| (prop.computed === false && prop.key.type === 'Identifier'))
|
| 157 |
+
&& getName(prop.key) !== null
|
| 158 |
+
)).forEach((prop) => {
|
| 159 |
+
classInfo.stateFields.add(prop);
|
| 160 |
+
});
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
// Adds the name of the given node as a used state field if the node is an
|
| 164 |
+
// Identifier or a Literal. Other node types are ignored.
|
| 165 |
+
function addUsedStateField(node) {
|
| 166 |
+
if (!classInfo) {
|
| 167 |
+
return;
|
| 168 |
+
}
|
| 169 |
+
const name = getName(node);
|
| 170 |
+
if (name) {
|
| 171 |
+
classInfo.usedStateFields.add(name);
|
| 172 |
+
}
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
// Records used state fields and new aliases for an ObjectPattern which
|
| 176 |
+
// destructures `this.state`.
|
| 177 |
+
function handleStateDestructuring(node) {
|
| 178 |
+
node.properties.forEach((prop) => {
|
| 179 |
+
if (prop.type === 'Property') {
|
| 180 |
+
addUsedStateField(prop.key);
|
| 181 |
+
} else if (
|
| 182 |
+
(prop.type === 'ExperimentalRestProperty' || prop.type === 'RestElement')
|
| 183 |
+
&& classInfo.aliases
|
| 184 |
+
) {
|
| 185 |
+
classInfo.aliases.add(getName(prop.argument));
|
| 186 |
+
}
|
| 187 |
+
});
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
// Used to record used state fields and new aliases for both
|
| 191 |
+
// AssignmentExpressions and VariableDeclarators.
|
| 192 |
+
function handleAssignment(left, right) {
|
| 193 |
+
const unwrappedRight = astUtil.unwrapTSAsExpression(right);
|
| 194 |
+
|
| 195 |
+
switch (left.type) {
|
| 196 |
+
case 'Identifier':
|
| 197 |
+
if (isStateReference(unwrappedRight) && classInfo.aliases) {
|
| 198 |
+
classInfo.aliases.add(left.name);
|
| 199 |
+
}
|
| 200 |
+
break;
|
| 201 |
+
case 'ObjectPattern':
|
| 202 |
+
if (isStateReference(unwrappedRight)) {
|
| 203 |
+
handleStateDestructuring(left);
|
| 204 |
+
} else if (isThisExpression(unwrappedRight) && classInfo.aliases) {
|
| 205 |
+
left.properties.forEach((prop) => {
|
| 206 |
+
if (prop.type === 'Property' && getName(prop.key) === 'state') {
|
| 207 |
+
const name = getName(prop.value);
|
| 208 |
+
if (name) {
|
| 209 |
+
classInfo.aliases.add(name);
|
| 210 |
+
} else if (prop.value.type === 'ObjectPattern') {
|
| 211 |
+
handleStateDestructuring(prop.value);
|
| 212 |
+
}
|
| 213 |
+
}
|
| 214 |
+
});
|
| 215 |
+
}
|
| 216 |
+
break;
|
| 217 |
+
default:
|
| 218 |
+
// pass
|
| 219 |
+
}
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
function reportUnusedFields() {
|
| 223 |
+
// Report all unused state fields.
|
| 224 |
+
classInfo.stateFields.forEach((node) => {
|
| 225 |
+
const name = getName(node.key);
|
| 226 |
+
if (!classInfo.usedStateFields.has(name)) {
|
| 227 |
+
report(context, messages.unusedStateField, 'unusedStateField', {
|
| 228 |
+
node,
|
| 229 |
+
data: {
|
| 230 |
+
name,
|
| 231 |
+
},
|
| 232 |
+
});
|
| 233 |
+
}
|
| 234 |
+
});
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
function handleES6ComponentEnter(node) {
|
| 238 |
+
if (componentUtil.isES6Component(node, context)) {
|
| 239 |
+
classInfo = getInitialClassInfo();
|
| 240 |
+
}
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
function handleES6ComponentExit() {
|
| 244 |
+
if (!classInfo) {
|
| 245 |
+
return;
|
| 246 |
+
}
|
| 247 |
+
reportUnusedFields();
|
| 248 |
+
classInfo = null;
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
function isGDSFP(node) {
|
| 252 |
+
const name = getName(node.key);
|
| 253 |
+
if (
|
| 254 |
+
!node.static
|
| 255 |
+
|| name !== 'getDerivedStateFromProps'
|
| 256 |
+
|| !node.value
|
| 257 |
+
|| !node.value.params
|
| 258 |
+
|| node.value.params.length < 2 // no `state` argument
|
| 259 |
+
) {
|
| 260 |
+
return false;
|
| 261 |
+
}
|
| 262 |
+
return true;
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
return {
|
| 266 |
+
ClassDeclaration: handleES6ComponentEnter,
|
| 267 |
+
|
| 268 |
+
'ClassDeclaration:exit': handleES6ComponentExit,
|
| 269 |
+
|
| 270 |
+
ClassExpression: handleES6ComponentEnter,
|
| 271 |
+
|
| 272 |
+
'ClassExpression:exit': handleES6ComponentExit,
|
| 273 |
+
|
| 274 |
+
ObjectExpression(node) {
|
| 275 |
+
if (componentUtil.isES5Component(node, context)) {
|
| 276 |
+
classInfo = getInitialClassInfo();
|
| 277 |
+
}
|
| 278 |
+
},
|
| 279 |
+
|
| 280 |
+
'ObjectExpression:exit'(node) {
|
| 281 |
+
if (!classInfo) {
|
| 282 |
+
return;
|
| 283 |
+
}
|
| 284 |
+
|
| 285 |
+
if (componentUtil.isES5Component(node, context)) {
|
| 286 |
+
reportUnusedFields();
|
| 287 |
+
classInfo = null;
|
| 288 |
+
}
|
| 289 |
+
},
|
| 290 |
+
|
| 291 |
+
CallExpression(node) {
|
| 292 |
+
if (!classInfo) {
|
| 293 |
+
return;
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
+
const unwrappedNode = astUtil.unwrapTSAsExpression(node);
|
| 297 |
+
const unwrappedArgumentNode = astUtil.unwrapTSAsExpression(unwrappedNode.arguments[0]);
|
| 298 |
+
|
| 299 |
+
// If we're looking at a `this.setState({})` invocation, record all the
|
| 300 |
+
// properties as state fields.
|
| 301 |
+
if (
|
| 302 |
+
isSetStateCall(unwrappedNode)
|
| 303 |
+
&& unwrappedNode.arguments.length > 0
|
| 304 |
+
&& unwrappedArgumentNode.type === 'ObjectExpression'
|
| 305 |
+
) {
|
| 306 |
+
addStateFields(unwrappedArgumentNode);
|
| 307 |
+
} else if (
|
| 308 |
+
isSetStateCall(unwrappedNode)
|
| 309 |
+
&& unwrappedNode.arguments.length > 0
|
| 310 |
+
&& unwrappedArgumentNode.type === 'ArrowFunctionExpression'
|
| 311 |
+
) {
|
| 312 |
+
const unwrappedBodyNode = astUtil.unwrapTSAsExpression(unwrappedArgumentNode.body);
|
| 313 |
+
|
| 314 |
+
if (unwrappedBodyNode.type === 'ObjectExpression') {
|
| 315 |
+
addStateFields(unwrappedBodyNode);
|
| 316 |
+
}
|
| 317 |
+
if (unwrappedArgumentNode.params.length > 0 && classInfo.aliases) {
|
| 318 |
+
const firstParam = unwrappedArgumentNode.params[0];
|
| 319 |
+
if (firstParam.type === 'ObjectPattern') {
|
| 320 |
+
handleStateDestructuring(firstParam);
|
| 321 |
+
} else {
|
| 322 |
+
classInfo.aliases.add(getName(firstParam));
|
| 323 |
+
}
|
| 324 |
+
}
|
| 325 |
+
}
|
| 326 |
+
},
|
| 327 |
+
|
| 328 |
+
'ClassProperty, PropertyDefinition'(node) {
|
| 329 |
+
if (!classInfo) {
|
| 330 |
+
return;
|
| 331 |
+
}
|
| 332 |
+
// If we see state being assigned as a class property using an object
|
| 333 |
+
// expression, record all the fields of that object as state fields.
|
| 334 |
+
const unwrappedValueNode = astUtil.unwrapTSAsExpression(node.value);
|
| 335 |
+
|
| 336 |
+
const name = getName(node.key);
|
| 337 |
+
if (
|
| 338 |
+
name === 'state'
|
| 339 |
+
&& !node.static
|
| 340 |
+
&& unwrappedValueNode
|
| 341 |
+
&& unwrappedValueNode.type === 'ObjectExpression'
|
| 342 |
+
) {
|
| 343 |
+
addStateFields(unwrappedValueNode);
|
| 344 |
+
}
|
| 345 |
+
|
| 346 |
+
if (
|
| 347 |
+
!node.static
|
| 348 |
+
&& unwrappedValueNode
|
| 349 |
+
&& unwrappedValueNode.type === 'ArrowFunctionExpression'
|
| 350 |
+
) {
|
| 351 |
+
// Create a new set for this.state aliases local to this method.
|
| 352 |
+
classInfo.aliases = new Set();
|
| 353 |
+
}
|
| 354 |
+
},
|
| 355 |
+
|
| 356 |
+
'ClassProperty:exit'(node) {
|
| 357 |
+
if (
|
| 358 |
+
classInfo
|
| 359 |
+
&& !node.static
|
| 360 |
+
&& node.value
|
| 361 |
+
&& node.value.type === 'ArrowFunctionExpression'
|
| 362 |
+
) {
|
| 363 |
+
// Forget our set of local aliases.
|
| 364 |
+
classInfo.aliases = null;
|
| 365 |
+
}
|
| 366 |
+
},
|
| 367 |
+
|
| 368 |
+
'PropertyDefinition, ClassProperty'(node) {
|
| 369 |
+
if (!isGDSFP(node)) {
|
| 370 |
+
return;
|
| 371 |
+
}
|
| 372 |
+
|
| 373 |
+
const childScope = getScope(context, node).childScopes.find((x) => x.block === node.value);
|
| 374 |
+
if (!childScope) {
|
| 375 |
+
return;
|
| 376 |
+
}
|
| 377 |
+
const scope = childScope.variableScope.childScopes.find((x) => x.block === node.value);
|
| 378 |
+
const stateArg = node.value.params[1]; // probably "state"
|
| 379 |
+
if (!scope || !scope.variables) {
|
| 380 |
+
return;
|
| 381 |
+
}
|
| 382 |
+
const argVar = scope.variables.find((x) => x.name === stateArg.name);
|
| 383 |
+
|
| 384 |
+
if (argVar) {
|
| 385 |
+
const stateRefs = argVar.references;
|
| 386 |
+
|
| 387 |
+
stateRefs.forEach((ref) => {
|
| 388 |
+
const identifier = ref.identifier;
|
| 389 |
+
if (identifier && identifier.parent && identifier.parent.type === 'MemberExpression') {
|
| 390 |
+
addUsedStateField(identifier.parent.property);
|
| 391 |
+
}
|
| 392 |
+
});
|
| 393 |
+
}
|
| 394 |
+
},
|
| 395 |
+
|
| 396 |
+
'PropertyDefinition:exit'(node) {
|
| 397 |
+
if (
|
| 398 |
+
classInfo
|
| 399 |
+
&& !node.static
|
| 400 |
+
&& node.value
|
| 401 |
+
&& node.value.type === 'ArrowFunctionExpression'
|
| 402 |
+
&& !isGDSFP(node)
|
| 403 |
+
) {
|
| 404 |
+
// Forget our set of local aliases.
|
| 405 |
+
classInfo.aliases = null;
|
| 406 |
+
}
|
| 407 |
+
},
|
| 408 |
+
|
| 409 |
+
MethodDefinition() {
|
| 410 |
+
if (!classInfo) {
|
| 411 |
+
return;
|
| 412 |
+
}
|
| 413 |
+
// Create a new set for this.state aliases local to this method.
|
| 414 |
+
classInfo.aliases = new Set();
|
| 415 |
+
},
|
| 416 |
+
|
| 417 |
+
'MethodDefinition:exit'() {
|
| 418 |
+
if (!classInfo) {
|
| 419 |
+
return;
|
| 420 |
+
}
|
| 421 |
+
// Forget our set of local aliases.
|
| 422 |
+
classInfo.aliases = null;
|
| 423 |
+
},
|
| 424 |
+
|
| 425 |
+
FunctionExpression(node) {
|
| 426 |
+
if (!classInfo) {
|
| 427 |
+
return;
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
const parent = node.parent;
|
| 431 |
+
if (!componentUtil.isES5Component(parent.parent, context)) {
|
| 432 |
+
return;
|
| 433 |
+
}
|
| 434 |
+
|
| 435 |
+
if (
|
| 436 |
+
'key' in parent
|
| 437 |
+
&& 'name' in parent.key
|
| 438 |
+
&& parent.key.name === 'getInitialState'
|
| 439 |
+
) {
|
| 440 |
+
const body = node.body.body;
|
| 441 |
+
const lastBodyNode = body[body.length - 1];
|
| 442 |
+
|
| 443 |
+
if (
|
| 444 |
+
lastBodyNode.type === 'ReturnStatement'
|
| 445 |
+
&& lastBodyNode.argument.type === 'ObjectExpression'
|
| 446 |
+
) {
|
| 447 |
+
addStateFields(lastBodyNode.argument);
|
| 448 |
+
}
|
| 449 |
+
} else {
|
| 450 |
+
// Create a new set for this.state aliases local to this method.
|
| 451 |
+
classInfo.aliases = new Set();
|
| 452 |
+
}
|
| 453 |
+
},
|
| 454 |
+
|
| 455 |
+
AssignmentExpression(node) {
|
| 456 |
+
if (!classInfo) {
|
| 457 |
+
return;
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
const unwrappedLeft = astUtil.unwrapTSAsExpression(node.left);
|
| 461 |
+
const unwrappedRight = astUtil.unwrapTSAsExpression(node.right);
|
| 462 |
+
|
| 463 |
+
// Check for assignments like `this.state = {}`
|
| 464 |
+
if (
|
| 465 |
+
unwrappedLeft.type === 'MemberExpression'
|
| 466 |
+
&& isThisExpression(unwrappedLeft.object)
|
| 467 |
+
&& getName(unwrappedLeft.property) === 'state'
|
| 468 |
+
&& unwrappedRight.type === 'ObjectExpression'
|
| 469 |
+
) {
|
| 470 |
+
// Find the nearest function expression containing this assignment.
|
| 471 |
+
/** @type {import('eslint').Rule.Node} */
|
| 472 |
+
let fn = node;
|
| 473 |
+
while (fn.type !== 'FunctionExpression' && fn.parent) {
|
| 474 |
+
fn = fn.parent;
|
| 475 |
+
}
|
| 476 |
+
// If the nearest containing function is the constructor, then we want
|
| 477 |
+
// to record all the assigned properties as state fields.
|
| 478 |
+
if (
|
| 479 |
+
fn.parent
|
| 480 |
+
&& fn.parent.type === 'MethodDefinition'
|
| 481 |
+
&& fn.parent.kind === 'constructor'
|
| 482 |
+
) {
|
| 483 |
+
addStateFields(unwrappedRight);
|
| 484 |
+
}
|
| 485 |
+
} else {
|
| 486 |
+
// Check for assignments like `alias = this.state` and record the alias.
|
| 487 |
+
handleAssignment(unwrappedLeft, unwrappedRight);
|
| 488 |
+
}
|
| 489 |
+
},
|
| 490 |
+
|
| 491 |
+
VariableDeclarator(node) {
|
| 492 |
+
if (!classInfo || !node.init) {
|
| 493 |
+
return;
|
| 494 |
+
}
|
| 495 |
+
handleAssignment(node.id, node.init);
|
| 496 |
+
},
|
| 497 |
+
|
| 498 |
+
'MemberExpression, OptionalMemberExpression'(node) {
|
| 499 |
+
if (!classInfo) {
|
| 500 |
+
return;
|
| 501 |
+
}
|
| 502 |
+
if (isStateReference(astUtil.unwrapTSAsExpression(node.object))) {
|
| 503 |
+
// If we see this.state[foo] access, give up.
|
| 504 |
+
if (node.computed && node.property.type !== 'Literal') {
|
| 505 |
+
classInfo = null;
|
| 506 |
+
return;
|
| 507 |
+
}
|
| 508 |
+
// Otherwise, record that we saw this property being accessed.
|
| 509 |
+
addUsedStateField(node.property);
|
| 510 |
+
// If we see a `this.state` access in a CallExpression, give up.
|
| 511 |
+
} else if (isStateReference(node) && astUtil.isCallExpression(node.parent)) {
|
| 512 |
+
classInfo = null;
|
| 513 |
+
}
|
| 514 |
+
},
|
| 515 |
+
|
| 516 |
+
JSXSpreadAttribute(node) {
|
| 517 |
+
if (classInfo && isStateReference(node.argument)) {
|
| 518 |
+
classInfo = null;
|
| 519 |
+
}
|
| 520 |
+
},
|
| 521 |
+
|
| 522 |
+
'ExperimentalSpreadProperty, SpreadElement'(node) {
|
| 523 |
+
if (classInfo && isStateReference(node.argument)) {
|
| 524 |
+
classInfo = null;
|
| 525 |
+
}
|
| 526 |
+
},
|
| 527 |
+
};
|
| 528 |
+
},
|
| 529 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/no-will-update-set-state.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=no-will-update-set-state.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/no-will-update-set-state.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"no-will-update-set-state.d.ts","sourceRoot":"","sources":["no-will-update-set-state.js"],"names":[],"mappings":"wBAUW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/no-will-update-set-state.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Prevent usage of setState in componentWillUpdate
|
| 3 |
+
* @author Yannick Croissant
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const makeNoMethodSetStateRule = require('../util/makeNoMethodSetStateRule');
|
| 9 |
+
const testReactVersion = require('../util/version').testReactVersion;
|
| 10 |
+
|
| 11 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 12 |
+
module.exports = makeNoMethodSetStateRule(
|
| 13 |
+
'componentWillUpdate',
|
| 14 |
+
(context) => testReactVersion(context, '>= 16.3.0')
|
| 15 |
+
);
|
node_modules/eslint-plugin-react/lib/rules/prefer-es6-class.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=prefer-es6-class.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/prefer-es6-class.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"prefer-es6-class.d.ts","sourceRoot":"","sources":["prefer-es6-class.js"],"names":[],"mappings":"wBAoBW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/prefer-es6-class.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Enforce ES5 or ES6 class for React Components
|
| 3 |
+
* @author Dan Hamilton
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const componentUtil = require('../util/componentUtil');
|
| 9 |
+
const docsUrl = require('../util/docsUrl');
|
| 10 |
+
const report = require('../util/report');
|
| 11 |
+
|
| 12 |
+
// ------------------------------------------------------------------------------
|
| 13 |
+
// Rule Definition
|
| 14 |
+
// ------------------------------------------------------------------------------
|
| 15 |
+
|
| 16 |
+
const messages = {
|
| 17 |
+
shouldUseES6Class: 'Component should use es6 class instead of createClass',
|
| 18 |
+
shouldUseCreateClass: 'Component should use createClass instead of es6 class',
|
| 19 |
+
};
|
| 20 |
+
|
| 21 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 22 |
+
module.exports = {
|
| 23 |
+
meta: {
|
| 24 |
+
docs: {
|
| 25 |
+
description: 'Enforce ES5 or ES6 class for React Components',
|
| 26 |
+
category: 'Stylistic Issues',
|
| 27 |
+
recommended: false,
|
| 28 |
+
url: docsUrl('prefer-es6-class'),
|
| 29 |
+
},
|
| 30 |
+
|
| 31 |
+
messages,
|
| 32 |
+
|
| 33 |
+
schema: [{
|
| 34 |
+
enum: ['always', 'never'],
|
| 35 |
+
}],
|
| 36 |
+
},
|
| 37 |
+
|
| 38 |
+
create(context) {
|
| 39 |
+
const configuration = context.options[0] || 'always';
|
| 40 |
+
|
| 41 |
+
return {
|
| 42 |
+
ObjectExpression(node) {
|
| 43 |
+
if (componentUtil.isES5Component(node, context) && configuration === 'always') {
|
| 44 |
+
report(context, messages.shouldUseES6Class, 'shouldUseES6Class', {
|
| 45 |
+
node,
|
| 46 |
+
});
|
| 47 |
+
}
|
| 48 |
+
},
|
| 49 |
+
ClassDeclaration(node) {
|
| 50 |
+
if (componentUtil.isES6Component(node, context) && configuration === 'never') {
|
| 51 |
+
report(context, messages.shouldUseCreateClass, 'shouldUseCreateClass', {
|
| 52 |
+
node,
|
| 53 |
+
});
|
| 54 |
+
}
|
| 55 |
+
},
|
| 56 |
+
};
|
| 57 |
+
},
|
| 58 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/prefer-exact-props.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=prefer-exact-props.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/prefer-exact-props.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"prefer-exact-props.d.ts","sourceRoot":"","sources":["prefer-exact-props.js"],"names":[],"mappings":"wBAwBW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/prefer-exact-props.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Prefer exact proptype definitions
|
| 3 |
+
*/
|
| 4 |
+
|
| 5 |
+
'use strict';
|
| 6 |
+
|
| 7 |
+
const Components = require('../util/Components');
|
| 8 |
+
const docsUrl = require('../util/docsUrl');
|
| 9 |
+
const astUtil = require('../util/ast');
|
| 10 |
+
const propsUtil = require('../util/props');
|
| 11 |
+
const propWrapperUtil = require('../util/propWrapper');
|
| 12 |
+
const variableUtil = require('../util/variable');
|
| 13 |
+
const report = require('../util/report');
|
| 14 |
+
const getText = require('../util/eslint').getText;
|
| 15 |
+
|
| 16 |
+
// -----------------------------------------------------------------------------
|
| 17 |
+
// Rule Definition
|
| 18 |
+
// -----------------------------------------------------------------------------
|
| 19 |
+
|
| 20 |
+
const messages = {
|
| 21 |
+
propTypes: 'Component propTypes should be exact by using {{exactPropWrappers}}.',
|
| 22 |
+
flow: 'Component flow props should be set with exact objects.',
|
| 23 |
+
};
|
| 24 |
+
|
| 25 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 26 |
+
module.exports = {
|
| 27 |
+
meta: {
|
| 28 |
+
docs: {
|
| 29 |
+
description: 'Prefer exact proptype definitions',
|
| 30 |
+
category: 'Possible Errors',
|
| 31 |
+
recommended: false,
|
| 32 |
+
url: docsUrl('prefer-exact-props'),
|
| 33 |
+
},
|
| 34 |
+
messages,
|
| 35 |
+
schema: [],
|
| 36 |
+
},
|
| 37 |
+
|
| 38 |
+
create: Components.detect((context, components, utils) => {
|
| 39 |
+
const typeAliases = {};
|
| 40 |
+
const exactWrappers = propWrapperUtil.getExactPropWrapperFunctions(context);
|
| 41 |
+
|
| 42 |
+
function getPropTypesErrorMessage() {
|
| 43 |
+
const formattedWrappers = propWrapperUtil.formatPropWrapperFunctions(exactWrappers);
|
| 44 |
+
const message = exactWrappers.size > 1 ? `one of ${formattedWrappers}` : formattedWrappers;
|
| 45 |
+
return { exactPropWrappers: message };
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
function isNonExactObjectTypeAnnotation(node) {
|
| 49 |
+
return (
|
| 50 |
+
node
|
| 51 |
+
&& node.type === 'ObjectTypeAnnotation'
|
| 52 |
+
&& node.properties.length > 0
|
| 53 |
+
&& !node.exact
|
| 54 |
+
);
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
function hasNonExactObjectTypeAnnotation(node) {
|
| 58 |
+
const typeAnnotation = node.typeAnnotation;
|
| 59 |
+
return (
|
| 60 |
+
typeAnnotation
|
| 61 |
+
&& typeAnnotation.typeAnnotation
|
| 62 |
+
&& isNonExactObjectTypeAnnotation(typeAnnotation.typeAnnotation)
|
| 63 |
+
);
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
function hasGenericTypeAnnotation(node) {
|
| 67 |
+
const typeAnnotation = node.typeAnnotation;
|
| 68 |
+
return (
|
| 69 |
+
typeAnnotation
|
| 70 |
+
&& typeAnnotation.typeAnnotation
|
| 71 |
+
&& typeAnnotation.typeAnnotation.type === 'GenericTypeAnnotation'
|
| 72 |
+
);
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
function isNonEmptyObjectExpression(node) {
|
| 76 |
+
return (
|
| 77 |
+
node
|
| 78 |
+
&& node.type === 'ObjectExpression'
|
| 79 |
+
&& node.properties.length > 0
|
| 80 |
+
);
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
function isNonExactPropWrapperFunction(node) {
|
| 84 |
+
return (
|
| 85 |
+
astUtil.isCallExpression(node)
|
| 86 |
+
&& !propWrapperUtil.isExactPropWrapperFunction(context, getText(context, node.callee))
|
| 87 |
+
);
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
function reportPropTypesError(node) {
|
| 91 |
+
report(context, messages.propTypes, 'propTypes', {
|
| 92 |
+
node,
|
| 93 |
+
data: getPropTypesErrorMessage(),
|
| 94 |
+
});
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
function reportFlowError(node) {
|
| 98 |
+
report(context, messages.flow, 'flow', {
|
| 99 |
+
node,
|
| 100 |
+
});
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
return {
|
| 104 |
+
TypeAlias(node) {
|
| 105 |
+
// working around an issue with eslint@3 and babel-eslint not finding the TypeAlias in scope
|
| 106 |
+
typeAliases[node.id.name] = node;
|
| 107 |
+
},
|
| 108 |
+
|
| 109 |
+
'ClassProperty, PropertyDefinition'(node) {
|
| 110 |
+
if (!propsUtil.isPropTypesDeclaration(node)) {
|
| 111 |
+
return;
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
if (hasNonExactObjectTypeAnnotation(node)) {
|
| 115 |
+
reportFlowError(node);
|
| 116 |
+
} else if (exactWrappers.size > 0 && isNonEmptyObjectExpression(node.value)) {
|
| 117 |
+
reportPropTypesError(node);
|
| 118 |
+
} else if (exactWrappers.size > 0 && isNonExactPropWrapperFunction(node.value)) {
|
| 119 |
+
reportPropTypesError(node);
|
| 120 |
+
}
|
| 121 |
+
},
|
| 122 |
+
|
| 123 |
+
Identifier(node) {
|
| 124 |
+
if (!utils.getStatelessComponent(node.parent)) {
|
| 125 |
+
return;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
if (hasNonExactObjectTypeAnnotation(node)) {
|
| 129 |
+
reportFlowError(node);
|
| 130 |
+
} else if (hasGenericTypeAnnotation(node)) {
|
| 131 |
+
const identifier = node.typeAnnotation.typeAnnotation.id.name;
|
| 132 |
+
const typeAlias = typeAliases[identifier];
|
| 133 |
+
const propsDefinition = typeAlias ? typeAlias.right : null;
|
| 134 |
+
if (isNonExactObjectTypeAnnotation(propsDefinition)) {
|
| 135 |
+
reportFlowError(node);
|
| 136 |
+
}
|
| 137 |
+
}
|
| 138 |
+
},
|
| 139 |
+
|
| 140 |
+
MemberExpression(node) {
|
| 141 |
+
if (!propsUtil.isPropTypesDeclaration(node) || exactWrappers.size === 0) {
|
| 142 |
+
return;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
const right = node.parent.right;
|
| 146 |
+
if (isNonEmptyObjectExpression(right)) {
|
| 147 |
+
reportPropTypesError(node);
|
| 148 |
+
} else if (isNonExactPropWrapperFunction(right)) {
|
| 149 |
+
reportPropTypesError(node);
|
| 150 |
+
} else if (right.type === 'Identifier') {
|
| 151 |
+
const identifier = right.name;
|
| 152 |
+
const propsDefinition = variableUtil.findVariableByName(context, node, identifier);
|
| 153 |
+
if (isNonEmptyObjectExpression(propsDefinition)) {
|
| 154 |
+
reportPropTypesError(node);
|
| 155 |
+
} else if (isNonExactPropWrapperFunction(propsDefinition)) {
|
| 156 |
+
reportPropTypesError(node);
|
| 157 |
+
}
|
| 158 |
+
}
|
| 159 |
+
},
|
| 160 |
+
};
|
| 161 |
+
}),
|
| 162 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/prefer-read-only-props.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=prefer-read-only-props.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/prefer-read-only-props.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"prefer-read-only-props.d.ts","sourceRoot":"","sources":["prefer-read-only-props.js"],"names":[],"mappings":"wBAiDW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/prefer-read-only-props.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Require component props to be typed as read-only.
|
| 3 |
+
* @author Luke Zapart
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const flatMap = require('array.prototype.flatmap');
|
| 9 |
+
const values = require('object.values');
|
| 10 |
+
|
| 11 |
+
const Components = require('../util/Components');
|
| 12 |
+
const docsUrl = require('../util/docsUrl');
|
| 13 |
+
const report = require('../util/report');
|
| 14 |
+
|
| 15 |
+
function isFlowPropertyType(node) {
|
| 16 |
+
return node.type === 'ObjectTypeProperty';
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
function isTypescriptPropertyType(node) {
|
| 20 |
+
return node.type === 'TSPropertySignature';
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
function isCovariant(node) {
|
| 24 |
+
return (node.variance && node.variance.kind === 'plus')
|
| 25 |
+
|| (
|
| 26 |
+
node.parent
|
| 27 |
+
&& node.parent.parent
|
| 28 |
+
&& node.parent.parent.parent
|
| 29 |
+
&& node.parent.parent.parent.id
|
| 30 |
+
&& node.parent.parent.parent.id.name === '$ReadOnly'
|
| 31 |
+
);
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
function isReadonly(node) {
|
| 35 |
+
return (
|
| 36 |
+
node.typeAnnotation
|
| 37 |
+
&& node.typeAnnotation.parent
|
| 38 |
+
&& node.typeAnnotation.parent.readonly
|
| 39 |
+
);
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
// ------------------------------------------------------------------------------
|
| 43 |
+
// Rule Definition
|
| 44 |
+
// ------------------------------------------------------------------------------
|
| 45 |
+
|
| 46 |
+
const messages = {
|
| 47 |
+
readOnlyProp: 'Prop \'{{name}}\' should be read-only.',
|
| 48 |
+
};
|
| 49 |
+
|
| 50 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 51 |
+
module.exports = {
|
| 52 |
+
meta: {
|
| 53 |
+
docs: {
|
| 54 |
+
description: 'Enforce that props are read-only',
|
| 55 |
+
category: 'Stylistic Issues',
|
| 56 |
+
recommended: false,
|
| 57 |
+
url: docsUrl('prefer-read-only-props'),
|
| 58 |
+
},
|
| 59 |
+
fixable: 'code',
|
| 60 |
+
|
| 61 |
+
messages,
|
| 62 |
+
|
| 63 |
+
schema: [],
|
| 64 |
+
},
|
| 65 |
+
|
| 66 |
+
create: Components.detect((context, components) => {
|
| 67 |
+
function reportReadOnlyProp(prop, propName, fixer) {
|
| 68 |
+
report(context, messages.readOnlyProp, 'readOnlyProp', {
|
| 69 |
+
node: prop.node,
|
| 70 |
+
data: {
|
| 71 |
+
name: propName,
|
| 72 |
+
},
|
| 73 |
+
fix: fixer,
|
| 74 |
+
});
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
return {
|
| 78 |
+
'Program:exit'() {
|
| 79 |
+
flatMap(
|
| 80 |
+
values(components.list()),
|
| 81 |
+
(component) => component.declaredPropTypes || []
|
| 82 |
+
).forEach((declaredPropTypes) => {
|
| 83 |
+
Object.keys(declaredPropTypes).forEach((propName) => {
|
| 84 |
+
const prop = declaredPropTypes[propName];
|
| 85 |
+
if (!prop.node) {
|
| 86 |
+
return;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
if (isFlowPropertyType(prop.node)) {
|
| 90 |
+
if (!isCovariant(prop.node)) {
|
| 91 |
+
reportReadOnlyProp(prop, propName, (fixer) => {
|
| 92 |
+
if (!prop.node.variance) {
|
| 93 |
+
// Insert covariance
|
| 94 |
+
return fixer.insertTextBefore(prop.node, '+');
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
// Replace contravariance with covariance
|
| 98 |
+
return fixer.replaceText(prop.node.variance, '+');
|
| 99 |
+
});
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
return;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
if (isTypescriptPropertyType(prop.node)) {
|
| 106 |
+
if (!isReadonly(prop.node)) {
|
| 107 |
+
reportReadOnlyProp(prop, propName, (fixer) => (
|
| 108 |
+
fixer.insertTextBefore(prop.node, 'readonly ')
|
| 109 |
+
));
|
| 110 |
+
}
|
| 111 |
+
}
|
| 112 |
+
});
|
| 113 |
+
});
|
| 114 |
+
},
|
| 115 |
+
};
|
| 116 |
+
}),
|
| 117 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/prefer-stateless-function.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=prefer-stateless-function.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/prefer-stateless-function.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"prefer-stateless-function.d.ts","sourceRoot":"","sources":["prefer-stateless-function.js"],"names":[],"mappings":"wBA8BW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/prefer-stateless-function.js
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Enforce stateless components to be written as a pure function
|
| 3 |
+
* @author Yannick Croissant
|
| 4 |
+
* @author Alberto Rodríguez
|
| 5 |
+
* @copyright 2015 Alberto Rodríguez. All rights reserved.
|
| 6 |
+
*/
|
| 7 |
+
|
| 8 |
+
'use strict';
|
| 9 |
+
|
| 10 |
+
const values = require('object.values');
|
| 11 |
+
|
| 12 |
+
const Components = require('../util/Components');
|
| 13 |
+
const testReactVersion = require('../util/version').testReactVersion;
|
| 14 |
+
const astUtil = require('../util/ast');
|
| 15 |
+
const componentUtil = require('../util/componentUtil');
|
| 16 |
+
const docsUrl = require('../util/docsUrl');
|
| 17 |
+
const report = require('../util/report');
|
| 18 |
+
const eslintUtil = require('../util/eslint');
|
| 19 |
+
|
| 20 |
+
const getScope = eslintUtil.getScope;
|
| 21 |
+
const getText = eslintUtil.getText;
|
| 22 |
+
|
| 23 |
+
// ------------------------------------------------------------------------------
|
| 24 |
+
// Rule Definition
|
| 25 |
+
// ------------------------------------------------------------------------------
|
| 26 |
+
|
| 27 |
+
const messages = {
|
| 28 |
+
componentShouldBePure: 'Component should be written as a pure function',
|
| 29 |
+
};
|
| 30 |
+
|
| 31 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 32 |
+
module.exports = {
|
| 33 |
+
meta: {
|
| 34 |
+
docs: {
|
| 35 |
+
description: 'Enforce stateless components to be written as a pure function',
|
| 36 |
+
category: 'Stylistic Issues',
|
| 37 |
+
recommended: false,
|
| 38 |
+
url: docsUrl('prefer-stateless-function'),
|
| 39 |
+
},
|
| 40 |
+
|
| 41 |
+
messages,
|
| 42 |
+
|
| 43 |
+
schema: [{
|
| 44 |
+
type: 'object',
|
| 45 |
+
properties: {
|
| 46 |
+
ignorePureComponents: {
|
| 47 |
+
default: false,
|
| 48 |
+
type: 'boolean',
|
| 49 |
+
},
|
| 50 |
+
},
|
| 51 |
+
additionalProperties: false,
|
| 52 |
+
}],
|
| 53 |
+
},
|
| 54 |
+
|
| 55 |
+
create: Components.detect((context, components, utils) => {
|
| 56 |
+
const configuration = context.options[0] || {};
|
| 57 |
+
const ignorePureComponents = configuration.ignorePureComponents || false;
|
| 58 |
+
|
| 59 |
+
// --------------------------------------------------------------------------
|
| 60 |
+
// Public
|
| 61 |
+
// --------------------------------------------------------------------------
|
| 62 |
+
|
| 63 |
+
/**
|
| 64 |
+
* Checks whether a given array of statements is a single call of `super`.
|
| 65 |
+
* @see eslint no-useless-constructor rule
|
| 66 |
+
* @param {ASTNode[]} body - An array of statements to check.
|
| 67 |
+
* @returns {boolean} `true` if the body is a single call of `super`.
|
| 68 |
+
*/
|
| 69 |
+
function isSingleSuperCall(body) {
|
| 70 |
+
return (
|
| 71 |
+
body.length === 1
|
| 72 |
+
&& body[0].type === 'ExpressionStatement'
|
| 73 |
+
&& astUtil.isCallExpression(body[0].expression)
|
| 74 |
+
&& body[0].expression.callee.type === 'Super'
|
| 75 |
+
);
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
/**
|
| 79 |
+
* Checks whether a given node is a pattern which doesn't have any side effects.
|
| 80 |
+
* Default parameters and Destructuring parameters can have side effects.
|
| 81 |
+
* @see eslint no-useless-constructor rule
|
| 82 |
+
* @param {ASTNode} node - A pattern node.
|
| 83 |
+
* @returns {boolean} `true` if the node doesn't have any side effects.
|
| 84 |
+
*/
|
| 85 |
+
function isSimple(node) {
|
| 86 |
+
return node.type === 'Identifier' || node.type === 'RestElement';
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
/**
|
| 90 |
+
* Checks whether a given array of expressions is `...arguments` or not.
|
| 91 |
+
* `super(...arguments)` passes all arguments through.
|
| 92 |
+
* @see eslint no-useless-constructor rule
|
| 93 |
+
* @param {ASTNode[]} superArgs - An array of expressions to check.
|
| 94 |
+
* @returns {boolean} `true` if the superArgs is `...arguments`.
|
| 95 |
+
*/
|
| 96 |
+
function isSpreadArguments(superArgs) {
|
| 97 |
+
return (
|
| 98 |
+
superArgs.length === 1
|
| 99 |
+
&& superArgs[0].type === 'SpreadElement'
|
| 100 |
+
&& superArgs[0].argument.type === 'Identifier'
|
| 101 |
+
&& superArgs[0].argument.name === 'arguments'
|
| 102 |
+
);
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
/**
|
| 106 |
+
* Checks whether given 2 nodes are identifiers which have the same name or not.
|
| 107 |
+
* @see eslint no-useless-constructor rule
|
| 108 |
+
* @param {ASTNode} ctorParam - A node to check.
|
| 109 |
+
* @param {ASTNode} superArg - A node to check.
|
| 110 |
+
* @returns {boolean} `true` if the nodes are identifiers which have the same
|
| 111 |
+
* name.
|
| 112 |
+
*/
|
| 113 |
+
function isValidIdentifierPair(ctorParam, superArg) {
|
| 114 |
+
return (
|
| 115 |
+
ctorParam.type === 'Identifier'
|
| 116 |
+
&& superArg.type === 'Identifier'
|
| 117 |
+
&& ctorParam.name === superArg.name
|
| 118 |
+
);
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
/**
|
| 122 |
+
* Checks whether given 2 nodes are a rest/spread pair which has the same values.
|
| 123 |
+
* @see eslint no-useless-constructor rule
|
| 124 |
+
* @param {ASTNode} ctorParam - A node to check.
|
| 125 |
+
* @param {ASTNode} superArg - A node to check.
|
| 126 |
+
* @returns {boolean} `true` if the nodes are a rest/spread pair which has the
|
| 127 |
+
* same values.
|
| 128 |
+
*/
|
| 129 |
+
function isValidRestSpreadPair(ctorParam, superArg) {
|
| 130 |
+
return (
|
| 131 |
+
ctorParam.type === 'RestElement'
|
| 132 |
+
&& superArg.type === 'SpreadElement'
|
| 133 |
+
&& isValidIdentifierPair(ctorParam.argument, superArg.argument)
|
| 134 |
+
);
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
/**
|
| 138 |
+
* Checks whether given 2 nodes have the same value or not.
|
| 139 |
+
* @see eslint no-useless-constructor rule
|
| 140 |
+
* @param {ASTNode} ctorParam - A node to check.
|
| 141 |
+
* @param {ASTNode} superArg - A node to check.
|
| 142 |
+
* @returns {boolean} `true` if the nodes have the same value or not.
|
| 143 |
+
*/
|
| 144 |
+
function isValidPair(ctorParam, superArg) {
|
| 145 |
+
return (
|
| 146 |
+
isValidIdentifierPair(ctorParam, superArg)
|
| 147 |
+
|| isValidRestSpreadPair(ctorParam, superArg)
|
| 148 |
+
);
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
/**
|
| 152 |
+
* Checks whether the parameters of a constructor and the arguments of `super()`
|
| 153 |
+
* have the same values or not.
|
| 154 |
+
* @see eslint no-useless-constructor rule
|
| 155 |
+
* @param {ASTNode[]} ctorParams - The parameters of a constructor to check.
|
| 156 |
+
* @param {ASTNode} superArgs - The arguments of `super()` to check.
|
| 157 |
+
* @returns {boolean} `true` if those have the same values.
|
| 158 |
+
*/
|
| 159 |
+
function isPassingThrough(ctorParams, superArgs) {
|
| 160 |
+
if (ctorParams.length !== superArgs.length) {
|
| 161 |
+
return false;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
for (let i = 0; i < ctorParams.length; ++i) {
|
| 165 |
+
if (!isValidPair(ctorParams[i], superArgs[i])) {
|
| 166 |
+
return false;
|
| 167 |
+
}
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
return true;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
/**
|
| 174 |
+
* Checks whether the constructor body is a redundant super call.
|
| 175 |
+
* @see eslint no-useless-constructor rule
|
| 176 |
+
* @param {Array} body - constructor body content.
|
| 177 |
+
* @param {Array} ctorParams - The params to check against super call.
|
| 178 |
+
* @returns {boolean} true if the constructor body is redundant
|
| 179 |
+
*/
|
| 180 |
+
function isRedundantSuperCall(body, ctorParams) {
|
| 181 |
+
return (
|
| 182 |
+
isSingleSuperCall(body)
|
| 183 |
+
&& ctorParams.every(isSimple)
|
| 184 |
+
&& (
|
| 185 |
+
isSpreadArguments(body[0].expression.arguments)
|
| 186 |
+
|| isPassingThrough(ctorParams, body[0].expression.arguments)
|
| 187 |
+
)
|
| 188 |
+
);
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
/**
|
| 192 |
+
* Check if a given AST node have any other properties the ones available in stateless components
|
| 193 |
+
* @param {ASTNode} node The AST node being checked.
|
| 194 |
+
* @returns {boolean} True if the node has at least one other property, false if not.
|
| 195 |
+
*/
|
| 196 |
+
function hasOtherProperties(node) {
|
| 197 |
+
const properties = astUtil.getComponentProperties(node);
|
| 198 |
+
return properties.some((property) => {
|
| 199 |
+
const name = astUtil.getPropertyName(property);
|
| 200 |
+
const isDisplayName = name === 'displayName';
|
| 201 |
+
const isPropTypes = name === 'propTypes' || ((name === 'props') && property.typeAnnotation);
|
| 202 |
+
const contextTypes = name === 'contextTypes';
|
| 203 |
+
const defaultProps = name === 'defaultProps';
|
| 204 |
+
const isUselessConstructor = property.kind === 'constructor'
|
| 205 |
+
&& !!property.value.body
|
| 206 |
+
&& isRedundantSuperCall(property.value.body.body, property.value.params);
|
| 207 |
+
const isRender = name === 'render';
|
| 208 |
+
return !isDisplayName && !isPropTypes && !contextTypes && !defaultProps && !isUselessConstructor && !isRender;
|
| 209 |
+
});
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
/**
|
| 213 |
+
* Mark component as pure as declared
|
| 214 |
+
* @param {ASTNode} node The AST node being checked.
|
| 215 |
+
*/
|
| 216 |
+
function markSCUAsDeclared(node) {
|
| 217 |
+
components.set(node, {
|
| 218 |
+
hasSCU: true,
|
| 219 |
+
});
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
/**
|
| 223 |
+
* Mark childContextTypes as declared
|
| 224 |
+
* @param {ASTNode} node The AST node being checked.
|
| 225 |
+
*/
|
| 226 |
+
function markChildContextTypesAsDeclared(node) {
|
| 227 |
+
components.set(node, {
|
| 228 |
+
hasChildContextTypes: true,
|
| 229 |
+
});
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
/**
|
| 233 |
+
* Mark a setState as used
|
| 234 |
+
* @param {ASTNode} node The AST node being checked.
|
| 235 |
+
*/
|
| 236 |
+
function markThisAsUsed(node) {
|
| 237 |
+
components.set(node, {
|
| 238 |
+
useThis: true,
|
| 239 |
+
});
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
/**
|
| 243 |
+
* Mark a props or context as used
|
| 244 |
+
* @param {ASTNode} node The AST node being checked.
|
| 245 |
+
*/
|
| 246 |
+
function markPropsOrContextAsUsed(node) {
|
| 247 |
+
components.set(node, {
|
| 248 |
+
usePropsOrContext: true,
|
| 249 |
+
});
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
/**
|
| 253 |
+
* Mark a ref as used
|
| 254 |
+
* @param {ASTNode} node The AST node being checked.
|
| 255 |
+
*/
|
| 256 |
+
function markRefAsUsed(node) {
|
| 257 |
+
components.set(node, {
|
| 258 |
+
useRef: true,
|
| 259 |
+
});
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
/**
|
| 263 |
+
* Mark return as invalid
|
| 264 |
+
* @param {ASTNode} node The AST node being checked.
|
| 265 |
+
*/
|
| 266 |
+
function markReturnAsInvalid(node) {
|
| 267 |
+
components.set(node, {
|
| 268 |
+
invalidReturn: true,
|
| 269 |
+
});
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
/**
|
| 273 |
+
* Mark a ClassDeclaration as having used decorators
|
| 274 |
+
* @param {ASTNode} node The AST node being checked.
|
| 275 |
+
*/
|
| 276 |
+
function markDecoratorsAsUsed(node) {
|
| 277 |
+
components.set(node, {
|
| 278 |
+
useDecorators: true,
|
| 279 |
+
});
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
function visitClass(node) {
|
| 283 |
+
if (ignorePureComponents && componentUtil.isPureComponent(node, context)) {
|
| 284 |
+
markSCUAsDeclared(node);
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
if (node.decorators && node.decorators.length) {
|
| 288 |
+
markDecoratorsAsUsed(node);
|
| 289 |
+
}
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
return {
|
| 293 |
+
ClassDeclaration: visitClass,
|
| 294 |
+
ClassExpression: visitClass,
|
| 295 |
+
|
| 296 |
+
// Mark `this` destructuring as a usage of `this`
|
| 297 |
+
VariableDeclarator(node) {
|
| 298 |
+
// Ignore destructuring on other than `this`
|
| 299 |
+
if (!node.id || node.id.type !== 'ObjectPattern' || !node.init || node.init.type !== 'ThisExpression') {
|
| 300 |
+
return;
|
| 301 |
+
}
|
| 302 |
+
// Ignore `props` and `context`
|
| 303 |
+
const useThis = node.id.properties.some((property) => {
|
| 304 |
+
const name = astUtil.getPropertyName(property);
|
| 305 |
+
return name !== 'props' && name !== 'context';
|
| 306 |
+
});
|
| 307 |
+
if (!useThis) {
|
| 308 |
+
markPropsOrContextAsUsed(node);
|
| 309 |
+
return;
|
| 310 |
+
}
|
| 311 |
+
markThisAsUsed(node);
|
| 312 |
+
},
|
| 313 |
+
|
| 314 |
+
// Mark `this` usage
|
| 315 |
+
MemberExpression(node) {
|
| 316 |
+
if (node.object.type !== 'ThisExpression') {
|
| 317 |
+
if (node.property && node.property.name === 'childContextTypes') {
|
| 318 |
+
const component = utils.getRelatedComponent(node);
|
| 319 |
+
if (!component) {
|
| 320 |
+
return;
|
| 321 |
+
}
|
| 322 |
+
markChildContextTypesAsDeclared(component.node);
|
| 323 |
+
}
|
| 324 |
+
return;
|
| 325 |
+
// Ignore calls to `this.props` and `this.context`
|
| 326 |
+
}
|
| 327 |
+
if (
|
| 328 |
+
(node.property.name || node.property.value) === 'props'
|
| 329 |
+
|| (node.property.name || node.property.value) === 'context'
|
| 330 |
+
) {
|
| 331 |
+
markPropsOrContextAsUsed(node);
|
| 332 |
+
return;
|
| 333 |
+
}
|
| 334 |
+
markThisAsUsed(node);
|
| 335 |
+
},
|
| 336 |
+
|
| 337 |
+
// Mark `ref` usage
|
| 338 |
+
JSXAttribute(node) {
|
| 339 |
+
const name = getText(context, node.name);
|
| 340 |
+
if (name !== 'ref') {
|
| 341 |
+
return;
|
| 342 |
+
}
|
| 343 |
+
markRefAsUsed(node);
|
| 344 |
+
},
|
| 345 |
+
|
| 346 |
+
// Mark `render` that do not return some JSX
|
| 347 |
+
ReturnStatement(node) {
|
| 348 |
+
let blockNode;
|
| 349 |
+
let scope = getScope(context, node);
|
| 350 |
+
while (scope) {
|
| 351 |
+
blockNode = scope.block && scope.block.parent;
|
| 352 |
+
if (blockNode && (blockNode.type === 'MethodDefinition' || blockNode.type === 'Property')) {
|
| 353 |
+
break;
|
| 354 |
+
}
|
| 355 |
+
scope = scope.upper;
|
| 356 |
+
}
|
| 357 |
+
const isRender = blockNode
|
| 358 |
+
&& blockNode.key
|
| 359 |
+
&& blockNode.key.name === 'render';
|
| 360 |
+
const allowNull = testReactVersion(context, '>= 15.0.0'); // Stateless components can return null since React 15
|
| 361 |
+
const isReturningJSX = utils.isReturningJSX(node, !allowNull);
|
| 362 |
+
const isReturningNull = node.argument && (node.argument.value === null || node.argument.value === false);
|
| 363 |
+
if (
|
| 364 |
+
!isRender
|
| 365 |
+
|| (allowNull && (isReturningJSX || isReturningNull))
|
| 366 |
+
|| (!allowNull && isReturningJSX)
|
| 367 |
+
) {
|
| 368 |
+
return;
|
| 369 |
+
}
|
| 370 |
+
markReturnAsInvalid(node);
|
| 371 |
+
},
|
| 372 |
+
|
| 373 |
+
'Program:exit'() {
|
| 374 |
+
const list = components.list();
|
| 375 |
+
values(list)
|
| 376 |
+
.filter((component) => (
|
| 377 |
+
!hasOtherProperties(component.node)
|
| 378 |
+
&& !component.useThis
|
| 379 |
+
&& !component.useRef
|
| 380 |
+
&& !component.invalidReturn
|
| 381 |
+
&& !component.hasChildContextTypes
|
| 382 |
+
&& !component.useDecorators
|
| 383 |
+
&& !component.hasSCU
|
| 384 |
+
&& (
|
| 385 |
+
componentUtil.isES5Component(component.node, context)
|
| 386 |
+
|| componentUtil.isES6Component(component.node, context)
|
| 387 |
+
)
|
| 388 |
+
))
|
| 389 |
+
.forEach((component) => {
|
| 390 |
+
report(context, messages.componentShouldBePure, 'componentShouldBePure', {
|
| 391 |
+
node: component.node,
|
| 392 |
+
});
|
| 393 |
+
});
|
| 394 |
+
},
|
| 395 |
+
};
|
| 396 |
+
}),
|
| 397 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/prop-types.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=prop-types.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/prop-types.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"prop-types.d.ts","sourceRoot":"","sources":["prop-types.js"],"names":[],"mappings":"wBAwBW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/prop-types.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Prevent missing props validation in a React component definition
|
| 3 |
+
* @author Yannick Croissant
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
// As for exceptions for props.children or props.className (and alike) look at
|
| 9 |
+
// https://github.com/jsx-eslint/eslint-plugin-react/issues/7
|
| 10 |
+
|
| 11 |
+
const values = require('object.values');
|
| 12 |
+
|
| 13 |
+
const Components = require('../util/Components');
|
| 14 |
+
const docsUrl = require('../util/docsUrl');
|
| 15 |
+
const report = require('../util/report');
|
| 16 |
+
|
| 17 |
+
// ------------------------------------------------------------------------------
|
| 18 |
+
// Rule Definition
|
| 19 |
+
// ------------------------------------------------------------------------------
|
| 20 |
+
|
| 21 |
+
const messages = {
|
| 22 |
+
missingPropType: '\'{{name}}\' is missing in props validation',
|
| 23 |
+
};
|
| 24 |
+
|
| 25 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 26 |
+
module.exports = {
|
| 27 |
+
meta: {
|
| 28 |
+
docs: {
|
| 29 |
+
description: 'Disallow missing props validation in a React component definition',
|
| 30 |
+
category: 'Best Practices',
|
| 31 |
+
recommended: true,
|
| 32 |
+
url: docsUrl('prop-types'),
|
| 33 |
+
},
|
| 34 |
+
|
| 35 |
+
messages,
|
| 36 |
+
|
| 37 |
+
schema: [{
|
| 38 |
+
type: 'object',
|
| 39 |
+
properties: {
|
| 40 |
+
ignore: {
|
| 41 |
+
type: 'array',
|
| 42 |
+
items: {
|
| 43 |
+
type: 'string',
|
| 44 |
+
},
|
| 45 |
+
},
|
| 46 |
+
customValidators: {
|
| 47 |
+
type: 'array',
|
| 48 |
+
items: {
|
| 49 |
+
type: 'string',
|
| 50 |
+
},
|
| 51 |
+
},
|
| 52 |
+
skipUndeclared: {
|
| 53 |
+
type: 'boolean',
|
| 54 |
+
},
|
| 55 |
+
},
|
| 56 |
+
additionalProperties: false,
|
| 57 |
+
}],
|
| 58 |
+
},
|
| 59 |
+
|
| 60 |
+
create: Components.detect((context, components) => {
|
| 61 |
+
const configuration = context.options[0] || {};
|
| 62 |
+
const ignored = configuration.ignore || [];
|
| 63 |
+
const skipUndeclared = configuration.skipUndeclared || false;
|
| 64 |
+
|
| 65 |
+
/**
|
| 66 |
+
* Checks if the prop is ignored
|
| 67 |
+
* @param {string} name Name of the prop to check.
|
| 68 |
+
* @returns {boolean} True if the prop is ignored, false if not.
|
| 69 |
+
*/
|
| 70 |
+
function isIgnored(name) {
|
| 71 |
+
return ignored.indexOf(name) !== -1;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
/**
|
| 75 |
+
* Checks if the component must be validated
|
| 76 |
+
* @param {Object} component The component to process
|
| 77 |
+
* @returns {boolean} True if the component must be validated, false if not.
|
| 78 |
+
*/
|
| 79 |
+
function mustBeValidated(component) {
|
| 80 |
+
const isSkippedByConfig = skipUndeclared && typeof component.declaredPropTypes === 'undefined';
|
| 81 |
+
return !!(
|
| 82 |
+
component
|
| 83 |
+
&& component.usedPropTypes
|
| 84 |
+
&& !component.ignorePropsValidation
|
| 85 |
+
&& !isSkippedByConfig
|
| 86 |
+
);
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
/**
|
| 90 |
+
* Internal: Checks if the prop is declared
|
| 91 |
+
* @param {Object} declaredPropTypes Description of propTypes declared in the current component
|
| 92 |
+
* @param {string[]} keyList Dot separated name of the prop to check.
|
| 93 |
+
* @returns {boolean} True if the prop is declared, false if not.
|
| 94 |
+
*/
|
| 95 |
+
function internalIsDeclaredInComponent(declaredPropTypes, keyList) {
|
| 96 |
+
for (let i = 0, j = keyList.length; i < j; i++) {
|
| 97 |
+
const key = keyList[i];
|
| 98 |
+
const propType = (
|
| 99 |
+
declaredPropTypes && (
|
| 100 |
+
// Check if this key is declared
|
| 101 |
+
(declaredPropTypes[key] // If not, check if this type accepts any key
|
| 102 |
+
|| declaredPropTypes.__ANY_KEY__) // eslint-disable-line no-underscore-dangle
|
| 103 |
+
)
|
| 104 |
+
);
|
| 105 |
+
|
| 106 |
+
if (!propType) {
|
| 107 |
+
// If it's a computed property, we can't make any further analysis, but is valid
|
| 108 |
+
return key === '__COMPUTED_PROP__';
|
| 109 |
+
}
|
| 110 |
+
if (typeof propType === 'object' && !propType.type) {
|
| 111 |
+
return true;
|
| 112 |
+
}
|
| 113 |
+
// Consider every children as declared
|
| 114 |
+
if (propType.children === true || propType.containsUnresolvedSpread || propType.containsIndexers) {
|
| 115 |
+
return true;
|
| 116 |
+
}
|
| 117 |
+
if (propType.acceptedProperties) {
|
| 118 |
+
return key in propType.acceptedProperties;
|
| 119 |
+
}
|
| 120 |
+
if (propType.type === 'union') {
|
| 121 |
+
// If we fall in this case, we know there is at least one complex type in the union
|
| 122 |
+
if (i + 1 >= j) {
|
| 123 |
+
// this is the last key, accept everything
|
| 124 |
+
return true;
|
| 125 |
+
}
|
| 126 |
+
// non trivial, check all of them
|
| 127 |
+
const unionTypes = propType.children;
|
| 128 |
+
const unionPropType = {};
|
| 129 |
+
for (let k = 0, z = unionTypes.length; k < z; k++) {
|
| 130 |
+
unionPropType[key] = unionTypes[k];
|
| 131 |
+
const isValid = internalIsDeclaredInComponent(
|
| 132 |
+
unionPropType,
|
| 133 |
+
keyList.slice(i)
|
| 134 |
+
);
|
| 135 |
+
if (isValid) {
|
| 136 |
+
return true;
|
| 137 |
+
}
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
// every possible union were invalid
|
| 141 |
+
return false;
|
| 142 |
+
}
|
| 143 |
+
declaredPropTypes = propType.children;
|
| 144 |
+
}
|
| 145 |
+
return true;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
/**
|
| 149 |
+
* Checks if the prop is declared
|
| 150 |
+
* @param {ASTNode} node The AST node being checked.
|
| 151 |
+
* @param {string[]} names List of names of the prop to check.
|
| 152 |
+
* @returns {boolean} True if the prop is declared, false if not.
|
| 153 |
+
*/
|
| 154 |
+
function isDeclaredInComponent(node, names) {
|
| 155 |
+
while (node) {
|
| 156 |
+
const component = components.get(node);
|
| 157 |
+
|
| 158 |
+
const isDeclared = component && component.confidence >= 2
|
| 159 |
+
&& internalIsDeclaredInComponent(component.declaredPropTypes || {}, names);
|
| 160 |
+
|
| 161 |
+
if (isDeclared) {
|
| 162 |
+
return true;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
node = node.parent;
|
| 166 |
+
}
|
| 167 |
+
return false;
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
/**
|
| 171 |
+
* Reports undeclared proptypes for a given component
|
| 172 |
+
* @param {Object} component The component to process
|
| 173 |
+
*/
|
| 174 |
+
function reportUndeclaredPropTypes(component) {
|
| 175 |
+
const undeclareds = component.usedPropTypes.filter((propType) => (
|
| 176 |
+
propType.node
|
| 177 |
+
&& !isIgnored(propType.allNames[0])
|
| 178 |
+
&& !isDeclaredInComponent(component.node, propType.allNames)
|
| 179 |
+
));
|
| 180 |
+
undeclareds.forEach((propType) => {
|
| 181 |
+
report(context, messages.missingPropType, 'missingPropType', {
|
| 182 |
+
node: propType.node,
|
| 183 |
+
data: {
|
| 184 |
+
name: propType.allNames.join('.').replace(/\.__COMPUTED_PROP__/g, '[]'),
|
| 185 |
+
},
|
| 186 |
+
});
|
| 187 |
+
});
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
/**
|
| 191 |
+
* @param {Object} component The current component to process
|
| 192 |
+
* @param {Array} list The all components to process
|
| 193 |
+
* @returns {boolean} True if the component is nested False if not.
|
| 194 |
+
*/
|
| 195 |
+
function checkNestedComponent(component, list) {
|
| 196 |
+
const componentIsMemo = component.node.callee && component.node.callee.name === 'memo';
|
| 197 |
+
const argumentIsForwardRef = component.node.arguments && component.node.arguments[0].callee && component.node.arguments[0].callee.name === 'forwardRef';
|
| 198 |
+
if (componentIsMemo && argumentIsForwardRef) {
|
| 199 |
+
const forwardComponent = list.find(
|
| 200 |
+
(innerComponent) => (
|
| 201 |
+
innerComponent.node.range[0] === component.node.arguments[0].range[0]
|
| 202 |
+
&& innerComponent.node.range[0] === component.node.arguments[0].range[0]
|
| 203 |
+
));
|
| 204 |
+
|
| 205 |
+
const isValidated = mustBeValidated(forwardComponent);
|
| 206 |
+
const isIgnorePropsValidation = forwardComponent.ignorePropsValidation;
|
| 207 |
+
|
| 208 |
+
return isIgnorePropsValidation || isValidated;
|
| 209 |
+
}
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
return {
|
| 213 |
+
'Program:exit'() {
|
| 214 |
+
const list = components.list();
|
| 215 |
+
// Report undeclared proptypes for all classes
|
| 216 |
+
values(list)
|
| 217 |
+
.filter((component) => mustBeValidated(component))
|
| 218 |
+
.forEach((component) => {
|
| 219 |
+
if (checkNestedComponent(component, values(list))) return;
|
| 220 |
+
reportUndeclaredPropTypes(component);
|
| 221 |
+
});
|
| 222 |
+
},
|
| 223 |
+
};
|
| 224 |
+
}),
|
| 225 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/react-in-jsx-scope.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=react-in-jsx-scope.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/react-in-jsx-scope.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"react-in-jsx-scope.d.ts","sourceRoot":"","sources":["react-in-jsx-scope.js"],"names":[],"mappings":"wBAoBW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/react-in-jsx-scope.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Prevent missing React when using JSX
|
| 3 |
+
* @author Glen Mailer
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const variableUtil = require('../util/variable');
|
| 9 |
+
const pragmaUtil = require('../util/pragma');
|
| 10 |
+
const docsUrl = require('../util/docsUrl');
|
| 11 |
+
const report = require('../util/report');
|
| 12 |
+
|
| 13 |
+
// -----------------------------------------------------------------------------
|
| 14 |
+
// Rule Definition
|
| 15 |
+
// -----------------------------------------------------------------------------
|
| 16 |
+
|
| 17 |
+
const messages = {
|
| 18 |
+
notInScope: '\'{{name}}\' must be in scope when using JSX',
|
| 19 |
+
};
|
| 20 |
+
|
| 21 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 22 |
+
module.exports = {
|
| 23 |
+
meta: {
|
| 24 |
+
docs: {
|
| 25 |
+
description: 'Disallow missing React when using JSX',
|
| 26 |
+
category: 'Possible Errors',
|
| 27 |
+
recommended: true,
|
| 28 |
+
url: docsUrl('react-in-jsx-scope'),
|
| 29 |
+
},
|
| 30 |
+
|
| 31 |
+
messages,
|
| 32 |
+
|
| 33 |
+
schema: [],
|
| 34 |
+
},
|
| 35 |
+
|
| 36 |
+
create(context) {
|
| 37 |
+
const pragma = pragmaUtil.getFromContext(context);
|
| 38 |
+
|
| 39 |
+
function checkIfReactIsInScope(node) {
|
| 40 |
+
if (variableUtil.getVariableFromContext(context, node, pragma)) {
|
| 41 |
+
return;
|
| 42 |
+
}
|
| 43 |
+
report(context, messages.notInScope, 'notInScope', {
|
| 44 |
+
node,
|
| 45 |
+
data: {
|
| 46 |
+
name: pragma,
|
| 47 |
+
},
|
| 48 |
+
});
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
return {
|
| 52 |
+
JSXOpeningElement: checkIfReactIsInScope,
|
| 53 |
+
JSXOpeningFragment: checkIfReactIsInScope,
|
| 54 |
+
};
|
| 55 |
+
},
|
| 56 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/require-default-props.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=require-default-props.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/require-default-props.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"require-default-props.d.ts","sourceRoot":"","sources":["require-default-props.js"],"names":[],"mappings":"wBAiCW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/require-default-props.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileOverview Enforce a defaultProps definition for every prop that is not a required prop.
|
| 3 |
+
* @author Vitor Balocco
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const entries = require('object.entries');
|
| 9 |
+
const values = require('object.values');
|
| 10 |
+
const Components = require('../util/Components');
|
| 11 |
+
const docsUrl = require('../util/docsUrl');
|
| 12 |
+
const astUtil = require('../util/ast');
|
| 13 |
+
const report = require('../util/report');
|
| 14 |
+
|
| 15 |
+
// ------------------------------------------------------------------------------
|
| 16 |
+
// Rule Definition
|
| 17 |
+
// ------------------------------------------------------------------------------
|
| 18 |
+
|
| 19 |
+
const messages = {
|
| 20 |
+
noDefaultWithRequired: 'propType "{{name}}" is required and should not have a defaultProps declaration.',
|
| 21 |
+
shouldHaveDefault: 'propType "{{name}}" is not required, but has no corresponding defaultProps declaration.',
|
| 22 |
+
noDefaultPropsWithFunction: 'Don’t use defaultProps with function components.',
|
| 23 |
+
shouldAssignObjectDefault: 'propType "{{name}}" is not required, but has no corresponding default argument value.',
|
| 24 |
+
destructureInSignature: 'Must destructure props in the function signature to initialize an optional prop.',
|
| 25 |
+
};
|
| 26 |
+
|
| 27 |
+
function isPropWithNoDefaulVal(prop) {
|
| 28 |
+
if (prop.type === 'RestElement' || prop.type === 'ExperimentalRestProperty') {
|
| 29 |
+
return false;
|
| 30 |
+
}
|
| 31 |
+
return prop.value.type !== 'AssignmentPattern';
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 35 |
+
module.exports = {
|
| 36 |
+
meta: {
|
| 37 |
+
docs: {
|
| 38 |
+
description: 'Enforce a defaultProps definition for every prop that is not a required prop',
|
| 39 |
+
category: 'Best Practices',
|
| 40 |
+
url: docsUrl('require-default-props'),
|
| 41 |
+
},
|
| 42 |
+
|
| 43 |
+
messages,
|
| 44 |
+
|
| 45 |
+
schema: [{
|
| 46 |
+
type: 'object',
|
| 47 |
+
properties: {
|
| 48 |
+
forbidDefaultForRequired: {
|
| 49 |
+
type: 'boolean',
|
| 50 |
+
},
|
| 51 |
+
classes: {
|
| 52 |
+
enum: ['defaultProps', 'ignore'],
|
| 53 |
+
},
|
| 54 |
+
functions: {
|
| 55 |
+
enum: ['defaultArguments', 'defaultProps', 'ignore'],
|
| 56 |
+
},
|
| 57 |
+
/**
|
| 58 |
+
* @deprecated
|
| 59 |
+
*/
|
| 60 |
+
ignoreFunctionalComponents: {
|
| 61 |
+
type: 'boolean',
|
| 62 |
+
},
|
| 63 |
+
},
|
| 64 |
+
additionalProperties: false,
|
| 65 |
+
}],
|
| 66 |
+
},
|
| 67 |
+
|
| 68 |
+
create: Components.detect((context, components) => {
|
| 69 |
+
const configuration = context.options[0] || {};
|
| 70 |
+
const forbidDefaultForRequired = configuration.forbidDefaultForRequired || false;
|
| 71 |
+
const classes = configuration.classes || 'defaultProps';
|
| 72 |
+
/**
|
| 73 |
+
* @todo
|
| 74 |
+
* - Remove ignoreFunctionalComponents
|
| 75 |
+
* - Change default to 'defaultArguments'
|
| 76 |
+
*/
|
| 77 |
+
const functions = configuration.ignoreFunctionalComponents
|
| 78 |
+
? 'ignore'
|
| 79 |
+
: configuration.functions || 'defaultProps';
|
| 80 |
+
|
| 81 |
+
/**
|
| 82 |
+
* Reports all propTypes passed in that don't have a defaultProps counterpart.
|
| 83 |
+
* @param {Object[]} propTypes List of propTypes to check.
|
| 84 |
+
* @param {Object} defaultProps Object of defaultProps to check. Keys are the props names.
|
| 85 |
+
* @return {void}
|
| 86 |
+
*/
|
| 87 |
+
function reportPropTypesWithoutDefault(propTypes, defaultProps) {
|
| 88 |
+
entries(propTypes).forEach((propType) => {
|
| 89 |
+
const propName = propType[0];
|
| 90 |
+
const prop = propType[1];
|
| 91 |
+
|
| 92 |
+
if (!prop.node) {
|
| 93 |
+
return;
|
| 94 |
+
}
|
| 95 |
+
if (prop.isRequired) {
|
| 96 |
+
if (forbidDefaultForRequired && defaultProps[propName]) {
|
| 97 |
+
report(context, messages.noDefaultWithRequired, 'noDefaultWithRequired', {
|
| 98 |
+
node: prop.node,
|
| 99 |
+
data: { name: propName },
|
| 100 |
+
});
|
| 101 |
+
}
|
| 102 |
+
return;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
if (defaultProps[propName]) {
|
| 106 |
+
return;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
report(context, messages.shouldHaveDefault, 'shouldHaveDefault', {
|
| 110 |
+
node: prop.node,
|
| 111 |
+
data: { name: propName },
|
| 112 |
+
});
|
| 113 |
+
});
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
/**
|
| 117 |
+
* If functions option is 'defaultArguments', reports defaultProps is used and all params that doesn't initialized.
|
| 118 |
+
* @param {Object} componentNode Node of component.
|
| 119 |
+
* @param {Object[]} declaredPropTypes List of propTypes to check `isRequired`.
|
| 120 |
+
* @param {Object} defaultProps Object of defaultProps to check used.
|
| 121 |
+
*/
|
| 122 |
+
function reportFunctionComponent(componentNode, declaredPropTypes, defaultProps) {
|
| 123 |
+
if (defaultProps) {
|
| 124 |
+
report(context, messages.noDefaultPropsWithFunction, 'noDefaultPropsWithFunction', {
|
| 125 |
+
node: componentNode,
|
| 126 |
+
});
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
const props = componentNode.params[0];
|
| 130 |
+
const propTypes = declaredPropTypes;
|
| 131 |
+
|
| 132 |
+
if (!props) {
|
| 133 |
+
return;
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
if (props.type === 'Identifier') {
|
| 137 |
+
const hasOptionalProp = values(propTypes).some((propType) => !propType.isRequired);
|
| 138 |
+
if (hasOptionalProp) {
|
| 139 |
+
report(context, messages.destructureInSignature, 'destructureInSignature', {
|
| 140 |
+
node: props,
|
| 141 |
+
});
|
| 142 |
+
}
|
| 143 |
+
} else if (props.type === 'ObjectPattern') {
|
| 144 |
+
// Filter required props with default value and report error
|
| 145 |
+
props.properties.filter((prop) => {
|
| 146 |
+
const propName = prop && prop.key && prop.key.name;
|
| 147 |
+
const isPropRequired = propTypes[propName] && propTypes[propName].isRequired;
|
| 148 |
+
return propTypes[propName] && isPropRequired && !isPropWithNoDefaulVal(prop);
|
| 149 |
+
}).forEach((prop) => {
|
| 150 |
+
report(context, messages.noDefaultWithRequired, 'noDefaultWithRequired', {
|
| 151 |
+
node: prop,
|
| 152 |
+
data: { name: prop.key.name },
|
| 153 |
+
});
|
| 154 |
+
});
|
| 155 |
+
|
| 156 |
+
// Filter non required props with no default value and report error
|
| 157 |
+
props.properties.filter((prop) => {
|
| 158 |
+
const propName = prop && prop.key && prop.key.name;
|
| 159 |
+
const isPropRequired = propTypes[propName] && propTypes[propName].isRequired;
|
| 160 |
+
return propTypes[propName] && !isPropRequired && isPropWithNoDefaulVal(prop);
|
| 161 |
+
}).forEach((prop) => {
|
| 162 |
+
report(context, messages.shouldAssignObjectDefault, 'shouldAssignObjectDefault', {
|
| 163 |
+
node: prop,
|
| 164 |
+
data: { name: prop.key.name },
|
| 165 |
+
});
|
| 166 |
+
});
|
| 167 |
+
}
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
// --------------------------------------------------------------------------
|
| 171 |
+
// Public API
|
| 172 |
+
// --------------------------------------------------------------------------
|
| 173 |
+
|
| 174 |
+
return {
|
| 175 |
+
'Program:exit'() {
|
| 176 |
+
const list = components.list();
|
| 177 |
+
|
| 178 |
+
values(list).filter((component) => {
|
| 179 |
+
if (functions === 'ignore' && astUtil.isFunctionLike(component.node)) {
|
| 180 |
+
return false;
|
| 181 |
+
}
|
| 182 |
+
if (classes === 'ignore' && astUtil.isClass(component.node)) {
|
| 183 |
+
return false;
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
// If this defaultProps is "unresolved", then we should ignore this component and not report
|
| 187 |
+
// any errors for it, to avoid false-positives with e.g. external defaultProps declarations or spread operators.
|
| 188 |
+
if (component.defaultProps === 'unresolved') {
|
| 189 |
+
return false;
|
| 190 |
+
}
|
| 191 |
+
return component.declaredPropTypes !== undefined;
|
| 192 |
+
}).forEach((component) => {
|
| 193 |
+
if (functions === 'defaultArguments' && astUtil.isFunctionLike(component.node)) {
|
| 194 |
+
reportFunctionComponent(
|
| 195 |
+
component.node,
|
| 196 |
+
component.declaredPropTypes,
|
| 197 |
+
component.defaultProps
|
| 198 |
+
);
|
| 199 |
+
} else {
|
| 200 |
+
reportPropTypesWithoutDefault(
|
| 201 |
+
component.declaredPropTypes,
|
| 202 |
+
component.defaultProps || {}
|
| 203 |
+
);
|
| 204 |
+
}
|
| 205 |
+
});
|
| 206 |
+
},
|
| 207 |
+
};
|
| 208 |
+
}),
|
| 209 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/require-optimization.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=require-optimization.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/require-optimization.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"require-optimization.d.ts","sourceRoot":"","sources":["require-optimization.js"],"names":[],"mappings":"wBAmBW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/require-optimization.js
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Enforce React components to have a shouldComponentUpdate method
|
| 3 |
+
* @author Evgueni Naverniouk
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const values = require('object.values');
|
| 9 |
+
|
| 10 |
+
const Components = require('../util/Components');
|
| 11 |
+
const componentUtil = require('../util/componentUtil');
|
| 12 |
+
const docsUrl = require('../util/docsUrl');
|
| 13 |
+
const report = require('../util/report');
|
| 14 |
+
const getScope = require('../util/eslint').getScope;
|
| 15 |
+
|
| 16 |
+
const messages = {
|
| 17 |
+
noShouldComponentUpdate: 'Component is not optimized. Please add a shouldComponentUpdate method.',
|
| 18 |
+
};
|
| 19 |
+
|
| 20 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 21 |
+
module.exports = {
|
| 22 |
+
meta: {
|
| 23 |
+
docs: {
|
| 24 |
+
description: 'Enforce React components to have a shouldComponentUpdate method',
|
| 25 |
+
category: 'Best Practices',
|
| 26 |
+
recommended: false,
|
| 27 |
+
url: docsUrl('require-optimization'),
|
| 28 |
+
},
|
| 29 |
+
|
| 30 |
+
messages,
|
| 31 |
+
|
| 32 |
+
schema: [{
|
| 33 |
+
type: 'object',
|
| 34 |
+
properties: {
|
| 35 |
+
allowDecorators: {
|
| 36 |
+
type: 'array',
|
| 37 |
+
items: {
|
| 38 |
+
type: 'string',
|
| 39 |
+
},
|
| 40 |
+
},
|
| 41 |
+
},
|
| 42 |
+
additionalProperties: false,
|
| 43 |
+
}],
|
| 44 |
+
},
|
| 45 |
+
|
| 46 |
+
create: Components.detect((context, components) => {
|
| 47 |
+
const configuration = context.options[0] || {};
|
| 48 |
+
const allowDecorators = configuration.allowDecorators || [];
|
| 49 |
+
|
| 50 |
+
/**
|
| 51 |
+
* Checks to see if our component is decorated by PureRenderMixin via reactMixin
|
| 52 |
+
* @param {ASTNode} node The AST node being checked.
|
| 53 |
+
* @returns {boolean} True if node is decorated with a PureRenderMixin, false if not.
|
| 54 |
+
*/
|
| 55 |
+
function hasPureRenderDecorator(node) {
|
| 56 |
+
if (node.decorators && node.decorators.length) {
|
| 57 |
+
for (let i = 0, l = node.decorators.length; i < l; i++) {
|
| 58 |
+
if (
|
| 59 |
+
node.decorators[i].expression
|
| 60 |
+
&& node.decorators[i].expression.callee
|
| 61 |
+
&& node.decorators[i].expression.callee.object
|
| 62 |
+
&& node.decorators[i].expression.callee.object.name === 'reactMixin'
|
| 63 |
+
&& node.decorators[i].expression.callee.property
|
| 64 |
+
&& node.decorators[i].expression.callee.property.name === 'decorate'
|
| 65 |
+
&& node.decorators[i].expression.arguments
|
| 66 |
+
&& node.decorators[i].expression.arguments.length
|
| 67 |
+
&& node.decorators[i].expression.arguments[0].name === 'PureRenderMixin'
|
| 68 |
+
) {
|
| 69 |
+
return true;
|
| 70 |
+
}
|
| 71 |
+
}
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
return false;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
/**
|
| 78 |
+
* Checks to see if our component is custom decorated
|
| 79 |
+
* @param {ASTNode} node The AST node being checked.
|
| 80 |
+
* @returns {boolean} True if node is decorated name with a custom decorated, false if not.
|
| 81 |
+
*/
|
| 82 |
+
function hasCustomDecorator(node) {
|
| 83 |
+
const allowLength = allowDecorators.length;
|
| 84 |
+
|
| 85 |
+
if (allowLength && node.decorators && node.decorators.length) {
|
| 86 |
+
for (let i = 0; i < allowLength; i++) {
|
| 87 |
+
for (let j = 0, l = node.decorators.length; j < l; j++) {
|
| 88 |
+
const expression = node.decorators[j].expression;
|
| 89 |
+
if (
|
| 90 |
+
expression
|
| 91 |
+
&& expression.name === allowDecorators[i]
|
| 92 |
+
) {
|
| 93 |
+
return true;
|
| 94 |
+
}
|
| 95 |
+
}
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
return false;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
/**
|
| 103 |
+
* Checks if we are declaring a shouldComponentUpdate method
|
| 104 |
+
* @param {ASTNode} node The AST node being checked.
|
| 105 |
+
* @returns {boolean} True if we are declaring a shouldComponentUpdate method, false if not.
|
| 106 |
+
*/
|
| 107 |
+
function isSCUDeclared(node) {
|
| 108 |
+
return !!node && node.name === 'shouldComponentUpdate';
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
/**
|
| 112 |
+
* Checks if we are declaring a PureRenderMixin mixin
|
| 113 |
+
* @param {ASTNode} node The AST node being checked.
|
| 114 |
+
* @returns {boolean} True if we are declaring a PureRenderMixin method, false if not.
|
| 115 |
+
*/
|
| 116 |
+
function isPureRenderDeclared(node) {
|
| 117 |
+
let hasPR = false;
|
| 118 |
+
if (node.value && node.value.elements) {
|
| 119 |
+
for (let i = 0, l = node.value.elements.length; i < l; i++) {
|
| 120 |
+
if (node.value.elements[i] && node.value.elements[i].name === 'PureRenderMixin') {
|
| 121 |
+
hasPR = true;
|
| 122 |
+
break;
|
| 123 |
+
}
|
| 124 |
+
}
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
return (
|
| 128 |
+
!!node
|
| 129 |
+
&& node.key.name === 'mixins'
|
| 130 |
+
&& hasPR
|
| 131 |
+
);
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
/**
|
| 135 |
+
* Mark shouldComponentUpdate as declared
|
| 136 |
+
* @param {ASTNode} node The AST node being checked.
|
| 137 |
+
*/
|
| 138 |
+
function markSCUAsDeclared(node) {
|
| 139 |
+
components.set(node, {
|
| 140 |
+
hasSCU: true,
|
| 141 |
+
});
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
/**
|
| 145 |
+
* Reports missing optimization for a given component
|
| 146 |
+
* @param {Object} component The component to process
|
| 147 |
+
*/
|
| 148 |
+
function reportMissingOptimization(component) {
|
| 149 |
+
report(context, messages.noShouldComponentUpdate, 'noShouldComponentUpdate', {
|
| 150 |
+
node: component.node,
|
| 151 |
+
});
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
/**
|
| 155 |
+
* Checks if we are declaring function in class
|
| 156 |
+
* @param {ASTNode} node
|
| 157 |
+
* @returns {boolean} True if we are declaring function in class, false if not.
|
| 158 |
+
*/
|
| 159 |
+
function isFunctionInClass(node) {
|
| 160 |
+
let blockNode;
|
| 161 |
+
let scope = getScope(context, node);
|
| 162 |
+
while (scope) {
|
| 163 |
+
blockNode = scope.block;
|
| 164 |
+
if (blockNode && blockNode.type === 'ClassDeclaration') {
|
| 165 |
+
return true;
|
| 166 |
+
}
|
| 167 |
+
scope = scope.upper;
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
return false;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
return {
|
| 174 |
+
ArrowFunctionExpression(node) {
|
| 175 |
+
// Skip if the function is declared in the class
|
| 176 |
+
if (isFunctionInClass(node)) {
|
| 177 |
+
return;
|
| 178 |
+
}
|
| 179 |
+
// Stateless Functional Components cannot be optimized (yet)
|
| 180 |
+
markSCUAsDeclared(node);
|
| 181 |
+
},
|
| 182 |
+
|
| 183 |
+
ClassDeclaration(node) {
|
| 184 |
+
if (!(
|
| 185 |
+
hasPureRenderDecorator(node)
|
| 186 |
+
|| hasCustomDecorator(node)
|
| 187 |
+
|| componentUtil.isPureComponent(node, context)
|
| 188 |
+
)) {
|
| 189 |
+
return;
|
| 190 |
+
}
|
| 191 |
+
markSCUAsDeclared(node);
|
| 192 |
+
},
|
| 193 |
+
|
| 194 |
+
FunctionDeclaration(node) {
|
| 195 |
+
// Skip if the function is declared in the class
|
| 196 |
+
if (isFunctionInClass(node)) {
|
| 197 |
+
return;
|
| 198 |
+
}
|
| 199 |
+
// Stateless Functional Components cannot be optimized (yet)
|
| 200 |
+
markSCUAsDeclared(node);
|
| 201 |
+
},
|
| 202 |
+
|
| 203 |
+
FunctionExpression(node) {
|
| 204 |
+
// Skip if the function is declared in the class
|
| 205 |
+
if (isFunctionInClass(node)) {
|
| 206 |
+
return;
|
| 207 |
+
}
|
| 208 |
+
// Stateless Functional Components cannot be optimized (yet)
|
| 209 |
+
markSCUAsDeclared(node);
|
| 210 |
+
},
|
| 211 |
+
|
| 212 |
+
MethodDefinition(node) {
|
| 213 |
+
if (!isSCUDeclared(node.key)) {
|
| 214 |
+
return;
|
| 215 |
+
}
|
| 216 |
+
markSCUAsDeclared(node);
|
| 217 |
+
},
|
| 218 |
+
|
| 219 |
+
ObjectExpression(node) {
|
| 220 |
+
// Search for the shouldComponentUpdate declaration
|
| 221 |
+
const found = node.properties.some((property) => (
|
| 222 |
+
property.key
|
| 223 |
+
&& (isSCUDeclared(property.key) || isPureRenderDeclared(property))
|
| 224 |
+
));
|
| 225 |
+
if (found) {
|
| 226 |
+
markSCUAsDeclared(node);
|
| 227 |
+
}
|
| 228 |
+
},
|
| 229 |
+
|
| 230 |
+
'Program:exit'() {
|
| 231 |
+
// Report missing shouldComponentUpdate for all components
|
| 232 |
+
values(components.list())
|
| 233 |
+
.filter((component) => !component.hasSCU)
|
| 234 |
+
.forEach((component) => {
|
| 235 |
+
reportMissingOptimization(component);
|
| 236 |
+
});
|
| 237 |
+
},
|
| 238 |
+
};
|
| 239 |
+
}),
|
| 240 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/require-render-return.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=require-render-return.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/require-render-return.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"require-render-return.d.ts","sourceRoot":"","sources":["require-render-return.js"],"names":[],"mappings":"wBAwBW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/require-render-return.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Enforce ES5 or ES6 class for returning value in render function.
|
| 3 |
+
* @author Mark Orel
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const values = require('object.values');
|
| 9 |
+
|
| 10 |
+
const Components = require('../util/Components');
|
| 11 |
+
const astUtil = require('../util/ast');
|
| 12 |
+
const componentUtil = require('../util/componentUtil');
|
| 13 |
+
const docsUrl = require('../util/docsUrl');
|
| 14 |
+
const report = require('../util/report');
|
| 15 |
+
const getAncestors = require('../util/eslint').getAncestors;
|
| 16 |
+
|
| 17 |
+
// ------------------------------------------------------------------------------
|
| 18 |
+
// Rule Definition
|
| 19 |
+
// ------------------------------------------------------------------------------
|
| 20 |
+
|
| 21 |
+
const messages = {
|
| 22 |
+
noRenderReturn: 'Your render method should have a return statement',
|
| 23 |
+
};
|
| 24 |
+
|
| 25 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 26 |
+
module.exports = {
|
| 27 |
+
meta: {
|
| 28 |
+
docs: {
|
| 29 |
+
description: 'Enforce ES5 or ES6 class for returning value in render function',
|
| 30 |
+
category: 'Possible Errors',
|
| 31 |
+
recommended: true,
|
| 32 |
+
url: docsUrl('require-render-return'),
|
| 33 |
+
},
|
| 34 |
+
|
| 35 |
+
messages,
|
| 36 |
+
|
| 37 |
+
schema: [],
|
| 38 |
+
},
|
| 39 |
+
|
| 40 |
+
create: Components.detect((context, components) => {
|
| 41 |
+
/**
|
| 42 |
+
* Mark a return statement as present
|
| 43 |
+
* @param {ASTNode} node The AST node being checked.
|
| 44 |
+
*/
|
| 45 |
+
function markReturnStatementPresent(node) {
|
| 46 |
+
components.set(node, {
|
| 47 |
+
hasReturnStatement: true,
|
| 48 |
+
});
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
/**
|
| 52 |
+
* Find render method in a given AST node
|
| 53 |
+
* @param {ASTNode} node The component to find render method.
|
| 54 |
+
* @returns {ASTNode} Method node if found, undefined if not.
|
| 55 |
+
*/
|
| 56 |
+
function findRenderMethod(node) {
|
| 57 |
+
const properties = astUtil.getComponentProperties(node);
|
| 58 |
+
return properties
|
| 59 |
+
.filter((property) => astUtil.getPropertyName(property) === 'render' && property.value)
|
| 60 |
+
.find((property) => astUtil.isFunctionLikeExpression(property.value));
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
return {
|
| 64 |
+
ReturnStatement(node) {
|
| 65 |
+
const ancestors = getAncestors(context, node).reverse();
|
| 66 |
+
let depth = 0;
|
| 67 |
+
ancestors.forEach((ancestor) => {
|
| 68 |
+
if (/Function(Expression|Declaration)$/.test(ancestor.type)) {
|
| 69 |
+
depth += 1;
|
| 70 |
+
}
|
| 71 |
+
if (
|
| 72 |
+
/(MethodDefinition|Property|ClassProperty|PropertyDefinition)$/.test(ancestor.type)
|
| 73 |
+
&& astUtil.getPropertyName(ancestor) === 'render'
|
| 74 |
+
&& depth <= 1
|
| 75 |
+
) {
|
| 76 |
+
markReturnStatementPresent(node);
|
| 77 |
+
}
|
| 78 |
+
});
|
| 79 |
+
},
|
| 80 |
+
|
| 81 |
+
ArrowFunctionExpression(node) {
|
| 82 |
+
if (node.expression === false || astUtil.getPropertyName(node.parent) !== 'render') {
|
| 83 |
+
return;
|
| 84 |
+
}
|
| 85 |
+
markReturnStatementPresent(node);
|
| 86 |
+
},
|
| 87 |
+
|
| 88 |
+
'Program:exit'() {
|
| 89 |
+
values(components.list())
|
| 90 |
+
.filter((component) => (
|
| 91 |
+
findRenderMethod(component.node)
|
| 92 |
+
&& !component.hasReturnStatement
|
| 93 |
+
&& (
|
| 94 |
+
componentUtil.isES5Component(component.node, context)
|
| 95 |
+
|| componentUtil.isES6Component(component.node, context)
|
| 96 |
+
)
|
| 97 |
+
))
|
| 98 |
+
.forEach((component) => {
|
| 99 |
+
report(context, messages.noRenderReturn, 'noRenderReturn', {
|
| 100 |
+
node: findRenderMethod(component.node),
|
| 101 |
+
});
|
| 102 |
+
});
|
| 103 |
+
},
|
| 104 |
+
};
|
| 105 |
+
}),
|
| 106 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/self-closing-comp.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=self-closing-comp.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/self-closing-comp.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"self-closing-comp.d.ts","sourceRoot":"","sources":["self-closing-comp.js"],"names":[],"mappings":"wBA4CW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|
node_modules/eslint-plugin-react/lib/rules/self-closing-comp.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* @fileoverview Prevent extra closing tags for components without children
|
| 3 |
+
* @author Yannick Croissant
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
'use strict';
|
| 7 |
+
|
| 8 |
+
const docsUrl = require('../util/docsUrl');
|
| 9 |
+
const jsxUtil = require('../util/jsx');
|
| 10 |
+
const report = require('../util/report');
|
| 11 |
+
|
| 12 |
+
const optionDefaults = { component: true, html: true };
|
| 13 |
+
|
| 14 |
+
function isComponent(node) {
|
| 15 |
+
return (
|
| 16 |
+
node.name
|
| 17 |
+
&& (node.name.type === 'JSXIdentifier' || node.name.type === 'JSXMemberExpression')
|
| 18 |
+
&& !jsxUtil.isDOMComponent(node)
|
| 19 |
+
);
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
function childrenIsEmpty(node) {
|
| 23 |
+
return node.parent.children.length === 0;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
function childrenIsMultilineSpaces(node) {
|
| 27 |
+
const childrens = node.parent.children;
|
| 28 |
+
|
| 29 |
+
return (
|
| 30 |
+
childrens.length === 1
|
| 31 |
+
&& (childrens[0].type === 'Literal' || childrens[0].type === 'JSXText')
|
| 32 |
+
&& childrens[0].value.indexOf('\n') !== -1
|
| 33 |
+
&& childrens[0].value.replace(/(?!\xA0)\s/g, '') === ''
|
| 34 |
+
);
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
// ------------------------------------------------------------------------------
|
| 38 |
+
// Rule Definition
|
| 39 |
+
// ------------------------------------------------------------------------------
|
| 40 |
+
|
| 41 |
+
const messages = {
|
| 42 |
+
notSelfClosing: 'Empty components are self-closing',
|
| 43 |
+
};
|
| 44 |
+
|
| 45 |
+
/** @type {import('eslint').Rule.RuleModule} */
|
| 46 |
+
module.exports = {
|
| 47 |
+
meta: {
|
| 48 |
+
docs: {
|
| 49 |
+
description: 'Disallow extra closing tags for components without children',
|
| 50 |
+
category: 'Stylistic Issues',
|
| 51 |
+
recommended: false,
|
| 52 |
+
url: docsUrl('self-closing-comp'),
|
| 53 |
+
},
|
| 54 |
+
fixable: 'code',
|
| 55 |
+
|
| 56 |
+
messages,
|
| 57 |
+
|
| 58 |
+
schema: [{
|
| 59 |
+
type: 'object',
|
| 60 |
+
properties: {
|
| 61 |
+
component: {
|
| 62 |
+
default: optionDefaults.component,
|
| 63 |
+
type: 'boolean',
|
| 64 |
+
},
|
| 65 |
+
html: {
|
| 66 |
+
default: optionDefaults.html,
|
| 67 |
+
type: 'boolean',
|
| 68 |
+
},
|
| 69 |
+
},
|
| 70 |
+
additionalProperties: false,
|
| 71 |
+
}],
|
| 72 |
+
},
|
| 73 |
+
|
| 74 |
+
create(context) {
|
| 75 |
+
function isShouldBeSelfClosed(node) {
|
| 76 |
+
const configuration = Object.assign({}, optionDefaults, context.options[0]);
|
| 77 |
+
return (
|
| 78 |
+
(configuration.component && isComponent(node))
|
| 79 |
+
|| (configuration.html && jsxUtil.isDOMComponent(node))
|
| 80 |
+
) && !node.selfClosing && (childrenIsEmpty(node) || childrenIsMultilineSpaces(node));
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
return {
|
| 84 |
+
JSXOpeningElement(node) {
|
| 85 |
+
if (!isShouldBeSelfClosed(node)) {
|
| 86 |
+
return;
|
| 87 |
+
}
|
| 88 |
+
report(context, messages.notSelfClosing, 'notSelfClosing', {
|
| 89 |
+
node,
|
| 90 |
+
fix(fixer) {
|
| 91 |
+
// Represents the last character of the JSXOpeningElement, the '>' character
|
| 92 |
+
const openingElementEnding = node.range[1] - 1;
|
| 93 |
+
// Represents the last character of the JSXClosingElement, the '>' character
|
| 94 |
+
const closingElementEnding = node.parent.closingElement.range[1];
|
| 95 |
+
|
| 96 |
+
// Replace />.*<\/.*>/ with '/>'
|
| 97 |
+
const range = [openingElementEnding, closingElementEnding];
|
| 98 |
+
return fixer.replaceTextRange(range, ' />');
|
| 99 |
+
},
|
| 100 |
+
});
|
| 101 |
+
},
|
| 102 |
+
};
|
| 103 |
+
},
|
| 104 |
+
};
|
node_modules/eslint-plugin-react/lib/rules/sort-comp.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
declare const _exports: import('eslint').Rule.RuleModule;
|
| 2 |
+
export = _exports;
|
| 3 |
+
//# sourceMappingURL=sort-comp.d.ts.map
|
node_modules/eslint-plugin-react/lib/rules/sort-comp.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"version":3,"file":"sort-comp.d.ts","sourceRoot":"","sources":["sort-comp.js"],"names":[],"mappings":"wBAwFW,OAAO,QAAQ,EAAE,IAAI,CAAC,UAAU"}
|