/
home
/
techb158
/
balavpn.abdallabala.com
/
node_modules
/
eslint-plugin-react
/
lib
/
util
/
/home/techb158/balavpn.abdallabala.com/node_modules/eslint-plugin-react/lib/util
mkdir
upload
Name
Size
Mode
Actions
annotations.d.ts
390
0666
edit
dl
rm
annotations.d.ts.map
155
0666
edit
dl
rm
annotations.js
1090
0666
edit
dl
rm
ast.d.ts
5186
0666
edit
dl
rm
ast.d.ts.map
1135
0666
edit
dl
rm
ast.js
12197
0666
edit
dl
rm
Components.d.ts
2396
0666
edit
dl
rm
Components.d.ts.map
466
0666
edit
dl
rm
Components.js
30079
0666
edit
dl
rm
componentUtil.d.ts
1397
0666
edit
dl
rm
componentUtil.d.ts.map
517
0666
edit
dl
rm
componentUtil.js
4824
0666
edit
dl
rm
defaultProps.d.ts
311
0666
edit
dl
rm
defaultProps.d.ts.map
128
0666
edit
dl
rm
defaultProps.js
8501
0666
edit
dl
rm
docsUrl.d.ts
104
0666
edit
dl
rm
docsUrl.d.ts.map
112
0666
edit
dl
rm
docsUrl.js
173
0666
edit
dl
rm
error.d.ts
207
0666
edit
dl
rm
error.d.ts.map
131
0666
edit
dl
rm
error.js
308
0666
edit
dl
rm
eslint.d.ts
413
0666
edit
dl
rm
eslint.d.ts.map
169
0666
edit
dl
rm
eslint.js
1296
0666
edit
dl
rm
getTokenBeforeClosingBracket.d.ts
327
0666
edit
dl
rm
getTokenBeforeClosingBracket.d.ts.map
188
0666
edit
dl
rm
getTokenBeforeClosingBracket.js
428
0666
edit
dl
rm
isCreateContext.d.ts
115
0666
edit
dl
rm
isCreateContext.d.ts.map
150
0666
edit
dl
rm
isCreateContext.js
1213
0666
edit
dl
rm
isCreateElement.d.ts
133
0666
edit
dl
rm
isCreateElement.d.ts.map
160
0666
edit
dl
rm
isCreateElement.js
894
0666
edit
dl
rm
isDestructuredFromPragmaImport.d.ts
182
0666
edit
dl
rm
isDestructuredFromPragmaImport.d.ts.map
201
0666
edit
dl
rm
isDestructuredFromPragmaImport.js
2708
0666
edit
dl
rm
isFirstLetterCapitalized.d.ts
123
0666
edit
dl
rm
isFirstLetterCapitalized.d.ts.map
167
0666
edit
dl
rm
isFirstLetterCapitalized.js
387
0666
edit
dl
rm
jsx.d.ts
1974
0666
edit
dl
rm
jsx.d.ts.map
480
0666
edit
dl
rm
jsx.js
5374
0666
edit
dl
rm
lifecycleMethods.d.ts
140
0666
edit
dl
rm
lifecycleMethods.d.ts.map
119
0666
edit
dl
rm
lifecycleMethods.js
611
0666
edit
dl
rm
linkComponents.d.ts
172
0666
edit
dl
rm
linkComponents.d.ts.map
137
0666
edit
dl
rm
linkComponents.js
1520
0666
edit
dl
rm
log.d.ts
201
0666
edit
dl
rm
log.d.ts.map
127
0666
edit
dl
rm
log.js
302
0666
edit
dl
rm
makeNoMethodSetStateRule.d.ts
233
0666
edit
dl
rm
makeNoMethodSetStateRule.d.ts.map
241
0666
edit
dl
rm
makeNoMethodSetStateRule.js
3747
0666
edit
dl
rm
message.d.ts
214
0666
edit
dl
rm
message.d.ts.map
117
0666
edit
dl
rm
message.js
266
0666
edit
dl
rm
pragma.d.ts
400
0666
edit
dl
rm
pragma.d.ts.map
231
0666
edit
dl
rm
pragma.js
2218
0666
edit
dl
rm
props.d.ts
2716
0666
edit
dl
rm
props.d.ts.map
501
0666
edit
dl
rm
props.js
4242
0666
edit
dl
rm
propTypes.d.ts
799
0666
edit
dl
rm
propTypes.d.ts.map
176
0666
edit
dl
rm
propTypes.js
46449
0666
edit
dl
rm
propTypesSort.d.ts
1933
0666
edit
dl
rm
propTypesSort.d.ts.map
419
0666
edit
dl
rm
propTypesSort.js
7353
0666
edit
dl
rm
propWrapper.d.ts
398
0666
edit
dl
rm
propWrapper.d.ts.map
168
0666
edit
dl
rm
propWrapper.js
1851
0666
edit
dl
rm
report.d.ts
143
0666
edit
dl
rm
report.d.ts.map
111
0666
edit
dl
rm
report.js
235
0666
edit
dl
rm
usedPropTypes.d.ts
638
0666
edit
dl
rm
usedPropTypes.d.ts.map
168
0666
edit
dl
rm
usedPropTypes.js
18578
0666
edit
dl
rm
variable.d.ts
1724
0666
edit
dl
rm
variable.d.ts.map
359
0666
edit
dl
rm
variable.js
2876
0666
edit
dl
rm
version.d.ts
319
0666
edit
dl
rm
version.d.ts.map
158
0666
edit
dl
rm
version.js
6964
0666
edit
dl
rm
Edit:
/home/techb158/balavpn.abdallabala.com/node_modules/eslint-plugin-react/lib/util/Components.js
(30079B)
/** * @fileoverview Utility class and functions for React components detection * @author Yannick Croissant */ 'use strict'; const arrayIncludes = require('array-includes'); const fromEntries = require('object.fromentries'); const values = require('object.values'); const iterFrom = require('es-iterator-helpers/Iterator.from'); const map = require('es-iterator-helpers/Iterator.prototype.map'); const variableUtil = require('./variable'); const pragmaUtil = require('./pragma'); const astUtil = require('./ast'); const componentUtil = require('./componentUtil'); const propTypesUtil = require('./propTypes'); const jsxUtil = require('./jsx'); const usedPropTypesUtil = require('./usedPropTypes'); const defaultPropsUtil = require('./defaultProps'); const isFirstLetterCapitalized = require('./isFirstLetterCapitalized'); const isDestructuredFromPragmaImport = require('./isDestructuredFromPragmaImport'); const eslintUtil = require('./eslint'); const getScope = eslintUtil.getScope; const getText = eslintUtil.getText; function getId(node) { return node ? `${node.range[0]}:${node.range[1]}` : ''; } function usedPropTypesAreEquivalent(propA, propB) { if (propA.name === propB.name) { if (!propA.allNames && !propB.allNames) { return true; } if (Array.isArray(propA.allNames) && Array.isArray(propB.allNames) && propA.allNames.join('') === propB.allNames.join('')) { return true; } return false; } return false; } function mergeUsedPropTypes(propsList, newPropsList) { const propsToAdd = newPropsList.filter((newProp) => { const newPropIsAlreadyInTheList = propsList.some((prop) => usedPropTypesAreEquivalent(prop, newProp)); return !newPropIsAlreadyInTheList; }); return propsList.concat(propsToAdd); } const USE_HOOK_PREFIX_REGEX = /^use[A-Z]/; const Lists = new WeakMap(); const ReactImports = new WeakMap(); /** * Components */ class Components { constructor() { Lists.set(this, {}); ReactImports.set(this, {}); } /** * Add a node to the components list, or update it if it's already in the list * * @param {ASTNode} node The AST node being added. * @param {number} confidence Confidence in the component detection (0=banned, 1=maybe, 2=yes) * @returns {Object} Added component object */ add(node, confidence) { const id = getId(node); const list = Lists.get(this); if (list[id]) { if (confidence === 0 || list[id].confidence === 0) { list[id].confidence = 0; } else { list[id].confidence = Math.max(list[id].confidence, confidence); } return list[id]; } list[id] = { node, confidence, }; return list[id]; } /** * Find a component in the list using its node * * @param {ASTNode} node The AST node being searched. * @returns {Object} Component object, undefined if the component is not found or has confidence value of 0. */ get(node) { const id = getId(node); const item = Lists.get(this)[id]; if (item && item.confidence >= 1) { return item; } return null; } /** * Update a component in the list * * @param {ASTNode} node The AST node being updated. * @param {Object} props Additional properties to add to the component. */ set(node, props) { const list = Lists.get(this); let component = list[getId(node)]; while (!component || component.confidence < 1) { node = node.parent; if (!node) { return; } component = list[getId(node)]; } Object.assign( component, props, { usedPropTypes: mergeUsedPropTypes( component.usedPropTypes || [], props.usedPropTypes || [] ), } ); } /** * Return the components list * Components for which we are not confident are not returned * * @returns {Object} Components list */ list() { const thisList = Lists.get(this); const list = {}; const usedPropTypes = {}; // Find props used in components for which we are not confident Object.keys(thisList).filter((i) => thisList[i].confidence < 2).forEach((i) => { let component = null; let node = null; node = thisList[i].node; while (!component && node.parent) { node = node.parent; // Stop moving up if we reach a decorator if (node.type === 'Decorator') { break; } component = this.get(node); } if (component) { const newUsedProps = (thisList[i].usedPropTypes || []).filter((propType) => !propType.node || propType.node.kind !== 'init'); const componentId = getId(component.node); usedPropTypes[componentId] = mergeUsedPropTypes(usedPropTypes[componentId] || [], newUsedProps); } }); // Assign used props in not confident components to the parent component Object.keys(thisList).filter((j) => thisList[j].confidence >= 2).forEach((j) => { const id = getId(thisList[j].node); list[j] = thisList[j]; if (usedPropTypes[id]) { list[j].usedPropTypes = mergeUsedPropTypes(list[j].usedPropTypes || [], usedPropTypes[id]); } }); return list; } /** * Return the length of the components list * Components for which we are not confident are not counted * * @returns {number} Components list length */ length() { const list = Lists.get(this); return values(list).filter((component) => component.confidence >= 2).length; } /** * Return the node naming the default React import * It can be used to determine the local name of import, even if it's imported * with an unusual name. * * @returns {ASTNode} React default import node */ getDefaultReactImports() { return ReactImports.get(this).defaultReactImports; } /** * Return the nodes of all React named imports * * @returns {Object} The list of React named imports */ getNamedReactImports() { return ReactImports.get(this).namedReactImports; } /** * Add the default React import specifier to the scope * * @param {ASTNode} specifier The AST Node of the default React import * @returns {void} */ addDefaultReactImport(specifier) { const info = ReactImports.get(this); ReactImports.set(this, Object.assign({}, info, { defaultReactImports: (info.defaultReactImports || []).concat(specifier), })); } /** * Add a named React import specifier to the scope * * @param {ASTNode} specifier The AST Node of a named React import * @returns {void} */ addNamedReactImport(specifier) { const info = ReactImports.get(this); ReactImports.set(this, Object.assign({}, info, { namedReactImports: (info.namedReactImports || []).concat(specifier), })); } } function getWrapperFunctions(context, pragma) { const componentWrapperFunctions = context.settings.componentWrapperFunctions || []; // eslint-disable-next-line arrow-body-style return componentWrapperFunctions.map((wrapperFunction) => { return typeof wrapperFunction === 'string' ? { property: wrapperFunction } : Object.assign({}, wrapperFunction, { object: wrapperFunction.object === '<pragma>' ? pragma : wrapperFunction.object, }); }).concat([ { property: 'forwardRef', object: pragma }, { property: 'memo', object: pragma }, ]); } // eslint-disable-next-line valid-jsdoc /** * Merge many eslint rules into one * @param {{[_: string]: Function}[]} rules the returned values for eslint rule.create(context) * @returns {{[_: string]: Function}} merged rule */ function mergeRules(rules) { /** @type {Map<string, Function[]>} */ const handlersByKey = new Map(); rules.forEach((rule) => { Object.keys(rule).forEach((key) => { const fns = handlersByKey.get(key); if (!fns) { handlersByKey.set(key, [rule[key]]); } else { fns.push(rule[key]); } }); }); /** @type {{ [key: string]: Function }} */ return fromEntries(map(iterFrom(handlersByKey), (entry) => [ entry[0], function mergedHandler(node) { entry[1].forEach((fn) => { fn(node); }); }, ])); } function componentRule(rule, context) { const pragma = pragmaUtil.getFromContext(context); const components = new Components(); const wrapperFunctions = getWrapperFunctions(context, pragma); // Utilities for component detection const utils = { /** * Check if variable is destructured from pragma import * * @param {ASTNode} node The AST node to check * @param {string} variable The variable name to check * @returns {boolean} True if createElement is destructured from the pragma */ isDestructuredFromPragmaImport(node, variable) { return isDestructuredFromPragmaImport(context, node, variable); }, /** * @param {ASTNode} node * @param {boolean=} strict * @returns {boolean} */ isReturningJSX(node, strict) { return jsxUtil.isReturningJSX(context, node, strict, true); }, isReturningJSXOrNull(node, strict) { return jsxUtil.isReturningJSX(context, node, strict); }, isReturningOnlyNull(node) { return jsxUtil.isReturningOnlyNull(node, context); }, getPragmaComponentWrapper(node) { let isPragmaComponentWrapper; let currentNode = node; let prevNode; do { currentNode = currentNode.parent; isPragmaComponentWrapper = this.isPragmaComponentWrapper(currentNode); if (isPragmaComponentWrapper) { prevNode = currentNode; } } while (isPragmaComponentWrapper); return prevNode; }, getComponentNameFromJSXElement(node) { if (node.type !== 'JSXElement') { return null; } if (node.openingElement && node.openingElement.name && node.openingElement.name.name) { return node.openingElement.name.name; } return null; }, /** * Getting the first JSX element's name. * @param {object} node * @returns {string | null} */ getNameOfWrappedComponent(node) { if (node.length < 1) { return null; } const body = node[0].body; if (!body) { return null; } if (body.type === 'JSXElement') { return this.getComponentNameFromJSXElement(body); } if (body.type === 'BlockStatement') { const jsxElement = body.body.find((item) => item.type === 'ReturnStatement'); return jsxElement && jsxElement.argument && this.getComponentNameFromJSXElement(jsxElement.argument); } return null; }, /** * Get the list of names of components created till now * @returns {string | boolean} */ getDetectedComponents() { const list = components.list(); return values(list).filter((val) => { if (val.node.type === 'ClassDeclaration') { return true; } if ( val.node.type === 'ArrowFunctionExpression' && val.node.parent && val.node.parent.type === 'VariableDeclarator' && val.node.parent.id ) { return true; } return false; }).map((val) => { if (val.node.type === 'ArrowFunctionExpression') return val.node.parent.id.name; return val.node.id && val.node.id.name; }); }, /** * It will check whether memo/forwardRef is wrapping existing component or * creating a new one. * @param {object} node * @returns {boolean} */ nodeWrapsComponent(node) { const childComponent = this.getNameOfWrappedComponent(node.arguments); const componentList = this.getDetectedComponents(); return !!childComponent && arrayIncludes(componentList, childComponent); }, isPragmaComponentWrapper(node) { if (!astUtil.isCallExpression(node)) { return false; } return wrapperFunctions.some((wrapperFunction) => { if (node.callee.type === 'MemberExpression') { return wrapperFunction.object && wrapperFunction.object === node.callee.object.name && wrapperFunction.property === node.callee.property.name && !this.nodeWrapsComponent(node); } return wrapperFunction.property === node.callee.name && (!wrapperFunction.object // Functions coming from the current pragma need special handling || (wrapperFunction.object === pragma && this.isDestructuredFromPragmaImport(node, node.callee.name)) ); }); }, /** * Find a return statement in the current node * * @param {ASTNode} node The AST node being checked */ findReturnStatement: astUtil.findReturnStatement, /** * Get the parent component node from the current scope * @param {ASTNode} node * * @returns {ASTNode} component node, null if we are not in a component */ getParentComponent(node) { return ( componentUtil.getParentES6Component(context, node) || componentUtil.getParentES5Component(context, node) || utils.getParentStatelessComponent(node) ); }, /** * @param {ASTNode} node * @returns {boolean} */ isInAllowedPositionForComponent(node) { switch (node.parent.type) { case 'VariableDeclarator': case 'AssignmentExpression': case 'Property': case 'ReturnStatement': case 'ExportDefaultDeclaration': case 'ArrowFunctionExpression': { return true; } case 'SequenceExpression': { return utils.isInAllowedPositionForComponent(node.parent) && node === node.parent.expressions[node.parent.expressions.length - 1]; } default: return false; } }, /** * Get node if node is a stateless component, or node.parent in cases like * `React.memo` or `React.forwardRef`. Otherwise returns `undefined`. * @param {ASTNode} node * @returns {ASTNode | undefined} */ getStatelessComponent(node) { const parent = node.parent; if ( node.type === 'FunctionDeclaration' && (!node.id || isFirstLetterCapitalized(node.id.name)) && utils.isReturningJSXOrNull(node) ) { return node; } if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') { const isPropertyAssignment = parent.type === 'AssignmentExpression' && parent.left.type === 'MemberExpression'; const isModuleExportsAssignment = isPropertyAssignment && parent.left.object.name === 'module' && parent.left.property.name === 'exports'; if (node.parent.type === 'ExportDefaultDeclaration') { if (utils.isReturningJSX(node)) { return node; } return undefined; } if (node.parent.type === 'VariableDeclarator' && utils.isReturningJSXOrNull(node)) { if (isFirstLetterCapitalized(node.parent.id.name)) { return node; } return undefined; } // case: const any = () => { return (props) => null } // case: const any = () => (props) => null if ( (node.parent.type === 'ReturnStatement' || (node.parent.type === 'ArrowFunctionExpression' && node.parent.expression)) && !utils.isReturningJSX(node) ) { return undefined; } // case: any = () => { return => null } // case: any = () => null if (node.parent.type === 'AssignmentExpression' && !isPropertyAssignment && utils.isReturningJSXOrNull(node)) { if (isFirstLetterCapitalized(node.parent.left.name)) { return node; } return undefined; } // case: any = () => () => null if (node.parent.type === 'ArrowFunctionExpression' && node.parent.parent.type === 'AssignmentExpression' && !isPropertyAssignment && utils.isReturningJSXOrNull(node)) { if (isFirstLetterCapitalized(node.parent.parent.left.name)) { return node; } return undefined; } // case: { any: () => () => null } if (node.parent.type === 'ArrowFunctionExpression' && node.parent.parent.type === 'Property' && !isPropertyAssignment && utils.isReturningJSXOrNull(node)) { if (isFirstLetterCapitalized(node.parent.parent.key.name)) { return node; } return undefined; } // case: any = function() {return function() {return null;};} if (node.parent.type === 'ReturnStatement') { if (isFirstLetterCapitalized(node.id && node.id.name)) { return node; } const functionExpr = node.parent.parent.parent; if (functionExpr.parent.type === 'AssignmentExpression' && !isPropertyAssignment && utils.isReturningJSXOrNull(node)) { if (isFirstLetterCapitalized(functionExpr.parent.left.name)) { return node; } return undefined; } } // case: { any: function() {return function() {return null;};} } if (node.parent.type === 'ReturnStatement') { const functionExpr = node.parent.parent.parent; if (functionExpr.parent.type === 'Property' && !isPropertyAssignment && utils.isReturningJSXOrNull(node)) { if (isFirstLetterCapitalized(functionExpr.parent.key.name)) { return node; } return undefined; } } // for case abc = { [someobject.somekey]: props => { ... return not-jsx } } if ( node.parent && node.parent.key && node.parent.key.type === 'MemberExpression' && !utils.isReturningJSX(node) && !utils.isReturningOnlyNull(node) ) { return undefined; } if ( node.parent.type === 'Property' && ( (node.parent.method && !node.parent.computed) // case: { f() { return ... } } || (!node.id && !node.parent.computed) // case: { f: () => ... } ) ) { if ( isFirstLetterCapitalized(node.parent.key.name) && utils.isReturningJSX(node) ) { return node; } return undefined; } // Case like `React.memo(() => <></>)` or `React.forwardRef(...)` const pragmaComponentWrapper = utils.getPragmaComponentWrapper(node); if (pragmaComponentWrapper && utils.isReturningJSXOrNull(node)) { return pragmaComponentWrapper; } if (!(utils.isInAllowedPositionForComponent(node) && utils.isReturningJSXOrNull(node))) { return undefined; } if (utils.isParentComponentNotStatelessComponent(node)) { return undefined; } if (node.id) { return isFirstLetterCapitalized(node.id.name) ? node : undefined; } if ( isPropertyAssignment && !isModuleExportsAssignment && !isFirstLetterCapitalized(parent.left.property.name) ) { return undefined; } if (parent.type === 'Property' && utils.isReturningOnlyNull(node)) { return undefined; } return node; } return undefined; }, /** * Get the parent stateless component node from the current scope * * @param {ASTNode} node The AST node being checked * @returns {ASTNode} component node, null if we are not in a component */ getParentStatelessComponent(node) { let scope = getScope(context, node); while (scope) { const statelessComponent = utils.getStatelessComponent(scope.block); if (statelessComponent) { return statelessComponent; } scope = scope.upper; } return null; }, /** * Get the related component from a node * * @param {ASTNode} node The AST node being checked (must be a MemberExpression). * @returns {ASTNode | null} component node, null if we cannot find the component */ getRelatedComponent(node) { let i; let j; let k; let l; let componentNode; // Get the component path const componentPath = []; let nodeTemp = node; while (nodeTemp) { if (nodeTemp.property && nodeTemp.property.type === 'Identifier') { componentPath.push(nodeTemp.property.name); } if (nodeTemp.object && nodeTemp.object.type === 'Identifier') { componentPath.push(nodeTemp.object.name); } nodeTemp = nodeTemp.object; } componentPath.reverse(); const componentName = componentPath.slice(0, componentPath.length - 1).join('.'); // Find the variable in the current scope const variableName = componentPath.shift(); if (!variableName) { return null; } const variableInScope = variableUtil.getVariableFromContext(context, node, variableName); if (!variableInScope) { return null; } // Try to find the component using variable references variableInScope.references.some((ref) => { let refId = ref.identifier; if (refId.parent && refId.parent.type === 'MemberExpression') { refId = refId.parent; } if (getText(context, refId) !== componentName) { return false; } if (refId.type === 'MemberExpression') { componentNode = refId.parent.right; } else if ( refId.parent && refId.parent.type === 'VariableDeclarator' && refId.parent.init && refId.parent.init.type !== 'Identifier' ) { componentNode = refId.parent.init; } return true; }); if (componentNode) { // Return the component return components.add(componentNode, 1); } // Try to find the component using variable declarations const defs = variableInScope.defs; const defInScope = defs.find((def) => ( def.type === 'ClassName' || def.type === 'FunctionName' || def.type === 'Variable' )); if (!defInScope || !defInScope.node) { return null; } componentNode = defInScope.node.init || defInScope.node; // Traverse the node properties to the component declaration for (i = 0, j = componentPath.length; i < j; i++) { if (!componentNode.properties) { continue; // eslint-disable-line no-continue } for (k = 0, l = componentNode.properties.length; k < l; k++) { if (componentNode.properties[k].key && componentNode.properties[k].key.name === componentPath[i]) { componentNode = componentNode.properties[k]; break; } } if (!componentNode || !componentNode.value) { return null; } componentNode = componentNode.value; } // Return the component return components.add(componentNode, 1); }, isParentComponentNotStatelessComponent(node) { return !!( node.parent && node.parent.key && node.parent.key.type === 'Identifier' // custom component functions must start with a capital letter (returns false otherwise) && node.parent.key.name.charAt(0) === node.parent.key.name.charAt(0).toLowerCase() // react render function cannot have params && !!(node.params || []).length ); }, /** * Identify whether a node (CallExpression) is a call to a React hook * * @param {ASTNode} node The AST node being searched. (expects CallExpression) * @param {('useCallback'|'useContext'|'useDebugValue'|'useEffect'|'useImperativeHandle'|'useLayoutEffect'|'useMemo'|'useReducer'|'useRef'|'useState')[]} [expectedHookNames] React hook names to which search is limited. * @returns {boolean} True if the node is a call to a React hook */ isReactHookCall(node, expectedHookNames) { if (!astUtil.isCallExpression(node)) { return false; } const defaultReactImports = components.getDefaultReactImports(); const namedReactImports = components.getNamedReactImports(); const defaultReactImportName = defaultReactImports && defaultReactImports[0] && defaultReactImports[0].local.name; const reactHookImportSpecifiers = namedReactImports && namedReactImports.filter((specifier) => USE_HOOK_PREFIX_REGEX.test(specifier.imported.name)); const reactHookImportNames = reactHookImportSpecifiers && fromEntries(reactHookImportSpecifiers.map((specifier) => [specifier.local.name, specifier.imported.name])); const isPotentialReactHookCall = defaultReactImportName && node.callee.type === 'MemberExpression' && node.callee.object.type === 'Identifier' && node.callee.object.name === defaultReactImportName && node.callee.property.type === 'Identifier' && node.callee.property.name.match(USE_HOOK_PREFIX_REGEX); const isPotentialHookCall = reactHookImportNames && node.callee.type === 'Identifier' && node.callee.name.match(USE_HOOK_PREFIX_REGEX); const scope = (isPotentialReactHookCall || isPotentialHookCall) && getScope(context, node); const reactResolvedDefs = isPotentialReactHookCall && scope.references && scope.references.find( (reference) => reference.identifier.name === defaultReactImportName ).resolved.defs; const isReactShadowed = isPotentialReactHookCall && reactResolvedDefs && reactResolvedDefs.some((reactDef) => reactDef.type !== 'ImportBinding'); const potentialHookReference = isPotentialHookCall && scope.references && scope.references.find( (reference) => reactHookImportNames[reference.identifier.name] ); const hookResolvedDefs = potentialHookReference && potentialHookReference.resolved.defs; const localHookName = ( isPotentialReactHookCall && node.callee.property.name ) || ( isPotentialHookCall && potentialHookReference && node.callee.name ); const isHookShadowed = isPotentialHookCall && hookResolvedDefs && hookResolvedDefs.some( (hookDef) => hookDef.name.name === localHookName && hookDef.type !== 'ImportBinding' ); const isHookCall = (isPotentialReactHookCall && !isReactShadowed) || (isPotentialHookCall && localHookName && !isHookShadowed); if (!isHookCall) { return false; } if (!expectedHookNames) { return true; } return arrayIncludes( expectedHookNames, (reactHookImportNames && reactHookImportNames[localHookName]) || localHookName ); }, }; // Component detection instructions const detectionInstructions = { CallExpression(node) { if (!utils.isPragmaComponentWrapper(node)) { return; } if (node.arguments.length > 0 && astUtil.isFunctionLikeExpression(node.arguments[0])) { components.add(node, 2); } }, ClassExpression(node) { if (!componentUtil.isES6Component(node, context)) { return; } components.add(node, 2); }, ClassDeclaration(node) { if (!componentUtil.isES6Component(node, context)) { return; } components.add(node, 2); }, ObjectExpression(node) { if (!componentUtil.isES5Component(node, context)) { return; } components.add(node, 2); }, FunctionExpression(node) { if (node.async && node.generator) { components.add(node, 0); return; } const component = utils.getStatelessComponent(node); if (!component) { return; } components.add(component, 2); }, FunctionDeclaration(node) { if (node.async && node.generator) { components.add(node, 0); return; } const cNode = utils.getStatelessComponent(node); if (!cNode) { return; } components.add(cNode, 2); }, ArrowFunctionExpression(node) { const component = utils.getStatelessComponent(node); if (!component) { return; } components.add(component, 2); }, ThisExpression(node) { const component = utils.getParentStatelessComponent(node); if (!component || !/Function/.test(component.type) || !node.parent.property) { return; } // Ban functions accessing a property on a ThisExpression components.add(node, 0); }, }; // Detect React import specifiers const reactImportInstructions = { ImportDeclaration(node) { const isReactImported = node.source.type === 'Literal' && node.source.value === 'react'; if (!isReactImported) { return; } node.specifiers.forEach((specifier) => { if (specifier.type === 'ImportDefaultSpecifier') { components.addDefaultReactImport(specifier); } if (specifier.type === 'ImportSpecifier') { components.addNamedReactImport(specifier); } }); }, }; const ruleInstructions = rule(context, components, utils); const propTypesInstructions = propTypesUtil(context, components, utils); const usedPropTypesInstructions = usedPropTypesUtil(context, components, utils); const defaultPropsInstructions = defaultPropsUtil(context, components, utils); const mergedRule = mergeRules([ detectionInstructions, propTypesInstructions, usedPropTypesInstructions, defaultPropsInstructions, reactImportInstructions, ruleInstructions, ]); return mergedRule; } module.exports = Object.assign(Components, { detect(rule) { return componentRule.bind(this, rule); }, });
Save
cmd:
run