import type { TSESLint , TSESTree } from '@typescript-eslint/experimental-utils' ; import docsUrl from '../utils/docs-url' ; import { issueLocation , report } from '../utils/locations' ; const message = 'Move this "if" to a new line or add the missing "else".' ; interface SiblingIfStatement { first : TSESTree . IfStatement ; following : TSESTree . IfStatement ; } const rule = { meta : { messages : { sameLineCondition : message , sonarRuntime : '{{sonarRuntimeData}}' , } , type : 'problem' , docs : { description : 'Conditionals should start on new lines' , recommended : 'error' , url : docsUrl ( __filename ) , } , schema : [ { enum : [ 'sonar-runtime' ] , } , ] , } , create ( context ) { function checkStatements ( statements ) { const sourceCode = context . getSourceCode ( ) ; const siblingIfStatements = getSiblingIfStatements ( statements ) ; siblingIfStatements . forEach ( siblingIfStatement => { const precedingIf = siblingIfStatement . first ; const followingIf = siblingIfStatement . following ; if ( ! ! precedingIf . loc && ! ! followingIf . loc && precedingIf . loc . end . line === followingIf . loc . start . line && precedingIf . loc . start . line !== followingIf . loc . end . line ) { const precedingIfLastToken = sourceCode . getLastToken ( precedingIf ) as TSESLint . AST . Token ; const followingIfToken = sourceCode . getFirstToken ( followingIf ) as TSESLint . AST . Token ; report ( context , { messageId : 'sameLineCondition' , loc : followingIfToken . loc , } , [ issueLocation ( precedingIfLastToken . loc ) ] , message ) ; } } ) ; } return { Program : ( node ) => checkStatements ( ( node as TSESTree . Program ) . body ) , BlockStatement : ( node ) => checkStatements ( ( node as TSESTree . BlockStatement ) . body ) , SwitchCase : ( node ) => checkStatements ( ( node as TSESTree . SwitchCase ) . consequent ) , } ; } , } ; function getSiblingIfStatements ( statements ) { return statements . reduce < SiblingIfStatement [ ] > ( ( siblingsArray , statement , currentIndex ) => { const previousStatement = statements [ currentIndex - 1 ] ; if ( statement . type === 'IfStatement' && ! ! previousStatement && previousStatement . type === 'IfStatement' ) { return [ { first : previousStatement , following : statement } , ... siblingsArray ] ; } return siblingsArray ; } , [ ] ) ; } export = rule ;