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

Extract used propTypes detection #1946

Merged
merged 5 commits into from Sep 20, 2018

Conversation

alexzherdev
Copy link
Contributor

@alexzherdev alexzherdev commented Aug 19, 2018

Pushing for visibility.
This is failing one existing test, which will get fixed after #1939 is merged (also will need a rebase).

Resolves #963, resolves #1871.

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.

LGTM overall

'Program:exit': function() {
const list = components.list();

for (const component in list) {
Copy link
Member

Choose a reason for hiding this comment

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

for..in should be avoided; can this use normal array iteration methods?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. Object.keys(list).forEach perhaps?
There's about a dozen other files already doing the same, handle them all?

Copy link
Member

Choose a reason for hiding this comment

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

yes, that would be great!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

already done in b35ea0c 😄

@alexzherdev
Copy link
Contributor Author

I went ahead and fixed other for..in occurrences; I can go back and undo those if necessary. Also rebased.
prop-types is 201 line now, no-unused-prop-types is 144 🎉

@@ -248,7 +247,7 @@ module.exports = {
}
}

if (!has(list, component) || (list[component].invalidProps || []).length) {
if ((list[component].invalidProps || []).length) {
Copy link
Member

Choose a reason for hiding this comment

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

maybe if (list[component].invalidProps && list[component].invalidProps.length > 0)?

continue;
Object.keys(list).forEach(component => {
if (list[component].hasDisplayName) {
return;
Copy link
Member

Choose a reason for hiding this comment

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

Object.keys(list).filter(component => !list[component].hasDisplayName).forEach?

for (const component in list) {
if (!has(list, component) || isIgnored(list[component]) || ++i === 1) {
continue;
Object.keys(list).forEach(component => {
Copy link
Member

Choose a reason for hiding this comment

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

(component, i) and then we don't need to ++ it, nor have let i = 0 above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can't do this because we only want to ++i if isIgnored is false and doesn't short-circuit. I.e. we want to start reporting from the second non-ignored component.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually found a way to achieve this, also using filter.

for (const component in list) {
if (!has(list, component) || isValid(list[component])) {
continue;
Object.keys(list).forEach(component => {
Copy link
Member

Choose a reason for hiding this comment

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

Object.keys(list).filter(component => !isValid(list[component])).forEach?

for (const component in list) {
if (!has(list, component) || !mustBeValidated(list[component])) {
continue;
Object.keys(list).forEach(component => {
Copy link
Member

Choose a reason for hiding this comment

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

Object.keys(list).filter(component => mustBeValidated(list[component])).forEach?


if (LIFE_CYCLE_METHODS.indexOf(name) >= 0) {
return true;
} else if (checkAsyncSafeLifeCycles && ASYNC_SAFE_LIFE_CYCLE_METHODS.indexOf(name) >= 0) {
Copy link
Member

Choose a reason for hiding this comment

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

no need for the else


if (node.kind === 'constructor') {
return true;
} else if (LIFE_CYCLE_METHODS.indexOf(nodeKeyName) >= 0) {
Copy link
Member

Choose a reason for hiding this comment

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

also here (ie, the no-else-return eslint rule)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, I wonder why this isn't warning

switch (type) {
case 'direct':
// Ignore Object methods
if (Object.prototype[name]) {
Copy link
Member

Choose a reason for hiding this comment

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

name in Object.prototype would be better, so as not to trigger getters

// method -- mark it for used props.
if (isNodeALifeCycleMethod(node.parent.parent)) {
node.properties.forEach((property, i) => {
if (i === 0) {
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 just:

if (node.properties.length > 0) {
  markPropTypesAsUsed(node.parent);
} 

the forEach seems useless?

'Program:exit': function() {
const list = components.list();

Object.keys(list).forEach(component => {
Copy link
Member

Choose a reason for hiding this comment

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

Object.keys(list).filter(component => mustBeValidated(list[component])).forEach?

@ljharb ljharb merged commit bd083bf into jsx-eslint:master Sep 20, 2018
@alexzherdev alexzherdev deleted the used-prop-types-refactoring branch September 20, 2018 20:06
@ThiefMaster
Copy link
Contributor

I believe this change caused #2017.

The old logic was:

    function isPropTypesUsage(node) {
      const isClassUsage = (
        (utils.getParentES6Component() || utils.getParentES5Component()) &&
        node.object.type === 'ThisExpression' && node.property.name === 'props'
      );
      const isStatelessFunctionUsage = node.object.name === 'props' && !isAssignmentToProp(node);
      const isNextPropsUsage = node.object.name === 'nextProps' && (inComponentWillReceiveProps() || inShouldComponentUpdate());
      return isClassUsage || isStatelessFunctionUsage || isNextPropsUsage;
}

and it got replaced with:

  function isPropTypesUsage(node) {
    const isClassUsage = (
      (utils.getParentES6Component() || utils.getParentES5Component()) &&
      ((node.object.type === 'ThisExpression' && node.property.name === 'props')
      || isPropArgumentInSetStateUpdater(node))
    );
    const isStatelessFunctionUsage = node.object.name === 'props' && !isAssignmentToProp(node);
    return isClassUsage || isStatelessFunctionUsage || inLifeCycleMethod();
  }

This was referenced Jan 4, 2019
@ghost ghost mentioned this pull request Jan 12, 2019
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

react/prop-types not working in getDerivedStateFromProps prop-types should cover props in setState() too
3 participants