Skip to content

Commit efb5bd7

Browse files
committed
Extract defaultProps detection code from default-props-match-prop-types
1 parent bd083bf commit efb5bd7

File tree

3 files changed

+278
-119
lines changed

3 files changed

+278
-119
lines changed

lib/rules/default-props-match-prop-types.js

Lines changed: 11 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -200,39 +200,6 @@ module.exports = {
200200
});
201201
}
202202

203-
/**
204-
* Extracts a DefaultProp from an ObjectExpression node.
205-
* @param {ASTNode} objectExpression ObjectExpression node.
206-
* @returns {Object|string} Object representation of a defaultProp, to be consumed by
207-
* `addDefaultPropsToComponent`, or string "unresolved", if the defaultProps
208-
* from this ObjectExpression can't be resolved.
209-
*/
210-
function getDefaultPropsFromObjectExpression(objectExpression) {
211-
const hasSpread = objectExpression.properties.find(property => property.type === 'ExperimentalSpreadProperty' || property.type === 'SpreadElement');
212-
213-
if (hasSpread) {
214-
return 'unresolved';
215-
}
216-
217-
return objectExpression.properties.map(defaultProp => ({
218-
name: defaultProp.key.name,
219-
node: defaultProp
220-
}));
221-
}
222-
223-
/**
224-
* Marks a component's DefaultProps declaration as "unresolved". A component's DefaultProps is
225-
* marked as "unresolved" if we cannot safely infer the values of its defaultProps declarations
226-
* without risking false negatives.
227-
* @param {Object} component The component to mark.
228-
* @returns {void}
229-
*/
230-
function markDefaultPropsAsUnresolved(component) {
231-
components.set(component.node, {
232-
defaultProps: 'unresolved'
233-
});
234-
}
235-
236203
/**
237204
* Adds propTypes to the component passed in.
238205
* @param {ASTNode} component The component to add the propTypes to.
@@ -247,31 +214,6 @@ module.exports = {
247214
});
248215
}
249216

250-
/**
251-
* Adds defaultProps to the component passed in.
252-
* @param {ASTNode} component The component to add the defaultProps to.
253-
* @param {String[]|String} defaultProps defaultProps to add to the component or the string "unresolved"
254-
* if this component has defaultProps that can't be resolved.
255-
* @returns {void}
256-
*/
257-
function addDefaultPropsToComponent(component, defaultProps) {
258-
// Early return if this component's defaultProps is already marked as "unresolved".
259-
if (component.defaultProps === 'unresolved') {
260-
return;
261-
}
262-
263-
if (defaultProps === 'unresolved') {
264-
markDefaultPropsAsUnresolved(component);
265-
return;
266-
}
267-
268-
const defaults = component.defaultProps || [];
269-
270-
components.set(component.node, {
271-
defaultProps: defaults.concat(defaultProps)
272-
});
273-
}
274-
275217
/**
276218
* Tries to find a props type annotation in a stateless component.
277219
* @param {ASTNode} node The AST node to look for a props type annotation.
@@ -352,9 +294,8 @@ module.exports = {
352294
return {
353295
MemberExpression: function(node) {
354296
const isPropType = propsUtil.isPropTypesDeclaration(node);
355-
const isDefaultProp = propsUtil.isDefaultPropsDeclaration(node);
356297

357-
if (!isPropType && !isDefaultProp) {
298+
if (!isPropType) {
358299
return;
359300
}
360301

@@ -375,21 +316,8 @@ module.exports = {
375316
// MyComponent.propTypes = myPropTypes;
376317
if (node.parent.type === 'AssignmentExpression') {
377318
const expression = resolveNodeValue(node.parent.right);
378-
if (!expression || expression.type !== 'ObjectExpression') {
379-
// If a value can't be found, we mark the defaultProps declaration as "unresolved", because
380-
// we should ignore this component and not report any errors for it, to avoid false-positives
381-
// with e.g. external defaultProps declarations.
382-
if (isDefaultProp) {
383-
markDefaultPropsAsUnresolved(component);
384-
}
385-
386-
return;
387-
}
388-
389-
if (isPropType) {
319+
if (expression && expression.type === 'ObjectExpression') {
390320
addPropTypesToComponent(component, getPropTypesFromObjectExpression(expression));
391-
} else {
392-
addDefaultPropsToComponent(component, getDefaultPropsFromObjectExpression(expression));
393321
}
394322

395323
return;
@@ -399,20 +327,11 @@ module.exports = {
399327
// MyComponent.propTypes.baz = React.PropTypes.string;
400328
if (node.parent.type === 'MemberExpression' && node.parent.parent &&
401329
node.parent.parent.type === 'AssignmentExpression') {
402-
if (isPropType) {
403-
addPropTypesToComponent(component, [{
404-
name: node.parent.property.name,
405-
isRequired: propsUtil.isRequiredPropType(node.parent.parent.right),
406-
node: node.parent.parent
407-
}]);
408-
} else {
409-
addDefaultPropsToComponent(component, [{
410-
name: node.parent.property.name,
411-
node: node.parent.parent
412-
}]);
413-
}
414-
415-
return;
330+
addPropTypesToComponent(component, [{
331+
name: node.parent.property.name,
332+
isRequired: propsUtil.isRequiredPropType(node.parent.parent.right),
333+
node: node.parent.parent
334+
}]);
416335
}
417336
},
418337

@@ -438,9 +357,8 @@ module.exports = {
438357
}
439358

440359
const isPropType = propsUtil.isPropTypesDeclaration(node);
441-
const isDefaultProp = propsUtil.isDefaultPropsDeclaration(node);
442360

443-
if (!isPropType && !isDefaultProp) {
361+
if (!isPropType) {
444362
return;
445363
}
446364

@@ -460,11 +378,7 @@ module.exports = {
460378
return;
461379
}
462380

463-
if (isPropType) {
464-
addPropTypesToComponent(component, getPropTypesFromObjectExpression(expression));
465-
} else {
466-
addDefaultPropsToComponent(component, getDefaultPropsFromObjectExpression(expression));
467-
}
381+
addPropTypesToComponent(component, getPropTypesFromObjectExpression(expression));
468382
},
469383

470384
// e.g.:
@@ -495,9 +409,8 @@ module.exports = {
495409

496410
const propName = astUtil.getPropertyName(node);
497411
const isPropType = propName === 'propTypes';
498-
const isDefaultProp = propName === 'defaultProps' || propName === 'getDefaultProps';
499412

500-
if (!isPropType && !isDefaultProp) {
413+
if (!isPropType) {
501414
return;
502415
}
503416

@@ -512,11 +425,7 @@ module.exports = {
512425
return;
513426
}
514427

515-
if (isPropType) {
516-
addPropTypesToComponent(component, getPropTypesFromObjectExpression(expression));
517-
} else {
518-
addDefaultPropsToComponent(component, getDefaultPropsFromObjectExpression(expression));
519-
}
428+
addPropTypesToComponent(component, getPropTypesFromObjectExpression(expression));
520429
},
521430

522431
// e.g.:
@@ -547,25 +456,11 @@ module.exports = {
547456
}
548457

549458
const isPropType = propsUtil.isPropTypesDeclaration(property);
550-
const isDefaultProp = propsUtil.isDefaultPropsDeclaration(property);
551-
552-
if (!isPropType && !isDefaultProp) {
553-
return;
554-
}
555459

556460
if (isPropType && property.value.type === 'ObjectExpression') {
557461
addPropTypesToComponent(component, getPropTypesFromObjectExpression(property.value));
558462
return;
559463
}
560-
561-
if (isDefaultProp && property.value.type === 'FunctionExpression') {
562-
const returnStatement = utils.findReturnStatement(property);
563-
if (!returnStatement || returnStatement.argument.type !== 'ObjectExpression') {
564-
return;
565-
}
566-
567-
addDefaultPropsToComponent(component, getDefaultPropsFromObjectExpression(returnStatement.argument));
568-
}
569464
});
570465
},
571466

lib/util/Components.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ const doctrine = require('doctrine');
99
const variableUtil = require('./variable');
1010
const pragmaUtil = require('./pragma');
1111
const astUtil = require('./ast');
12-
const propTypes = require('./propTypes');
12+
const propTypesUtil = require('./propTypes');
1313
const jsxUtil = require('./jsx');
1414
const usedPropTypesUtil = require('./usedPropTypes');
15+
const defaultPropsUtil = require('./defaultProps');
1516

1617
function getId(node) {
1718
return node && node.range.join(':');
@@ -708,12 +709,15 @@ function componentRule(rule, context) {
708709
// Update the provided rule instructions to add the component detection
709710
const ruleInstructions = rule(context, components, utils);
710711
const updatedRuleInstructions = util._extend({}, ruleInstructions);
711-
const propTypesInstructions = propTypes(context, components, utils);
712+
const propTypesInstructions = propTypesUtil(context, components, utils);
712713
const usedPropTypesInstructions = usedPropTypesUtil(context, components, utils);
714+
const defaultPropsInstructions = defaultPropsUtil(context, components, utils);
713715
const allKeys = new Set(Object.keys(detectionInstructions).concat(
714716
Object.keys(propTypesInstructions),
715-
Object.keys(usedPropTypesInstructions)
717+
Object.keys(usedPropTypesInstructions),
718+
Object.keys(defaultPropsInstructions)
716719
));
720+
717721
allKeys.forEach(instruction => {
718722
updatedRuleInstructions[instruction] = function(node) {
719723
if (instruction in detectionInstructions) {
@@ -725,6 +729,9 @@ function componentRule(rule, context) {
725729
if (instruction in usedPropTypesInstructions) {
726730
usedPropTypesInstructions[instruction](node);
727731
}
732+
if (instruction in defaultPropsInstructions) {
733+
defaultPropsInstructions[instruction](node);
734+
}
728735
return ruleInstructions[instruction] ? ruleInstructions[instruction](node) : void 0;
729736
};
730737
});

0 commit comments

Comments
 (0)