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

Add new rule 'default-props-match-prop-types' #1087

Merged
merged 8 commits into from
May 17, 2017

Conversation

webOS101
Copy link
Contributor

Fixes #1022

There's currently one caveat that I haven't addressed: If there are no propTypes at all no warnings are issued. I didn't distinguish between that case and the case where they are not able to be determined (e.g.: external import). Also, this rule may conflict with require-default-props as I am re-using the same component members, though testing did not reveal any problems using the two rules together.

@lencioni
Copy link
Collaborator

Thanks for the contribution! I haven't had time to review the code here yet, but I wanted to mention that I think no-invalid-default-props isn't quite the right name for this rule. To me that name implies that the default props are going to be checked against the propTypes validators.

I'm not quite sure what a good name might be. Maybe something along the lines of no-extra-default-props?

Also, I'm not entirely sure this makes sense as a separate rule instead of enhancing the prop-types rule to include this. @ljharb what do you think?

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

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

Your test cases look very thorough!

/**
* Checks if the Identifier node passed in looks like a defaultProps declaration.
* @param {ASTNode} node The node to check. Must be an Identifier node.
* @returns {Boolean} `true` if the node is a defaultProps declaration, `false` if not
Copy link
Member

Choose a reason for hiding this comment

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

I don't think any of these spaces are needed; do we typically visually align these comments in other rules?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Happy to make changes, but this code is nearly identical to require-default-props. Do you want me to update the source there, too?

Copy link
Member

Choose a reason for hiding this comment

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

in that case (that our rules already are inconsistent) then don't worry about it; it can be cleaned up in a separate PR.

* @returns {Boolean} `true` if the node is a defaultProps declaration, `false` if not
*/
function isDefaultPropsDeclaration(node) {
return (getPropertyName(node) === 'defaultProps' || getPropertyName(node) === 'getDefaultProps');
Copy link
Member

Choose a reason for hiding this comment

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

Let's cache the property name rather than calling the function twice.


// e.g.:
// MyComponent.propTypes.baz = React.PropTypes.string;
if (node.parent.type === 'MemberExpression' && node.parent.parent.type === 'AssignmentExpression') {
Copy link
Member

Choose a reason for hiding this comment

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

Will node.parent always have a .parent node?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it's unlikely you wouldn't have a parent node in the case of a MemberExpression whose parent is a MemberExpression and belongs to a Component. But, I will admit I'm not intimately familiar with this code.

Copy link
Member

Choose a reason for hiding this comment

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

I don't know much of anything about AST nodes, I just want to avoid a crash in the future when a new node type comes out

return;
}

var isPropType = getPropertyName(node) === 'propTypes';
Copy link
Member

Choose a reason for hiding this comment

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

Let's cache the property name here rather than calling the function thrice.

@ljharb
Copy link
Member

ljharb commented Feb 24, 2017

Hmm, that makes sense that "invalid" isn't the best name. extra works, I suppose - or no-superfluous-default-props, or some other synonym?

@ljharb
Copy link
Member

ljharb commented Feb 24, 2017

I do think it belongs as a separate rule since it warns on defaults, not prop types.

@webOS101
Copy link
Contributor Author

no-unnecessary-default-props? no-unneeded-default-props? no-useless-default-props?

@ljharb
Copy link
Member

ljharb commented Feb 24, 2017

A defaultProp for a required prop is arguably not "useless" since it may serve as documentation (not that I would ever use the option that allows it) so I don't think that's the right word.

unnecessary could work too (along with extra or superfluous).

no-unused-default-props would be good but there's no safe way to tell if the user uses it, only if React will use it.

Let's keep bikeshedding on the name, might as well pick the best one now.

@webOS101
Copy link
Contributor Author

@lencioni A rule that validates the types of the defaultProps seems very useful!

@webOS101
Copy link
Contributor Author

I addressed some of the concerns raised in the review, but understand we're still searching for a good name.

@webOS101
Copy link
Contributor Author

webOS101 commented Mar 2, 2017

Anyone had any good ideas on the naming? Nothing particularly new has come to me. Maybe no-stray-default-props?

@ljharb
Copy link
Member

ljharb commented Mar 31, 2017

What about default-props-match-prop-types?

@webOS101
Copy link
Contributor Author

webOS101 commented Apr 4, 2017

That seems more in keeping with @lencioni 's checker that would validate types. no-undefined-default-props? no-unexpected-default-props? only-meaningful-default-props?

@ljharb
Copy link
Member

ljharb commented Apr 4, 2017

I think default-props-match-prop-types is good, and checking for matching types would be enabled in that rule via an additional option :-)

@webOS101
Copy link
Contributor Author

webOS101 commented Apr 6, 2017

I'm curious how accurate we could be in matching the types. Certainly simple types would be easy, more complicated ones could easily become problematic. If you like the new name a lot, I can update the PR to the new name.

@ljharb
Copy link
Member

ljharb commented Apr 6, 2017

I think matching the types will likely only be possible when using the built-in PropTypes validators, or else it'd have to actually pull in and evaluate any custom prop types - but that's a discussion for that separate PR.

I think "match" doesn't necessarily connote "types match", which is why I don't think having the option to match types is a blocker. I mainly just want to get this in, and I think that's a good enough name ¯\_(ツ)_/¯

@webOS101
Copy link
Contributor Author

Updated the name of the rule and rebased on master.

@ljharb ljharb changed the title Add new rule 'no-invalid-default-props' Add new rule 'default-props-match-prop-types' Apr 30, 2017
Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

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

Looks great overall!

'use strict';

var has = require('has');
var find = require('array.prototype.find');
Copy link
Member

Choose a reason for hiding this comment

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

this is no longer necessary, since master now only supports node 4+

Copy link
Contributor Author

@webOS101 webOS101 May 1, 2017

Choose a reason for hiding this comment

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

What's sad is I originally implemented with Array.find() but realized this didn't match with the (then) current style.

* @returns {ASTNode|null} Return null if the variable could not be found, ASTNode otherwise.
*/
function findVariableByName(name) {
var variable = find(variableUtil.variablesInScope(context), function(item) {
Copy link
Member

Choose a reason for hiding this comment

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

so this can be const variable = variableUtil.variablesInScope(context).find(item => item.name === name);

* from this ObjectExpression can't be resolved.
*/
function getDefaultPropsFromObjectExpression(objectExpression) {
var hasSpread = find(objectExpression.properties, function(property) {
Copy link
Member

Choose a reason for hiding this comment

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

and this

}

function propFromName(propTypes, name) {
return find(propTypes, function (prop) {
Copy link
Member

Choose a reason for hiding this comment

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

and this can be return propTypes.find(prop => prop.name === name);

Enact-DCO-1.0-Signed-off-by: Roy Sutton [email protected]
@webOS101
Copy link
Contributor Author

webOS101 commented May 1, 2017

Updated all the var declarations as well.

@webOS101
Copy link
Contributor Author

Anything else needed for this?

@ljharb
Copy link
Member

ljharb commented May 17, 2017

Sorry for the delay. I'll give this another day or so, and if there's no objections, I'll merge it.

@ljharb ljharb merged commit 62daf82 into jsx-eslint:master May 17, 2017
@webOS101
Copy link
Contributor Author

webOS101 commented Jun 5, 2017

Whoops, looks like I didn't add the rule to the README.md in the root. Should I create a separate PR for that?

@ljharb
Copy link
Member

ljharb commented Jun 5, 2017

@webOS101 yes, thanks, that'd be great!

@webOS101
Copy link
Contributor Author

webOS101 commented Jun 6, 2017

#1239

@webOS101 webOS101 deleted the no-invalid-default-props branch June 6, 2017 04:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

4 participants