eslint-plugin-react
Advanced tools
Comparing version 7.35.0 to 7.35.1
@@ -13,2 +13,3 @@ /** | ||
const propsUtil = require('../util/props'); | ||
const astUtil = require('../util/ast'); | ||
const docsUrl = require('../util/docsUrl'); | ||
@@ -22,2 +23,14 @@ const propWrapperUtil = require('../util/propWrapper'); | ||
/** | ||
* Checks if prop is nested | ||
* @param {Object} prop Property object, single prop type declaration | ||
* @returns {boolean} | ||
*/ | ||
function nestedPropTypes(prop) { | ||
return ( | ||
prop.type === 'Property' | ||
&& astUtil.isCallExpression(prop.value) | ||
); | ||
} | ||
// ------------------------------------------------------------------------------ | ||
@@ -133,3 +146,3 @@ // Rule Definition | ||
* @param {Object} prop Property object, single prop type declaration | ||
* @returns {Boolean} | ||
* @returns {boolean} | ||
*/ | ||
@@ -147,3 +160,3 @@ function flowCheck(prop) { | ||
* @param {Object} prop Property object, single prop type declaration | ||
* @returns {Boolean} | ||
* @returns {boolean} | ||
*/ | ||
@@ -170,14 +183,2 @@ function regularCheck(prop) { | ||
/** | ||
* Checks if prop is nested | ||
* @param {Object} prop Property object, single prop type declaration | ||
* @returns {Boolean} | ||
*/ | ||
function nestedPropTypes(prop) { | ||
return ( | ||
prop.type === 'Property' | ||
&& prop.value.type === 'CallExpression' | ||
); | ||
} | ||
/** | ||
* Runs recursive check on all proptypes | ||
@@ -188,11 +189,13 @@ * @param {Array} proptypes A list of Property object (for each proptype defined) | ||
function runCheck(proptypes, addInvalidProp) { | ||
(proptypes || []).forEach((prop) => { | ||
if (config.validateNested && nestedPropTypes(prop)) { | ||
runCheck(prop.value.arguments[0].properties, addInvalidProp); | ||
return; | ||
} | ||
if (flowCheck(prop) || regularCheck(prop) || tsCheck(prop)) { | ||
addInvalidProp(prop); | ||
} | ||
}); | ||
if (proptypes) { | ||
proptypes.forEach((prop) => { | ||
if (config.validateNested && nestedPropTypes(prop)) { | ||
runCheck(prop.value.arguments[0].properties, addInvalidProp); | ||
return; | ||
} | ||
if (flowCheck(prop) || regularCheck(prop) || tsCheck(prop)) { | ||
addInvalidProp(prop); | ||
} | ||
}); | ||
} | ||
} | ||
@@ -318,3 +321,3 @@ | ||
node.value | ||
&& node.value.type === 'CallExpression' | ||
&& astUtil.isCallExpression(node.value) | ||
&& propWrapperUtil.isPropWrapperFunction( | ||
@@ -345,3 +348,3 @@ context, | ||
if ( | ||
right.type === 'CallExpression' | ||
astUtil.isCallExpression(right) | ||
&& propWrapperUtil.isPropWrapperFunction( | ||
@@ -348,0 +351,0 @@ context, |
@@ -76,8 +76,9 @@ /** | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if React.forwardRef is nested inside React.memo, false if not. | ||
* @returns {boolean} True if React.forwardRef is nested inside React.memo, false if not. | ||
*/ | ||
function isNestedMemo(node) { | ||
const argumentIsCallExpression = node.arguments && node.arguments[0] && node.arguments[0].type === 'CallExpression'; | ||
return node.type === 'CallExpression' && argumentIsCallExpression && utils.isPragmaComponentWrapper(node); | ||
return astUtil.isCallExpression(node) | ||
&& node.arguments | ||
&& astUtil.isCallExpression(node.arguments[0]) | ||
&& utils.isPragmaComponentWrapper(node); | ||
} | ||
@@ -115,3 +116,3 @@ | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if component has a name, false if not. | ||
* @returns {boolean} True if component has a name, false if not. | ||
*/ | ||
@@ -203,3 +204,3 @@ function hasTranspilerName(node) { | ||
} | ||
markDisplayNameAsDeclared(component.node.type === 'TSAsExpression' ? component.node.expression : component.node); | ||
markDisplayNameAsDeclared(astUtil.unwrapTSAsExpression(component.node)); | ||
}, | ||
@@ -206,0 +207,0 @@ |
@@ -137,3 +137,3 @@ /** | ||
} | ||
if (value.type === 'CallExpression') { | ||
if (astUtil.isCallExpression(value)) { | ||
if (!isPropTypesPackage(value.callee)) { | ||
@@ -162,25 +162,21 @@ return; | ||
function checkNode(node) { | ||
switch (node && node.type) { | ||
case 'ObjectExpression': | ||
checkProperties(node.properties); | ||
break; | ||
case 'Identifier': { | ||
const propTypesObject = variableUtil.findVariableByName(context, node, node.name); | ||
if (propTypesObject && propTypesObject.properties) { | ||
checkProperties(propTypesObject.properties); | ||
} | ||
break; | ||
if (!node) { | ||
return; | ||
} | ||
if (node.type === 'ObjectExpression') { | ||
checkProperties(node.properties); | ||
} else if (node.type === 'Identifier') { | ||
const propTypesObject = variableUtil.findVariableByName(context, node, node.name); | ||
if (propTypesObject && propTypesObject.properties) { | ||
checkProperties(propTypesObject.properties); | ||
} | ||
case 'CallExpression': { | ||
const innerNode = node.arguments && node.arguments[0]; | ||
if ( | ||
propWrapperUtil.isPropWrapperFunction(context, getText(context, node.callee)) | ||
} else if (astUtil.isCallExpression(node)) { | ||
const innerNode = node.arguments && node.arguments[0]; | ||
if ( | ||
propWrapperUtil.isPropWrapperFunction(context, getText(context, node.callee)) | ||
&& innerNode | ||
) { | ||
checkNode(innerNode); | ||
} | ||
break; | ||
) { | ||
checkNode(innerNode); | ||
} | ||
default: | ||
break; | ||
} | ||
@@ -187,0 +183,0 @@ } |
@@ -103,3 +103,3 @@ /** | ||
* @param {Object} tokens Locations of the opening bracket, closing bracket and last prop | ||
* @return {String} Expected location for the closing bracket | ||
* @return {string} Expected location for the closing bracket | ||
*/ | ||
@@ -125,3 +125,3 @@ function getExpectedLocation(tokens) { | ||
* @param {Object} tokens Locations of the opening bracket, closing bracket and last prop | ||
* @param {String} expectedLocation Expected location for the closing bracket | ||
* @param {string} expectedLocation Expected location for the closing bracket | ||
* @return {?Number} The correct column for the closing bracket, or null | ||
@@ -145,4 +145,4 @@ */ | ||
* @param {Object} tokens Locations of the opening bracket, closing bracket and last prop | ||
* @param {String} expectedLocation Expected location for the closing bracket | ||
* @return {Boolean} True if the closing bracket is correctly located, false if not | ||
* @param {string} expectedLocation Expected location for the closing bracket | ||
* @return {boolean} True if the closing bracket is correctly located, false if not | ||
*/ | ||
@@ -169,5 +169,5 @@ function hasCorrectLocation(tokens, expectedLocation) { | ||
* @param {Object} tokens Locations of the opening bracket, closing bracket and last prop | ||
* @param {String} expectedLocation Expected location for the closing bracket | ||
* @param {Number} [correctColumn] Expected column for the closing bracket. Default to 0 | ||
* @return {String} The characters used for indentation | ||
* @param {string} expectedLocation Expected location for the closing bracket | ||
* @param {number} [correctColumn] Expected column for the closing bracket. Default to 0 | ||
* @return {string} The characters used for indentation | ||
*/ | ||
@@ -242,3 +242,3 @@ function getIndentation(tokens, expectedLocation, correctColumn) { | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {String} Unique ID (based on its range) | ||
* @returns {string} Unique ID (based on its range) | ||
*/ | ||
@@ -245,0 +245,0 @@ function getOpeningElementId(node) { |
@@ -34,2 +34,104 @@ /** | ||
const HTML_ENTITY_REGEX = () => /&[A-Za-z\d#]+;/g; | ||
function containsLineTerminators(rawStringValue) { | ||
return /[\n\r\u2028\u2029]/.test(rawStringValue); | ||
} | ||
function containsBackslash(rawStringValue) { | ||
return arrayIncludes(rawStringValue, '\\'); | ||
} | ||
function containsHTMLEntity(rawStringValue) { | ||
return HTML_ENTITY_REGEX().test(rawStringValue); | ||
} | ||
function containsOnlyHtmlEntities(rawStringValue) { | ||
return rawStringValue.replace(HTML_ENTITY_REGEX(), '').trim() === ''; | ||
} | ||
function containsDisallowedJSXTextChars(rawStringValue) { | ||
return /[{<>}]/.test(rawStringValue); | ||
} | ||
function containsQuoteCharacters(value) { | ||
return /['"]/.test(value); | ||
} | ||
function containsMultilineComment(value) { | ||
return /\/\*/.test(value); | ||
} | ||
function escapeDoubleQuotes(rawStringValue) { | ||
return rawStringValue.replace(/\\"/g, '"').replace(/"/g, '\\"'); | ||
} | ||
function escapeBackslashes(rawStringValue) { | ||
return rawStringValue.replace(/\\/g, '\\\\'); | ||
} | ||
function needToEscapeCharacterForJSX(raw, node) { | ||
return ( | ||
containsBackslash(raw) | ||
|| containsHTMLEntity(raw) | ||
|| (node.parent.type !== 'JSXAttribute' && containsDisallowedJSXTextChars(raw)) | ||
); | ||
} | ||
function containsWhitespaceExpression(child) { | ||
if (child.type === 'JSXExpressionContainer') { | ||
const value = child.expression.value; | ||
return value ? jsxUtil.isWhiteSpaces(value) : false; | ||
} | ||
return false; | ||
} | ||
function isLineBreak(text) { | ||
return containsLineTerminators(text) && text.trim() === ''; | ||
} | ||
function wrapNonHTMLEntities(text) { | ||
const HTML_ENTITY = '<HTML_ENTITY>'; | ||
const withCurlyBraces = text.split(HTML_ENTITY_REGEX()).map((word) => ( | ||
word === '' ? '' : `{${JSON.stringify(word)}}` | ||
)).join(HTML_ENTITY); | ||
const htmlEntities = text.match(HTML_ENTITY_REGEX()); | ||
return htmlEntities.reduce((acc, htmlEntity) => ( | ||
acc.replace(HTML_ENTITY, htmlEntity) | ||
), withCurlyBraces); | ||
} | ||
function wrapWithCurlyBraces(rawText) { | ||
if (!containsLineTerminators(rawText)) { | ||
return `{${JSON.stringify(rawText)}}`; | ||
} | ||
return rawText.split('\n').map((line) => { | ||
if (line.trim() === '') { | ||
return line; | ||
} | ||
const firstCharIndex = line.search(/[^\s]/); | ||
const leftWhitespace = line.slice(0, firstCharIndex); | ||
const text = line.slice(firstCharIndex); | ||
if (containsHTMLEntity(line)) { | ||
return `${leftWhitespace}${wrapNonHTMLEntities(text)}`; | ||
} | ||
return `${leftWhitespace}{${JSON.stringify(text)}}`; | ||
}).join('\n'); | ||
} | ||
function isWhiteSpaceLiteral(node) { | ||
return node.type && node.type === 'Literal' && node.value && jsxUtil.isWhiteSpaces(node.value); | ||
} | ||
function isStringWithTrailingWhiteSpaces(value) { | ||
return /^\s|\s$/.test(value); | ||
} | ||
function isLiteralWithTrailingWhiteSpaces(node) { | ||
return node.type && node.type === 'Literal' && node.value && isStringWithTrailingWhiteSpaces(node.value); | ||
} | ||
// ------------------------------------------------------------------------------ | ||
@@ -78,3 +180,2 @@ // Rule Definition | ||
create(context) { | ||
const HTML_ENTITY_REGEX = () => /&[A-Za-z\d#]+;/g; | ||
const ruleOptions = context.options[0]; | ||
@@ -85,90 +186,2 @@ const userConfig = typeof ruleOptions === 'string' | ||
function containsLineTerminators(rawStringValue) { | ||
return /[\n\r\u2028\u2029]/.test(rawStringValue); | ||
} | ||
function containsBackslash(rawStringValue) { | ||
return arrayIncludes(rawStringValue, '\\'); | ||
} | ||
function containsHTMLEntity(rawStringValue) { | ||
return HTML_ENTITY_REGEX().test(rawStringValue); | ||
} | ||
function containsOnlyHtmlEntities(rawStringValue) { | ||
return rawStringValue.replace(HTML_ENTITY_REGEX(), '').trim() === ''; | ||
} | ||
function containsDisallowedJSXTextChars(rawStringValue) { | ||
return /[{<>}]/.test(rawStringValue); | ||
} | ||
function containsQuoteCharacters(value) { | ||
return /['"]/.test(value); | ||
} | ||
function containsMultilineComment(value) { | ||
return /\/\*/.test(value); | ||
} | ||
function escapeDoubleQuotes(rawStringValue) { | ||
return rawStringValue.replace(/\\"/g, '"').replace(/"/g, '\\"'); | ||
} | ||
function escapeBackslashes(rawStringValue) { | ||
return rawStringValue.replace(/\\/g, '\\\\'); | ||
} | ||
function needToEscapeCharacterForJSX(raw, node) { | ||
return ( | ||
containsBackslash(raw) | ||
|| containsHTMLEntity(raw) | ||
|| (node.parent.type !== 'JSXAttribute' && containsDisallowedJSXTextChars(raw)) | ||
); | ||
} | ||
function containsWhitespaceExpression(child) { | ||
if (child.type === 'JSXExpressionContainer') { | ||
const value = child.expression.value; | ||
return value ? jsxUtil.isWhiteSpaces(value) : false; | ||
} | ||
return false; | ||
} | ||
function isLineBreak(text) { | ||
return containsLineTerminators(text) && text.trim() === ''; | ||
} | ||
function wrapNonHTMLEntities(text) { | ||
const HTML_ENTITY = '<HTML_ENTITY>'; | ||
const withCurlyBraces = text.split(HTML_ENTITY_REGEX()).map((word) => ( | ||
word === '' ? '' : `{${JSON.stringify(word)}}` | ||
)).join(HTML_ENTITY); | ||
const htmlEntities = text.match(HTML_ENTITY_REGEX()); | ||
return htmlEntities.reduce((acc, htmlEntity) => ( | ||
acc.replace(HTML_ENTITY, htmlEntity) | ||
), withCurlyBraces); | ||
} | ||
function wrapWithCurlyBraces(rawText) { | ||
if (!containsLineTerminators(rawText)) { | ||
return `{${JSON.stringify(rawText)}}`; | ||
} | ||
return rawText.split('\n').map((line) => { | ||
if (line.trim() === '') { | ||
return line; | ||
} | ||
const firstCharIndex = line.search(/[^\s]/); | ||
const leftWhitespace = line.slice(0, firstCharIndex); | ||
const text = line.slice(firstCharIndex); | ||
if (containsHTMLEntity(line)) { | ||
return `${leftWhitespace}${wrapNonHTMLEntities(text)}`; | ||
} | ||
return `${leftWhitespace}{${JSON.stringify(text)}}`; | ||
}).join('\n'); | ||
} | ||
/** | ||
@@ -239,14 +252,2 @@ * Report and fix an unnecessary curly brace violation on a node | ||
function isWhiteSpaceLiteral(node) { | ||
return node.type && node.type === 'Literal' && node.value && jsxUtil.isWhiteSpaces(node.value); | ||
} | ||
function isStringWithTrailingWhiteSpaces(value) { | ||
return /^\s|\s$/.test(value); | ||
} | ||
function isLiteralWithTrailingWhiteSpaces(node) { | ||
return node.type && node.type === 'Literal' && node.value && isStringWithTrailingWhiteSpaces(node.value); | ||
} | ||
// Bail out if there is any character that needs to be escaped in JSX | ||
@@ -275,3 +276,3 @@ // because escaping decreases readability and the original code may be more | ||
jsxUtil.isJSX(JSXExpressionNode.parent) | ||
|| !containsQuoteCharacters(expression.value) | ||
|| (!containsQuoteCharacters(expression.value) || typeof expression.value === 'string') | ||
) | ||
@@ -278,0 +279,0 @@ ) { |
@@ -119,4 +119,4 @@ /** | ||
* @param {ASTNode} node Node violating the indent rule | ||
* @param {Number} needed Expected indentation character count | ||
* @param {Number} gotten Indentation character count in the actual node/code | ||
* @param {number} needed Expected indentation character count | ||
* @param {number} gotten Indentation character count in the actual node/code | ||
*/ | ||
@@ -145,3 +145,3 @@ function report(node, needed, gotten) { | ||
* @param {ASTNode} node Node to examine | ||
* @return {Number} Indent | ||
* @return {number} Indent | ||
*/ | ||
@@ -178,3 +178,3 @@ function getNodeIndent(node) { | ||
* @param {ASTNode[]} nodes list of node objects | ||
* @param {Number} indent needed indent | ||
* @param {number} indent needed indent | ||
*/ | ||
@@ -181,0 +181,0 @@ function checkNodesIndent(nodes, indent) { |
@@ -108,3 +108,3 @@ /** | ||
* @param {ASTNode} node Node violating the indent rule | ||
* @param {Number} needed Expected indentation character count | ||
* @param {number} needed Expected indentation character count | ||
* @returns {Function} function to be executed by the fixer | ||
@@ -150,4 +150,4 @@ * @private | ||
* @param {ASTNode} node Node violating the indent rule | ||
* @param {Number} needed Expected indentation character count | ||
* @param {Number} gotten Indentation character count in the actual node/code | ||
* @param {number} needed Expected indentation character count | ||
* @param {number} gotten Indentation character count in the actual node/code | ||
* @param {Object} [loc] Error line and column location | ||
@@ -173,5 +173,5 @@ */ | ||
* @param {ASTNode} node Node to examine | ||
* @param {Boolean} [byLastLine] get indent of node's last line | ||
* @param {Boolean} [excludeCommas] skip comma on start of line | ||
* @return {Number} Indent | ||
* @param {boolean} [byLastLine] get indent of node's last line | ||
* @param {boolean} [excludeCommas] skip comma on start of line | ||
* @return {number} Indent | ||
*/ | ||
@@ -203,3 +203,3 @@ function getNodeIndent(node, byLastLine, excludeCommas) { | ||
* @param {ASTNode} node The node to check | ||
* @return {Boolean} true if its the case, false if not | ||
* @return {boolean} true if its the case, false if not | ||
*/ | ||
@@ -219,3 +219,3 @@ function isRightInLogicalExp(node) { | ||
* @param {ASTNode} node The node to check | ||
* @return {Boolean} true if its the case, false if not | ||
* @return {boolean} true if its the case, false if not | ||
*/ | ||
@@ -235,3 +235,3 @@ function isAlternateInConditionalExp(node) { | ||
* @param {ASTNode} node The node to check | ||
* @return {Boolean} true if its the case, false if not | ||
* @return {boolean} true if its the case, false if not | ||
*/ | ||
@@ -307,4 +307,4 @@ function isSecondOrSubsequentExpWithinDoExp(node) { | ||
* @param {ASTNode} node The node to check | ||
* @param {Number} indent needed indent | ||
* @param {Boolean} [excludeCommas] skip comma on start of line | ||
* @param {number} indent needed indent | ||
* @param {boolean} [excludeCommas] skip comma on start of line | ||
*/ | ||
@@ -328,3 +328,3 @@ function checkNodesIndent(node, indent, excludeCommas) { | ||
* @param {ASTNode} node The node to check | ||
* @param {Number} indent needed indent | ||
* @param {number} indent needed indent | ||
*/ | ||
@@ -331,0 +331,0 @@ function checkLiteralNodeIndent(node, indent) { |
@@ -12,2 +12,3 @@ /** | ||
const docsUrl = require('../util/docsUrl'); | ||
const astUtil = require('../util/ast'); | ||
const jsxUtil = require('../util/jsx'); | ||
@@ -87,6 +88,5 @@ const report = require('../util/report'); | ||
function getNodeViolationType(node) { | ||
const nodeType = node.type; | ||
if ( | ||
!configuration.allowBind | ||
&& nodeType === 'CallExpression' | ||
&& astUtil.isCallExpression(node) | ||
&& node.callee.type === 'MemberExpression' | ||
@@ -98,3 +98,3 @@ && node.callee.property.type === 'Identifier' | ||
} | ||
if (nodeType === 'ConditionalExpression') { | ||
if (node.type === 'ConditionalExpression') { | ||
return getNodeViolationType(node.test) | ||
@@ -104,3 +104,3 @@ || getNodeViolationType(node.consequent) | ||
} | ||
if (!configuration.allowArrowFunctions && nodeType === 'ArrowFunctionExpression') { | ||
if (!configuration.allowArrowFunctions && node.type === 'ArrowFunctionExpression') { | ||
return 'arrowFunc'; | ||
@@ -110,7 +110,7 @@ } | ||
!configuration.allowFunctions | ||
&& (nodeType === 'FunctionExpression' || nodeType === 'FunctionDeclaration') | ||
&& (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration') | ||
) { | ||
return 'func'; | ||
} | ||
if (!configuration.allowBind && nodeType === 'BindExpression') { | ||
if (!configuration.allowBind && node.type === 'BindExpression') { | ||
return 'bindExpression'; | ||
@@ -117,0 +117,0 @@ } |
@@ -77,4 +77,3 @@ /** | ||
function defaultMessageId() { | ||
const ancestorIsJSXElement = arguments.length >= 1 && arguments[0]; | ||
function defaultMessageId(ancestorIsJSXElement) { | ||
if (config.noAttributeStrings && !ancestorIsJSXElement) { | ||
@@ -81,0 +80,0 @@ return 'noStringsInAttributes'; |
@@ -73,3 +73,3 @@ /** | ||
* @param {ASTNode} targetValue The AST node being checked. | ||
* @returns {String | String[] | null} The string value, or null if not a string. | ||
* @returns {string | string[] | null} The string value, or null if not a string. | ||
*/ | ||
@@ -76,0 +76,0 @@ function getStringFromValue(value, targetValue) { |
@@ -10,2 +10,3 @@ /** | ||
const pragmaUtil = require('../util/pragma'); | ||
const astUtil = require('../util/ast'); | ||
const jsxUtil = require('../util/jsx'); | ||
@@ -79,4 +80,3 @@ const docsUrl = require('../util/docsUrl'); | ||
&& node.type === 'JSXExpressionContainer' | ||
&& node.expression | ||
&& node.expression.type === 'CallExpression'; | ||
&& astUtil.isCallExpression(node.expression); | ||
} | ||
@@ -83,0 +83,0 @@ |
@@ -60,3 +60,3 @@ /** | ||
* @param {Object} node - Property. | ||
* @returns {String} Property name. | ||
* @returns {string} Property name. | ||
*/ | ||
@@ -82,3 +82,3 @@ function getPropertyName(node) { | ||
* @param {ASTNode} node The node to check. Must be an Identifier node. | ||
* @returns {Boolean} `true` if the node is a defaultProps declaration, `false` if not | ||
* @returns {boolean} `true` if the node is a defaultProps declaration, `false` if not | ||
*/ | ||
@@ -85,0 +85,0 @@ function isDefaultPropsDeclaration(node) { |
@@ -15,2 +15,3 @@ /** | ||
const report = require('../util/report'); | ||
const propTypesSortUtil = require('../util/propTypesSort'); | ||
const eslintUtil = require('../util/eslint'); | ||
@@ -25,6 +26,2 @@ | ||
function isCallbackPropName(name) { | ||
return /^on[A-Z]/.test(name); | ||
} | ||
function isMultilineProp(node) { | ||
@@ -90,4 +87,4 @@ return node.loc.start.line !== node.loc.end.line; | ||
if (options.callbacksLast) { | ||
const aIsCallback = isCallbackPropName(aProp); | ||
const bIsCallback = isCallbackPropName(bProp); | ||
const aIsCallback = propTypesSortUtil.isCallbackPropName(aProp); | ||
const bIsCallback = propTypesSortUtil.isCallbackPropName(bProp); | ||
if (aIsCallback && !bIsCallback) { | ||
@@ -285,4 +282,4 @@ return 1; | ||
* @param {Object} context The context of the rule | ||
* @param {Boolean|Array<String>} reservedFirst The `reservedFirst` option | ||
* @return {Function|undefined} If an error is detected, a function to generate the error message, otherwise, `undefined` | ||
* @param {boolean | string[]} reservedFirst The `reservedFirst` option | ||
* @return {Function | undefined} If an error is detected, a function to generate the error message, otherwise, `undefined` | ||
*/ | ||
@@ -432,4 +429,4 @@ // eslint-disable-next-line consistent-return | ||
const currentValue = decl.value; | ||
const previousIsCallback = isCallbackPropName(previousPropName); | ||
const currentIsCallback = isCallbackPropName(currentPropName); | ||
const previousIsCallback = propTypesSortUtil.isCallbackPropName(previousPropName); | ||
const currentIsCallback = propTypesSortUtil.isCallbackPropName(currentPropName); | ||
@@ -436,0 +433,0 @@ if (ignoreCase) { |
@@ -9,2 +9,3 @@ /** | ||
const docsUrl = require('../util/docsUrl'); | ||
const astUtil = require('../util/ast'); | ||
const componentUtil = require('../util/componentUtil'); | ||
@@ -36,3 +37,3 @@ const report = require('../util/report'); | ||
function isSetStateCall(node) { | ||
return node.type === 'CallExpression' | ||
return astUtil.isCallExpression(node) | ||
&& node.callee.property | ||
@@ -39,0 +40,0 @@ && node.callee.property.name === 'setState' |
@@ -11,2 +11,3 @@ /** | ||
const report = require('../util/report'); | ||
const astUtil = require('../util/ast'); | ||
@@ -66,3 +67,3 @@ // ------------------------------------------------------------------------------ | ||
} | ||
if (node.type === 'CallExpression' && inlineNames.indexOf(node.arguments[0].value) > -1) { | ||
if (astUtil.isCallExpression(node) && inlineNames.indexOf(node.arguments[0].value) > -1) { | ||
return true; | ||
@@ -69,0 +70,0 @@ } |
@@ -192,10 +192,11 @@ /** | ||
if (node.type === 'CallExpression' | ||
&& node.callee | ||
&& node.callee.type === 'MemberExpression' | ||
&& node.callee.object | ||
&& isArrayIndex(node.callee.object) | ||
&& node.callee.property | ||
&& node.callee.property.type === 'Identifier' | ||
&& node.callee.property.name === 'toString' | ||
if ( | ||
astUtil.isCallExpression(node) | ||
&& node.callee | ||
&& node.callee.type === 'MemberExpression' | ||
&& node.callee.object | ||
&& isArrayIndex(node.callee.object) | ||
&& node.callee.property | ||
&& node.callee.property.type === 'Identifier' | ||
&& node.callee.property.name === 'toString' | ||
) { | ||
@@ -209,9 +210,10 @@ // key={bar.toString()} | ||
if (node.type === 'CallExpression' | ||
&& node.callee | ||
&& node.callee.type === 'Identifier' | ||
&& node.callee.name === 'String' | ||
&& Array.isArray(node.arguments) | ||
&& node.arguments.length > 0 | ||
&& isArrayIndex(node.arguments[0]) | ||
if ( | ||
astUtil.isCallExpression(node) | ||
&& node.callee | ||
&& node.callee.type === 'Identifier' | ||
&& node.callee.name === 'String' | ||
&& Array.isArray(node.arguments) | ||
&& node.arguments.length > 0 | ||
&& isArrayIndex(node.arguments[0]) | ||
) { | ||
@@ -218,0 +220,0 @@ // key={String(bar)} |
@@ -20,3 +20,3 @@ /** | ||
* @param {Context} context - The AST node being checked. | ||
* @returns {Boolean} - True if node is a createElement call with a props | ||
* @returns {boolean} - True if node is a createElement call with a props | ||
* object literal, False if not. | ||
@@ -23,0 +23,0 @@ */ |
@@ -88,3 +88,3 @@ /** | ||
* @param {ASTNode} node The AST node being checked | ||
* @returns {Boolean} True if node is a line break, false if not | ||
* @returns {boolean} True if node is a line break, false if not | ||
*/ | ||
@@ -91,0 +91,0 @@ function isLineBreak(node) { |
@@ -32,3 +32,3 @@ /** | ||
* Checks if a JSX attribute is dangerous. | ||
* @param {String} name - Name of the attribute to check. | ||
* @param {string} name - Name of the attribute to check. | ||
* @returns {boolean} Whether or not the attribute is dangerous. | ||
@@ -35,0 +35,0 @@ */ |
@@ -41,6 +41,6 @@ /** | ||
* @param {Object} component The component to process | ||
* @returns {Boolean} True if the component is valid, false if not. | ||
* @returns {boolean} True if the component is valid, false if not. | ||
*/ | ||
function isValid(component) { | ||
return Boolean(component && !component.mutateSetState); | ||
return !!component && !component.mutateSetState; | ||
} | ||
@@ -77,3 +77,3 @@ | ||
* @param {?Object} component The component to process | ||
* @returns {Boolean} True if we should skip assignment checks. | ||
* @returns {boolean} True if we should skip assignment checks. | ||
*/ | ||
@@ -80,0 +80,0 @@ function shouldIgnoreComponent(component) { |
@@ -38,4 +38,7 @@ /** | ||
const isfindDOMNode = (callee.name === 'findDOMNode') | ||
|| (callee.property && callee.property.name === 'findDOMNode'); | ||
const isfindDOMNode = callee.name === 'findDOMNode' || ( | ||
callee.property | ||
&& callee.property.name === 'findDOMNode' | ||
); | ||
if (!isfindDOMNode) { | ||
@@ -42,0 +45,0 @@ return; |
@@ -292,3 +292,3 @@ /** | ||
const singleAttributeParts = splitIntoRangedParts(node, /(\S+)/g); | ||
for (const singlePart of singleAttributeParts) { | ||
singleAttributeParts.forEach((singlePart) => { | ||
const allowedTags = VALID_VALUES.get(attributeName).get(singlePart.value); | ||
@@ -333,3 +333,3 @@ const reportingValue = singlePart.reportingValue; | ||
} | ||
} | ||
}); | ||
@@ -339,6 +339,4 @@ const allowedPairsForAttribute = VALID_PAIR_VALUES.get(attributeName); | ||
const pairAttributeParts = splitIntoRangedParts(node, /(?=(\b\S+\s*\S+))/g); | ||
for (const pairPart of pairAttributeParts) { | ||
for (const allowedPair of allowedPairsForAttribute) { | ||
const pairing = allowedPair[0]; | ||
const siblings = allowedPair[1]; | ||
pairAttributeParts.forEach((pairPart) => { | ||
allowedPairsForAttribute.forEach((siblings, pairing) => { | ||
const attributes = pairPart.reportingValue.split('\u0020'); | ||
@@ -363,8 +361,8 @@ const firstValue = attributes[0]; | ||
} | ||
} | ||
} | ||
}); | ||
}); | ||
} | ||
const whitespaceParts = splitIntoRangedParts(node, /(\s+)/g); | ||
for (const whitespacePart of whitespaceParts) { | ||
whitespaceParts.forEach((whitespacePart) => { | ||
const data = { attributeName }; | ||
@@ -393,3 +391,3 @@ | ||
} | ||
} | ||
}); | ||
} | ||
@@ -587,5 +585,5 @@ | ||
if (prop.value.type === 'ArrayExpression') { | ||
for (const value of prop.value.elements) { | ||
prop.value.elements.forEach((value) => { | ||
checkPropValidValue(context, node, value, attribute); | ||
} | ||
}); | ||
@@ -655,5 +653,5 @@ // eslint-disable-next-line no-continue | ||
for (const attribute of attributes) { | ||
attributes.forEach((attribute) => { | ||
checkCreateProps(context, node, attribute); | ||
} | ||
}); | ||
}, | ||
@@ -660,0 +658,0 @@ }; |
@@ -53,3 +53,3 @@ /** | ||
* @param {Object} component The component being checked. | ||
* @returns {Boolean} True if the component is ignored, false if not. | ||
* @returns {boolean} True if the component is ignored, false if not. | ||
*/ | ||
@@ -56,0 +56,0 @@ function isIgnored(component) { |
@@ -12,2 +12,3 @@ /** | ||
const docsUrl = require('../util/docsUrl'); | ||
const astUtil = require('../util/ast'); | ||
const report = require('../util/report'); | ||
@@ -59,3 +60,3 @@ | ||
} else if ( | ||
propDefaultValueType === 'CallExpression' | ||
astUtil.isCallExpression(propDefaultValue.right) | ||
&& propDefaultValue.right.callee.type === 'Identifier' | ||
@@ -62,0 +63,0 @@ && propDefaultValue.right.callee.name === 'Symbol' |
@@ -39,3 +39,3 @@ /** | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} Whether or not the property exists. | ||
* @returns {boolean} Whether or not the property exists. | ||
*/ | ||
@@ -53,3 +53,3 @@ function hasShouldComponentUpdate(node) { | ||
* @param {ASTNode} node The AST node being checked. | ||
* @return {String} The name of the node | ||
* @return {string} The name of the node | ||
*/ | ||
@@ -56,0 +56,0 @@ function getNodeName(node) { |
@@ -41,6 +41,6 @@ /** | ||
* @param {Object} component The component to process | ||
* @returns {Boolean} True if the component is valid, false if not. | ||
* @returns {boolean} True if the component is valid, false if not. | ||
*/ | ||
function isValid(component) { | ||
return Boolean(component && !component.useSetState); | ||
return !!component && !component.useSetState; | ||
} | ||
@@ -53,5 +53,4 @@ | ||
function reportSetStateUsages(component) { | ||
let setStateUsage; | ||
for (let i = 0, j = component.setStateUsages.length; i < j; i++) { | ||
setStateUsage = component.setStateUsages[i]; | ||
const setStateUsage = component.setStateUsages[i]; | ||
report(context, messages.noSetState, 'noSetState', { | ||
@@ -58,0 +57,0 @@ node: setStateUsage, |
@@ -49,3 +49,3 @@ /** | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if we are using refs, false if not. | ||
* @returns {boolean} True if we are using refs, false if not. | ||
*/ | ||
@@ -63,10 +63,8 @@ function isRefsUsage(node) { | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if we are using a ref attribute, false if not. | ||
* @returns {boolean} True if we are using a ref attribute, false if not. | ||
*/ | ||
function isRefAttribute(node) { | ||
return !!( | ||
node.type === 'JSXAttribute' | ||
&& node.name | ||
&& node.name.name === 'ref' | ||
); | ||
return node.type === 'JSXAttribute' | ||
&& !!node.name | ||
&& node.name.name === 'ref'; | ||
} | ||
@@ -77,10 +75,8 @@ | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if the node contains a string value, false if not. | ||
* @returns {boolean} True if the node contains a string value, false if not. | ||
*/ | ||
function containsStringLiteral(node) { | ||
return !!( | ||
node.value | ||
return !!node.value | ||
&& node.value.type === 'Literal' | ||
&& typeof node.value.value === 'string' | ||
); | ||
&& typeof node.value.value === 'string'; | ||
} | ||
@@ -91,12 +87,10 @@ | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if the node contains a string value within a jsx expression, false if not. | ||
* @returns {boolean} True if the node contains a string value within a jsx expression, false if not. | ||
*/ | ||
function containsStringExpressionContainer(node) { | ||
return !!( | ||
node.value | ||
return !!node.value | ||
&& node.value.type === 'JSXExpressionContainer' | ||
&& node.value.expression | ||
&& ((node.value.expression.type === 'Literal' && typeof node.value.expression.value === 'string') | ||
|| (node.value.expression.type === 'TemplateLiteral' && detectTemplateLiterals)) | ||
); | ||
|| (node.value.expression.type === 'TemplateLiteral' && detectTemplateLiterals)); | ||
} | ||
@@ -112,2 +106,3 @@ | ||
}, | ||
JSXAttribute(node) { | ||
@@ -114,0 +109,0 @@ if ( |
@@ -10,2 +10,3 @@ /** | ||
const docsUrl = require('../util/docsUrl'); | ||
const astUtil = require('../util/ast'); | ||
const componentUtil = require('../util/componentUtil'); | ||
@@ -113,7 +114,7 @@ const report = require('../util/report'); | ||
checkValidPropType(node.property); | ||
} else if (node.object.type === 'CallExpression') { | ||
} else if (astUtil.isCallExpression(node.object)) { | ||
checkValidPropTypeQualifier(node.property); | ||
checkValidCallExpression(node.object); | ||
} | ||
} else if (node.type === 'CallExpression') { | ||
} else if (astUtil.isCallExpression(node)) { | ||
checkValidCallExpression(node); | ||
@@ -199,3 +200,4 @@ } | ||
const propTypesSpecifier = node.specifiers.find((specifier) => ( | ||
specifier.imported && specifier.imported.name === 'PropTypes' | ||
specifier.imported | ||
&& specifier.imported.name === 'PropTypes' | ||
)); | ||
@@ -202,0 +204,0 @@ if (propTypesSpecifier) { |
@@ -418,4 +418,4 @@ /** | ||
* | ||
* @param {String} name - Attribute name to be normalized | ||
* @returns {String} Result | ||
* @param {string} name - Attribute name to be normalized | ||
* @returns {string} Result | ||
*/ | ||
@@ -432,3 +432,3 @@ function normalizeAttributeCase(name) { | ||
* | ||
* @param {String} name - Attribute name to be tested | ||
* @param {string} name - Attribute name to be tested | ||
* @returns {boolean} Result | ||
@@ -443,3 +443,3 @@ */ | ||
* | ||
* @param {String} name | ||
* @param {string} name | ||
* @returns {boolean} Result | ||
@@ -455,4 +455,4 @@ */ | ||
* | ||
* @param {String} name - Attribute name to be tested | ||
* @returns {Boolean} Result | ||
* @param {string} name - Attribute name to be tested | ||
* @returns {boolean} Result | ||
*/ | ||
@@ -467,6 +467,10 @@ | ||
* @param {JSXAttribute} node - JSXAttribute being tested. | ||
* @returns {String|null} tag name | ||
* @returns {string | null} tag name | ||
*/ | ||
function getTagName(node) { | ||
if (node && node.parent && node.parent.name && node.parent.name) { | ||
if ( | ||
node | ||
&& node.parent | ||
&& node.parent.name | ||
) { | ||
return node.parent.name.name; | ||
@@ -481,3 +485,3 @@ } | ||
* @param {JSXAttribute} node - JSXAttribute being tested. | ||
* @returns {Boolean} result | ||
* @returns {boolean} result | ||
*/ | ||
@@ -494,5 +498,5 @@ function tagNameHasDot(node) { | ||
* Get the standard name of the attribute. | ||
* @param {String} name - Name of the attribute. | ||
* @param {String} context - eslint context | ||
* @returns {String | undefined} The standard name of the attribute, or undefined if no standard name was found. | ||
* @param {string} name - Name of the attribute. | ||
* @param {string} context - eslint context | ||
* @returns {string | undefined} The standard name of the attribute, or undefined if no standard name was found. | ||
*/ | ||
@@ -602,3 +606,5 @@ function getStandardName(name, context) { | ||
// Some attributes are allowed on some tags only | ||
const allowedTags = has(ATTRIBUTE_TAGS_MAP, name) ? ATTRIBUTE_TAGS_MAP[/** @type {keyof ATTRIBUTE_TAGS_MAP} */ (name)] : null; | ||
const allowedTags = has(ATTRIBUTE_TAGS_MAP, name) | ||
? ATTRIBUTE_TAGS_MAP[/** @type {keyof ATTRIBUTE_TAGS_MAP} */ (name)] | ||
: null; | ||
if (tagName && allowedTags) { | ||
@@ -605,0 +611,0 @@ // Scenario 1A: Allowed attribute found where not supposed to, report it |
@@ -60,14 +60,11 @@ /** | ||
newMethod: 'componentDidMount', | ||
details: | ||
'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.', | ||
details: 'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.', | ||
}, | ||
UNSAFE_componentWillReceiveProps: { | ||
newMethod: 'getDerivedStateFromProps', | ||
details: | ||
'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.', | ||
details: 'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.', | ||
}, | ||
UNSAFE_componentWillUpdate: { | ||
newMethod: 'componentDidUpdate', | ||
details: | ||
'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.', | ||
details: 'See https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html.', | ||
}, | ||
@@ -74,0 +71,0 @@ }; |
@@ -10,2 +10,3 @@ /** | ||
const docsUrl = require('../util/docsUrl'); | ||
const astUtil = require('../util/ast'); | ||
const isCreateElement = require('../util/isCreateElement'); | ||
@@ -27,4 +28,4 @@ const report = require('../util/report'); | ||
* Generate error message with given parent component name | ||
* @param {String} parentName Name of the parent component, if known | ||
* @returns {String} Error message with parent component name | ||
* @param {string} parentName Name of the parent component, if known | ||
* @returns {string} Error message with parent component name | ||
*/ | ||
@@ -37,7 +38,7 @@ function generateErrorMessageWithParentName(parentName) { | ||
* Check whether given text starts with `render`. Comparison is case-sensitive. | ||
* @param {String} text Text to validate | ||
* @returns {Boolean} | ||
* @param {string} text Text to validate | ||
* @returns {boolean} | ||
*/ | ||
function startsWithRender(text) { | ||
return (text || '').startsWith('render'); | ||
return typeof text === 'string' && text.startsWith('render'); | ||
} | ||
@@ -68,8 +69,7 @@ | ||
* @param {Context} context eslint context | ||
* @returns {Boolean} True if node is a `createElement` call, false if not | ||
* @returns {boolean} True if node is a `createElement` call, false if not | ||
*/ | ||
function isCreateElementMatcher(node, context) { | ||
return ( | ||
node | ||
&& node.type === 'CallExpression' | ||
astUtil.isCallExpression(node) | ||
&& isCreateElement(context, node) | ||
@@ -82,3 +82,3 @@ ); | ||
* @param {ASTNode} node The AST node | ||
* @returns {Boolean} True if node is a `ObjectExpression`, false if not | ||
* @returns {boolean} True if node is a `ObjectExpression`, false if not | ||
*/ | ||
@@ -92,3 +92,3 @@ function isObjectExpressionMatcher(node) { | ||
* @param {ASTNode} node The AST node | ||
* @returns {Boolean} True if node is a `JSXExpressionContainer`, false if not | ||
* @returns {boolean} True if node is a `JSXExpressionContainer`, false if not | ||
*/ | ||
@@ -102,3 +102,3 @@ function isJSXExpressionContainerMatcher(node) { | ||
* @param {ASTNode} node The AST node | ||
* @returns {Boolean} True if node is a `JSXAttribute` of `JSXExpressionContainer`, false if not | ||
* @returns {boolean} True if node is a `JSXAttribute` of `JSXExpressionContainer`, false if not | ||
*/ | ||
@@ -117,3 +117,3 @@ function isJSXAttributeOfExpressionContainerMatcher(node) { | ||
* @param {ASTNode} node The AST node | ||
* @returns {Boolean} True if node is a `Property`, false if not | ||
* @returns {boolean} True if node is a `Property`, false if not | ||
*/ | ||
@@ -129,11 +129,2 @@ function isPropertyOfObjectExpressionMatcher(node) { | ||
/** | ||
* Matcher used to check whether given node is a `CallExpression` | ||
* @param {ASTNode} node The AST node | ||
* @returns {Boolean} True if node is a `CallExpression`, false if not | ||
*/ | ||
function isCallExpressionMatcher(node) { | ||
return node && node.type === 'CallExpression'; | ||
} | ||
/** | ||
* Check whether given node or its parent is directly inside `map` call | ||
@@ -144,3 +135,3 @@ * ```jsx | ||
* @param {ASTNode} node The AST node | ||
* @returns {Boolean} True if node is directly inside `map` call, false if not | ||
* @returns {boolean} True if node is directly inside `map` call, false if not | ||
*/ | ||
@@ -160,3 +151,3 @@ function isMapCall(node) { | ||
* @param {Context} context eslint context | ||
* @returns {Boolean} True if node is a `ReturnStatement` of a React hook, false if not | ||
* @returns {boolean} True if node is a `ReturnStatement` of a React hook, false if not | ||
*/ | ||
@@ -172,3 +163,3 @@ function isReturnStatementOfHook(node, context) { | ||
const callExpression = getClosestMatchingParent(node, context, isCallExpressionMatcher); | ||
const callExpression = getClosestMatchingParent(node, context, astUtil.isCallExpression); | ||
return ( | ||
@@ -189,3 +180,3 @@ callExpression | ||
* @param {Context} context eslint context | ||
* @returns {Boolean} True if component is declared inside a render prop, false if not | ||
* @returns {boolean} True if component is declared inside a render prop, false if not | ||
*/ | ||
@@ -247,3 +238,3 @@ function isComponentInRenderProp(node, context) { | ||
* @param {ASTNode} node The AST node | ||
* @returns {Boolean} True if component is declared inside a render property, false if not | ||
* @returns {boolean} True if component is declared inside a render property, false if not | ||
*/ | ||
@@ -264,3 +255,3 @@ function isDirectValueOfRenderProperty(node) { | ||
* @param {ASTNode} node The AST node of the component | ||
* @returns {String} Name of the component, if any | ||
* @returns {string} Name of the component, if any | ||
*/ | ||
@@ -321,3 +312,3 @@ function resolveComponentName(node) { | ||
* @param {ASTNode} node The AST node being checked | ||
* @returns {Boolean} True if node is inside class component's render block, false if not | ||
* @returns {boolean} True if node is inside class component's render block, false if not | ||
*/ | ||
@@ -350,3 +341,3 @@ function isInsideRenderMethod(node) { | ||
* @param {ASTNode} node The AST node being checked | ||
* @returns {Boolean} True if given node a function component declared inside class component, false if not | ||
* @returns {boolean} True if given node a function component declared inside class component, false if not | ||
*/ | ||
@@ -374,3 +365,3 @@ function isFunctionComponentInsideClassComponent(node) { | ||
* @param {ASTNode} node The AST node | ||
* @returns {Boolean} True if node is declare inside `createElement` call's props, false if not | ||
* @returns {boolean} True if node is declare inside `createElement` call's props, false if not | ||
*/ | ||
@@ -398,3 +389,3 @@ function isComponentInsideCreateElementsProp(node) { | ||
* @param {ASTNode} node The AST node being checked | ||
* @returns {Boolean} True if node is a component declared inside prop, false if not | ||
* @returns {boolean} True if node is a component declared inside prop, false if not | ||
*/ | ||
@@ -421,3 +412,3 @@ function isComponentInProp(node) { | ||
* @param {ASTNode} node The AST node being checked | ||
* @returns {Boolean} True if node is a stateless component returning non-JSX, false if not | ||
* @returns {boolean} True if node is a stateless component returning non-JSX, false if not | ||
*/ | ||
@@ -424,0 +415,0 @@ function isStatelessComponentReturningNull(node) { |
@@ -17,2 +17,11 @@ /** | ||
/** | ||
* Checks if the component must be validated | ||
* @param {Object} component The component to process | ||
* @returns {boolean} True if the component must be validated, false if not. | ||
*/ | ||
function mustBeValidated(component) { | ||
return !!component && !component.ignoreUnusedPropTypesValidation; | ||
} | ||
// ------------------------------------------------------------------------------ | ||
@@ -68,4 +77,4 @@ // Rule Definition | ||
* Checks if the prop is ignored | ||
* @param {String} name Name of the prop to check. | ||
* @returns {Boolean} True if the prop is ignored, false if not. | ||
* @param {string} name Name of the prop to check. | ||
* @returns {boolean} True if the prop is ignored, false if not. | ||
*/ | ||
@@ -77,18 +86,6 @@ function isIgnored(name) { | ||
/** | ||
* Checks if the component must be validated | ||
* @param {Object} component The component to process | ||
* @returns {Boolean} True if the component must be validated, false if not. | ||
*/ | ||
function mustBeValidated(component) { | ||
return Boolean( | ||
component | ||
&& !component.ignoreUnusedPropTypesValidation | ||
); | ||
} | ||
/** | ||
* Checks if a prop is used | ||
* @param {ASTNode} node The AST node being checked. | ||
* @param {Object} prop Declared prop object | ||
* @returns {Boolean} True if the prop is used, false if not. | ||
* @returns {boolean} True if the prop is used, false if not. | ||
*/ | ||
@@ -95,0 +92,0 @@ function isPropUsed(node, prop) { |
@@ -13,3 +13,3 @@ /** | ||
const docsUrl = require('../util/docsUrl'); | ||
const ast = require('../util/ast'); | ||
const astUtil = require('../util/ast'); | ||
const componentUtil = require('../util/componentUtil'); | ||
@@ -48,3 +48,3 @@ const report = require('../util/report'); | ||
function isThisExpression(node) { | ||
return ast.unwrapTSAsExpression(uncast(node)).type === 'ThisExpression'; | ||
return astUtil.unwrapTSAsExpression(uncast(node)).type === 'ThisExpression'; | ||
} | ||
@@ -70,3 +70,3 @@ | ||
function isSetStateCall(node) { | ||
const unwrappedCalleeNode = ast.unwrapTSAsExpression(node.callee); | ||
const unwrappedCalleeNode = astUtil.unwrapTSAsExpression(node.callee); | ||
@@ -180,3 +180,3 @@ return ( | ||
function handleStateDestructuring(node) { | ||
for (const prop of node.properties) { | ||
node.properties.forEach((prop) => { | ||
if (prop.type === 'Property') { | ||
@@ -190,3 +190,3 @@ addUsedStateField(prop.key); | ||
} | ||
} | ||
}); | ||
} | ||
@@ -197,3 +197,3 @@ | ||
function handleAssignment(left, right) { | ||
const unwrappedRight = ast.unwrapTSAsExpression(right); | ||
const unwrappedRight = astUtil.unwrapTSAsExpression(right); | ||
@@ -210,3 +210,3 @@ switch (left.type) { | ||
} else if (isThisExpression(unwrappedRight) && classInfo.aliases) { | ||
for (const prop of left.properties) { | ||
left.properties.forEach((prop) => { | ||
if (prop.type === 'Property' && getName(prop.key) === 'state') { | ||
@@ -220,3 +220,3 @@ const name = getName(prop.value); | ||
} | ||
} | ||
}); | ||
} | ||
@@ -231,3 +231,3 @@ break; | ||
// Report all unused state fields. | ||
for (const node of classInfo.stateFields) { | ||
classInfo.stateFields.forEach((node) => { | ||
const name = getName(node.key); | ||
@@ -242,3 +242,3 @@ if (!classInfo.usedStateFields.has(name)) { | ||
} | ||
} | ||
}); | ||
} | ||
@@ -305,4 +305,4 @@ | ||
const unwrappedNode = ast.unwrapTSAsExpression(node); | ||
const unwrappedArgumentNode = ast.unwrapTSAsExpression(unwrappedNode.arguments[0]); | ||
const unwrappedNode = astUtil.unwrapTSAsExpression(node); | ||
const unwrappedArgumentNode = astUtil.unwrapTSAsExpression(unwrappedNode.arguments[0]); | ||
@@ -322,3 +322,3 @@ // If we're looking at a `this.setState({})` invocation, record all the | ||
) { | ||
const unwrappedBodyNode = ast.unwrapTSAsExpression(unwrappedArgumentNode.body); | ||
const unwrappedBodyNode = astUtil.unwrapTSAsExpression(unwrappedArgumentNode.body); | ||
@@ -345,3 +345,3 @@ if (unwrappedBodyNode.type === 'ObjectExpression') { | ||
// expression, record all the fields of that object as state fields. | ||
const unwrappedValueNode = ast.unwrapTSAsExpression(node.value); | ||
const unwrappedValueNode = astUtil.unwrapTSAsExpression(node.value); | ||
@@ -468,4 +468,4 @@ const name = getName(node.key); | ||
const unwrappedLeft = ast.unwrapTSAsExpression(node.left); | ||
const unwrappedRight = ast.unwrapTSAsExpression(node.right); | ||
const unwrappedLeft = astUtil.unwrapTSAsExpression(node.left); | ||
const unwrappedRight = astUtil.unwrapTSAsExpression(node.right); | ||
@@ -510,3 +510,3 @@ // Check for assignments like `this.state = {}` | ||
} | ||
if (isStateReference(ast.unwrapTSAsExpression(node.object))) { | ||
if (isStateReference(astUtil.unwrapTSAsExpression(node.object))) { | ||
// If we see this.state[foo] access, give up. | ||
@@ -520,3 +520,3 @@ if (node.computed && node.property.type !== 'Literal') { | ||
// If we see a `this.state` access in a CallExpression, give up. | ||
} else if (isStateReference(node) && node.parent.type === 'CallExpression') { | ||
} else if (isStateReference(node) && astUtil.isCallExpression(node.parent)) { | ||
classInfo = null; | ||
@@ -523,0 +523,0 @@ } |
@@ -9,2 +9,3 @@ /** | ||
const docsUrl = require('../util/docsUrl'); | ||
const astUtil = require('../util/ast'); | ||
const propsUtil = require('../util/props'); | ||
@@ -85,4 +86,3 @@ const propWrapperUtil = require('../util/propWrapper'); | ||
return ( | ||
node | ||
&& node.type === 'CallExpression' | ||
astUtil.isCallExpression(node) | ||
&& !propWrapperUtil.isExactPropWrapperFunction(context, getText(context, node.callee)) | ||
@@ -89,0 +89,0 @@ ); |
@@ -73,3 +73,3 @@ /** | ||
&& body[0].type === 'ExpressionStatement' | ||
&& body[0].expression.type === 'CallExpression' | ||
&& astUtil.isCallExpression(body[0].expression) | ||
&& body[0].expression.callee.type === 'Super' | ||
@@ -195,3 +195,3 @@ ); | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if the node has at least one other property, false if not. | ||
* @returns {boolean} True if the node has at least one other property, false if not. | ||
*/ | ||
@@ -359,3 +359,5 @@ function hasOtherProperties(node) { | ||
} | ||
const isRender = blockNode && blockNode.key && blockNode.key.name === 'render'; | ||
const isRender = blockNode | ||
&& blockNode.key | ||
&& blockNode.key.name === 'render'; | ||
const allowNull = testReactVersion(context, '>= 15.0.0'); // Stateless components can return null since React 15 | ||
@@ -362,0 +364,0 @@ const isReturningJSX = utils.isReturningJSX(node, !allowNull); |
@@ -67,4 +67,4 @@ /** | ||
* Checks if the prop is ignored | ||
* @param {String} name Name of the prop to check. | ||
* @returns {Boolean} True if the prop is ignored, false if not. | ||
* @param {string} name Name of the prop to check. | ||
* @returns {boolean} True if the prop is ignored, false if not. | ||
*/ | ||
@@ -93,3 +93,3 @@ function isIgnored(name) { | ||
* @param {Object} declaredPropTypes Description of propTypes declared in the current component | ||
* @param {String[]} keyList Dot separated name of the prop to check. | ||
* @param {string[]} keyList Dot separated name of the prop to check. | ||
* @returns {boolean} True if the prop is declared, false if not. | ||
@@ -153,4 +153,4 @@ */ | ||
* @param {ASTNode} node The AST node being checked. | ||
* @param {String[]} names List of names of the prop to check. | ||
* @returns {Boolean} True if the prop is declared, false if not. | ||
* @param {string[]} names List of names of the prop to check. | ||
* @returns {boolean} True if the prop is declared, false if not. | ||
*/ | ||
@@ -196,3 +196,3 @@ function isDeclaredInComponent(node, names) { | ||
* @param {Array} list The all components to process | ||
* @returns {Boolean} True if the component is nested False if not. | ||
* @returns {boolean} True if the component is nested False if not. | ||
*/ | ||
@@ -199,0 +199,0 @@ function checkNestedComponent(component, list) { |
@@ -53,3 +53,3 @@ /** | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if node is decorated with a PureRenderMixin, false if not. | ||
* @returns {boolean} True if node is decorated with a PureRenderMixin, false if not. | ||
*/ | ||
@@ -81,3 +81,3 @@ function hasPureRenderDecorator(node) { | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if node is decorated name with a custom decorated, false if not. | ||
* @returns {boolean} True if node is decorated name with a custom decorated, false if not. | ||
*/ | ||
@@ -90,5 +90,6 @@ function hasCustomDecorator(node) { | ||
for (let j = 0, l = node.decorators.length; j < l; j++) { | ||
const expression = node.decorators[j].expression; | ||
if ( | ||
node.decorators[j].expression | ||
&& node.decorators[j].expression.name === allowDecorators[i] | ||
expression | ||
&& expression.name === allowDecorators[i] | ||
) { | ||
@@ -107,9 +108,6 @@ return true; | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if we are declaring a shouldComponentUpdate method, false if not. | ||
* @returns {boolean} True if we are declaring a shouldComponentUpdate method, false if not. | ||
*/ | ||
function isSCUDeclared(node) { | ||
return Boolean( | ||
node | ||
&& node.name === 'shouldComponentUpdate' | ||
); | ||
return !!node && node.name === 'shouldComponentUpdate'; | ||
} | ||
@@ -120,3 +118,3 @@ | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if we are declaring a PureRenderMixin method, false if not. | ||
* @returns {boolean} True if we are declaring a PureRenderMixin method, false if not. | ||
*/ | ||
@@ -134,4 +132,4 @@ function isPureRenderDeclared(node) { | ||
return Boolean( | ||
node | ||
return ( | ||
!!node | ||
&& node.key.name === 'mixins' | ||
@@ -138,0 +136,0 @@ && hasPR |
@@ -12,2 +12,27 @@ /** | ||
const optionDefaults = { component: true, html: true }; | ||
function isComponent(node) { | ||
return ( | ||
node.name | ||
&& (node.name.type === 'JSXIdentifier' || node.name.type === 'JSXMemberExpression') | ||
&& !jsxUtil.isDOMComponent(node) | ||
); | ||
} | ||
function childrenIsEmpty(node) { | ||
return node.parent.children.length === 0; | ||
} | ||
function childrenIsMultilineSpaces(node) { | ||
const childrens = node.parent.children; | ||
return ( | ||
childrens.length === 1 | ||
&& (childrens[0].type === 'Literal' || childrens[0].type === 'JSXText') | ||
&& childrens[0].value.indexOf('\n') !== -1 | ||
&& childrens[0].value.replace(/(?!\xA0)\s/g, '') === '' | ||
); | ||
} | ||
// ------------------------------------------------------------------------------ | ||
@@ -17,4 +42,2 @@ // Rule Definition | ||
const optionDefaults = { component: true, html: true }; | ||
const messages = { | ||
@@ -54,25 +77,2 @@ notSelfClosing: 'Empty components are self-closing', | ||
create(context) { | ||
function isComponent(node) { | ||
return ( | ||
node.name | ||
&& (node.name.type === 'JSXIdentifier' || node.name.type === 'JSXMemberExpression') | ||
&& !jsxUtil.isDOMComponent(node) | ||
); | ||
} | ||
function childrenIsEmpty(node) { | ||
return node.parent.children.length === 0; | ||
} | ||
function childrenIsMultilineSpaces(node) { | ||
const childrens = node.parent.children; | ||
return ( | ||
childrens.length === 1 | ||
&& (childrens[0].type === 'Literal' || childrens[0].type === 'JSXText') | ||
&& childrens[0].value.indexOf('\n') !== -1 | ||
&& childrens[0].value.replace(/(?!\xA0)\s/g, '') === '' | ||
); | ||
} | ||
function isShouldBeSelfClosed(node) { | ||
@@ -79,0 +79,0 @@ const configuration = Object.assign({}, optionDefaults, context.options[0]); |
@@ -237,3 +237,3 @@ /** | ||
* @param {Object} node - Property. | ||
* @returns {String} Property name. | ||
* @returns {string} Property name. | ||
*/ | ||
@@ -240,0 +240,0 @@ function getPropertyName(node) { |
@@ -55,3 +55,3 @@ /** | ||
* @param {Object} node - Property. | ||
* @returns {String} Property name. | ||
* @returns {string} Property name. | ||
*/ | ||
@@ -77,3 +77,3 @@ function getPropertyName(node) { | ||
* @param {ASTNode} node The node to check. Must be an Identifier node. | ||
* @returns {Boolean} `true` if the node is a defaultProps declaration, `false` if not | ||
* @returns {boolean} `true` if the node is a defaultProps declaration, `false` if not | ||
*/ | ||
@@ -80,0 +80,0 @@ function isDefaultPropsDeclaration(node) { |
@@ -7,2 +7,3 @@ /** | ||
const astUtil = require('../util/ast'); | ||
const variableUtil = require('../util/variable'); | ||
@@ -39,24 +40,2 @@ const propsUtil = require('../util/props'); | ||
function getValueName(node) { | ||
return node.type === 'Property' && node.value.property && node.value.property.name; | ||
} | ||
function isCallbackPropName(propName) { | ||
return /^on[A-Z]/.test(propName); | ||
} | ||
function isRequiredProp(node) { | ||
return getValueName(node) === 'isRequired'; | ||
} | ||
function isShapeProp(node) { | ||
return Boolean( | ||
node && node.callee && node.callee.property && node.callee.property.name === 'shape' | ||
); | ||
} | ||
function toLowerCase(item) { | ||
return String(item).toLowerCase(); | ||
} | ||
/** @type {import('eslint').Rule.RuleModule} */ | ||
@@ -150,10 +129,10 @@ module.exports = { | ||
let currentPropName = getKey(context, curr); | ||
const previousIsRequired = isRequiredProp(prev); | ||
const currentIsRequired = isRequiredProp(curr); | ||
const previousIsCallback = isCallbackPropName(prevPropName); | ||
const currentIsCallback = isCallbackPropName(currentPropName); | ||
const previousIsRequired = propTypesSortUtil.isRequiredProp(prev); | ||
const currentIsRequired = propTypesSortUtil.isRequiredProp(curr); | ||
const previousIsCallback = propTypesSortUtil.isCallbackPropName(prevPropName); | ||
const currentIsCallback = propTypesSortUtil.isCallbackPropName(currentPropName); | ||
if (ignoreCase) { | ||
prevPropName = toLowerCase(prevPropName); | ||
currentPropName = toLowerCase(currentPropName); | ||
prevPropName = String(prevPropName).toLowerCase(); | ||
currentPropName = String(currentPropName).toLowerCase(); | ||
} | ||
@@ -213,22 +192,18 @@ | ||
function checkNode(node) { | ||
switch (node && node.type) { | ||
case 'ObjectExpression': | ||
checkSorted(node.properties); | ||
break; | ||
case 'Identifier': { | ||
const propTypesObject = variableUtil.findVariableByName(context, node, node.name); | ||
if (propTypesObject && propTypesObject.properties) { | ||
checkSorted(propTypesObject.properties); | ||
} | ||
break; | ||
if (!node) { | ||
return; | ||
} | ||
if (node.type === 'ObjectExpression') { | ||
checkSorted(node.properties); | ||
} else if (node.type === 'Identifier') { | ||
const propTypesObject = variableUtil.findVariableByName(context, node, node.name); | ||
if (propTypesObject && propTypesObject.properties) { | ||
checkSorted(propTypesObject.properties); | ||
} | ||
case 'CallExpression': { | ||
const innerNode = node.arguments && node.arguments[0]; | ||
if (propWrapperUtil.isPropWrapperFunction(context, node.callee.name) && innerNode) { | ||
checkNode(innerNode); | ||
} | ||
break; | ||
} else if (astUtil.isCallExpression(node)) { | ||
const innerNode = node.arguments && node.arguments[0]; | ||
if (propWrapperUtil.isPropWrapperFunction(context, node.callee.name) && innerNode) { | ||
checkNode(innerNode); | ||
} | ||
default: | ||
break; | ||
} | ||
@@ -267,3 +242,3 @@ } | ||
CallExpression(node) { | ||
if (!sortShapeProp || !isShapeProp(node) || !(node.arguments && node.arguments[0])) { | ||
if (!sortShapeProp || !propTypesSortUtil.isShapeProp(node) || !(node.arguments && node.arguments[0])) { | ||
return; | ||
@@ -270,0 +245,0 @@ } |
@@ -102,3 +102,3 @@ /** | ||
* @param {ASTNode} node | ||
* @returns {Boolean} True if we are declaring context in class, false if not. | ||
* @returns {boolean} True if we are declaring context in class, false if not. | ||
*/ | ||
@@ -105,0 +105,0 @@ function isContextInClass(node) { |
@@ -15,3 +15,3 @@ /** | ||
* @param {Object} context | ||
* @returns {Boolean} True if the node is a type annotated props declaration, false if not. | ||
* @returns {boolean} True if the node is a type annotated props declaration, false if not. | ||
*/ | ||
@@ -18,0 +18,0 @@ function isAnnotatedFunctionPropsDeclaration(node, context) { |
@@ -95,3 +95,3 @@ /** | ||
/* TODO: properly warn on React.forwardRefs having typo properties | ||
if (nodeType === 'CallExpression') { | ||
if (astUtil.isCallExpression(ASTNode)) { | ||
const callee = ASTNode.callee; | ||
@@ -152,3 +152,7 @@ const pragma = pragmaUtil.getFromContext(context); | ||
function getPropertyNameNode(node) { | ||
if (node.key || ['MethodDefinition', 'Property'].indexOf(node.type) !== -1) { | ||
if ( | ||
node.key | ||
|| node.type === 'MethodDefinition' | ||
|| node.type === 'Property' | ||
) { | ||
return node.key; | ||
@@ -165,3 +169,3 @@ } | ||
* @param {Object} node - Property. | ||
* @returns {String} Property name. | ||
* @returns {string} Property name. | ||
*/ | ||
@@ -216,3 +220,3 @@ function getPropertyName(node) { | ||
* @param {ASTNode} node The node to check | ||
* @return {Boolean} true if it's the first node in its line | ||
* @return {boolean} true if it's the first node in its line | ||
*/ | ||
@@ -229,3 +233,3 @@ function isNodeFirstInLine(context, node) { | ||
* @param {ASTNode} node The node to check | ||
* @return {Boolean} true if it's a function-like expression | ||
* @return {boolean} true if it's a function-like expression | ||
*/ | ||
@@ -239,3 +243,3 @@ function isFunctionLikeExpression(node) { | ||
* @param {ASTNode} node The node to check | ||
* @return {Boolean} true if it's a function | ||
* @return {boolean} true if it's a function | ||
*/ | ||
@@ -249,3 +253,3 @@ function isFunction(node) { | ||
* @param {ASTNode} node The node to check | ||
* @return {Boolean} true if it's a function-like | ||
* @return {boolean} true if it's a function-like | ||
*/ | ||
@@ -259,3 +263,3 @@ function isFunctionLike(node) { | ||
* @param {ASTNode} node The node to check | ||
* @return {Boolean} true if it's a class | ||
* @return {boolean} true if it's a class | ||
*/ | ||
@@ -340,3 +344,3 @@ function isClass(node) { | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} | ||
* @returns {boolean} | ||
*/ | ||
@@ -351,3 +355,16 @@ function isAssignmentLHS(node) { | ||
function isTSAsExpression(node) { | ||
return node && node.type === 'TSAsExpression'; | ||
} | ||
/** | ||
* Matcher used to check whether given node is a `CallExpression` | ||
* @param {ASTNode} node The AST node | ||
* @returns {boolean} True if node is a `CallExpression`, false if not | ||
*/ | ||
function isCallExpression(node) { | ||
return node && node.type === 'CallExpression'; | ||
} | ||
/** | ||
* Extracts the expression node that is wrapped inside a TS type assertion | ||
@@ -359,4 +376,3 @@ * | ||
function unwrapTSAsExpression(node) { | ||
if (node && node.type === 'TSAsExpression') return node.expression; | ||
return node; | ||
return isTSAsExpression(node) ? node.expression : node; | ||
} | ||
@@ -366,114 +382,114 @@ | ||
if (!node) return false; | ||
const nodeType = node.type; | ||
return nodeType === 'TSTypeReference'; | ||
return node.type === 'TSTypeReference'; | ||
} | ||
function isTSTypeAnnotation(node) { | ||
if (!node) return false; | ||
const nodeType = node.type; | ||
return nodeType === 'TSTypeAnnotation'; | ||
if (!node) { return false; } | ||
return node.type === 'TSTypeAnnotation'; | ||
} | ||
function isTSTypeLiteral(node) { | ||
if (!node) return false; | ||
const nodeType = node.type; | ||
return nodeType === 'TSTypeLiteral'; | ||
if (!node) { return false; } | ||
return node.type === 'TSTypeLiteral'; | ||
} | ||
function isTSIntersectionType(node) { | ||
if (!node) return false; | ||
const nodeType = node.type; | ||
return nodeType === 'TSIntersectionType'; | ||
if (!node) { return false; } | ||
return node.type === 'TSIntersectionType'; | ||
} | ||
function isTSInterfaceHeritage(node) { | ||
if (!node) return false; | ||
const nodeType = node.type; | ||
return nodeType === 'TSInterfaceHeritage'; | ||
if (!node) { return false; } | ||
return node.type === 'TSInterfaceHeritage'; | ||
} | ||
function isTSInterfaceDeclaration(node) { | ||
if (!node) return false; | ||
let nodeType = node.type; | ||
if (node.type === 'ExportNamedDeclaration' && node.declaration) { | ||
nodeType = node.declaration.type; | ||
} | ||
return nodeType === 'TSInterfaceDeclaration'; | ||
if (!node) { return false; } | ||
return (node.type === 'ExportNamedDeclaration' && node.declaration | ||
? node.declaration.type | ||
: node.type | ||
) === 'TSInterfaceDeclaration'; | ||
} | ||
function isTSTypeDeclaration(node) { | ||
if (!node) return false; | ||
let nodeType = node.type; | ||
let nodeKind = node.kind; | ||
if (node.type === 'ExportNamedDeclaration' && node.declaration) { | ||
nodeType = node.declaration.type; | ||
nodeKind = node.declaration.kind; | ||
} | ||
return nodeType === 'VariableDeclaration' && nodeKind === 'type'; | ||
if (!node) { return false; } | ||
const nodeToCheck = node.type === 'ExportNamedDeclaration' && node.declaration | ||
? node.declaration | ||
: node; | ||
return nodeToCheck.type === 'VariableDeclaration' && nodeToCheck.kind === 'type'; | ||
} | ||
function isTSTypeAliasDeclaration(node) { | ||
if (!node) return false; | ||
let nodeType = node.type; | ||
if (!node) { return false; } | ||
if (node.type === 'ExportNamedDeclaration' && node.declaration) { | ||
nodeType = node.declaration.type; | ||
return nodeType === 'TSTypeAliasDeclaration' && node.exportKind === 'type'; | ||
return node.declaration.type === 'TSTypeAliasDeclaration' && node.exportKind === 'type'; | ||
} | ||
return nodeType === 'TSTypeAliasDeclaration'; | ||
return node.type === 'TSTypeAliasDeclaration'; | ||
} | ||
function isTSParenthesizedType(node) { | ||
if (!node) return false; | ||
const nodeType = node.type; | ||
return nodeType === 'TSTypeAliasDeclaration'; | ||
if (!node) { return false; } | ||
return node.type === 'TSTypeAliasDeclaration'; | ||
} | ||
function isTSFunctionType(node) { | ||
if (!node) return false; | ||
const nodeType = node.type; | ||
return nodeType === 'TSFunctionType'; | ||
if (!node) { return false; } | ||
return node.type === 'TSFunctionType'; | ||
} | ||
function isTSTypeQuery(node) { | ||
if (!node) return false; | ||
const nodeType = node.type; | ||
return nodeType === 'TSTypeQuery'; | ||
if (!node) { return false; } | ||
return node.type === 'TSTypeQuery'; | ||
} | ||
function isTSTypeParameterInstantiation(node) { | ||
if (!node) return false; | ||
const nodeType = node.type; | ||
return nodeType === 'TSTypeParameterInstantiation'; | ||
if (!node) { return false; } | ||
return node.type === 'TSTypeParameterInstantiation'; | ||
} | ||
module.exports = { | ||
traverse, | ||
findReturnStatement, | ||
getComponentProperties, | ||
getFirstNodeInLine, | ||
getKeyValue, | ||
getPropertyName, | ||
getPropertyNameNode, | ||
getComponentProperties, | ||
getKeyValue, | ||
isParenthesized, | ||
inConstructor, | ||
isAssignmentLHS, | ||
isCallExpression, | ||
isClass, | ||
isFunction, | ||
isFunctionLike, | ||
isFunctionLikeExpression, | ||
isFunctionLike, | ||
inConstructor, | ||
isNodeFirstInLine, | ||
unwrapTSAsExpression, | ||
traverseReturns, | ||
isTSTypeReference, | ||
isParenthesized, | ||
isTSAsExpression, | ||
isTSFunctionType, | ||
isTSInterfaceDeclaration, | ||
isTSInterfaceHeritage, | ||
isTSIntersectionType, | ||
isTSParenthesizedType, | ||
isTSTypeAliasDeclaration, | ||
isTSTypeAnnotation, | ||
isTSTypeDeclaration, | ||
isTSTypeLiteral, | ||
isTSIntersectionType, | ||
isTSInterfaceHeritage, | ||
isTSInterfaceDeclaration, | ||
isTSTypeAliasDeclaration, | ||
isTSParenthesizedType, | ||
isTSFunctionType, | ||
isTSTypeParameterInstantiation, | ||
isTSTypeQuery, | ||
isTSTypeParameterInstantiation, | ||
isTSTypeDeclaration, | ||
isTSTypeReference, | ||
traverse, | ||
traverseReturns, | ||
unwrapTSAsExpression, | ||
}; |
@@ -73,3 +73,3 @@ /** | ||
* @param {ASTNode} node The AST node being added. | ||
* @param {Number} confidence Confidence in the component detection (0=banned, 1=maybe, 2=yes) | ||
* @param {number} confidence Confidence in the component detection (0=banned, 1=maybe, 2=yes) | ||
* @returns {Object} Added component object | ||
@@ -187,3 +187,3 @@ */ | ||
* | ||
* @returns {Number} Components list length | ||
* @returns {number} Components list length | ||
*/ | ||
@@ -308,16 +308,16 @@ length() { | ||
/** | ||
* @param {ASTNode} ASTNode | ||
* @param {ASTNode} node | ||
* @param {boolean=} strict | ||
* @returns {boolean} | ||
*/ | ||
isReturningJSX(ASTNode, strict) { | ||
return jsxUtil.isReturningJSX(context, ASTNode, strict, true); | ||
isReturningJSX(node, strict) { | ||
return jsxUtil.isReturningJSX(context, node, strict, true); | ||
}, | ||
isReturningJSXOrNull(ASTNode, strict) { | ||
return jsxUtil.isReturningJSX(context, ASTNode, strict); | ||
isReturningJSXOrNull(node, strict) { | ||
return jsxUtil.isReturningJSX(context, node, strict); | ||
}, | ||
isReturningOnlyNull(ASTNode) { | ||
return jsxUtil.isReturningOnlyNull(ASTNode, context); | ||
isReturningOnlyNull(node) { | ||
return jsxUtil.isReturningOnlyNull(node, context); | ||
}, | ||
@@ -413,3 +413,3 @@ | ||
isPragmaComponentWrapper(node) { | ||
if (!node || node.type !== 'CallExpression') { | ||
if (!astUtil.isCallExpression(node)) { | ||
return false; | ||
@@ -574,3 +574,9 @@ } | ||
// 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)) { | ||
if ( | ||
node.parent | ||
&& node.parent.key | ||
&& node.parent.key.type === 'MemberExpression' | ||
&& !utils.isReturningJSX(node) | ||
&& !utils.isReturningOnlyNull(node) | ||
) { | ||
return undefined; | ||
@@ -585,3 +591,6 @@ } | ||
) { | ||
if (isFirstLetterCapitalized(node.parent.key.name) && utils.isReturningJSX(node)) { | ||
if ( | ||
isFirstLetterCapitalized(node.parent.key.name) | ||
&& utils.isReturningJSX(node) | ||
) { | ||
return node; | ||
@@ -650,3 +659,3 @@ } | ||
* @param {ASTNode} node The AST node being checked (must be a MemberExpression). | ||
* @returns {ASTNode} component node, null if we cannot find the component | ||
* @returns {ASTNode | null} component node, null if we cannot find the component | ||
*/ | ||
@@ -761,6 +770,6 @@ getRelatedComponent(node) { | ||
* @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 | ||
* @returns {boolean} True if the node is a call to a React hook | ||
*/ | ||
isReactHookCall(node, expectedHookNames) { | ||
if (node.type !== 'CallExpression') { | ||
if (!astUtil.isCallExpression(node)) { | ||
return false; | ||
@@ -809,4 +818,10 @@ } | ||
const hookResolvedDefs = potentialHookReference && potentialHookReference.resolved.defs; | ||
const localHookName = (isPotentialReactHookCall && node.callee.property.name) | ||
|| (isPotentialHookCall && potentialHookReference && node.callee.name); | ||
const localHookName = ( | ||
isPotentialReactHookCall | ||
&& node.callee.property.name | ||
) || ( | ||
isPotentialHookCall | ||
&& potentialHookReference | ||
&& node.callee.name | ||
); | ||
const isHookShadowed = isPotentialHookCall | ||
@@ -888,7 +903,7 @@ && hookResolvedDefs | ||
node = utils.getStatelessComponent(node); | ||
if (!node) { | ||
const cNode = utils.getStatelessComponent(node); | ||
if (!cNode) { | ||
return; | ||
} | ||
components.add(node, 2); | ||
components.add(cNode, 2); | ||
}, | ||
@@ -895,0 +910,0 @@ |
@@ -177,3 +177,5 @@ 'use strict'; | ||
function isStateMemberExpression(node) { | ||
return node.type === 'MemberExpression' && node.object.type === 'ThisExpression' && node.property.name === 'state'; | ||
return node.type === 'MemberExpression' | ||
&& node.object.type === 'ThisExpression' | ||
&& node.property.name === 'state'; | ||
} | ||
@@ -180,0 +182,0 @@ |
@@ -29,3 +29,3 @@ /** | ||
if ( | ||
node.type === 'CallExpression' | ||
astUtil.isCallExpression(node) | ||
&& propWrapperUtil.isPropWrapperFunction(context, node.callee.name) | ||
@@ -32,0 +32,0 @@ && node.arguments && node.arguments[0] |
@@ -5,3 +5,3 @@ 'use strict'; | ||
* Logs out a message if there is no format option set. | ||
* @param {String} message - Message to log. | ||
* @param {string} message - Message to log. | ||
*/ | ||
@@ -8,0 +8,0 @@ function error(message) { |
'use strict'; | ||
const astUtil = require('./ast'); | ||
/** | ||
* Checks if the node is a React.createContext call | ||
* @param {ASTNode} node - The AST node being checked. | ||
* @returns {Boolean} - True if node is a React.createContext call, false if not. | ||
* @returns {boolean} - True if node is a React.createContext call, false if not. | ||
*/ | ||
@@ -11,17 +13,18 @@ module.exports = function isCreateContext(node) { | ||
node.init | ||
&& node.init.type === 'CallExpression' | ||
&& node.init.callee | ||
&& node.init.callee.name === 'createContext' | ||
) { | ||
return true; | ||
} | ||
if ( | ||
astUtil.isCallExpression(node.init) | ||
&& node.init.callee.name === 'createContext' | ||
) { | ||
return true; | ||
} | ||
if ( | ||
node.init | ||
&& node.init.callee | ||
&& node.init.callee.type === 'MemberExpression' | ||
&& node.init.callee.property | ||
&& node.init.callee.property.name === 'createContext' | ||
) { | ||
return true; | ||
if ( | ||
node.init.callee.type === 'MemberExpression' | ||
&& node.init.callee.property | ||
&& node.init.callee.property.name === 'createContext' | ||
) { | ||
return true; | ||
} | ||
} | ||
@@ -33,20 +36,18 @@ | ||
&& node.expression.operator === '=' | ||
&& node.expression.right.type === 'CallExpression' | ||
&& astUtil.isCallExpression(node.expression.right) | ||
&& node.expression.right.callee | ||
&& node.expression.right.callee.name === 'createContext' | ||
) { | ||
return true; | ||
} | ||
const right = node.expression.right; | ||
if ( | ||
node.expression | ||
&& node.expression.type === 'AssignmentExpression' | ||
&& node.expression.operator === '=' | ||
&& node.expression.right.type === 'CallExpression' | ||
&& node.expression.right.callee | ||
&& node.expression.right.callee.type === 'MemberExpression' | ||
&& node.expression.right.callee.property | ||
&& node.expression.right.callee.property.name === 'createContext' | ||
) { | ||
return true; | ||
if (right.callee.name === 'createContext') { | ||
return true; | ||
} | ||
if ( | ||
right.callee.type === 'MemberExpression' | ||
&& right.callee.property | ||
&& right.callee.property.name === 'createContext' | ||
) { | ||
return true; | ||
} | ||
} | ||
@@ -53,0 +54,0 @@ |
@@ -13,5 +13,8 @@ 'use strict'; | ||
module.exports = function isCreateElement(context, node) { | ||
if (!node.callee) { | ||
return false; | ||
} | ||
if ( | ||
node.callee | ||
&& node.callee.type === 'MemberExpression' | ||
node.callee.type === 'MemberExpression' | ||
&& node.callee.property.name === 'createElement' | ||
@@ -25,5 +28,3 @@ && node.callee.object | ||
if ( | ||
node | ||
&& node.callee | ||
&& node.callee.name === 'createElement' | ||
node.callee.name === 'createElement' | ||
&& isDestructuredFromPragmaImport(context, node, 'createElement') | ||
@@ -30,0 +31,0 @@ ) { |
'use strict'; | ||
const astUtil = require('./ast'); | ||
const pragmaUtil = require('./pragma'); | ||
@@ -25,4 +26,4 @@ const variableUtil = require('./variable'); | ||
latestDef.node.init.type === 'MemberExpression' | ||
&& latestDef.node.init.object.type === 'Identifier' | ||
&& latestDef.node.init.object.name === pragma | ||
&& latestDef.node.init.object.type === 'Identifier' | ||
&& latestDef.node.init.object.name === pragma | ||
) { | ||
@@ -34,3 +35,3 @@ return true; | ||
latestDef.node.init.type === 'Identifier' | ||
&& latestDef.node.init.name === pragma | ||
&& latestDef.node.init.name === pragma | ||
) { | ||
@@ -44,3 +45,3 @@ return true; | ||
// get "require('react')" from: "{variable} = require('react')" | ||
if (latestDef.node.init.type === 'CallExpression') { | ||
if (astUtil.isCallExpression(latestDef.node.init)) { | ||
requireExpression = latestDef.node.init; | ||
@@ -51,4 +52,4 @@ } | ||
!requireExpression | ||
&& latestDef.node.init.type === 'MemberExpression' | ||
&& latestDef.node.init.object.type === 'CallExpression' | ||
&& latestDef.node.init.type === 'MemberExpression' | ||
&& astUtil.isCallExpression(latestDef.node.init.object) | ||
) { | ||
@@ -61,6 +62,6 @@ requireExpression = latestDef.node.init.object; | ||
requireExpression | ||
&& requireExpression.callee | ||
&& requireExpression.callee.name === 'require' | ||
&& requireExpression.arguments[0] | ||
&& requireExpression.arguments[0].value === pragma.toLocaleLowerCase() | ||
&& requireExpression.callee | ||
&& requireExpression.callee.name === 'require' | ||
&& requireExpression.arguments[0] | ||
&& requireExpression.arguments[0].value === pragma.toLocaleLowerCase() | ||
) { | ||
@@ -76,4 +77,4 @@ return true; | ||
latestDef.parent | ||
&& latestDef.parent.type === 'ImportDeclaration' | ||
&& latestDef.parent.source.value === pragma.toLocaleLowerCase() | ||
&& latestDef.parent.type === 'ImportDeclaration' | ||
&& latestDef.parent.source.value === pragma.toLocaleLowerCase() | ||
) { | ||
@@ -80,0 +81,0 @@ return true; |
@@ -5,6 +5,6 @@ 'use strict'; | ||
* Check if the first letter of a string is capitalized. | ||
* @param {String} word String to check | ||
* @returns {Boolean} True if first letter is capitalized. | ||
* @param {string} word String to check | ||
* @returns {boolean} True if first letter is capitalized. | ||
*/ | ||
function isFirstLetterCapitalized(word) { | ||
module.exports = function isFirstLetterCapitalized(word) { | ||
if (!word) { | ||
@@ -15,4 +15,2 @@ return false; | ||
return firstLetter.toUpperCase() === firstLetter; | ||
} | ||
module.exports = isFirstLetterCapitalized; | ||
}; |
@@ -79,3 +79,3 @@ /** | ||
* Check if value has only whitespaces | ||
* @param {string} value | ||
* @param {unknown} value | ||
* @returns {boolean} | ||
@@ -92,5 +92,5 @@ */ | ||
* @param {ASTNode} ASTnode The AST node being checked | ||
* @param {Boolean} [strict] If true, in a ternary condition the node must return JSX in both cases | ||
* @param {Boolean} [ignoreNull] If true, null return values will be ignored | ||
* @returns {Boolean} True if the node is returning JSX or null, false if not | ||
* @param {boolean} [strict] If true, in a ternary condition the node must return JSX in both cases | ||
* @param {boolean} [ignoreNull] If true, null return values will be ignored | ||
* @returns {boolean} True if the node is returning JSX or null, false if not | ||
*/ | ||
@@ -150,3 +150,3 @@ function isReturningJSX(context, ASTnode, strict, ignoreNull) { | ||
* @param {Context} context The context of `ASTNode`. | ||
* @returns {Boolean} True if the node is returning only null values | ||
* @returns {boolean} True if the node is returning only null values | ||
*/ | ||
@@ -153,0 +153,0 @@ function isReturningOnlyNull(ASTnode, context) { |
@@ -5,3 +5,3 @@ 'use strict'; | ||
* Logs out a message if there is no format option set. | ||
* @param {String} message - Message to log. | ||
* @param {string} message - Message to log. | ||
*/ | ||
@@ -8,0 +8,0 @@ function log(message) { |
@@ -12,3 +12,3 @@ /** | ||
* @param {ASTNode} node The node to check. Must be an Identifier node. | ||
* @returns {Boolean} `true` if the node is a propTypes declaration, `false` if not | ||
* @returns {boolean} `true` if the node is a propTypes declaration, `false` if not | ||
*/ | ||
@@ -28,3 +28,3 @@ function isPropTypesDeclaration(node) { | ||
* @param {ASTNode} node The node to check. | ||
* @returns {Boolean} `true` if the node is a contextTypes declaration, `false` if not | ||
* @returns {boolean} `true` if the node is a contextTypes declaration, `false` if not | ||
*/ | ||
@@ -44,3 +44,3 @@ function isContextTypesDeclaration(node) { | ||
* @param {ASTNode} node The node to check. | ||
* @returns {Boolean} `true` if the node is a contextType declaration, `false` if not | ||
* @returns {boolean} `true` if the node is a contextType declaration, `false` if not | ||
*/ | ||
@@ -54,3 +54,3 @@ function isContextTypeDeclaration(node) { | ||
* @param {ASTNode} node The node to check. | ||
* @returns {Boolean} `true` if the node is a childContextTypes declaration, `false` if not | ||
* @returns {boolean} `true` if the node is a childContextTypes declaration, `false` if not | ||
*/ | ||
@@ -64,3 +64,3 @@ function isChildContextTypesDeclaration(node) { | ||
* @param {ASTNode} node The node to check. Must be an Identifier node. | ||
* @returns {Boolean} `true` if the node is a defaultProps declaration, `false` if not | ||
* @returns {boolean} `true` if the node is a defaultProps declaration, `false` if not | ||
*/ | ||
@@ -75,3 +75,3 @@ function isDefaultPropsDeclaration(node) { | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if we are declaring a display name, false if not. | ||
* @returns {boolean} True if we are declaring a display name, false if not. | ||
*/ | ||
@@ -95,6 +95,7 @@ function isDisplayNameDeclaration(node) { | ||
* @param {ASTNode} propTypeExpression node to check. Must be a `PropTypes` MemberExpression. | ||
* @returns {Boolean} `true` if this PropType is required, `false` if not. | ||
* @returns {boolean} `true` if this PropType is required, `false` if not. | ||
*/ | ||
function isRequiredPropType(propTypeExpression) { | ||
return propTypeExpression.type === 'MemberExpression' && propTypeExpression.property.name === 'isRequired'; | ||
return propTypeExpression.type === 'MemberExpression' | ||
&& propTypeExpression.property.name === 'isRequired'; | ||
} | ||
@@ -101,0 +102,0 @@ |
@@ -26,3 +26,3 @@ /** | ||
* @param {ASTNode} node | ||
* @returns {Boolean} | ||
* @returns {boolean} | ||
*/ | ||
@@ -41,3 +41,3 @@ function isFunctionType(node) { | ||
* @param {ASTNode} node the AST node being checked. | ||
* @returns {Boolean} True if the node is a class with generic prop types, false if not. | ||
* @returns {boolean} True if the node is a class with generic prop types, false if not. | ||
*/ | ||
@@ -81,4 +81,4 @@ function isSuperTypeParameterPropsDeclaration(node) { | ||
* | ||
* @param {ASTNode} node the AST node being checked. | ||
* @returns {Boolean} True if the node has a ClassBody ancestor, false if not. | ||
* @param {ASTNode} node the AST node being checked. | ||
* @returns {boolean} True if the node has a ClassBody ancestor, false if not. | ||
*/ | ||
@@ -158,4 +158,4 @@ function isInsideClassBody(node) { | ||
* Checks if prop should be validated by plugin-react-proptypes | ||
* @param {String} validator Name of validator to check. | ||
* @returns {Boolean} True if validator should be checked by custom validator. | ||
* @param {string} validator Name of validator to check. | ||
* @returns {boolean} True if validator should be checked by custom validator. | ||
*/ | ||
@@ -179,3 +179,3 @@ function hasCustomValidator(validator) { | ||
let containsSpread = false; | ||
const containsIndexers = Boolean(annotation.indexers && annotation.indexers.length); | ||
const containsIndexers = !!annotation.indexers && annotation.indexers.length > 0; | ||
const shapeTypeDefinition = { | ||
@@ -275,3 +275,3 @@ type: 'shape', | ||
* @param {ASTNode} annotation Type annotation for the props class property. | ||
* @param {String} parentName | ||
* @param {string} parentName | ||
* @param {Set<ASTNode>} [seen] | ||
@@ -305,3 +305,3 @@ * @return {Object} The representation of the declaration, empty object means | ||
* @param {Object} declaredPropTypes | ||
* @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported) | ||
* @returns {boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported) | ||
*/ | ||
@@ -344,3 +344,3 @@ function declarePropTypesForObjectTypeAnnotation(propTypes, declaredPropTypes) { | ||
* @param {Object} declaredPropTypes | ||
* @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported) | ||
* @returns {boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported) | ||
*/ | ||
@@ -438,3 +438,2 @@ function declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes) { | ||
&& value.property | ||
&& value.property.name | ||
&& value.property.name === 'isRequired' | ||
@@ -459,4 +458,3 @@ ) { | ||
if ( | ||
value | ||
&& value.type === 'CallExpression' | ||
astUtil.isCallExpression(value) | ||
&& value.callee | ||
@@ -510,3 +508,3 @@ && value.callee.property | ||
!argument.elements | ||
|| !argument.elements.length | ||
|| argument.elements.length === 0 | ||
) { | ||
@@ -590,4 +588,8 @@ // Invalid proptype or cannot analyse statically | ||
return ( | ||
(node.id && node.id.name === typeName) | ||
|| (node.declaration && node.declaration.id && node.declaration.id.name === typeName) | ||
node.id | ||
&& node.id.name === typeName | ||
) || ( | ||
node.declaration | ||
&& node.declaration.id | ||
&& node.declaration.id.name === typeName | ||
); | ||
@@ -710,3 +712,11 @@ } | ||
candidateTypes, | ||
(type) => type.declarations || (type.declaration && type.declaration.declarations) || type.declaration); | ||
(type) => ( | ||
type.declarations | ||
|| ( | ||
type.declaration | ||
&& type.declaration.declarations | ||
) | ||
|| type.declaration | ||
) | ||
); | ||
@@ -799,3 +809,3 @@ // we tried to find either an interface or a type with the TypeReference name | ||
iterateProperties(context, res.properties, (key, value, propNode) => { | ||
if (propNode && propNode.argument && propNode.argument.type === 'CallExpression') { | ||
if (propNode && astUtil.isCallExpression(propNode.argument)) { | ||
const propNodeTypeParams = propNode.argument.typeParameters; | ||
@@ -1152,3 +1162,3 @@ if (propNodeTypeParams) { | ||
* @param {ASTNode} node The AST node being checked. | ||
* @returns {Boolean} True if the node is a type annotated props declaration, false if not. | ||
* @returns {boolean} True if the node is a type annotated props declaration, false if not. | ||
*/ | ||
@@ -1155,0 +1165,0 @@ function isAnnotatedClassPropsDeclaration(node) { |
@@ -19,6 +19,8 @@ /** | ||
* @param {ASTNode} node the node to check. | ||
* @returns {String} The name of the node. | ||
* @returns {string} The name of the node. | ||
*/ | ||
function getValueName(node) { | ||
return node.type === 'Property' && node.value.property && node.value.property.name; | ||
return node.type === 'Property' | ||
&& node.value.property | ||
&& node.value.property.name; | ||
} | ||
@@ -30,3 +32,3 @@ | ||
* @param {ASTNode} node the prop to check. | ||
* @returns {Boolean} true if the prop is required. | ||
* @returns {boolean} true if the prop is required. | ||
*/ | ||
@@ -40,4 +42,4 @@ function isRequiredProp(node) { | ||
* | ||
* @param {String} propName the name of the proptype to check. | ||
* @returns {Boolean} true if the proptype is a callback. | ||
* @param {string} propName the name of the proptype to check. | ||
* @returns {boolean} true if the proptype is a callback. | ||
*/ | ||
@@ -52,7 +54,10 @@ function isCallbackPropName(propName) { | ||
* @param {ASTNode} node the prop to check. | ||
* @returns {Boolean} true if the prop is PropTypes.shape. | ||
* @returns {boolean} true if the prop is PropTypes.shape. | ||
*/ | ||
function isShapeProp(node) { | ||
return Boolean( | ||
node && node.callee && node.callee.property && node.callee.property.name === 'shape' | ||
return !!( | ||
node | ||
&& node.callee | ||
&& node.callee.property | ||
&& node.callee.property.name === 'shape' | ||
); | ||
@@ -68,3 +73,5 @@ } | ||
function getShapeProperties(node) { | ||
return node.arguments && node.arguments[0] && node.arguments[0].properties; | ||
return node.arguments | ||
&& node.arguments[0] | ||
&& node.arguments[0].properties; | ||
} | ||
@@ -78,7 +85,7 @@ | ||
* @param {Context} context The context of the two nodes. | ||
* @param {Boolean=} ignoreCase whether or not to ignore case when comparing the two elements. | ||
* @param {Boolean=} requiredFirst whether or not to sort required elements first. | ||
* @param {Boolean=} callbacksLast whether or not to sort callbacks after everything else. | ||
* @param {Boolean=} noSortAlphabetically whether or not to disable alphabetical sorting of the elements. | ||
* @returns {Number} the sort order of the two elements. | ||
* @param {boolean=} ignoreCase whether or not to ignore case when comparing the two elements. | ||
* @param {boolean=} requiredFirst whether or not to sort required elements first. | ||
* @param {boolean=} callbacksLast whether or not to sort callbacks after everything else. | ||
* @param {boolean=} noSortAlphabetically whether or not to disable alphabetical sorting of the elements. | ||
* @returns {number} the sort order of the two elements. | ||
*/ | ||
@@ -130,8 +137,8 @@ function sorter(a, b, context, ignoreCase, requiredFirst, callbacksLast, noSortAlphabetically) { | ||
* @param {Array} declarations The context of the two nodes. | ||
* @param {Boolean=} ignoreCase whether or not to ignore case when comparing the two elements. | ||
* @param {Boolean=} requiredFirst whether or not to sort required elements first. | ||
* @param {Boolean=} callbacksLast whether or not to sort callbacks after everything else. | ||
* @param {Boolean=} noSortAlphabetically whether or not to disable alphabetical sorting of the elements. | ||
* @param {Boolean=} sortShapeProp whether or not to sort propTypes defined in PropTypes.shape. | ||
* @param {Boolean=} checkTypes whether or not sorting of prop type definitions are checked. | ||
* @param {boolean=} ignoreCase whether or not to ignore case when comparing the two elements. | ||
* @param {boolean=} requiredFirst whether or not to sort required elements first. | ||
* @param {boolean=} callbacksLast whether or not to sort callbacks after everything else. | ||
* @param {boolean=} noSortAlphabetically whether or not to disable alphabetical sorting of the elements. | ||
* @param {boolean=} sortShapeProp whether or not to sort propTypes defined in PropTypes.shape. | ||
* @param {boolean=} checkTypes whether or not sorting of prop type definitions are checked. | ||
* @returns {Object|*|{range, text}} the sort order of the two elements. | ||
@@ -230,2 +237,5 @@ */ | ||
fixPropTypesSort, | ||
isCallbackPropName, | ||
isRequiredProp, | ||
isShapeProp, | ||
}; |
@@ -69,3 +69,3 @@ /** | ||
* @param {string} name The AST node being checked. | ||
* @returns {Boolean} True if the prop name matches | ||
* @returns {boolean} True if the prop name matches | ||
*/ | ||
@@ -79,3 +79,3 @@ function isCommonVariableNameForProps(name) { | ||
* @param {Object} component The component to process | ||
* @returns {Boolean} True if the component must be validated, false if not. | ||
* @returns {boolean} True if the component must be validated, false if not. | ||
*/ | ||
@@ -115,16 +115,23 @@ function mustBeValidated(component) { | ||
* @param {boolean} checkAsyncSafeLifeCycles | ||
* @return {Boolean} True if the node is a lifecycle method | ||
* @return {boolean} True if the node is a lifecycle method | ||
*/ | ||
function isNodeALifeCycleMethod(node, checkAsyncSafeLifeCycles) { | ||
const nodeKeyName = (node.key || /** @type {ASTNode} */ ({})).name; | ||
if (node.key) { | ||
if (node.kind === 'constructor') { | ||
return true; | ||
} | ||
if (node.kind === 'constructor') { | ||
return true; | ||
const nodeKeyName = node.key.name; | ||
if (typeof nodeKeyName !== 'string') { | ||
return false; | ||
} | ||
if (LIFE_CYCLE_METHODS.indexOf(nodeKeyName) >= 0) { | ||
return true; | ||
} | ||
if (checkAsyncSafeLifeCycles && ASYNC_SAFE_LIFE_CYCLE_METHODS.indexOf(nodeKeyName) >= 0) { | ||
return true; | ||
} | ||
} | ||
if (LIFE_CYCLE_METHODS.indexOf(nodeKeyName) >= 0) { | ||
return true; | ||
} | ||
if (checkAsyncSafeLifeCycles && ASYNC_SAFE_LIFE_CYCLE_METHODS.indexOf(nodeKeyName) >= 0) { | ||
return true; | ||
} | ||
@@ -139,6 +146,9 @@ return false; | ||
* @param {boolean} checkAsyncSafeLifeCycles | ||
* @return {Boolean} True if the node is inside a lifecycle method | ||
* @return {boolean} True if the node is inside a lifecycle method | ||
*/ | ||
function isInLifeCycleMethod(node, checkAsyncSafeLifeCycles) { | ||
if ((node.type === 'MethodDefinition' || node.type === 'Property') && isNodeALifeCycleMethod(node, checkAsyncSafeLifeCycles)) { | ||
if ( | ||
(node.type === 'MethodDefinition' || node.type === 'Property') | ||
&& isNodeALifeCycleMethod(node, checkAsyncSafeLifeCycles) | ||
) { | ||
return true; | ||
@@ -160,3 +170,3 @@ } | ||
function isSetStateUpdater(node) { | ||
const unwrappedParentCalleeNode = node.parent && node.parent.type === 'CallExpression' | ||
const unwrappedParentCalleeNode = astUtil.isCallExpression(node.parent) | ||
&& ast.unwrapTSAsExpression(node.parent.callee); | ||
@@ -178,4 +188,3 @@ | ||
const unwrappedParentCalleeNode = scope.block | ||
&& scope.block.parent | ||
&& scope.block.parent.type === 'CallExpression' | ||
&& astUtil.isCallExpression(scope.block.parent) | ||
&& ast.unwrapTSAsExpression(scope.block.parent.callee); | ||
@@ -223,3 +232,3 @@ if ( | ||
* @param {ASTNode} node The AST node being marked. | ||
* @returns {Boolean} True if the prop has spread operator, false if not. | ||
* @returns {boolean} True if the prop has spread operator, false if not. | ||
*/ | ||
@@ -226,0 +235,0 @@ function hasSpreadOperator(context, node) { |
@@ -14,3 +14,3 @@ /** | ||
* @param {string} name The name of the variable to search. | ||
* @returns {Boolean} True if the variable was found, false if not. | ||
* @returns {boolean} True if the variable was found, false if not. | ||
*/ | ||
@@ -17,0 +17,0 @@ function findVariable(variables, name) { |
{ | ||
"name": "eslint-plugin-react", | ||
"version": "7.35.0", | ||
"version": "7.35.1", | ||
"author": "Yannick Croissant <yannick.croissant+npm@gmail.com>", | ||
@@ -16,3 +16,3 @@ "description": "React specific linting rules for ESLint", | ||
"test": "npm run unit-test", | ||
"posttest": "aud --production", | ||
"posttest": "npx npm@'>= 10.2' audit --production", | ||
"type-check": "tsc", | ||
@@ -49,4 +49,4 @@ "unit-test": "istanbul cover node_modules/mocha/bin/_mocha tests/lib/**/*.js tests/util/**/*.js tests/index.js tests/flat-config.js", | ||
"devDependencies": { | ||
"@babel/core": "^7.24.9", | ||
"@babel/eslint-parser": "^7.24.8", | ||
"@babel/core": "^7.25.2", | ||
"@babel/eslint-parser": "^7.25.1", | ||
"@babel/plugin-syntax-decorators": "^7.24.7", | ||
@@ -60,3 +60,2 @@ "@babel/plugin-syntax-do-expressions": "^7.24.7", | ||
"@typescript-eslint/parser": "^2.34.0 || ^3.10.1 || ^4.0.0 || ^5.0.0", | ||
"aud": "^2.0.4", | ||
"babel-eslint": "^8 || ^9 || ^10.1.0", | ||
@@ -63,0 +62,0 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
30
22327
828965