-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
New boolean-prop-naming
rule for enforcing the naming of booleans
#1264
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about custom propTypes that enforce booleans but aren't PropTypes.bool
? For example, mutuallyExclusiveTrueProps
from https://www.npmjs.com/package/airbnb-prop-types.
Can there be a way to customize the name of custom propTypes that are booleans?
docs/rules/boolean-prop-naming.md
Outdated
```jsx | ||
var Hello = createReactClass({ | ||
propTypes: { | ||
enabled: PropTypes.boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PropTypes.bool
- .boolean
isn't a thing (same throughout)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. Good catch.
docs/rules/boolean-prop-naming.md
Outdated
|
||
### `rule` | ||
|
||
The Regex pattern to use when validating the name of the prop. Some common examples are: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
regex
or RegExp
docs/rules/boolean-prop-naming.md
Outdated
|
||
## About component detection | ||
|
||
For this rule to work we need to detect React components, this could be very hard since components could be declared in a lot of ways. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be using Components.detect
in all our rules; is there a reason this paragraph needs to exist?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was copy/pasted from another rule's document. Should I remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this seems more like a project-level thing, not a rule-level thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WIll remove.
lib/rules/boolean-prop-naming.js
Outdated
*/ | ||
'use strict'; | ||
|
||
var has = require('has'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Not all rules were using ES6, wasn't sure which version of Node we're supporting. Will update accordingly.
// createReactClass components with PropTypes | ||
code: [ | ||
'var Hello = createReactClass({', | ||
' propTypes: {isSomething: PropTypes.boolean},', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think all the PropType test cases are invalid - s/boolean/bool/g
.
ae2b074
to
82e35b8
Compare
Good idea. I've added a new |
82e35b8
to
b16fd19
Compare
docs/rules/boolean-prop-naming.md
Outdated
|
||
### `rule` | ||
|
||
The RegExp pattern to use when validating the name of the prop. Some common examples are: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the default for this option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null
is the default at the moment (ie. the naming checks are disabled). It didn't seem right to enforce my own preferences on all users. Do you think is makes sense to set "(is|has)*" as the default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since if not, the rule does nothing by default, yes.
The ideal scenario is that nobody ever needs to write a regex, except for the minority edge cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Will set a default.
create: Components.detect(function(context, components, utils) { | ||
const sourceCode = context.getSourceCode(); | ||
const config = context.options[0] || {}; | ||
const rule = config.rule ? new RegExp(config.rule) : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm really really not a fan of user-supplied regexes, and passing unsanitized input into new RegExp
can definitely cause catastrophic backtracking and other malicious regexes to be invoked.
Can we simplify this somehow, perhaps requiring a list of prefixes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not opposed to replacing the RegExp entry to just prefixes, however, that makes the rule much less powerful and less customizable. Having user-supplied regexes in ESLint rules isn't uncommon (eg. http://eslint.org/docs/rules/id-match) when specifying naming conventions for things.
return false; | ||
} | ||
|
||
return Boolean( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
usually we just do ‼x
instead of Boolean(x)
, nbd tho
require('babel-eslint'); | ||
|
||
var parserOptions = { | ||
ecmaVersion: 8, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can probably be 6
/2015
, yes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix.
ecmaVersion: 8, | ||
sourceType: 'module', | ||
ecmaFeatures: { | ||
experimentalObjectRestSpread: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think we're using this feature in these tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix.
c9d8647
to
d76c2fb
Compare
lib/rules/boolean-prop-naming.js
Outdated
type: 'array' | ||
}, | ||
rule: { | ||
default: null, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we put the default here, in the schema, and use minLength: 1
to avoid the empty string?
lib/rules/boolean-prop-naming.js
Outdated
const sourceCode = context.getSourceCode(); | ||
const config = context.options[0] || {}; | ||
const rule = new RegExp(config.rule || DEFAULT_RULE); | ||
const propTypeNames = config.propTypeNames ? config.propTypeNames : ['bool']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, can this default go in the schema instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason, default
schema definition doesn't work for this option. Maybe because it's an array
type? Specifying a default
at the schema level here never returns anything from config object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i guess you can't have a default array in jsonschema.
in that case, a ? a : b
should always be a || b
:-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated. Thanks!
lib/rules/boolean-prop-naming.js
Outdated
items: { | ||
type: 'string' | ||
}, | ||
type: 'array' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add uniqueItems: true and minItems: 1
fe71deb
to
38e479a
Compare
lib/rules/boolean-prop-naming.js
Outdated
} | ||
|
||
const list = components.list(); | ||
for (let component in list) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's avoid for..in; can we use Object.keys().forEach here instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
38e479a
to
519dc2b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Let's wait til we get at least one other collab review before merging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution!
lib/rules/boolean-prop-naming.js
Outdated
( | ||
prop.type === 'ObjectTypeProperty' && | ||
prop.value.type === 'BooleanTypeAnnotation' && | ||
getPropName(prop).search(rule) < 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think rule.test(getPropName(prop))
might be more appropriate here (and below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will change to use .exec()
actually, since (after some research) that appears to be the most performant way to execute Regex rules. Hope that's ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exec
mutates; test
doesn't - test might be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
lib/rules/boolean-prop-naming.js
Outdated
const propName = getPropName(propNode); | ||
context.report({ | ||
node: propNode, | ||
message: `Prop name (${propName}) doesn't match specified rule (${config.rule})`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"specified" seems redundant in this message. I think you can remove it without losing any meaning. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Will remove.
lib/rules/boolean-prop-naming.js
Outdated
const propTypeNames = config.propTypeNames || ['bool']; | ||
|
||
// Remembers all Flowtype object definitions | ||
var ObjectTypeAnnonations = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo? ObjectTypeAnnotations
?
Also, since this isn't instantiated, it should probably start with a lowercase letter.
And it might be a bit nicer to use a Map
instead of a plain object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on all 3 points, nice catch
d27f42e
to
f9c5fae
Compare
f9c5fae
to
da0affa
Compare
At my workplace, we prefer to name our boolean props as "isSomething" or "hasWhatever". This is an ESLint rule which allows devs to specify a Regex pattern for how they want their boolean props named.
Tested with createReactClass, ES6 components, stateless components and Flowtype.
I support, in the future, this rule can be expanded to support naming rules for ANY props, but that felt like overkill for the time being. Hopefully this rule will be useful as is.