Skip to content

Commit bb47625

Browse files
committed
Support Object.assign, et al, for bool-prop-naming
With `propObjectAssignFunctions` set in settings like so: ``` { ... propOjectAssignFunctions: ["Object.assign"] ... } ``` One can use `Object.assign` for setting the propTypes like this: ``` function Foo() {...} Foo.propTypes = Object.assign({}, morePropTypes, { isLoading: PropTypes.bool }); ``` And the boolean-prop-naming rule should be able to verify the prop `isLoading` against the defined options.
1 parent e2ca690 commit bb47625

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ You can also specify some settings that will be shared across all the plugin rul
4343
"flowVersion": "0.53" // Flow version
4444
},
4545
"propWrapperFunctions": [ "forbidExtraProps" ] // The names of any functions used to wrap the propTypes object, such as `forbidExtraProps`. If this isn't set, any propTypes wrapped in a function will be skipped.
46+
"propObjectAssignFunctions": [ "Object.assign" ] // The names of functions used to merge props when declaring propTypes. If this isn't set, any propTypes set using any assign/merge function will be skipped.
4647
}
4748
}
4849
```

lib/rules/boolean-prop-naming.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ module.exports = {
4646
const config = context.options[0] || {};
4747
const rule = config.rule ? new RegExp(config.rule) : null;
4848
const propTypeNames = config.propTypeNames || ['bool'];
49+
const propObjectAssignFunctions = new Set(context.settings.propObjectAssignFunctions || []);
4950

5051
// Remembers all Flowtype object definitions
5152
const objectTypeAnnotations = new Map();
@@ -138,6 +139,22 @@ module.exports = {
138139
});
139140
}
140141

142+
/**
143+
* Checks if call expression node is one of the propObjectAssignFunctions in the settings
144+
* @param {ASTNode} node The node to process
145+
* @returns {Boolean} True if the function name is defined in the settings, false if not
146+
*/
147+
function isPropObjectAssignFunction(node) {
148+
if (!node) {
149+
return false;
150+
} else if (node.type === 'MemberExpression') {
151+
return propObjectAssignFunctions.has(`${node.object.name}.${node.property.name}`);
152+
} else if (node.type === 'Identifier') {
153+
return propObjectAssignFunctions.has(node.name);
154+
}
155+
return false;
156+
}
157+
141158
// --------------------------------------------------------------------------
142159
// Public
143160
// --------------------------------------------------------------------------
@@ -160,7 +177,12 @@ module.exports = {
160177
return;
161178
}
162179
const component = utils.getRelatedComponent(node);
163-
if (!component || !node.parent.right.properties) {
180+
if (!component || !node.parent.right) {
181+
return;
182+
}
183+
const right = node.parent.right;
184+
if (right.type === 'CallExpression' && isPropObjectAssignFunction(right.callee)) {
185+
right.arguments.filter(arg => arg.type === 'ObjectExpression').forEach(object => validatePropNaming(component.node, object.properties));
164186
return;
165187
}
166188
validatePropNaming(component.node, node.parent.right.properties);

tests/lib/rules/boolean-prop-naming.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,18 @@ ruleTester.run('boolean-prop-naming', rule, {
295295
rule: '^is[A-Z]([A-Za-z0-9]?)+'
296296
}],
297297
parser: 'babel-eslint'
298+
}, {
299+
// No propObjectAssignFunctions setting
300+
code: `
301+
function Card(props) {
302+
return <div>{props.showScore ? 'yeh' : 'no'}</div>;
303+
}
304+
Card.propTypes = merge({}, Card.propTypes, {
305+
showScore: PropTypes.bool
306+
});`,
307+
options: [{
308+
rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
309+
}]
298310
}],
299311

300312
invalid: [{
@@ -515,5 +527,56 @@ ruleTester.run('boolean-prop-naming', rule, {
515527
}, {
516528
message: 'Prop name (somethingElse) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
517529
}]
530+
}, {
531+
code: `
532+
function Card(props) {
533+
return <div>{props.showScore ? 'yeh' : 'no'}</div>;
534+
}
535+
Card.propTypes = merge({}, Card.propTypes, {
536+
showScore: PropTypes.bool
537+
});`,
538+
settings: {
539+
propObjectAssignFunctions: ['merge']
540+
},
541+
options: [{
542+
rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
543+
}],
544+
errors: [{
545+
message: 'Prop name (showScore) doesn\'t match rule (^(is|has)[A-Z]([A-Za-z0-9]?)+)'
546+
}]
547+
}, {
548+
code: `
549+
function Card(props) {
550+
return <div>{props.showScore ? 'yeh' : 'no'}</div>;
551+
}
552+
Card.propTypes = Object.assign({}, Card.propTypes, {
553+
showScore: PropTypes.bool
554+
});`,
555+
settings: {
556+
propObjectAssignFunctions: ['Object.assign']
557+
},
558+
options: [{
559+
rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
560+
}],
561+
errors: [{
562+
message: 'Prop name (showScore) doesn\'t match rule (^(is|has)[A-Z]([A-Za-z0-9]?)+)'
563+
}]
564+
}, {
565+
code: `
566+
function Card(props) {
567+
return <div>{props.showScore ? 'yeh' : 'no'}</div>;
568+
}
569+
Card.propTypes = _.assign({}, Card.propTypes, {
570+
showScore: PropTypes.bool
571+
});`,
572+
settings: {
573+
propObjectAssignFunctions: ['_.assign']
574+
},
575+
options: [{
576+
rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
577+
}],
578+
errors: [{
579+
message: 'Prop name (showScore) doesn\'t match rule (^(is|has)[A-Z]([A-Za-z0-9]?)+)'
580+
}]
518581
}]
519582
});

0 commit comments

Comments
 (0)