From 9425d5d22f03acd892b6dee4f6043ab3f9814ab7 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 15 Jan 2021 19:30:12 +0800 Subject: [PATCH 1/6] `prefer-ternary`: Add `only-single-line` option --- rules/prefer-ternary.js | 22 ++++++- test/prefer-ternary.js | 130 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 1 deletion(-) diff --git a/rules/prefer-ternary.js b/rules/prefer-ternary.js index 40524dbe6e..69b5641416 100644 --- a/rules/prefer-ternary.js +++ b/rules/prefer-ternary.js @@ -56,6 +56,7 @@ const getScopes = scope => [ ]; const create = context => { + const onlySingleLine = context.options[0] === 'only-single-line'; const sourceCode = context.getSourceCode(); const scopeToNamesGeneratedByFixer = new WeakMap(); const isSafeName = (name, scopes) => scopes.every(scope => { @@ -76,6 +77,11 @@ const create = context => { `(${text})` : text; }; + const isSingleLineNode = node => { + const [start, end] = node.range.map(index => sourceCode.getLocFromIndex(index)); + return start.line === end.line; + }; + function merge(options, mergeOptions) { const { before = '', @@ -189,6 +195,13 @@ const create = context => { const consequent = getNodeBody(node.consequent); const alternate = getNodeBody(node.alternate); + if ( + onlySingleLine && + [consequent, alternate, node.test].some(node => !isSingleLineNode(node)) + ) { + return; + } + const result = merge({node, consequent, alternate}, { checkThrowStatement: true, returnFalseIfNotMergeable: true @@ -199,7 +212,6 @@ const create = context => { } const scope = context.getScope(); - const sourceCode = context.getSourceCode(); context.report({ node, @@ -252,6 +264,13 @@ const create = context => { }; }; +const schema = [ + { + enum: ['always', 'only-single-line'], + default: 'always' + } +]; + module.exports = { create, meta: { @@ -262,6 +281,7 @@ module.exports = { messages: { [messageId]: 'This `if` statement can be replaced by a ternary expression.' }, + schema, fixable: 'code' } }; diff --git a/test/prefer-ternary.js b/test/prefer-ternary.js index c120340c3e..7d48a415e4 100644 --- a/test/prefer-ternary.js +++ b/test/prefer-ternary.js @@ -4,6 +4,8 @@ import {test} from './utils/test.js'; const messageId = 'prefer-ternary'; const errors = [{messageId}]; +const onlySingleLineOptions = ['only-single-line']; + // ReturnStatement test({ valid: [ @@ -957,6 +959,134 @@ test({ ] }); +// `only-single-line` +test({ + valid: [ + { + code: outdent` + if (test) { + a = { + multiline: 'in consequent' + }; + } else{ + a = foo; + } + `, + options: onlySingleLineOptions + }, + { + code: outdent` + if (test) { + a = foo; + } else{ + a = { + multiline: 'in alternate' + }; + } + `, + options: onlySingleLineOptions + }, + { + code: outdent` + if ( + test({ + multiline: 'in test' + }) + ) { + a = foo; + } else{ + a = bar; + } + `, + options: onlySingleLineOptions + }, + { + code: outdent` + if (test) { + a = foo; b = 1; + } else{ + a = bar; + } + `, + options: onlySingleLineOptions + } + ], + invalid: [ + { + code: outdent` + if (test) { + a = foo; + } else { + a = bar; + } + `, + output: 'a = test ? foo : bar;', + options: onlySingleLineOptions, + errors + }, + // Parentheses is not considered part of `Node` + { + code: outdent` + if ( + ( + test + ) + ) { + a = foo; + } else { + a = bar; + } + `, + output: 'a = (test) ? foo : bar;', + options: onlySingleLineOptions, + errors + }, + { + code: outdent` + if (test) { + ( + a = foo + ); + } else { + a = bar; + } + `, + output: 'a = test ? foo : bar;', + options: onlySingleLineOptions, + errors + }, + // Semicolon of `ExpressionStatement` is not considered part of `Node` + { + code: outdent` + if (test) { + a = foo + ; + } else { + a = bar; + } + `, + output: 'a = test ? foo : bar;', + options: onlySingleLineOptions, + errors + }, + // `EmptyStatement`s is excluded + { + code: outdent` + if (test) { + ;;;;;; + a = foo; + ;;;;;; + } else { + a = bar; + } + `, + output: 'a = test ? foo : bar;', + options: onlySingleLineOptions, + errors + }, + ] +}) + test({ valid: [ // No `consequent` / `alternate` From 1b612c6549252895b94912ce40291c1cda26b76a Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 15 Jan 2021 19:40:02 +0800 Subject: [PATCH 2/6] Update docs --- docs/rules/prefer-ternary.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/rules/prefer-ternary.md b/docs/rules/prefer-ternary.md index 67f916852b..e603d11119 100644 --- a/docs/rules/prefer-ternary.md +++ b/docs/rules/prefer-ternary.md @@ -120,3 +120,26 @@ if (test) { baz = 2; } ``` + +## Options + +Type: `string`\ +Default: `always` + +- `always` (default) + - Always check `IfStatement` +- `only-single-line` + - Only check if `test`, `consequent`, and `alternate` of `IfStatement` are single line + +The following case is considered valid: + +```js +// eslint unicorn/prefer-ternary: ["error", "only-single-line"] +if (test) { + foo = [ + 'multiple line array' + ]; +} else { + bar = baz; +} +``` From 7473f3e682caa970e1abc47a26709bf0079bf831 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 15 Jan 2021 19:44:00 +0800 Subject: [PATCH 3/6] Style --- test/prefer-ternary.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/prefer-ternary.js b/test/prefer-ternary.js index 7d48a415e4..7ae8c39cf2 100644 --- a/test/prefer-ternary.js +++ b/test/prefer-ternary.js @@ -1083,9 +1083,9 @@ test({ output: 'a = test ? foo : bar;', options: onlySingleLineOptions, errors - }, + } ] -}) +}); test({ valid: [ From 48e4030daa13e33be596047fae00348fab7a61ec Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 15 Jan 2021 20:24:06 +0800 Subject: [PATCH 4/6] Update prefer-ternary.js --- test/prefer-ternary.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/prefer-ternary.js b/test/prefer-ternary.js index 7ae8c39cf2..54c352d923 100644 --- a/test/prefer-ternary.js +++ b/test/prefer-ternary.js @@ -1024,7 +1024,7 @@ test({ options: onlySingleLineOptions, errors }, - // Parentheses is not considered part of `Node` + // Parentheses are not considered part of `Node` { code: outdent` if ( @@ -1069,7 +1069,7 @@ test({ options: onlySingleLineOptions, errors }, - // `EmptyStatement`s is excluded + // `EmptyStatement`s are excluded { code: outdent` if (test) { From aa734410d4e41859a21fdca05da7e4f583715e5a Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Tue, 19 Jan 2021 13:29:44 +0800 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: Sindre Sorhus Co-authored-by: Elliot --- docs/rules/prefer-ternary.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/rules/prefer-ternary.md b/docs/rules/prefer-ternary.md index e603d11119..0729d876a7 100644 --- a/docs/rules/prefer-ternary.md +++ b/docs/rules/prefer-ternary.md @@ -124,12 +124,12 @@ if (test) { ## Options Type: `string`\ -Default: `always` +Default: `'always'` - `always` (default) - - Always check `IfStatement` + - Always report when using an `IfStatement` where a ternary expression can be used. - `only-single-line` - - Only check if `test`, `consequent`, and `alternate` of `IfStatement` are single line + - Only check if the content of the `if` and/or `else` block is less than one line long. The following case is considered valid: From c53f6ca1ed6dfef9507098c08b3a58cf060ed0d9 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Tue, 19 Jan 2021 13:31:12 +0800 Subject: [PATCH 6/6] Quote values --- docs/rules/prefer-ternary.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/rules/prefer-ternary.md b/docs/rules/prefer-ternary.md index 0729d876a7..e66bb90853 100644 --- a/docs/rules/prefer-ternary.md +++ b/docs/rules/prefer-ternary.md @@ -126,9 +126,9 @@ if (test) { Type: `string`\ Default: `'always'` -- `always` (default) +- `'always'` (default) - Always report when using an `IfStatement` where a ternary expression can be used. -- `only-single-line` +- `'only-single-line'` - Only check if the content of the `if` and/or `else` block is less than one line long. The following case is considered valid: