Repository: yannickcr/eslint-plugin-react
Pull request #1375 (2017-08-15 19:51:56)

More robust no typos fix
Second attempt at fixing https://github.com/yannickcr/eslint-plugin-react/issues/1353

I think this is a better approach, but it means that currently one case is not supported. See the added test:

```js
      MyComponent.PROPTYPES = {}
      /** @extends React.Component */
      class MyComponent extends BaseComponent {}
```

I suppose that is acceptable for now, at least it is better than having the rule crash.

Also explained why the try/catch is needed and linked to relevant eslint-scope issue that needs to be implemented before it can be removed.


Patch:
diff --git a/lib/rules/no-typos.js b/lib/rules/no-typos.js
index ba597228..60426c4e 100644
--- a/lib/rules/no-typos.js
+++ b/lib/rules/no-typos.js
@@ -66,10 +66,6 @@ module.exports = {
       },
 
       MemberExpression: function(node) {
-        if (node.parent.type !== 'AssignmentExpression') {
-          return;
-        }
-
         const relatedComponent = utils.getRelatedComponent(node);
 
         if (
diff --git a/lib/util/Components.js b/lib/util/Components.js
index 1311fd9f..baa2cbea 100644
--- a/lib/util/Components.js
+++ b/lib/util/Components.js
@@ -215,7 +215,16 @@ function componentRule(rule, context) {
      * @returns {Boolean} True if the node is explicitly declared as a descendant of a React Component, false if not
      */
     isExplicitComponent: function(node) {
-      const comment = sourceCode.getJSDocComment(node);
+      let comment;
+      // Sometimes the passed node may not have been parsed yet by eslint, and this function call crashes.
+      // Can be removed when eslint sets "parent" property for all nodes on initial AST traversal: https://github.com/eslint/eslint-scope/issues/27
+      // eslint-disable-next-line no-warning-comments
+      // FIXME: Remove try/catch when https://github.com/eslint/eslint-scope/issues/27 is implemented.
+      try {
+        comment = sourceCode.getJSDocComment(node);
+      } catch (e) {
+        comment = null;
+      }
 
       if (comment === null) {
         return false;


Test patch:
diff --git a/tests/lib/rules/no-typos.js b/tests/lib/rules/no-typos.js
index 31acac4b..bd510bb6 100644
--- a/tests/lib/rules/no-typos.js
+++ b/tests/lib/rules/no-typos.js
@@ -240,6 +240,15 @@ ruleTester.run('no-typos', rule, {
       '}'
     ].join('\n'),
     parserOptions: parserOptions
+  }, {
+    // PropTypes declared on a component that is detected through JSDoc comments and is
+    // declared AFTER the PropTypes assignment does not work.
+    code: `
+      MyComponent.PROPTYPES = {}
+      /** @extends React.Component */
+      class MyComponent extends BaseComponent {}
+    `,
+    parserOptions: parserOptions
   }, {
     // https://github.com/yannickcr/eslint-plugin-react/issues/1353
     code: `
@@ -435,6 +444,21 @@ ruleTester.run('no-typos', rule, {
     ].join('\n'),
     parserOptions: parserOptions,
     errors: [{message: ERROR_MESSAGE}]
+  }, {
+    code: [
+      'Component.defaultprops = {}',
+      'class Component extends React.Component {}'
+    ].join('\n'),
+    parserOptions: parserOptions,
+    errors: [{message: ERROR_MESSAGE}]
+  }, {
+    code: `
+      /** @extends React.Component */
+      class MyComponent extends BaseComponent {}
+      MyComponent.PROPTYPES = {}
+    `,
+    parserOptions: parserOptions,
+    errors: [{message: ERROR_MESSAGE}]
   }, {
     code: [
       'class Hello extends React.Component {',