import type { TSESTree , TSESLint } from '@typescript-eslint/experimental-utils' ; import { isBinaryExpression } from '../utils/nodes' ; import docsUrl from '../utils/docs-url' ; const invertedOperators = { '==' : '!=' , '!=' : '==' , '===' : '!==' , '!==' : '===' , '>' : '<=' , '<' : '>=' , '>=' : '<' , '<=' : '>' , } ; const rule = { meta : { messages : { useOppositeOperator : 'Use the opposite operator ({{invertedOperator}}) instead.' , } , schema : [ ] , type : 'suggestion' , docs : { description : 'Boolean checks should not be inverted' , recommended : 'error' , url : docsUrl ( __filename ) , } , fixable : 'code' , } , create ( context ) { return { UnaryExpression : ( node ) => visitUnaryExpression ( node as TSESTree . UnaryExpression , context ) , } ; } , } ; function visitUnaryExpression ( unaryExpression , context ) { if ( unaryExpression . operator === '!' && isBinaryExpression ( unaryExpression . argument ) ) { const condition = unaryExpression . argument ; const invertedOperator = invertedOperators [ condition . operator ] ; if ( invertedOperator ) { const left = context . getSourceCode ( ) . getText ( condition . left ) ; const right = context . getSourceCode ( ) . getText ( condition . right ) ; const [ start , end ] = unaryExpression . parent ?. type === 'UnaryExpression' ? [ '(' , ')' ] : [ '' , '' ] ; context . report ( { messageId : 'useOppositeOperator' , data : { invertedOperator } , node : unaryExpression , fix : fixer => fixer . replaceText ( unaryExpression , `${ start }${ left } ${ invertedOperator } ${ right }${ end }` ) , } ) ; } } } export = rule ;