Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce memory allocation in rules and utils #2976

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
43 changes: 22 additions & 21 deletions lib/rules/boolean-prop-naming.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

'use strict';

const values = require('object.values');
const Components = require('../util/Components');
const propsUtil = require('../util/props');
const docsUrl = require('../util/docsUrl');
Expand Down Expand Up @@ -173,17 +174,17 @@ module.exports = {
* @param {Function} addInvalidProp callback to run for each error
*/
function runCheck(proptypes, addInvalidProp) {
proptypes = 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);
}
});
if (proptypes && proptypes.length > 0) {
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);
}
});
}
}

/**
Expand Down Expand Up @@ -312,18 +313,18 @@ module.exports = {
}

const list = components.list();
Object.keys(list).forEach((component) => {
values(list).forEach((component) => {
// If this is a functional component that uses a global type, check it
if (
(
list[component].node.type === 'FunctionDeclaration'
|| list[component].node.type === 'ArrowFunctionExpression'
component.node.type === 'FunctionDeclaration'
|| component.node.type === 'ArrowFunctionExpression'
)
&& list[component].node.params
&& list[component].node.params.length
&& list[component].node.params[0].typeAnnotation
&& component.node.params
&& component.node.params.length
&& component.node.params[0].typeAnnotation
) {
const typeNode = list[component].node.params[0].typeAnnotation;
const typeNode = component.node.params[0].typeAnnotation;
const annotation = typeNode.typeAnnotation;
let propType;
if (annotation.type === 'GenericTypeAnnotation') {
Expand All @@ -336,14 +337,14 @@ module.exports = {

if (propType) {
validatePropNaming(
list[component].node,
component.node,
propType.properties || propType.members
);
}
}

if (list[component].invalidProps && list[component].invalidProps.length > 0) {
reportInvalidNaming(list[component]);
if (component.invalidProps && component.invalidProps.length > 0) {
reportInvalidNaming(component);
}
});

Expand Down
7 changes: 4 additions & 3 deletions lib/rules/default-props-match-prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

'use strict';

const values = require('object.values');
const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');

Expand Down Expand Up @@ -93,10 +94,10 @@ module.exports = {
const list = components.list();

// If no defaultProps could be found, we don't report anything.
Object.keys(list).filter((component) => list[component].defaultProps).forEach((component) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same with this .filter change to an if check inside forEach?

values(list).filter((component) => component.defaultProps).forEach((component) => {
reportInvalidDefaultProps(
list[component].declaredPropTypes,
list[component].defaultProps || {}
component.declaredPropTypes,
component.defaultProps || {}
);
});
}
Expand Down
8 changes: 5 additions & 3 deletions lib/rules/display-name.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

'use strict';

const values = require('object.values');
const Components = require('../util/Components');
const astUtil = require('../util/ast');
const docsUrl = require('../util/docsUrl');
Expand Down Expand Up @@ -229,9 +230,10 @@ module.exports = {
'Program:exit'() {
const list = components.list();
// Report missing display name for all components
Object.keys(list).filter((component) => !list[component].hasDisplayName).forEach((component) => {
reportMissingDisplayName(list[component]);
});
values(list).filter((component) => !component.hasDisplayName)
.forEach((component) => {
reportMissingDisplayName(component);
});
}
};
})
Expand Down
5 changes: 3 additions & 2 deletions lib/rules/function-component-definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

'use strict';

const entries = require('object.entries');
const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');

Expand All @@ -13,8 +14,8 @@ const docsUrl = require('../util/docsUrl');
// ------------------------------------------------------------------------------

function buildFunction(template, parts) {
return Object.keys(parts)
.reduce((acc, key) => acc.replace(`{${key}}`, parts[key] || ''), template);
return entries(parts)
.reduce((acc, entry) => acc.replace(`{${entry[0]}}`, entry[1] || ''), template);
}

const NAMED_FUNCTION_TEMPLATES = {
Expand Down
18 changes: 10 additions & 8 deletions lib/rules/jsx-one-expression-per-line.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

'use strict';

const entries = require('object.entries');
const values = require('object.values');
const docsUrl = require('../util/docsUrl');
const jsxUtil = require('../util/jsx');

Expand Down Expand Up @@ -123,12 +125,14 @@ module.exports = {
}
});

Object.keys(childrenGroupedByLine).forEach((_line) => {
const line = parseInt(_line, 10);
entries(childrenGroupedByLine).forEach((lineEntry) => {
const lineKey = lineEntry[0];
const lineValue = lineEntry[1];
const line = parseInt(lineKey, 10);
const firstIndex = 0;
const lastIndex = childrenGroupedByLine[line].length - 1;
const lastIndex = lineValue.length - 1;

childrenGroupedByLine[line].forEach((child, i) => {
lineValue.forEach((child, i) => {
let prevChild;
let nextChild;

Expand All @@ -137,7 +141,7 @@ module.exports = {
prevChild = openingElement;
}
} else {
prevChild = childrenGroupedByLine[line][i - 1];
prevChild = lineValue[i - 1];
}

if (i === lastIndex) {
Expand Down Expand Up @@ -196,9 +200,7 @@ module.exports = {
});
});

Object.keys(fixDetailsByNode).forEach((key) => {
const details = fixDetailsByNode[key];

values(fixDetailsByNode).forEach((details) => {
const nodeToReport = details.node;
const descriptor = details.descriptor;
const source = details.source.replace(/(^ +| +(?=\n)*$)/g, '');
Expand Down
7 changes: 4 additions & 3 deletions lib/rules/no-direct-mutation-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

'use strict';

const values = require('object.values');
const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');

Expand Down Expand Up @@ -140,9 +141,9 @@ module.exports = {
'Program:exit'() {
const list = components.list();

Object.keys(list).forEach((key) => {
if (!isValid(list[key])) {
reportMutations(list[key]);
values(list).forEach((val) => {
if (!isValid(val)) {
reportMutations(val);
}
});
}
Expand Down
5 changes: 3 additions & 2 deletions lib/rules/no-multi-comp.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

'use strict';

const values = require('object.values');
const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');

Expand Down Expand Up @@ -67,10 +68,10 @@ module.exports = {

const list = components.list();

Object.keys(list).filter((component) => !isIgnored(list[component])).forEach((component, i) => {
values(list).filter((component) => !isIgnored(component)).forEach((component, i) => {
if (i >= 1) {
context.report({
node: list[component].node,
node: component.node,
messageId: 'onlyOneComponent'
});
}
Expand Down
5 changes: 3 additions & 2 deletions lib/rules/no-set-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

'use strict';

const values = require('object.values');
const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');

Expand Down Expand Up @@ -79,8 +80,8 @@ module.exports = {

'Program:exit'() {
const list = components.list();
Object.keys(list).filter((component) => !isValid(list[component])).forEach((component) => {
reportSetStateUsages(list[component]);
values(list).filter((component) => !isValid(component)).forEach((component) => {
reportSetStateUsages(component);
});
}
};
Expand Down
10 changes: 5 additions & 5 deletions lib/rules/no-unused-prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// As for exceptions for props.children or props.className (and alike) look at
// https://github.com/yannickcr/eslint-plugin-react/issues/7

const values = require('object.values');
const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');

Expand Down Expand Up @@ -111,8 +112,7 @@ module.exports = {
return;
}

Object.keys(props || {}).forEach((key) => {
const prop = props[key];
values(props || {}).forEach((prop) => {
// Skip props that check instances
if (prop === true) {
return;
Expand Down Expand Up @@ -159,11 +159,11 @@ module.exports = {
'Program:exit'() {
const list = components.list();
// Report undeclared proptypes for all classes
Object.keys(list).filter((component) => mustBeValidated(list[component])).forEach((component) => {
if (!mustBeValidated(list[component])) {
values(list).filter((component) => mustBeValidated(component)).forEach((component) => {
if (!mustBeValidated(component)) {
return;
}
reportUnusedPropTypes(list[component]);
reportUnusedPropTypes(component);
});
}
};
Expand Down
60 changes: 32 additions & 28 deletions lib/rules/prefer-read-only-props.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

'use strict';

const entries = require('object.entries');
const values = require('object.values');
const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');

Expand All @@ -16,6 +18,33 @@ function isCovariant(node) {
return (node.variance && (node.variance.kind === 'plus')) || (node.parent.parent.parent.id && (node.parent.parent.parent.id.name === '$ReadOnly'));
}

const reportPropTypeWithContext = (context) => (propEntry) => {
const propName = propEntry[0];
const prop = propEntry[1];
if (!isFlowPropertyType(prop.node)) {
return;
}

if (!isCovariant(prop.node)) {
context.report({
node: prop.node,
messageId: 'readOnlyProp',
data: {
name: propName
},
fix: (fixer) => {
if (!prop.node.variance) {
// Insert covariance
return fixer.insertTextBefore(prop.node, '+');
}

// Replace contravariance with covariance
return fixer.replaceText(prop.node.variance, '+');
}
});
}
};

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
Expand All @@ -41,39 +70,14 @@ module.exports = {
'Program:exit'() {
const list = components.list();

Object.keys(list).forEach((key) => {
const component = list[key];
const reportPropType = reportPropTypeWithContext(context);

values(list).forEach((component) => {
if (!component.declaredPropTypes) {
return;
}

Object.keys(component.declaredPropTypes).forEach((propName) => {
const prop = component.declaredPropTypes[propName];

if (!isFlowPropertyType(prop.node)) {
return;
}

if (!isCovariant(prop.node)) {
context.report({
node: prop.node,
messageId: 'readOnlyProp',
data: {
name: propName
},
fix: (fixer) => {
if (!prop.node.variance) {
// Insert covariance
return fixer.insertTextBefore(prop.node, '+');
}

// Replace contravariance with covariance
return fixer.replaceText(prop.node.variance, '+');
}
});
}
});
entries(component.declaredPropTypes).forEach(reportPropType);
});
}
}))
Expand Down