-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Allow custom PropType classes with no-typos rule #1671
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
Conversation
It's a minor corner case, and removing it allows the major issue to be resolved. If it's really necessary to handle that corner case, I suggest creating a new issue to track just that case.
...well, I thought I'd rebased on master. Fixing. |
The typos were being ignored, because without `PropTypes`, the un-namespaced identifiers looked like custom proptypes.
b1c1c25
to
d91154e
Compare
Ok, rebased again, conflicts resolved, tests fixed up to handle changes on master. PTAL |
Thanks, will review soon. |
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 also add tests for using React.PropTypes
, and const { PropTypes } = React
?
Added them. They fail. 😕 Looking into it. |
Added tests for: - `import { PropTypes } from 'react';` - `React.PropTypes`o Fixed a couple subtle bugs that made these new tests fail, and made a small refactoring that made this code easier to understand and fix.
Ok, new tests (and fixes) pushed. Apologies if it's a touch sloppy; I just now got this to work and wanted to get it out before I unplug for the day. PTAL, thanks for the feedback! |
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 createClass components?
cefe6e7
to
7d05324
Compare
These two tests fail on master as well as this branch, so they expose a pre-existing bug with the no-typos rule.
@ljharb How crucial is that? There are no pre-existing Also, there's an implicit test matrix in the
I wouldn't feel confident about I created a couple quick-and-dirty |
I think it's crucial in that no createClass-related bugs have been reported for it, so even though there's no tests, any change to the rule might break it - and tests ensure that it's not broken. DRY is generally a bad idea in tests; it'd be better to copy-paste all the needed tests. However - if, in fact, this rule never worked on createClass components, which your tests seem to suggest, would you be willing to add commented-out createClass tests in this PR, and file a new PR after this one is merged that uncomments the tests? (From that point I can try to get the rule passing, if you don't have the time) |
Strongly disagree on "generally" and definitely in this particular case. The repetition makes it hard to know which are "all the needed tests" - it's hard to see which tests test which behavior, since there is clearly a cross product of behaviors under test. It would be better IMO if that was extracted and made explicit. Thankfully, we don't have to agree on that to make progress with this PR. :)
Sure, sounds good. I only have a couple such tests, but it'll be a start, anyway. Pushing shortly. |
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.
LGTM! just two more comments :-)
) { | ||
context.report({ | ||
node: node, | ||
message: 'Method returning JSX should be written as stateless function component' |
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 should probably be pluralized; Methods returning JSX should be written as stateless functional components
@@ -298,6 +302,20 @@ module.exports = { | |||
markThisAsUsed(node); | |||
}, | |||
|
|||
// Report non-"render" methods that return JSX | |||
MethodDefinition: function(node) { |
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 computed methods? like ['foo']() { return <div /> }
or [Symbol()]() { return <div />; }
?
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.
TBH I'm not sure why this commit was in the original branch that I started from here. I'd be fine just removing that commit from this PR, but I'm not sure what would be correct in regards to your comment here.
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.
ah yes, good call. This PR is about the no-typos rule; but it has prefer-stateless-function changes. Let's remove all the parts that aren't about no-typos :-)
e91f763
to
e9d9990
Compare
Removed |
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 you add test cases for require
as well? we should be able to handle top-level static requires along with import
.
Separately, can we make sure that every test using babel-eslint has a duplicate test that uses the default parser?
lib/rules/no-typos.js
Outdated
} else if (callee.type === 'MemberExpression' && callee.property.name === 'oneOfType') { | ||
const args = node.arguments[0]; | ||
if (args && args.type === 'ArrayExpression') { | ||
args.elements.forEach(el => checkValidProp(el)); |
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 forEach ignores its return value, this should be an explicit-return arrow function 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.
You're saying you'd prefer args.elements.forEach(el => { checkValidProp(el); });
? It seems strictly noisier to me, but I don't feel strongly ¯\_(ツ)_/¯
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.
yep, exactly; implicit return should only be used where the return value matters.
lib/rules/no-typos.js
Outdated
@@ -54,38 +57,69 @@ module.exports = { | |||
} | |||
} | |||
|
|||
function isPropTypesPackage(node) { | |||
// Note: we really do want == with the package names here, | |||
// since we need value equality, not identity - and |
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 confused about this - every string that has the same contents is the same string by identity, iow 'abc' === 'abc'
. Why do we need ==
here?
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 thought that too, but when I was testing, it seemed that only every string literal with the same contents is the same string by identity. I found that was not the case when comparing a literal to a value read from a file.
But maybe there was another issue that I didn't fully understand; I made this jsfiddle to test this, and the results indicate no difference between ===
and ==
, even when comparing a literal to a computed or read-from-external-source value.
I can dig into this more tomorrow, probably.
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.
Perhaps there's invisible characters in the strings? When you run into the difference, try comparing .length
(altho then ==
would fail too). All strings in JS that have the same contents are ===
.
Specifically, ==
is "===
after type coercion", so if they're both typeof "string"
, ==
and ===
are identical, by spec.
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 your feedback. However, I'm concerned that we're getting solidly into scope creep territory again.
There are no such tests currently; it's not part of this PR to add that coverage. Can we make a separate issue for that?
It would be similarly out of scope to ask this for every Also, are all tests valid with both parsers? I don't really understand the difference between babel-eslint and the "default parser", so I'm not sure I'm the one to make that change anyway, even if it were in scope here. |
Yes, certainly only the added tests :-) if the others are missing tests for both the default parser and babel-eslint, that's something we'll have to fix separately. "Noisy" isn't really a concern in tests; copy-pasting in tests is also fine. The value in testing with both parsers is that each parser might generate different node names, making the rule behave differently (even though it's unlikely). Including both tests prevents any regressions on that in the future as we update eslint and/or babel-eslint. |
Added copies of this PR's new tests with the default parser. |
Anything else needed on this one? I'd love to get it merged soon. |
lib/rules/no-typos.js
Outdated
node.specifiers | ||
.filter(specifier => specifier.imported && specifier.imported.name === 'PropTypes') | ||
.map(specifier => specifier.local.name) | ||
)[0] : 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.
should this use .find
instead of .filter
?
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.
Sure; it makes this code clearer. Updated.
Thanks for dealing with this @brettdh - I also hope to see this merged and released soon 👍 |
f21b267
to
fc06f85
Compare
Any idea when is this going to be released? Or is that a temporary workaround for it until then? |
@lucaslim looks like there's an RC now: https://github.com/yannickcr/eslint-plugin-react/releases/tag/v7.8.0-rc.0 |
@yannickcr That's awesome! Thanks :) |
This is simply a rebase of @jseminck's branch, plus the removal of the
lingering failing test.
I removed the failing test because I believe it's a very small corner case
that should not block the resolution of this issue, which seems to affect
a lot of people and limits our ability to keep our components' proptypes DRY.
If it's determined that this corner case should be handled, I suggest creating
a new issue to track just that case.
Closes #1389.