From e4aaa42a780e2b155fa25fcba457162308dec36b Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Wed, 16 Nov 2022 22:28:07 +0800 Subject: [PATCH] Add `no-negated-condition` rule (#1963) --- configs/recommended.js | 2 + docs/rules/expiring-todo-comments.md | 2 +- docs/rules/no-negated-condition.md | 92 +++ docs/rules/no-nested-ternary.md | 2 +- readme.md | 1 + rules/no-negated-condition.js | 137 +++++ test/no-negated-condition.mjs | 109 ++++ test/package.mjs | 1 + test/snapshots/no-negated-condition.mjs.md | 592 +++++++++++++++++++ test/snapshots/no-negated-condition.mjs.snap | Bin 0 -> 1824 bytes 10 files changed, 936 insertions(+), 2 deletions(-) create mode 100644 docs/rules/no-negated-condition.md create mode 100644 rules/no-negated-condition.js create mode 100644 test/no-negated-condition.mjs create mode 100644 test/snapshots/no-negated-condition.mjs.md create mode 100644 test/snapshots/no-negated-condition.mjs.snap diff --git a/configs/recommended.js b/configs/recommended.js index a1d26d031a..158d265bdf 100644 --- a/configs/recommended.js +++ b/configs/recommended.js @@ -40,6 +40,8 @@ module.exports = { 'unicorn/no-invalid-remove-event-listener': 'error', 'unicorn/no-keyword-prefix': 'off', 'unicorn/no-lonely-if': 'error', + 'no-negated-condition': 'off', + 'unicorn/no-negated-condition': 'error', 'no-nested-ternary': 'off', 'unicorn/no-nested-ternary': 'error', 'unicorn/no-new-array': 'error', diff --git a/docs/rules/expiring-todo-comments.md b/docs/rules/expiring-todo-comments.md index 0f572fd547..16b19cc772 100644 --- a/docs/rules/expiring-todo-comments.md +++ b/docs/rules/expiring-todo-comments.md @@ -7,7 +7,7 @@ This rule makes it possible to pass arguments to TODO, FIXME and XXX comments to trigger ESLint to report. -From [ESLint's documentation](https://eslint.org/docs/rules/no-warning-comments): +From [ESLint's documentation](https://eslint.org/docs/latest/rules/no-warning-comments): > Developers often add comments to code which is not complete or needs review. diff --git a/docs/rules/no-negated-condition.md b/docs/rules/no-negated-condition.md new file mode 100644 index 0000000000..be8c9b1276 --- /dev/null +++ b/docs/rules/no-negated-condition.md @@ -0,0 +1,92 @@ +# Disallow negated conditions + +βœ… This rule is enabled in the `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs). + +πŸ”§ This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix). + + + + +Negated conditions are more difficult to understand. Code can be made more readable by inverting the condition. + +This is an improved version of the [`no-negated-condition`](https://eslint.org/docs/latest/rules/no-negated-condition) ESLint rule that makes it automatically fixable. [ESLint did not want to make it fixable.](https://github.com/eslint/eslint/issues/14792) + +## Fail + +```js +if (!a) { + doSomethingC(); +} else { + doSomethingB(); +} +``` + +```js +if (a !== b) { + doSomethingC(); +} else { + doSomethingB(); +} +``` + +```js +!a ? c : b +``` + +```js +if (a != b) { + doSomethingC(); +} else { + doSomethingB(); +} +``` + +## Pass + +```js +if (a) { + doSomethingB(); +} else { + doSomethingC(); +} +``` + +```js +if (a === b) { + doSomethingB(); +} else { + doSomethingC(); +} +``` + +```js +a ? b : c +``` + +```js +if (a == b) { + doSomethingB(); +} else { + doSomethingC(); +} +``` + +```js +if (!a) { + doSomething(); +} +``` + +```js +if (!a) { + doSomething(); +} else if (b) { + doSomethingElse(); +} +``` + +```js +if (a != b) { + doSomething(); +} +``` diff --git a/docs/rules/no-nested-ternary.md b/docs/rules/no-nested-ternary.md index 47095175e9..eb9cb3a7a6 100644 --- a/docs/rules/no-nested-ternary.md +++ b/docs/rules/no-nested-ternary.md @@ -7,7 +7,7 @@ -Improved version of the [`no-nested-ternary`](https://eslint.org/docs/rules/no-nested-ternary) ESLint rule, which allows cases where the nested ternary is only one level and wrapped in parens. +Improved version of the [`no-nested-ternary`](https://eslint.org/docs/latest/rules/no-nested-ternary) ESLint rule, which allows cases where the nested ternary is only one level and wrapped in parens. ## Fail diff --git a/readme.md b/readme.md index 9653435077..ea819880ce 100644 --- a/readme.md +++ b/readme.md @@ -81,6 +81,7 @@ Use a [preset config](#preset-configs) or configure each rules in `package.json` | [no-invalid-remove-event-listener](docs/rules/no-invalid-remove-event-listener.md) | Prevent calling `EventTarget#removeEventListener()` with the result of an expression. | βœ… | | | | [no-keyword-prefix](docs/rules/no-keyword-prefix.md) | Disallow identifiers starting with `new` or `class`. | | | | | [no-lonely-if](docs/rules/no-lonely-if.md) | Disallow `if` statements as the only statement in `if` blocks without `else`. | βœ… | πŸ”§ | | +| [no-negated-condition](docs/rules/no-negated-condition.md) | Disallow negated conditions. | βœ… | πŸ”§ | | | [no-nested-ternary](docs/rules/no-nested-ternary.md) | Disallow nested ternary expressions. | βœ… | πŸ”§ | | | [no-new-array](docs/rules/no-new-array.md) | Disallow `new Array()`. | βœ… | πŸ”§ | πŸ’‘ | | [no-new-buffer](docs/rules/no-new-buffer.md) | Enforce the use of `Buffer.from()` and `Buffer.alloc()` instead of the deprecated `new Buffer()`. | βœ… | πŸ”§ | πŸ’‘ | diff --git a/rules/no-negated-condition.js b/rules/no-negated-condition.js new file mode 100644 index 0000000000..8e1f6045a8 --- /dev/null +++ b/rules/no-negated-condition.js @@ -0,0 +1,137 @@ +/* +Based on ESLint builtin `no-negated-condition` rule +https://github.com/eslint/eslint/blob/5c39425fc55ecc0b97bbd07ac22654c0eb4f789c/lib/rules/no-negated-condition.js +*/ +'use strict'; +const {matches} = require('./selectors/index.js'); +const { + removeParentheses, + fixSpaceAroundKeyword, + addParenthesizesToReturnOrThrowExpression, +} = require('./fix/index.js'); +const { + getParenthesizedRange, + isParenthesized, +} = require('./utils/parentheses.js'); +const isOnSameLine = require('./utils/is-on-same-line.js'); +const needsSemicolon = require('./utils/needs-semicolon.js'); + +const MESSAGE_ID = 'no-negated-condition'; +const messages = { + [MESSAGE_ID]: 'Unexpected negated condition.', +}; + +const selector = [ + matches([ + 'IfStatement[alternate][alternate.type!="IfStatement"]', + 'ConditionalExpression', + ]), + matches([ + '[test.type="UnaryExpression"][test.operator="!"]', + '[test.type="BinaryExpression"][test.operator="!="]', + '[test.type="BinaryExpression"][test.operator="!=="]', + ]), +].join(''); + +function * convertNegatedCondition(fixer, node, sourceCode) { + const {test} = node; + if (test.type === 'UnaryExpression') { + const token = sourceCode.getFirstToken(test); + + if (node.type === 'IfStatement') { + yield * removeParentheses(test.argument, fixer, sourceCode); + } + + yield fixer.remove(token); + return; + } + + const token = sourceCode.getTokenAfter( + test.left, + token => token.type === 'Punctuator' && token.value === test.operator, + ); + + yield fixer.replaceText(token, '=' + token.value.slice(1)); +} + +function * swapConsequentAndAlternate(fixer, node, sourceCode) { + const isIfStatement = node.type === 'IfStatement'; + const [consequent, alternate] = [ + node.consequent, + node.alternate, + ].map(node => { + const range = getParenthesizedRange(node, sourceCode); + let text = sourceCode.text.slice(...range); + // `if (!a) b(); else c()` can't fix to `if (!a) c() else b();` + if (isIfStatement && node.type !== 'BlockStatement') { + text = `{${text}}`; + } + + return { + range, + text, + }; + }); + + if (consequent.text === alternate.text) { + return; + } + + yield fixer.replaceTextRange(consequent.range, alternate.text); + yield fixer.replaceTextRange(alternate.range, consequent.text); +} + +/** @param {import('eslint').Rule.RuleContext} context */ +const create = context => ({ + [selector](node) { + return { + node: node.test, + messageId: MESSAGE_ID, + /** @param {import('eslint').Rule.RuleFixer} fixer */ + * fix(fixer) { + const sourceCode = context.getSourceCode(); + yield * convertNegatedCondition(fixer, node, sourceCode); + yield * swapConsequentAndAlternate(fixer, node, sourceCode); + + if ( + node.type !== 'ConditionalExpression' + || node.test.type !== 'UnaryExpression' + ) { + return; + } + + yield * fixSpaceAroundKeyword(fixer, node, sourceCode); + + const {test, parent} = node; + const [firstToken, secondToken] = sourceCode.getFirstTokens(test, 2); + if ( + (parent.type === 'ReturnStatement' || parent.type === 'ThrowStatement') + && parent.argument === node + && !(isParenthesized(node, sourceCode) && !isParenthesized(test, sourceCode)) + && !isOnSameLine(firstToken, secondToken) + ) { + yield * addParenthesizesToReturnOrThrowExpression(fixer, parent, sourceCode); + return; + } + + const tokenBefore = sourceCode.getTokenBefore(node); + if (needsSemicolon(tokenBefore, sourceCode, secondToken.value)) { + yield fixer.insertTextBefore(node, ';'); + } + }, + }; + }, +}); + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + create, + meta: { + type: 'suggestion', + docs: { + description: 'Disallow negated conditions.', + }, + fixable: 'code', + messages, + }, +}; diff --git a/test/no-negated-condition.mjs b/test/no-negated-condition.mjs new file mode 100644 index 0000000000..9b8ecceffb --- /dev/null +++ b/test/no-negated-condition.mjs @@ -0,0 +1,109 @@ +import outdent from 'outdent'; +import {getTester} from './utils/test.mjs'; + +const {test} = getTester(import.meta); + +test.snapshot({ + valid: [ + 'if (a) {}', + 'if (a) {} else {}', + 'if (!a) {}', + 'if (!a) {} else if (b) {}', + 'if (!a) {} else if (b) {} else {}', + 'if (a == b) {}', + 'if (a == b) {} else {}', + 'if (a != b) {}', + 'if (a != b) {} else if (b) {}', + 'if (a != b) {} else if (b) {} else {}', + 'if (a !== b) {}', + 'if (a === b) {} else {}', + 'a ? b : c', + ], + invalid: [ + 'if (!a) {;} else {;}', + 'if (a != b) {;} else {;}', + 'if (a !== b) {;} else {;}', + '!a ? b : c', + 'a != b ? c : d', + 'a !== b ? c : d', + '(( !a )) ? b : c', + '!(( a )) ? b : c', + 'if(!(( a ))) b(); else c();', + 'if((( !a ))) b(); else c();', + 'function a() {return!a ? b : c}', + 'function a() {return!(( a )) ? b : c}', + outdent` + function a() { + return ! // comment + a ? b : c; + } + `, + outdent` + function a() { + return (! // ReturnStatement argument is parenthesized + a ? b : c); + } + `, + outdent` + function a() { + return ( + ! // UnaryExpression argument is parenthesized + a) ? b : c; + } + `, + outdent` + function a() { + throw ! // comment + a ? b : c; + } + `, + '!a ? b : c ? d : e', + '!a ? b : (( c ? d : e ))', + outdent` + a + ![] ? b : c + `, + outdent` + a + !+b ? c : d + `, + outdent` + a + !(b) ? c : d + `, + outdent` + a + !b ? c : d + `, + outdent` + if (!a) + b() + else + c() + `, + 'if(!a) b(); else c()', + outdent` + function fn() { + if(!a) b(); else return + } + `, + 'if(!a) {b()} else {c()}', + 'if(!!a) b(); else c();', + '(!!a) ? b() : c();', + outdent` + function fn() { + return!a !== b ? c : d + return((!((a)) != b)) ? c : d + } + `, + outdent` + if (!a) { + b(); + } else if (!c) { + d(); + } else { + e(); + } + `, + ], +}); diff --git a/test/package.mjs b/test/package.mjs index ee429d2758..895ce850f1 100644 --- a/test/package.mjs +++ b/test/package.mjs @@ -14,6 +14,7 @@ test.before(async () => { const ignoredRules = [ 'no-nested-ternary', + 'no-negated-condition', ]; const deprecatedRules = Object.entries(eslintPluginUnicorn.rules) diff --git a/test/snapshots/no-negated-condition.mjs.md b/test/snapshots/no-negated-condition.mjs.md new file mode 100644 index 0000000000..6f93474548 --- /dev/null +++ b/test/snapshots/no-negated-condition.mjs.md @@ -0,0 +1,592 @@ +# Snapshot report for `test/no-negated-condition.mjs` + +The actual snapshot is saved in `no-negated-condition.mjs.snap`. + +Generated by [AVA](https://avajs.dev). + +## Invalid #1 + 1 | if (!a) {;} else {;} + +> Output + + `␊ + 1 | if (a) {;} else {;}␊ + ` + +> Error 1/1 + + `␊ + > 1 | if (!a) {;} else {;}␊ + | ^^ Unexpected negated condition.␊ + ` + +## Invalid #2 + 1 | if (a != b) {;} else {;} + +> Output + + `␊ + 1 | if (a == b) {;} else {;}␊ + ` + +> Error 1/1 + + `␊ + > 1 | if (a != b) {;} else {;}␊ + | ^^^^^^ Unexpected negated condition.␊ + ` + +## Invalid #3 + 1 | if (a !== b) {;} else {;} + +> Output + + `␊ + 1 | if (a === b) {;} else {;}␊ + ` + +> Error 1/1 + + `␊ + > 1 | if (a !== b) {;} else {;}␊ + | ^^^^^^^ Unexpected negated condition.␊ + ` + +## Invalid #4 + 1 | !a ? b : c + +> Output + + `␊ + 1 | a ? c : b␊ + ` + +> Error 1/1 + + `␊ + > 1 | !a ? b : c␊ + | ^^ Unexpected negated condition.␊ + ` + +## Invalid #5 + 1 | a != b ? c : d + +> Output + + `␊ + 1 | a == b ? d : c␊ + ` + +> Error 1/1 + + `␊ + > 1 | a != b ? c : d␊ + | ^^^^^^ Unexpected negated condition.␊ + ` + +## Invalid #6 + 1 | a !== b ? c : d + +> Output + + `␊ + 1 | a === b ? d : c␊ + ` + +> Error 1/1 + + `␊ + > 1 | a !== b ? c : d␊ + | ^^^^^^^ Unexpected negated condition.␊ + ` + +## Invalid #7 + 1 | (( !a )) ? b : c + +> Output + + `␊ + 1 | (( a )) ? c : b␊ + ` + +> Error 1/1 + + `␊ + > 1 | (( !a )) ? b : c␊ + | ^^ Unexpected negated condition.␊ + ` + +## Invalid #8 + 1 | !(( a )) ? b : c + +> Output + + `␊ + 1 | (( a )) ? c : b␊ + ` + +> Error 1/1 + + `␊ + > 1 | !(( a )) ? b : c␊ + | ^^^^^^^^ Unexpected negated condition.␊ + ` + +## Invalid #9 + 1 | if(!(( a ))) b(); else c(); + +> Output + + `␊ + 1 | if( a ) {c();} else {b();}␊ + ` + +> Error 1/1 + + `␊ + > 1 | if(!(( a ))) b(); else c();␊ + | ^^^^^^^^ Unexpected negated condition.␊ + ` + +## Invalid #10 + 1 | if((( !a ))) b(); else c(); + +> Output + + `␊ + 1 | if((( a ))) {c();} else {b();}␊ + ` + +> Error 1/1 + + `␊ + > 1 | if((( !a ))) b(); else c();␊ + | ^^ Unexpected negated condition.␊ + ` + +## Invalid #11 + 1 | function a() {return!a ? b : c} + +> Output + + `␊ + 1 | function a() {return a ? c : b}␊ + ` + +> Error 1/1 + + `␊ + > 1 | function a() {return!a ? b : c}␊ + | ^^ Unexpected negated condition.␊ + ` + +## Invalid #12 + 1 | function a() {return!(( a )) ? b : c} + +> Output + + `␊ + 1 | function a() {return (( a )) ? c : b}␊ + ` + +> Error 1/1 + + `␊ + > 1 | function a() {return!(( a )) ? b : c}␊ + | ^^^^^^^^ Unexpected negated condition.␊ + ` + +## Invalid #13 + 1 | function a() { + 2 | return ! // comment + 3 | a ? b : c; + 4 | } + +> Output + + `␊ + 1 | function a() {␊ + 2 | return ( // comment␊ + 3 | a ? c : b);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | function a() {␊ + > 2 | return ! // comment␊ + | ^^^^^^^^^^^^␊ + > 3 | a ? b : c;␊ + | ^^^^ Unexpected negated condition.␊ + 4 | }␊ + ` + +## Invalid #14 + 1 | function a() { + 2 | return (! // ReturnStatement argument is parenthesized + 3 | a ? b : c); + 4 | } + +> Output + + `␊ + 1 | function a() {␊ + 2 | return ( // ReturnStatement argument is parenthesized␊ + 3 | a ? c : b);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | function a() {␊ + > 2 | return (! // ReturnStatement argument is parenthesized␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^␊ + > 3 | a ? b : c);␊ + | ^^^^ Unexpected negated condition.␊ + 4 | }␊ + ` + +## Invalid #15 + 1 | function a() { + 2 | return ( + 3 | ! // UnaryExpression argument is parenthesized + 4 | a) ? b : c; + 5 | } + +> Output + + `␊ + 1 | function a() {␊ + 2 | return ( (␊ + 3 | // UnaryExpression argument is parenthesized␊ + 4 | a) ? c : b);␊ + 5 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | function a() {␊ + 2 | return (␊ + > 3 | ! // UnaryExpression argument is parenthesized␊ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^␊ + > 4 | a) ? b : c;␊ + | ^^^^ Unexpected negated condition.␊ + 5 | }␊ + ` + +## Invalid #16 + 1 | function a() { + 2 | throw ! // comment + 3 | a ? b : c; + 4 | } + +> Output + + `␊ + 1 | function a() {␊ + 2 | throw ( // comment␊ + 3 | a ? c : b);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | function a() {␊ + > 2 | throw ! // comment␊ + | ^^^^^^^^^^^^␊ + > 3 | a ? b : c;␊ + | ^^^^ Unexpected negated condition.␊ + 4 | }␊ + ` + +## Invalid #17 + 1 | !a ? b : c ? d : e + +> Output + + `␊ + 1 | a ? c ? d : e : b␊ + ` + +> Error 1/1 + + `␊ + > 1 | !a ? b : c ? d : e␊ + | ^^ Unexpected negated condition.␊ + ` + +## Invalid #18 + 1 | !a ? b : (( c ? d : e )) + +> Output + + `␊ + 1 | a ? (( c ? d : e )) : b␊ + ` + +> Error 1/1 + + `␊ + > 1 | !a ? b : (( c ? d : e ))␊ + | ^^ Unexpected negated condition.␊ + ` + +## Invalid #19 + 1 | a + 2 | ![] ? b : c + +> Output + + `␊ + 1 | a␊ + 2 | ;[] ? c : b␊ + ` + +> Error 1/1 + + `␊ + 1 | a␊ + > 2 | ![] ? b : c␊ + | ^^^ Unexpected negated condition.␊ + ` + +## Invalid #20 + 1 | a + 2 | !+b ? c : d + +> Output + + `␊ + 1 | a␊ + 2 | ;+b ? d : c␊ + ` + +> Error 1/1 + + `␊ + 1 | a␊ + > 2 | !+b ? c : d␊ + | ^^^ Unexpected negated condition.␊ + ` + +## Invalid #21 + 1 | a + 2 | !(b) ? c : d + +> Output + + `␊ + 1 | a␊ + 2 | ;(b) ? d : c␊ + ` + +> Error 1/1 + + `␊ + 1 | a␊ + > 2 | !(b) ? c : d␊ + | ^^^^ Unexpected negated condition.␊ + ` + +## Invalid #22 + 1 | a + 2 | !b ? c : d + +> Output + + `␊ + 1 | a␊ + 2 | b ? d : c␊ + ` + +> Error 1/1 + + `␊ + 1 | a␊ + > 2 | !b ? c : d␊ + | ^^ Unexpected negated condition.␊ + ` + +## Invalid #23 + 1 | if (!a) + 2 | b() + 3 | else + 4 | c() + +> Output + + `␊ + 1 | if (a)␊ + 2 | {c()}␊ + 3 | else␊ + 4 | {b()}␊ + ` + +> Error 1/1 + + `␊ + > 1 | if (!a)␊ + | ^^ Unexpected negated condition.␊ + 2 | b()␊ + 3 | else␊ + 4 | c()␊ + ` + +## Invalid #24 + 1 | if(!a) b(); else c() + +> Output + + `␊ + 1 | if(a) {c()} else {b();}␊ + ` + +> Error 1/1 + + `␊ + > 1 | if(!a) b(); else c()␊ + | ^^ Unexpected negated condition.␊ + ` + +## Invalid #25 + 1 | function fn() { + 2 | if(!a) b(); else return + 3 | } + +> Output + + `␊ + 1 | function fn() {␊ + 2 | if(a) {return} else {b();}␊ + 3 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | function fn() {␊ + > 2 | if(!a) b(); else return␊ + | ^^ Unexpected negated condition.␊ + 3 | }␊ + ` + +## Invalid #26 + 1 | if(!a) {b()} else {c()} + +> Output + + `␊ + 1 | if(a) {c()} else {b()}␊ + ` + +> Error 1/1 + + `␊ + > 1 | if(!a) {b()} else {c()}␊ + | ^^ Unexpected negated condition.␊ + ` + +## Invalid #27 + 1 | if(!!a) b(); else c(); + +> Output + + `␊ + 1 | if(a) {b();} else {c();}␊ + ` + +> Error 1/1 + + `␊ + > 1 | if(!!a) b(); else c();␊ + | ^^^ Unexpected negated condition.␊ + ` + +## Invalid #28 + 1 | (!!a) ? b() : c(); + +> Output + + `␊ + 1 | (a) ? b() : c();␊ + ` + +> Error 1/1 + + `␊ + > 1 | (!!a) ? b() : c();␊ + | ^^^ Unexpected negated condition.␊ + ` + +## Invalid #29 + 1 | function fn() { + 2 | return!a !== b ? c : d + 3 | return((!((a)) != b)) ? c : d + 4 | } + +> Output + + `␊ + 1 | function fn() {␊ + 2 | return!a === b ? d : c␊ + 3 | return((!((a)) == b)) ? d : c␊ + 4 | }␊ + ` + +> Error 1/2 + + `␊ + 1 | function fn() {␊ + > 2 | return!a !== b ? c : d␊ + | ^^^^^^^^ Unexpected negated condition.␊ + 3 | return((!((a)) != b)) ? c : d␊ + 4 | }␊ + ` + +> Error 2/2 + + `␊ + 1 | function fn() {␊ + 2 | return!a !== b ? c : d␊ + > 3 | return((!((a)) != b)) ? c : d␊ + | ^^^^^^^^^^^ Unexpected negated condition.␊ + 4 | }␊ + ` + +## Invalid #30 + 1 | if (!a) { + 2 | b(); + 3 | } else if (!c) { + 4 | d(); + 5 | } else { + 6 | e(); + 7 | } + +> Output + + `␊ + 1 | if (!a) {␊ + 2 | b();␊ + 3 | } else if (c) {␊ + 4 | e();␊ + 5 | } else {␊ + 6 | d();␊ + 7 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | if (!a) {␊ + 2 | b();␊ + > 3 | } else if (!c) {␊ + | ^^ Unexpected negated condition.␊ + 4 | d();␊ + 5 | } else {␊ + 6 | e();␊ + 7 | }␊ + ` diff --git a/test/snapshots/no-negated-condition.mjs.snap b/test/snapshots/no-negated-condition.mjs.snap new file mode 100644 index 0000000000000000000000000000000000000000..9a6ae5dc8cd7ce63ef4bfb7031a7f88938edde86 GIT binary patch literal 1824 zcmV+*2jBQXRzVw6Y)j_S^6FcK7y<+jHERXKwG^cfa@j-rw)t z;BEvlga~YC+pit46Bt8hFm$Z{Hl!w2nm7tr&M8(*HO=xb#p> z@yH&NZoaLF8T;y84rm8TX!QpJvhCS~7q{)CP>P&?32QIU6j0+e6#v z&+cAsH5ZVGnvHP;;*GX@aq4HjSr#(5X3m2(jg2It{)v&JCWsZ|OQI{7DCW}Cvfh1% z)T&5CJ%TYekRVpx|0{A$L!3&hQZ)s3)K!v*T7mIB#Jk&#mm?eADT}&umnjH8aEnCL zhZw2d31WS9QQB#$t~_Nyi1p0pZS^FguElr&v2E1h%#4+`v1_lDEDQWO<1G?Vmj`jk z)j$u{FEZ{iY^IwpmN|YuLEI-1^-GM{V1lShJ~wyLpxn-0YIEL!z#qa$L`}um#B$Vj zgr}?sD{dS{Kdc%*721QPHeiJGAc$Sjo63TVTdLDfC+0AjRp&`W9fMH;QC*#E+R_p+ zV8RFLmR&_3PaqMsTTc!*A!_GTFRU|eJ6N3Za@d&{Drb<0+AD;^Y>4{(t+P7R=HF^s z!;XKuG2|?Xs3$QN^dg9(Q4_Nw=Kgd1wuQQ?>c2IBMAU5#t5!R%GL1ykR*X?vf;dA*C#<*@xo?_d#P#Ow zjTI!K(imT`9L*CK8+O*esx4mC8d|;{YRppm^x^O+#DyC{3zM%0^$u(Ly2shqZZwk| z6@z+`AbyDrOx@G}#E%mbc313et^A5a)C`Pjh>oCs4%5XOOTIff({QZyu!cm`77RmQ zf>06NQPu~j32i|CU;tu4383Ncv+&mhCIAZ<56r&vA;~{}^_hgmHr0_9p2?I4(k%e;uNc)^`iJ4?H<3EJjAa=6FxR|N)_Kaaw~5ywaSIu()Ak@2Ksz!297 zoaWBnf?6lxO%@DZEVIeQj2o(7laEOn?&3ns9|Fat2d5MFlwv1A8Xm9F$yYC6lF6@) zZuuoH)x1EtGA22t`Bbu{O6r_SIv18va*HP=rB)Fu8Sk4wPo==0L=N{BLDI=%vN(i9 zW1GM66CUhpfpE-n9c$s1-5TN)X+xB};a7W{;aj`#Yn*uBr*7bRo_NdyMVRx;0e3K? zSd*g>T=r-{>2y*)>~w{t9EgL?B=}@tc8@w?;c^Q*@y8-1O6Vj*cNbH4nq=zkdhG5> OoBsi-l-$5Y7ytked1nUz literal 0 HcmV?d00001