Skip to content

Commit 438c21a

Browse files
golopotljharb
authored andcommitted
[Refactor] improve performance of rule merging
1 parent c8833f3 commit 438c21a

File tree

2 files changed

+44
-32
lines changed

2 files changed

+44
-32
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
3131
* [Refactor] improve performance by avoiding unnecessary `Components.detect` ([#3273][] @golopot)
3232
* [Refactor] add `isParenthesized` AST util ([#3203][] @Belco90)
3333
* [Docs] `default-props-match-prop-types`, `require-default-props`, `sort-prop-types`: fix typos ([#3279][] @nix6839)
34+
* [Refactor] improve performance of rule merging ([#3281][] @golopot)
3435

36+
[#3281]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3281
3537
[#3280]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3280
3638
[#3279]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3279
3739
[#3273]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3273

lib/util/Components.js

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,39 @@ function getWrapperFunctions(context, pragma) {
247247
]);
248248
}
249249

250+
// eslint-disable-next-line valid-jsdoc
251+
/**
252+
* Merge many eslint rules into one
253+
* @param {{[_: string]: Function}[]} rules the returned values for eslint rule.create(context)
254+
* @returns {{[_: string]: Function}} merged rule
255+
*/
256+
function mergeRules(rules) {
257+
/** @type {Map<string, Function[]>} */
258+
const handlersByKey = new Map();
259+
rules.forEach((rule) => {
260+
Object.keys(rule).forEach((key) => {
261+
const fns = handlersByKey.get(key);
262+
if (!fns) {
263+
handlersByKey.set(key, [rule[key]]);
264+
} else {
265+
fns.push(rule[key]);
266+
}
267+
});
268+
});
269+
270+
/** @type {{[key: string]: Function}} */
271+
const rule = {};
272+
handlersByKey.forEach((fns, key) => {
273+
rule[key] = function mergedHandler(node) {
274+
fns.forEach((fn) => {
275+
fn(node);
276+
});
277+
};
278+
});
279+
280+
return rule;
281+
}
282+
250283
function componentRule(rule, context) {
251284
const pragma = pragmaUtil.getFromContext(context);
252285
const sourceCode = context.getSourceCode();
@@ -859,44 +892,21 @@ function componentRule(rule, context) {
859892
},
860893
};
861894

862-
// Update the provided rule instructions to add the component detection
863895
const ruleInstructions = rule(context, components, utils);
864-
const updatedRuleInstructions = Object.assign({}, ruleInstructions);
865896
const propTypesInstructions = propTypesUtil(context, components, utils);
866897
const usedPropTypesInstructions = usedPropTypesUtil(context, components, utils);
867898
const defaultPropsInstructions = defaultPropsUtil(context, components, utils);
868-
const allKeys = new Set(Object.keys(detectionInstructions).concat(
869-
Object.keys(propTypesInstructions),
870-
Object.keys(usedPropTypesInstructions),
871-
Object.keys(defaultPropsInstructions),
872-
Object.keys(reactImportInstructions)
873-
));
874899

875-
allKeys.forEach((instruction) => {
876-
updatedRuleInstructions[instruction] = (node) => {
877-
if (instruction in detectionInstructions) {
878-
detectionInstructions[instruction](node);
879-
}
880-
if (instruction in propTypesInstructions) {
881-
propTypesInstructions[instruction](node);
882-
}
883-
if (instruction in usedPropTypesInstructions) {
884-
usedPropTypesInstructions[instruction](node);
885-
}
886-
if (instruction in defaultPropsInstructions) {
887-
defaultPropsInstructions[instruction](node);
888-
}
889-
if (instruction in reactImportInstructions) {
890-
reactImportInstructions[instruction](node);
891-
}
892-
if (ruleInstructions[instruction]) {
893-
return ruleInstructions[instruction](node);
894-
}
895-
};
896-
});
900+
const mergedRule = mergeRules([
901+
detectionInstructions,
902+
propTypesInstructions,
903+
usedPropTypesInstructions,
904+
defaultPropsInstructions,
905+
reactImportInstructions,
906+
ruleInstructions,
907+
]);
897908

898-
// Return the updated rule instructions
899-
return updatedRuleInstructions;
909+
return mergedRule;
900910
}
901911

902912
module.exports = Object.assign(Components, {

0 commit comments

Comments
 (0)