From 0d1aaf8b569e6d22bba90467fe46ee7062e5e5ba Mon Sep 17 00:00:00 2001 From: Krasimir Nedelchev Date: Fri, 21 Jun 2019 17:23:54 +0300 Subject: [PATCH 1/4] Handle fragments in jsx-key --- lib/rules/jsx-key.js | 16 +++++++++++++++- tests/lib/rules/jsx-key.js | 10 +++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/rules/jsx-key.js b/lib/rules/jsx-key.js index 83e7873cfd..5c3450e7d9 100644 --- a/lib/rules/jsx-key.js +++ b/lib/rules/jsx-key.js @@ -31,6 +31,11 @@ module.exports = { node, message: 'Missing "key" prop for element in iterator' }); + } else if (node.type === 'JSXFragment') { + context.report({ + node, + message: 'Missing "key" prop for element in iterator. Shorthand fragment syntax does support providing keys' + }); } } @@ -52,6 +57,15 @@ module.exports = { } }, + JSXFragment(node) { + if (node.parent.type === 'ArrayExpression') { + context.report({ + node, + message: 'Missing "key" prop for element in array. Shorthand fragment syntax does support providing keys' + }); + } + }, + // Array.prototype.map CallExpression(node) { if (node.callee && node.callee.type !== 'MemberExpression') { @@ -66,7 +80,7 @@ module.exports = { const isFn = fn && fn.type === 'FunctionExpression'; const isArrFn = fn && fn.type === 'ArrowFunctionExpression'; - if (isArrFn && fn.body.type === 'JSXElement') { + if (isArrFn && (fn.body.type === 'JSXElement' || fn.body.type === 'JSXFragment')) { checkIteratorElement(fn.body); } diff --git a/tests/lib/rules/jsx-key.js b/tests/lib/rules/jsx-key.js index d4dea2b148..e55977b987 100644 --- a/tests/lib/rules/jsx-key.js +++ b/tests/lib/rules/jsx-key.js @@ -37,7 +37,9 @@ ruleTester.run('jsx-key', rule, { {code: '[1, 2, 3].foo(x => );'}, {code: 'var App = () =>
;'}, {code: '[1, 2, 3].map(function(x) { return; });'}, - {code: 'foo(() =>
);'} + {code: 'foo(() =>
);'}, + {code: 'foo(() => <>);'}, + {code: '<>;'} ], invalid: [{ code: '[];', @@ -57,5 +59,11 @@ ruleTester.run('jsx-key', rule, { }, { code: '[1, 2 ,3].map(x => { return });', errors: [{message: 'Missing "key" prop for element in iterator'}] + }, { + code: '[1, 2, 3].map(x => <>{x});', + errors: [{message: 'Missing "key" prop for element in iterator. Shorthand fragment syntax does support providing keys'}] + }, { + code: '[<>];', + errors: [{message: 'Missing "key" prop for element in array. Shorthand fragment syntax does support providing keys'}] }] }); From ed04c2fd48a1c1ad21daade6225229e281446c6a Mon Sep 17 00:00:00 2001 From: Krasimir Nedelchev <19822240+kaykayehnn@users.noreply.github.com> Date: Sat, 22 Jun 2019 20:10:43 +0300 Subject: [PATCH 2/4] Fix tests in eslint < 5 --- tests/lib/rules/jsx-key.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/lib/rules/jsx-key.js b/tests/lib/rules/jsx-key.js index e55977b987..a61ed628d8 100644 --- a/tests/lib/rules/jsx-key.js +++ b/tests/lib/rules/jsx-key.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-key'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -38,8 +40,8 @@ ruleTester.run('jsx-key', rule, { {code: 'var App = () =>
;'}, {code: '[1, 2, 3].map(function(x) { return; });'}, {code: 'foo(() =>
);'}, - {code: 'foo(() => <>);'}, - {code: '<>;'} + {code: 'foo(() => <>);', parser: parsers.BABEL_ESLINT}, + {code: '<>;', parser: parsers.BABEL_ESLINT} ], invalid: [{ code: '[];', @@ -61,9 +63,11 @@ ruleTester.run('jsx-key', rule, { errors: [{message: 'Missing "key" prop for element in iterator'}] }, { code: '[1, 2, 3].map(x => <>{x});', + parser: parsers.BABEL_ESLINT, errors: [{message: 'Missing "key" prop for element in iterator. Shorthand fragment syntax does support providing keys'}] }, { code: '[<>];', + parser: parsers.BABEL_ESLINT, errors: [{message: 'Missing "key" prop for element in array. Shorthand fragment syntax does support providing keys'}] }] }); From 7c1abedb575bd97404933ec85144697a30778443 Mon Sep 17 00:00:00 2001 From: Krasimir Nedelchev <19822240+kaykayehnn@users.noreply.github.com> Date: Sat, 22 Jun 2019 20:42:31 +0300 Subject: [PATCH 3/4] Add checkFragmentShorthand option --- lib/rules/jsx-key.js | 24 ++++++++++++++++++++++-- tests/lib/rules/jsx-key.js | 2 ++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/rules/jsx-key.js b/lib/rules/jsx-key.js index 5c3450e7d9..614527c6cc 100644 --- a/lib/rules/jsx-key.js +++ b/lib/rules/jsx-key.js @@ -13,6 +13,10 @@ const docsUrl = require('../util/docsUrl'); // Rule Definition // ------------------------------------------------------------------------------ +const defaultOptions = { + checkFragmentShorthand: false +} + module.exports = { meta: { docs: { @@ -21,17 +25,29 @@ module.exports = { recommended: true, url: docsUrl('jsx-key') }, - schema: [] + schema: [{ + type: 'object', + properties: { + checkFragmentShorthand: { + type: 'boolean', + default: defaultOptions.checkFragmentShorthand + } + }, + additionalProperties: false + }] }, create(context) { + const options = Object.assign({}, defaultOptions, context.options[0]) + const checkFragmentShorthand = options.checkFragmentShorthand + function checkIteratorElement(node) { if (node.type === 'JSXElement' && !hasProp(node.openingElement.attributes, 'key')) { context.report({ node, message: 'Missing "key" prop for element in iterator' }); - } else if (node.type === 'JSXFragment') { + } else if (checkFragmentShorthand && node.type === 'JSXFragment') { context.report({ node, message: 'Missing "key" prop for element in iterator. Shorthand fragment syntax does support providing keys' @@ -58,6 +74,10 @@ module.exports = { }, JSXFragment(node) { + if (!checkFragmentShorthand) { + return; + } + if (node.parent.type === 'ArrayExpression') { context.report({ node, diff --git a/tests/lib/rules/jsx-key.js b/tests/lib/rules/jsx-key.js index a61ed628d8..fd28fa5dca 100644 --- a/tests/lib/rules/jsx-key.js +++ b/tests/lib/rules/jsx-key.js @@ -64,10 +64,12 @@ ruleTester.run('jsx-key', rule, { }, { code: '[1, 2, 3].map(x => <>{x});', parser: parsers.BABEL_ESLINT, + options: [{checkFragmentShorthand: true}], errors: [{message: 'Missing "key" prop for element in iterator. Shorthand fragment syntax does support providing keys'}] }, { code: '[<>];', parser: parsers.BABEL_ESLINT, + options: [{checkFragmentShorthand: true}], errors: [{message: 'Missing "key" prop for element in array. Shorthand fragment syntax does support providing keys'}] }] }); From 0364ed210b95f1a14bda0180a3d194cf9e6b7176 Mon Sep 17 00:00:00 2001 From: Krasimir Nedelchev <19822240+kaykayehnn@users.noreply.github.com> Date: Sat, 22 Jun 2019 20:55:27 +0300 Subject: [PATCH 4/4] Fix formatting issues --- lib/rules/jsx-key.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/rules/jsx-key.js b/lib/rules/jsx-key.js index 614527c6cc..c40e476d26 100644 --- a/lib/rules/jsx-key.js +++ b/lib/rules/jsx-key.js @@ -15,7 +15,7 @@ const docsUrl = require('../util/docsUrl'); const defaultOptions = { checkFragmentShorthand: false -} +}; module.exports = { meta: { @@ -38,8 +38,8 @@ module.exports = { }, create(context) { - const options = Object.assign({}, defaultOptions, context.options[0]) - const checkFragmentShorthand = options.checkFragmentShorthand + const options = Object.assign({}, defaultOptions, context.options[0]); + const checkFragmentShorthand = options.checkFragmentShorthand; function checkIteratorElement(node) { if (node.type === 'JSXElement' && !hasProp(node.openingElement.attributes, 'key')) { @@ -77,7 +77,7 @@ module.exports = { if (!checkFragmentShorthand) { return; } - + if (node.parent.type === 'ArrayExpression') { context.report({ node,