diff --git a/lib/rules/boolean-prop-naming.js b/lib/rules/boolean-prop-naming.js
index 546e921532..7409a62855 100644
--- a/lib/rules/boolean-prop-naming.js
+++ b/lib/rules/boolean-prop-naming.js
@@ -227,7 +227,9 @@ module.exports = {
if (!node || !Array.isArray(args)) {
return;
}
- args.filter((arg) => arg.type === 'ObjectExpression').forEach((object) => validatePropNaming(node, object.properties));
+ args.forEach((object) => object.type === 'ObjectExpression'
+ && validatePropNaming(node, object.properties)
+ );
}
// --------------------------------------------------------------------------
diff --git a/lib/rules/default-props-match-prop-types.js b/lib/rules/default-props-match-prop-types.js
index d57e178c82..63dcc642f1 100644
--- a/lib/rules/default-props-match-prop-types.js
+++ b/lib/rules/default-props-match-prop-types.js
@@ -94,11 +94,13 @@ module.exports = {
const list = components.list();
// If no defaultProps could be found, we don't report anything.
- values(list).filter((component) => component.defaultProps).forEach((component) => {
- reportInvalidDefaultProps(
- component.declaredPropTypes,
- component.defaultProps || {}
- );
+ values(list).forEach((component) => {
+ if (component.defaultProps) {
+ reportInvalidDefaultProps(
+ component.declaredPropTypes,
+ component.defaultProps || {}
+ );
+ }
});
}
};
diff --git a/lib/rules/destructuring-assignment.js b/lib/rules/destructuring-assignment.js
index 58b45e86f5..d4ca1cd263 100644
--- a/lib/rules/destructuring-assignment.js
+++ b/lib/rules/destructuring-assignment.js
@@ -13,6 +13,16 @@ const DEFAULT_OPTION = 'always';
function createSFCParams() {
const queue = [];
+ const identifyProps = (params) => {
+ const props = params[0];
+ return props && !props.destructuring && props.name;
+ };
+
+ const identifyContext = (params) => {
+ const context = params[1];
+ return context && !context.destructuring && context.name;
+ };
+
return {
push(params) {
queue.unshift(params);
@@ -21,17 +31,11 @@ function createSFCParams() {
queue.shift();
},
propsName() {
- const found = queue.find((params) => {
- const props = params[0];
- return props && !props.destructuring && props.name;
- });
+ const found = queue.find(identifyProps);
return found && found[0] && found[0].name;
},
contextName() {
- const found = queue.find((params) => {
- const context = params[1];
- return context && !context.destructuring && context.name;
- });
+ const found = queue.find(identifyContext);
return found && found[1] && found.name;
}
};
@@ -87,24 +91,26 @@ module.exports = {
* FunctionDeclaration, or FunctionExpression
*/
function handleStatelessComponent(node) {
- const params = evalParams(node.params);
-
const SFCComponent = components.get(context.getScope(node).block);
if (!SFCComponent) {
return;
}
+ const params = evalParams(node.params);
+
sfcParams.push(params);
- if (params[0] && params[0].destructuring && components.get(node) && configuration === 'never') {
- context.report({
- node,
- messageId: 'noDestructPropsInSFCArg'
- });
- } else if (params[1] && params[1].destructuring && components.get(node) && configuration === 'never') {
- context.report({
- node,
- messageId: 'noDestructContextInSFCArg'
- });
+ if (configuration === 'never') {
+ if (params[0] && params[0].destructuring && components.get(node)) {
+ context.report({
+ node,
+ messageId: 'noDestructPropsInSFCArg'
+ });
+ } else if (params[1] && params[1].destructuring && components.get(node)) {
+ context.report({
+ node,
+ messageId: 'noDestructContextInSFCArg'
+ });
+ }
}
}
@@ -116,15 +122,11 @@ module.exports = {
}
function handleSFCUsage(node) {
- const propsName = sfcParams.propsName();
- const contextName = sfcParams.contextName();
// props.aProp || context.aProp
- const isPropUsed = (
- (propsName && node.object.name === propsName)
- || (contextName && node.object.name === contextName)
- )
- && !isAssignmentLHS(node);
- if (isPropUsed && configuration === 'always') {
+ const isPropUsed = node.object.name && (
+ node.object.name === sfcParams.propsName() || node.object.name === sfcParams.contextName()
+ ) && !isAssignmentLHS(node);
+ if (isPropUsed) {
context.report({
node,
messageId: 'useDestructAssignment',
@@ -155,8 +157,7 @@ module.exports = {
);
if (
- isPropUsed && configuration === 'always'
- && !(ignoreClassFields && isInClassProperty(node))
+ isPropUsed && !(ignoreClassFields && isInClassProperty(node))
) {
context.report({
node,
@@ -183,49 +184,51 @@ module.exports = {
'FunctionExpression:exit': handleStatelessComponentExit,
MemberExpression(node) {
- const SFCComponent = components.get(context.getScope(node).block);
- const classComponent = utils.getParentComponent(node);
- if (SFCComponent) {
- handleSFCUsage(node);
- }
- if (classComponent) {
- handleClassUsage(node);
+ if (configuration === 'always') {
+ const SFCComponent = components.get(context.getScope(node).block);
+ const classComponent = utils.getParentComponent(node);
+ if (SFCComponent) {
+ handleSFCUsage(node);
+ }
+ if (classComponent) {
+ handleClassUsage(node);
+ }
}
},
VariableDeclarator(node) {
- const classComponent = utils.getParentComponent(node);
- const SFCComponent = components.get(context.getScope(node).block);
-
- const destructuring = (node.init && node.id && node.id.type === 'ObjectPattern');
- // let {foo} = props;
- const destructuringSFC = destructuring && (node.init.name === 'props' || node.init.name === 'context');
- // let {foo} = this.props;
- const destructuringClass = destructuring && node.init.object && node.init.object.type === 'ThisExpression' && (
- node.init.property.name === 'props' || node.init.property.name === 'context' || node.init.property.name === 'state'
- );
-
- if (SFCComponent && destructuringSFC && configuration === 'never') {
- context.report({
- node,
- messageId: 'noDestructAssignment',
- data: {
- type: node.init.name
- }
- });
- }
+ if (configuration === 'never') {
+ const destructuring = (node.init && node.id && node.id.type === 'ObjectPattern');
+ // let {foo} = props;
+ const destructuringSFC = destructuring && (node.init.name === 'props' || node.init.name === 'context');
+ // let {foo} = this.props;
+ const destructuringClass = destructuring && node.init.object && node.init.object.type === 'ThisExpression' && (
+ node.init.property.name === 'props' || node.init.property.name === 'context' || node.init.property.name === 'state'
+ );
+
+ if (destructuringSFC && components.get(context.getScope(node).block)) {
+ context.report({
+ node,
+ messageId: 'noDestructAssignment',
+ data: {
+ type: node.init.name
+ }
+ });
+ }
- if (
- classComponent && destructuringClass && configuration === 'never'
- && !(ignoreClassFields && node.parent.type === 'ClassProperty')
- ) {
- context.report({
- node,
- messageId: 'noDestructAssignment',
- data: {
- type: node.init.property.name
- }
- });
+ if (
+ destructuringClass
+ && !(ignoreClassFields && node.parent.type === 'ClassProperty')
+ && utils.getParentComponent(node)
+ ) {
+ context.report({
+ node,
+ messageId: 'noDestructAssignment',
+ data: {
+ type: node.init.property.name
+ }
+ });
+ }
}
}
};
diff --git a/lib/rules/display-name.js b/lib/rules/display-name.js
index 8d5da40322..89265f9ada 100644
--- a/lib/rules/display-name.js
+++ b/lib/rules/display-name.js
@@ -43,14 +43,16 @@ module.exports = {
const config = context.options[0] || {};
const ignoreTranspilerName = config.ignoreTranspilerName || false;
+ const markFlag = {
+ hasDisplayName: true
+ };
+
/**
* Mark a prop type as declared
* @param {ASTNode} node The AST node being checked.
*/
function markDisplayNameAsDeclared(node) {
- components.set(node, {
- hasDisplayName: true
- });
+ components.set(node, markFlag);
}
/**
@@ -230,9 +232,11 @@ module.exports = {
'Program:exit'() {
const list = components.list();
// Report missing display name for all components
- values(list).filter((component) => !component.hasDisplayName)
+ values(list)
.forEach((component) => {
- reportMissingDisplayName(component);
+ if (!component.hasDisplayName) {
+ reportMissingDisplayName(component);
+ }
});
}
};
diff --git a/lib/rules/forbid-component-props.js b/lib/rules/forbid-component-props.js
index d1f61f4171..eb316c8423 100644
--- a/lib/rules/forbid-component-props.js
+++ b/lib/rules/forbid-component-props.js
@@ -83,8 +83,6 @@ module.exports = {
return {
JSXAttribute(node) {
const parentName = node.parent.name;
- // Extract a component name when using a "namespace", e.g. ``.
- const tag = parentName.name || `${parentName.object.name}.${parentName.property.name}`;
const componentName = parentName.name || parentName.property.name;
if (componentName && typeof componentName[0] === 'string' && componentName[0] !== componentName[0].toUpperCase()) {
// This is a DOM node, not a Component, so exit.
@@ -93,6 +91,9 @@ module.exports = {
const prop = node.name.name;
+ // Extract a component name when using a "namespace", e.g. ``.
+ const tag = parentName.name || `${parentName.object.name}.${parentName.property.name}`;
+
if (!isForbidden(prop, tag)) {
return;
}
diff --git a/lib/rules/jsx-indent.js b/lib/rules/jsx-indent.js
index 89b5f7f7f8..39fbcdc002 100644
--- a/lib/rules/jsx-indent.js
+++ b/lib/rules/jsx-indent.js
@@ -277,13 +277,11 @@ module.exports = {
*/
function checkNodesIndent(node, indent, excludeCommas) {
const nodeIndent = getNodeIndent(node, false, excludeCommas);
- const isCorrectRightInLogicalExp = isRightInLogicalExp(node) && (nodeIndent - indent) === indentSize;
- const isCorrectAlternateInCondExp = isAlternateInConditionalExp(node) && (nodeIndent - indent) === 0;
if (
nodeIndent !== indent
&& astUtil.isNodeFirstInLine(context, node)
- && !isCorrectRightInLogicalExp
- && !isCorrectAlternateInCondExp
+ && !(isRightInLogicalExp(node) && (nodeIndent - indent) === indentSize)
+ && !(isAlternateInConditionalExp(node) && (nodeIndent - indent) === 0)
) {
report(node, indent, nodeIndent);
}
diff --git a/lib/rules/jsx-key.js b/lib/rules/jsx-key.js
index 5586d589ab..c32a654d07 100644
--- a/lib/rules/jsx-key.js
+++ b/lib/rules/jsx-key.js
@@ -19,6 +19,8 @@ const defaultOptions = {
checkKeyMustBeforeSpread: false
};
+const hasReturnStatementType = (item) => item.type === 'ReturnStatement';
+
module.exports = {
meta: {
docs: {
@@ -78,7 +80,7 @@ module.exports = {
}
function getReturnStatement(body) {
- return body.filter((item) => item.type === 'ReturnStatement')[0];
+ return body.find(hasReturnStatementType);
}
function isKeyAfterSpread(attributes) {
diff --git a/lib/rules/jsx-no-bind.js b/lib/rules/jsx-no-bind.js
index 1b14050326..649003cbaa 100644
--- a/lib/rules/jsx-no-bind.js
+++ b/lib/rules/jsx-no-bind.js
@@ -7,6 +7,7 @@
'use strict';
+const entries = require('object.entries');
const propName = require('jsx-ast-utils/propName');
const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');
@@ -110,27 +111,34 @@ module.exports = {
blockVariableNameSets[blockStart][violationType].add(variableName);
}
+ function onlyBlockStatements(ancestor) {
+ return ancestor.type === 'BlockStatement';
+ }
+
function getBlockStatementAncestors(node) {
- return context.getAncestors(node).reverse().filter(
- (ancestor) => ancestor.type === 'BlockStatement'
- );
+ return context.getAncestors(node).filter(onlyBlockStatements).reverse();
}
function reportVariableViolation(node, name, blockStart) {
const blockSets = blockVariableNameSets[blockStart];
- const violationTypes = Object.keys(blockSets);
-
- return violationTypes.find((type) => {
- if (blockSets[type].has(name)) {
- context.report({
- node,
- messageId: type
- });
+ const violationTypes = entries(blockSets);
+
+ const foundTypeEntry = violationTypes.find((typeEntry) => {
+ if (typeEntry[1].has(name)) {
return true;
}
return false;
});
+
+ if (foundTypeEntry) {
+ context.report({
+ node,
+ messageId: foundTypeEntry[0]
+ });
+ }
+
+ return foundTypeEntry;
}
function findVariableViolation(node, name) {
@@ -148,40 +156,43 @@ module.exports = {
if (!node.init) {
return;
}
- const blockAncestors = getBlockStatementAncestors(node);
- const variableViolationType = getNodeViolationType(node.init);
-
- if (
- blockAncestors.length > 0
- && variableViolationType
- && node.parent.kind === 'const' // only support const right now
- ) {
- addVariableNameToSet(
- variableViolationType, node.id.name, blockAncestors[0].range[0]
- );
+
+ // only support const right now
+ if (node.parent.kind === 'const') {
+ const blockAncestors = getBlockStatementAncestors(node);
+ const variableViolationType = getNodeViolationType(node.init);
+
+ if (
+ blockAncestors.length > 0
+ && variableViolationType
+ ) {
+ addVariableNameToSet(
+ variableViolationType, node.id.name, blockAncestors[0].range[0]
+ );
+ }
}
},
JSXAttribute(node) {
- const isRef = configuration.ignoreRefs && propName(node) === 'ref';
- if (isRef || !node.value || !node.value.expression) {
+ if (!node.value || !node.value.expression || (configuration.ignoreRefs && propName(node) === 'ref')) {
return;
}
- const isDOMComponent = jsxUtil.isDOMComponent(node.parent);
- if (configuration.ignoreDOMComponents && isDOMComponent) {
+ if (configuration.ignoreDOMComponents && jsxUtil.isDOMComponent(node.parent)) {
return;
}
const valueNode = node.value.expression;
const valueNodeType = valueNode.type;
- const nodeViolationType = getNodeViolationType(valueNode);
if (valueNodeType === 'Identifier') {
findVariableViolation(node, valueNode.name);
- } else if (nodeViolationType) {
- context.report({
- node,
- messageId: nodeViolationType
- });
+ } else {
+ const nodeViolationType = getNodeViolationType(valueNode);
+ if (nodeViolationType) {
+ context.report({
+ node,
+ messageId: nodeViolationType
+ });
+ }
}
}
};
diff --git a/lib/rules/jsx-no-useless-fragment.js b/lib/rules/jsx-no-useless-fragment.js
index cc6187abbd..8554546ac1 100644
--- a/lib/rules/jsx-no-useless-fragment.js
+++ b/lib/rules/jsx-no-useless-fragment.js
@@ -27,7 +27,7 @@ function isOnlyWhitespace(text) {
* @returns {boolean}
*/
function isNonspaceJSXTextOrJSXCurly(node) {
- return (isJSXText(node) && !isOnlyWhitespace(node.raw)) || node.type === 'JSXExpressionContainer';
+ return node.type === 'JSXExpressionContainer' || (isJSXText(node) && !isOnlyWhitespace(node.raw));
}
/**
diff --git a/lib/rules/jsx-pascal-case.js b/lib/rules/jsx-pascal-case.js
index 696525dfda..a6f3f11f71 100644
--- a/lib/rules/jsx-pascal-case.js
+++ b/lib/rules/jsx-pascal-case.js
@@ -25,20 +25,23 @@ function testLowerCase(char) {
return char === lowerCase && lowerCase !== char.toUpperCase();
}
+const isCharNonAlphanumeric = (char) => !testDigit(char) && char.toLowerCase() === char.toUpperCase();
+const isCharLowerCaseOrDigit = (char) => testLowerCase(char) || testDigit(char);
+
function testPascalCase(name) {
if (!testUpperCase(name.charAt(0))) {
return false;
}
const anyNonAlphaNumeric = Array.prototype.some.call(
name.slice(1),
- (char) => char.toLowerCase() === char.toUpperCase() && !testDigit(char)
+ isCharNonAlphanumeric
);
if (anyNonAlphaNumeric) {
return false;
}
return Array.prototype.some.call(
name.slice(1),
- (char) => testLowerCase(char) || testDigit(char)
+ isCharLowerCaseOrDigit
);
}
@@ -120,23 +123,25 @@ module.exports = {
if (isCompatTag) return undefined;
const name = elementType(node);
- let checkNames = [name];
+ let checkNames;
let index = 0;
if (name.lastIndexOf(':') > -1) {
checkNames = name.split(':');
} else if (name.lastIndexOf('.') > -1) {
checkNames = name.split('.');
+ } else {
+ checkNames = [name];
}
do {
const splitName = checkNames[index];
if (splitName.length === 1) return undefined;
- const isPascalCase = testPascalCase(splitName);
- const isAllowedAllCaps = allowAllCaps && testAllCaps(splitName);
- const isIgnored = ignoreCheck(ignore, splitName);
- if (!isPascalCase && !isAllowedAllCaps && !isIgnored) {
+ if (!testPascalCase(splitName)
+ && !(allowAllCaps && testAllCaps(splitName))
+ && !ignoreCheck(ignore, splitName)
+ ) {
context.report({
node,
messageId: allowAllCaps ? 'usePascalOrSnakeCase' : 'usePascalCase',
diff --git a/lib/rules/no-access-state-in-setstate.js b/lib/rules/no-access-state-in-setstate.js
index a0a910842d..21c6b839e5 100644
--- a/lib/rules/no-access-state-in-setstate.js
+++ b/lib/rules/no-access-state-in-setstate.js
@@ -157,12 +157,13 @@ module.exports = {
while (current.type !== 'Program') {
if (isFirstArgumentInSetStateCall(current, node)) {
vars
- .filter((v) => v.scope === context.getScope() && v.variableName === node.name)
.forEach((v) => {
- context.report({
- node: v.node,
- messageId: 'useCallback'
- });
+ if (v.scope === context.getScope() && v.variableName === node.name) {
+ context.report({
+ node: v.node,
+ messageId: 'useCallback'
+ });
+ }
});
}
current = current.parent;
diff --git a/lib/rules/no-array-index-key.js b/lib/rules/no-array-index-key.js
index 9b3e6eb617..4999c12ff9 100644
--- a/lib/rules/no-array-index-key.js
+++ b/lib/rules/no-array-index-key.js
@@ -47,6 +47,8 @@ module.exports = {
some: 1
};
+ const pragmaFromContext = pragma.getFromContext(context);
+
const reactChildMethods = ['map', 'forEach'];
function isArrayIndex(node) {
@@ -73,7 +75,7 @@ module.exports = {
if (obj && obj.name === 'Children') {
return true;
}
- if (obj && obj.object && obj.object.name === pragma.getFromContext(context)) {
+ if (obj && obj.object && obj.object.name === pragmaFromContext) {
return true;
}
@@ -141,8 +143,10 @@ module.exports = {
if (node.type === 'TemplateLiteral') {
// key={`foo-${bar}`}
- node.expressions.filter(isArrayIndex).forEach(() => {
- context.report({node, messageId: 'noArrayIndex'});
+ node.expressions.forEach((expressionNode) => {
+ if (isArrayIndex(expressionNode)) {
+ context.report({node, messageId: 'noArrayIndex'});
+ }
});
return;
@@ -152,8 +156,10 @@ module.exports = {
// key={'foo' + bar}
const identifiers = getIdentifiersFromBinaryExpression(node);
- identifiers.filter(isArrayIndex).forEach(() => {
- context.report({node, messageId: 'noArrayIndex'});
+ identifiers.forEach((identifierNode) => {
+ if (isArrayIndex(identifierNode)) {
+ context.report({node, messageId: 'noArrayIndex'});
+ }
});
}
}
diff --git a/lib/rules/no-set-state.js b/lib/rules/no-set-state.js
index abf0c0a337..46b1399d38 100644
--- a/lib/rules/no-set-state.js
+++ b/lib/rules/no-set-state.js
@@ -80,8 +80,10 @@ module.exports = {
'Program:exit'() {
const list = components.list();
- values(list).filter((component) => !isValid(component)).forEach((component) => {
- reportSetStateUsages(component);
+ values(list).forEach((component) => {
+ if (!isValid(component)) {
+ reportSetStateUsages(component);
+ }
});
}
};
diff --git a/lib/rules/no-string-refs.js b/lib/rules/no-string-refs.js
index 920a8a5cf7..e21c44e6d8 100644
--- a/lib/rules/no-string-refs.js
+++ b/lib/rules/no-string-refs.js
@@ -46,12 +46,12 @@ module.exports = {
*/
function isRefsUsage(node) {
return Boolean(
- (
+ node.object.type === 'ThisExpression'
+ && node.property.name === 'refs'
+ && (
utils.getParentES6Component()
|| utils.getParentES5Component()
)
- && node.object.type === 'ThisExpression'
- && node.property.name === 'refs'
);
}
diff --git a/lib/rules/no-unused-prop-types.js b/lib/rules/no-unused-prop-types.js
index b59b549bce..cf5682a964 100644
--- a/lib/rules/no-unused-prop-types.js
+++ b/lib/rules/no-unused-prop-types.js
@@ -112,35 +112,37 @@ module.exports = {
return;
}
- values(props || {}).forEach((prop) => {
- // Skip props that check instances
- if (prop === true) {
- return;
- }
+ if (props) {
+ values(props).forEach((prop) => {
+ // Skip props that check instances
+ if (prop === true) {
+ return;
+ }
- if ((prop.type === 'shape' || prop.type === 'exact') && configuration.skipShapeProps) {
- return;
- }
+ if ((prop.type === 'shape' || prop.type === 'exact') && configuration.skipShapeProps) {
+ return;
+ }
- if (prop.node && prop.node.typeAnnotation && prop.node.typeAnnotation.typeAnnotation
- && prop.node.typeAnnotation.typeAnnotation.type === 'TSNeverKeyword') {
- return;
- }
+ if (prop.node && prop.node.typeAnnotation && prop.node.typeAnnotation.typeAnnotation
+ && prop.node.typeAnnotation.typeAnnotation.type === 'TSNeverKeyword') {
+ return;
+ }
- if (prop.node && !isIgnored(prop.fullName) && !isPropUsed(component, prop)) {
- context.report({
- node: prop.node.key || prop.node,
- messageId: 'unusedPropType',
- data: {
- name: prop.fullName
- }
- });
- }
+ if (prop.node && !isIgnored(prop.fullName) && !isPropUsed(component, prop)) {
+ context.report({
+ node: prop.node.key || prop.node,
+ messageId: 'unusedPropType',
+ data: {
+ name: prop.fullName
+ }
+ });
+ }
- if (prop.children) {
- reportUnusedPropType(component, prop.children);
- }
- });
+ if (prop.children) {
+ reportUnusedPropType(component, prop.children);
+ }
+ });
+ }
}
/**
@@ -159,11 +161,10 @@ module.exports = {
'Program:exit'() {
const list = components.list();
// Report undeclared proptypes for all classes
- values(list).filter((component) => mustBeValidated(component)).forEach((component) => {
- if (!mustBeValidated(component)) {
- return;
+ values(list).forEach((component) => {
+ if (mustBeValidated(component)) {
+ reportUnusedPropTypes(component);
}
- reportUnusedPropTypes(component);
});
}
};
diff --git a/lib/rules/no-unused-state.js b/lib/rules/no-unused-state.js
index d91a94c9a9..d6eb9144b0 100644
--- a/lib/rules/no-unused-state.js
+++ b/lib/rules/no-unused-state.js
@@ -144,14 +144,16 @@ module.exports = {
// Takes an ObjectExpression node and adds all named Property nodes to the
// current set of state fields.
function addStateFields(node) {
- node.properties.filter((prop) => (
- prop.type === 'Property'
- && (prop.key.type === 'Literal'
- || (prop.key.type === 'TemplateLiteral' && prop.key.expressions.length === 0)
- || (prop.computed === false && prop.key.type === 'Identifier'))
- && getName(prop.key) !== null
- )).forEach((prop) => {
- classInfo.stateFields.add(prop);
+ node.properties.forEach((prop) => {
+ if (
+ prop.type === 'Property'
+ && (prop.key.type === 'Literal'
+ || (prop.key.type === 'TemplateLiteral' && prop.key.expressions.length === 0)
+ || (prop.computed === false && prop.key.type === 'Identifier'))
+ && getName(prop.key) !== null
+ ) {
+ classInfo.stateFields.add(prop);
+ }
});
}
diff --git a/lib/rules/prop-types.js b/lib/rules/prop-types.js
index 312756d8f1..db5f7b073e 100644
--- a/lib/rules/prop-types.js
+++ b/lib/rules/prop-types.js
@@ -167,19 +167,19 @@ module.exports = {
* @param {Object} component The component to process
*/
function reportUndeclaredPropTypes(component) {
- const undeclareds = component.usedPropTypes.filter((propType) => (
- propType.node
- && !isIgnored(propType.allNames[0])
- && !isDeclaredInComponent(component.node, propType.allNames)
- ));
- undeclareds.forEach((propType) => {
- context.report({
- node: propType.node,
- messageId: 'missingPropType',
- data: {
- name: propType.allNames.join('.').replace(/\.__COMPUTED_PROP__/g, '[]')
- }
- });
+ component.usedPropTypes.forEach((propType) => {
+ if (propType.node
+ && !isIgnored(propType.allNames[0])
+ && !isDeclaredInComponent(component.node, propType.allNames)
+ ) {
+ context.report({
+ node: propType.node,
+ messageId: 'missingPropType',
+ data: {
+ name: propType.allNames.join('.').replace(/\.__COMPUTED_PROP__/g, '[]')
+ }
+ });
+ }
});
}
@@ -191,8 +191,10 @@ module.exports = {
'Program:exit'() {
const list = components.list();
// Report undeclared proptypes for all classes
- values(list).filter((component) => mustBeValidated(component)).forEach((component) => {
- reportUndeclaredPropTypes(component);
+ values(list).forEach((component) => {
+ if (mustBeValidated(component)) {
+ reportUndeclaredPropTypes(component);
+ }
});
}
};
diff --git a/lib/rules/require-default-props.js b/lib/rules/require-default-props.js
index aa9ee112fb..ff0f441e67 100644
--- a/lib/rules/require-default-props.js
+++ b/lib/rules/require-default-props.js
@@ -94,17 +94,17 @@ module.exports = {
'Program:exit'() {
const list = components.list();
- values(list).filter((component) => {
+ values(list).forEach((component) => {
if (ignoreFunctionalComponents
&& (astUtil.isFunction(component.node) || astUtil.isFunctionLikeExpression(component.node))) {
- return false;
+ return;
+ }
+ if (component.declaredPropTypes) {
+ reportPropTypesWithoutDefault(
+ component.declaredPropTypes,
+ component.defaultProps || {}
+ );
}
- return component.declaredPropTypes;
- }).forEach((component) => {
- reportPropTypesWithoutDefault(
- component.declaredPropTypes,
- component.defaultProps || {}
- );
});
}
};
diff --git a/lib/rules/require-optimization.js b/lib/rules/require-optimization.js
index 1445ef6101..7646255fd4 100644
--- a/lib/rules/require-optimization.js
+++ b/lib/rules/require-optimization.js
@@ -222,8 +222,10 @@ module.exports = {
const list = components.list();
// Report missing shouldComponentUpdate for all components
- values(list).filter((component) => !component.hasSCU).forEach((component) => {
- reportMissingOptimization(component);
+ values(list).forEach((component) => {
+ if (!component.hasSCU) {
+ reportMissingOptimization(component);
+ }
});
}
};
diff --git a/lib/rules/require-render-return.js b/lib/rules/require-render-return.js
index 1f70cfc196..ff7b751617 100644
--- a/lib/rules/require-render-return.js
+++ b/lib/rules/require-render-return.js
@@ -49,8 +49,9 @@ module.exports = {
function findRenderMethod(node) {
const properties = astUtil.getComponentProperties(node);
return properties
- .filter((property) => astUtil.getPropertyName(property) === 'render' && property.value)
- .find((property) => astUtil.isFunctionLikeExpression(property.value));
+ .find((property) => astUtil.getPropertyName(property) === 'render'
+ && property.value && astUtil.isFunctionLikeExpression(property.value)
+ );
}
return {
diff --git a/lib/rules/static-property-placement.js b/lib/rules/static-property-placement.js
index 318230d2c6..f04d5e416d 100644
--- a/lib/rules/static-property-placement.js
+++ b/lib/rules/static-property-placement.js
@@ -168,7 +168,7 @@ module.exports = {
MethodDefinition: (node) => {
// If the function is inside a class and is static getter then check if correctly positioned
- if (utils.getParentES6Component() && node.static && node.kind === 'get') {
+ if (node.static && node.kind === 'get' && utils.getParentES6Component()) {
// Report error if needed
reportNodeIncorrectlyPositioned(node, STATIC_GETTER);
}
diff --git a/lib/rules/void-dom-elements-no-children.js b/lib/rules/void-dom-elements-no-children.js
index 634eac517b..d5c2cacbea 100644
--- a/lib/rules/void-dom-elements-no-children.js
+++ b/lib/rules/void-dom-elements-no-children.js
@@ -40,6 +40,22 @@ function isVoidDOMElement(elementName) {
return has(VOID_DOM_ELEMENTS, elementName);
}
+function isChildrenOrDangerProp(prop) {
+ if (!prop.key) {
+ return false;
+ }
+
+ return prop.key.name === 'children' || prop.key.name === 'dangerouslySetInnerHTML';
+}
+
+function isChildrenOrDangerAttribute(attribute) {
+ if (!attribute.name) {
+ return false;
+ }
+
+ return attribute.name.name === 'children' || attribute.name.name === 'dangerouslySetInnerHTML';
+}
+
// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
@@ -82,13 +98,7 @@ module.exports = {
const attributes = node.openingElement.attributes;
- const hasChildrenAttributeOrDanger = attributes.some((attribute) => {
- if (!attribute.name) {
- return false;
- }
-
- return attribute.name.name === 'children' || attribute.name.name === 'dangerouslySetInnerHTML';
- });
+ const hasChildrenAttributeOrDanger = attributes.some(isChildrenOrDangerAttribute);
if (hasChildrenAttributeOrDanger) {
// e.g.
@@ -143,13 +153,7 @@ module.exports = {
const props = args[1].properties;
- const hasChildrenPropOrDanger = props.some((prop) => {
- if (!prop.key) {
- return false;
- }
-
- return prop.key.name === 'children' || prop.key.name === 'dangerouslySetInnerHTML';
- });
+ const hasChildrenPropOrDanger = props.some(isChildrenOrDangerProp);
if (hasChildrenPropOrDanger) {
// e.g. React.createElement('br', { children: 'Foo' })
diff --git a/lib/util/annotations.js b/lib/util/annotations.js
index d52fb214f1..ad8d7acdd1 100644
--- a/lib/util/annotations.js
+++ b/lib/util/annotations.js
@@ -19,12 +19,20 @@ function isAnnotatedFunctionPropsDeclaration(node, context) {
const typeNode = node.params[0].type === 'AssignmentPattern' ? node.params[0].left : node.params[0];
- const tokens = context.getFirstTokens(typeNode, 2);
const isAnnotated = typeNode.typeAnnotation;
const isDestructuredProps = typeNode.type === 'ObjectPattern';
- const isProps = tokens[0].value === 'props' || (tokens[1] && tokens[1].value === 'props');
- return (isAnnotated && (isDestructuredProps || isProps));
+ if (isAnnotated) {
+ if (isDestructuredProps) {
+ return true;
+ }
+
+ const tokens = context.getFirstTokens(typeNode, 2);
+ const isProps = tokens[0].value === 'props' || (tokens[1] && tokens[1].value === 'props');
+ return isProps;
+ }
+
+ return false;
}
module.exports = {
diff --git a/lib/util/usedPropTypes.js b/lib/util/usedPropTypes.js
index ff462ee729..44fd6d0d0c 100644
--- a/lib/util/usedPropTypes.js
+++ b/lib/util/usedPropTypes.js
@@ -447,18 +447,20 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
}
function handleCustomValidators(component) {
- const propTypes = component.declaredPropTypes;
- if (!propTypes) {
- return;
- }
+ if (mustBeValidated(component)) {
+ const propTypes = component.declaredPropTypes;
+ if (!propTypes) {
+ return;
+ }
- values(propTypes).forEach((val) => {
- const node = val.node;
+ values(propTypes).forEach((val) => {
+ const node = val.node;
- if (node.value && astUtil.isFunctionLikeExpression(node.value)) {
- markPropTypesAsUsed(node.value);
- }
- });
+ if (node.value && astUtil.isFunctionLikeExpression(node.value)) {
+ markPropTypesAsUsed(node.value);
+ }
+ });
+ }
}
return {
@@ -555,7 +557,7 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
'Program:exit'() {
const list = components.list();
- values(list).filter((component) => mustBeValidated(component)).forEach(handleCustomValidators);
+ values(list).forEach(handleCustomValidators);
}
};
};