diff --git a/lib/util/Components.js b/lib/util/Components.js index 4b545fa75a..4d9fee6827 100644 --- a/lib/util/Components.js +++ b/lib/util/Components.js @@ -247,6 +247,40 @@ function getWrapperFunctions(context, pragma) { ]); } +// eslint-disable-next-line valid-jsdoc +/** + * Merge many eslint rules into one + * @param {{[_: string]: Function}[]} rules the returned values for eslint rule.create(context) + * @returns {{[_: string]: Function}} merged rule + */ +function mergeRules(rules) { + /** @type {Map} */ + const handlersByKey = new Map(); + for (const rule of rules) { + for (const key of Object.keys(rule)) { + const fns = handlersByKey.get(key); + if (!fns) { + handlersByKey.set(key, [rule[key]]); + } else { + fns.push(rule[key]); + } + } + } + + /** @type {{[key: string]: Function}} */ + const rule = {}; + for (const key of handlersByKey.keys()) { + const fns = handlersByKey.get(key); + rule[key] = function mergedHandler(node) { + for (const fn of fns) { + fn(node); + } + }; + } + + return rule; +} + function componentRule(rule, context) { const pragma = pragmaUtil.getFromContext(context); const sourceCode = context.getSourceCode(); @@ -859,44 +893,21 @@ function componentRule(rule, context) { }, }; - // Update the provided rule instructions to add the component detection const ruleInstructions = rule(context, components, utils); - const updatedRuleInstructions = Object.assign({}, ruleInstructions); const propTypesInstructions = propTypesUtil(context, components, utils); const usedPropTypesInstructions = usedPropTypesUtil(context, components, utils); const defaultPropsInstructions = defaultPropsUtil(context, components, utils); - const allKeys = new Set(Object.keys(detectionInstructions).concat( - Object.keys(propTypesInstructions), - Object.keys(usedPropTypesInstructions), - Object.keys(defaultPropsInstructions), - Object.keys(reactImportInstructions) - )); - allKeys.forEach((instruction) => { - updatedRuleInstructions[instruction] = (node) => { - if (instruction in detectionInstructions) { - detectionInstructions[instruction](node); - } - if (instruction in propTypesInstructions) { - propTypesInstructions[instruction](node); - } - if (instruction in usedPropTypesInstructions) { - usedPropTypesInstructions[instruction](node); - } - if (instruction in defaultPropsInstructions) { - defaultPropsInstructions[instruction](node); - } - if (instruction in reactImportInstructions) { - reactImportInstructions[instruction](node); - } - if (ruleInstructions[instruction]) { - return ruleInstructions[instruction](node); - } - }; - }); + const mergedRule = mergeRules([ + detectionInstructions, + propTypesInstructions, + usedPropTypesInstructions, + defaultPropsInstructions, + reactImportInstructions, + ruleInstructions, + ]); - // Return the updated rule instructions - return updatedRuleInstructions; + return mergedRule; } module.exports = Object.assign(Components, {