Repository: yannickcr/eslint-plugin-react
Pull request #1322 (2017-07-24 18:50:30)

Issue #1309
Fixes issue #1309 

DianaSuvorova: @ljharb , I am done updating this PR. Thanks 😄 
ljharb: (also it'd be great to have the PR title explain the change being made, and confine the issue reference to the OP description)

Patch:
diff --git a/lib/rules/jsx-no-duplicate-props.js b/lib/rules/jsx-no-duplicate-props.js
index a57d236c..7e1e0ddf 100644
--- a/lib/rules/jsx-no-duplicate-props.js
+++ b/lib/rules/jsx-no-duplicate-props.js
@@ -45,10 +45,6 @@ module.exports = {
 
           let name = decl.name.name;
 
-          if (typeof name !== 'string') {
-            return;
-          }
-
           if (ignoreCase) {
             name = name.toLowerCase();
           }
diff --git a/lib/util/Components.js b/lib/util/Components.js
index 1d1ac484..1311fd9f 100644
--- a/lib/util/Components.js
+++ b/lib/util/Components.js
@@ -10,6 +10,30 @@ const doctrine = require('doctrine');
 const variableUtil = require('./variable');
 const pragmaUtil = require('./pragma');
 
+const usedPropTypesAreEquivalent = (propA, propB) => {
+  if (propA.name === propB.name) {
+    if (!propA.allNames && !propB.allNames) {
+      return true;
+    } else if (Array.isArray(propA.allNames) && Array.isArray(propB.allNames) && propA.allNames.join('') === propB.allNames.join('')) {
+      return true;
+    }
+    return false;
+  }
+  return false;
+};
+
+const mergeUsedPropTypes = (propsList, newPropsList) => {
+  const propsToAdd = [];
+  newPropsList.forEach(newProp => {
+    const newPropisAlreadyInTheList = propsList.some(prop => usedPropTypesAreEquivalent(prop, newProp));
+    if (!newPropisAlreadyInTheList) {
+      propsToAdd.push(newProp);
+    }
+  });
+  return propsList.concat(propsToAdd);
+};
+
+
 /**
  * Components
  * @class
@@ -70,7 +94,16 @@ Components.prototype.set = function(node, props) {
     return;
   }
   const id = this._getId(node);
+  let copyUsedPropTypes;
+  if (this._list[id]) {
+    // usedPropTypes is an array. _extend replaces existing array with a new one which caused issue #1309.
+    // preserving original array so it can be merged later on.
+    copyUsedPropTypes = this._list[id].usedPropTypes && this._list[id].usedPropTypes.slice();
+  }
   this._list[id] = util._extend(this._list[id], props);
+  if (this._list[id] && props.usedPropTypes) {
+    this._list[id].usedPropTypes = mergeUsedPropTypes(copyUsedPropTypes || [], props.usedPropTypes);
+  }
 };
 
 /**


Test patch:
diff --git a/tests/lib/rules/jsx-no-duplicate-props.js b/tests/lib/rules/jsx-no-duplicate-props.js
index c3e544cd..1344391a 100644
--- a/tests/lib/rules/jsx-no-duplicate-props.js
+++ b/tests/lib/rules/jsx-no-duplicate-props.js
@@ -49,8 +49,7 @@ ruleTester.run('jsx-no-duplicate-props', rule, {
     {code: '<App c="a" {...this.props} a="c" b="b" />;'},
     {code: '<App A a />;'},
     {code: '<App A b a />;'},
-    {code: '<App A="a" b="b" B="B" />;'},
-    {code: '<App a:b="c" />;', options: ignoreCaseArgs}
+    {code: '<App A="a" b="b" B="B" />;'}
   ],
   invalid: [
     {code: '<App a a />;', errors: [expectedError]},
diff --git a/tests/lib/rules/no-unused-prop-types.js b/tests/lib/rules/no-unused-prop-types.js
index 74707109..9bcbd8b6 100644
--- a/tests/lib/rules/no-unused-prop-types.js
+++ b/tests/lib/rules/no-unused-prop-types.js
@@ -1897,7 +1897,7 @@ ruleTester.run('no-unused-prop-types', rule, {
         'const Thing = (props) => (',
         '    <div>',
         '      {(() => {',
-        '            if(props.enabled){',
+        '            if(props.enabled && props.test){',
         '                return (',
         '                    <span>Enabled!</span>',
         '                )',
@@ -1910,13 +1910,13 @@ ruleTester.run('no-unused-prop-types', rule, {
         ');',
 
         'Thing.propTypes = {',
-        '    enabled: React.PropTypes.bool',
+        '    enabled: React.PropTypes.bool,',
+        '    test: React.PropTypes.bool',
         '};'
       ].join('\n')
     }
   ],
 
-
   invalid: [
     {
       code: [