diff --git a/rules/no-nested-ternary.js b/rules/no-nested-ternary.js index 6780b4cef5..b73d44c936 100644 --- a/rules/no-nested-ternary.js +++ b/rules/no-nested-ternary.js @@ -2,41 +2,33 @@ const {isParenthesized} = require('eslint-utils'); const getDocumentationUrl = require('./utils/get-documentation-url'); -const MESSAGE_ID = 'no-nested-ternary'; +const MESSAGE_ID_TOO_DEEP = 'too-deep'; +const MESSAGE_ID_SHOULD_PARENTHESIZED = 'should-parenthesized'; const messages = { - [MESSAGE_ID]: 'Do not nest ternary expressions.' + [MESSAGE_ID_TOO_DEEP]: 'Do not nest ternary expressions.', + [MESSAGE_ID_SHOULD_PARENTHESIZED]: 'Nest ternary expression should be parenthesized.' }; +const nestTernarySelector = level => `:not(ConditionalExpression)${' > ConditionalExpression'.repeat(level)}`; + const create = context => { const sourceCode = context.getSourceCode(); return { - ConditionalExpression: node => { - const nodesToCheck = [node.alternate, node.consequent]; - - for (const childNode of nodesToCheck) { - if (childNode.type !== 'ConditionalExpression') { - continue; - } - - // Nesting more than one level not allowed. - if ( - childNode.alternate.type === 'ConditionalExpression' || - childNode.consequent.type === 'ConditionalExpression' - ) { - // TODO: Improve report location - context.report({node, messageId: MESSAGE_ID}); - break; - } else if (!isParenthesized(childNode, sourceCode)) { - context.report({ - node: childNode, - messageId: MESSAGE_ID, - fix: fixer => [ - fixer.insertTextBefore(childNode, '('), - fixer.insertTextAfter(childNode, ')') - ] - }); - } + [nestTernarySelector(3)]: node => { + // Nesting more than one level not allowed. + context.report({node, messageId: MESSAGE_ID_TOO_DEEP}); + }, + [nestTernarySelector(2)]: node => { + if (!isParenthesized(node, sourceCode)) { + context.report({ + node, + messageId: MESSAGE_ID_SHOULD_PARENTHESIZED, + fix: fixer => [ + fixer.insertTextBefore(node, '('), + fixer.insertTextAfter(node, ')') + ] + }); } } }; diff --git a/test/no-nested-ternary.js b/test/no-nested-ternary.js index 6c913e1dea..47e005ac3e 100644 --- a/test/no-nested-ternary.js +++ b/test/no-nested-ternary.js @@ -14,12 +14,6 @@ const typescriptRuleTester = avaRuleTester(test, { parser: require.resolve('@typescript-eslint/parser') }); -const errors = [ - { - messageId: 'no-nested-ternary' - } -]; - ruleTester.run('no-nested-ternary', rule, { valid: [ 'const foo = i > 5 ? true : false;', @@ -33,43 +27,36 @@ ruleTester.run('no-nested-ternary', rule, { invalid: [ { code: 'const foo = i > 5 ? true : (i < 100 ? true : (i < 1000 ? true : false));', - errors + errors: 1 }, { code: 'const foo = i > 5 ? true : (i < 100 ? (i > 50 ? false : true) : false);', - errors + errors: 1 }, { code: 'const foo = i > 5 ? i < 100 ? true : false : true;', output: 'const foo = i > 5 ? (i < 100 ? true : false) : true;', - errors + errors: 1 }, { code: 'const foo = i > 5 ? i < 100 ? true : false : i < 100 ? true : false;', output: 'const foo = i > 5 ? (i < 100 ? true : false) : (i < 100 ? true : false);', - errors: [ - { - column: 21 - }, - { - column: 46 - } - ] + errors: 2 }, { code: 'const foo = i > 5 ? true : i < 100 ? true : false;', output: 'const foo = i > 5 ? true : (i < 100 ? true : false);', - errors + errors: 1 }, { code: 'foo ? bar : baz === qux ? quxx : foobar;', output: 'foo ? bar : (baz === qux ? quxx : foobar);', - errors + errors: 1 }, { code: 'foo ? baz === qux ? quxx : foobar : bar;', output: 'foo ? (baz === qux ? quxx : foobar) : bar;', - errors + errors: 1 } ] }); @@ -96,5 +83,19 @@ const visualizeTester = visualizeRuleTester(test, { } }); visualizeTester.run('no-nested-ternary', rule, [ - 'const foo = i > 5 ? true : (i < 100 ? true : (i < 1000 ? true : false));' + 'const foo = i > 5 ? i < 100 ? true : false : i < 100 ? true : false;', + 'const foo = i > 5 ? true : (i < 100 ? true : (i < 1000 ? true : false));', + outdent` + const foo = a ? + b : + ( + c ? + d : + ( + e ? + f : + (g ? h : i) + ) + ) + ` ]); diff --git a/test/snapshots/no-nested-ternary.js.md b/test/snapshots/no-nested-ternary.js.md index ab56544d29..feb015d7b6 100644 --- a/test/snapshots/no-nested-ternary.js.md +++ b/test/snapshots/no-nested-ternary.js.md @@ -6,6 +6,25 @@ Generated by [AVA](https://avajs.dev). ## no-nested-ternary - #1 +> Snapshot 1 + + `␊ + Input:␊ + 1 | const foo = i > 5 ? i < 100 ? true : false : i < 100 ? true : false;␊ + ␊ + Output:␊ + 1 | const foo = i > 5 ? (i < 100 ? true : false) : (i < 100 ? true : false);␊ + ␊ + Error 1/2:␊ + > 1 | const foo = i > 5 ? i < 100 ? true : false : i < 100 ? true : false;␊ + | ^^^^^^^^^^^^^^^^^^^^^^ Nest ternary expression should be parenthesized.␊ + Error 2/2:␊ + > 1 | const foo = i > 5 ? i < 100 ? true : false : i < 100 ? true : false;␊ + | ^^^^^^^^^^^^^^^^^^^^^^ Nest ternary expression should be parenthesized.␊ + ` + +## no-nested-ternary - #2 + > Snapshot 1 `␊ @@ -17,5 +36,43 @@ Generated by [AVA](https://avajs.dev). ␊ Error 1/1:␊ > 1 | const foo = i > 5 ? true : (i < 100 ? true : (i < 1000 ? true : false));␊ - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not nest ternary expressions.␊ + | ^^^^^^^^^^^^^^^^^^^^^^^ Do not nest ternary expressions.␊ + ` + +## no-nested-ternary - #3 + +> Snapshot 1 + + `␊ + Input:␊ + 1 | const foo = a ?␊ + 2 | b :␊ + 3 | (␊ + 4 | c ?␊ + 5 | d :␊ + 6 | (␊ + 7 | e ?␊ + 8 | f :␊ + 9 | (g ? h : i)␊ + 10 | )␊ + 11 | )␊ + ␊ + Output:␊ + [Same as input]␊ + ␊ + Error 1/1:␊ + 1 | const foo = a ?␊ + 2 | b :␊ + 3 | (␊ + 4 | c ?␊ + 5 | d :␊ + 6 | (␊ + > 7 | e ?␊ + | ^^^␊ + > 8 | f :␊ + | ^^^^^^^^␊ + > 9 | (g ? h : i)␊ + | ^^^^^^^^^^^^^^^^^ Do not nest ternary expressions.␊ + 10 | )␊ + 11 | )␊ ` diff --git a/test/snapshots/no-nested-ternary.js.snap b/test/snapshots/no-nested-ternary.js.snap index 438a2ecc69..b4d43fa14b 100644 Binary files a/test/snapshots/no-nested-ternary.js.snap and b/test/snapshots/no-nested-ternary.js.snap differ