From 0dbd28cd39f220bb4eaf44824d668e9f9c6b7b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20=C3=85n=C3=B6stam?= Date: Sun, 19 Jul 2015 09:51:27 +0200 Subject: [PATCH] Added rule for no duplicated props --- index.js | 6 ++- lib/rules/jsx-no-duplicate-props.js | 50 ++++++++++++++++++++ tests/lib/rules/jsx-no-duplicate-props.js | 57 +++++++++++++++++++++++ 3 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 lib/rules/jsx-no-duplicate-props.js create mode 100644 tests/lib/rules/jsx-no-duplicate-props.js diff --git a/index.js b/index.js index 57446f641c..7735937e25 100644 --- a/index.js +++ b/index.js @@ -21,7 +21,8 @@ module.exports = { 'jsx-sort-prop-types': require('./lib/rules/jsx-sort-prop-types'), 'jsx-boolean-value': require('./lib/rules/jsx-boolean-value'), 'sort-comp': require('./lib/rules/sort-comp'), - 'require-extension': require('./lib/rules/require-extension') + 'require-extension': require('./lib/rules/require-extension'), + 'jsx-no-duplicate-props': require('./lib/rules/jsx-no-duplicate-props') }, rulesConfig: { 'jsx-uses-react': 0, @@ -43,6 +44,7 @@ module.exports = { 'jsx-sort-prop-types': 0, 'jsx-boolean-value': 0, 'sort-comp': 0, - 'require-extension': 0 + 'require-extension': 0, + 'jsx-no-duplicate-props': 0 } }; diff --git a/lib/rules/jsx-no-duplicate-props.js b/lib/rules/jsx-no-duplicate-props.js new file mode 100644 index 0000000000..0bdb84b009 --- /dev/null +++ b/lib/rules/jsx-no-duplicate-props.js @@ -0,0 +1,50 @@ +/** + * @fileoverview Enforce no duplicate props + * @author Markus Ånöstam + */ + +'use strict'; + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = function (context) { + + var configuration = context.options[0] || {}; + var ignoreCase = configuration.ignoreCase || false; + + return { + JSXOpeningElement: function (node) { + var props = {}; + + node.attributes.forEach(function(decl) { + if (decl.type === 'JSXSpreadAttribute') { + return; + } + + var name = decl.name.name; + + if (ignoreCase) { + name = name.toLowerCase(); + } + + if (props.hasOwnProperty(name)) { + context.report(decl, 'No duplicate props allowed'); + } else { + props[name] = 1; + } + }); + } + }; +}; + +module.exports.schema = [{ + type: 'object', + properties: { + ignoreCase: { + type: 'boolean' + } + }, + additionalProperties: false +}]; diff --git a/tests/lib/rules/jsx-no-duplicate-props.js b/tests/lib/rules/jsx-no-duplicate-props.js new file mode 100644 index 0000000000..603fb53a4c --- /dev/null +++ b/tests/lib/rules/jsx-no-duplicate-props.js @@ -0,0 +1,57 @@ +/** + * @fileoverview Enforce no duplicate props + * @author Markus Ånöstam + */ + +'use strict'; + +// ----------------------------------------------------------------------------- +// Requirements +// ----------------------------------------------------------------------------- + +var eslint = require('eslint').linter; +var ESLintTester = require('eslint-tester'); + +// ----------------------------------------------------------------------------- +// Tests +// ----------------------------------------------------------------------------- + +var eslintTester = new ESLintTester(eslint); + +var expectedError = { + message: 'No duplicate props allowed', + type: 'JSXAttribute' +}; + +var ignoreCaseArgs = [1, { + ignoreCase: true +}]; + +var features = { + jsx: true +}; + +eslintTester.addRuleTest('lib/rules/jsx-no-duplicate-props', { + valid: [ + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features}, + {code: ';', ecmaFeatures: features} + ], + invalid: [ + {code: ';', errors: [expectedError], ecmaFeatures: features}, + {code: ';', errors: [expectedError], ecmaFeatures: features}, + {code: ';', errors: [expectedError], ecmaFeatures: features}, + {code: ';', args: ignoreCaseArgs, errors: [expectedError], ecmaFeatures: features}, + {code: ';', args: ignoreCaseArgs, errors: [expectedError], ecmaFeatures: features}, + {code: ';', args: ignoreCaseArgs, errors: [expectedError], ecmaFeatures: features} + ] +});