import type { TSESTree , TSESLint } from '@typescript-eslint/experimental-utils' ; import docsUrl from '../utils/docs-url' ; const loops = 'WhileStatement, ForStatement, DoWhileStatement, ForInStatement, ForOfStatement' ; const rule = { meta : { messages : { removeRedundantJump : 'Remove this redundant jump.' , } , schema : [ ] , type : 'suggestion' , docs : { description : 'Jump statements should not be redundant' , recommended : 'error' , url : docsUrl ( __filename ) , } , } , create ( context ) { function reportIfLastStatement ( node ) { const withArgument = node . type === 'ContinueStatement' ? ! ! node . label : ! ! node . argument ; if ( ! withArgument ) { const block = node . parent as TSESTree . BlockStatement ; if ( block . body [ block . body . length - 1 ] === node && block . body . length > 1 ) { context . report ( { messageId : 'removeRedundantJump' , node , } ) ; } } } function reportIfLastStatementInsideIf ( node ) { const ancestors = context . getAncestors ( ) ; const ifStatement = ancestors [ ancestors . length - 2 ] ; const upperBlock = ancestors [ ancestors . length - 3 ] as TSESTree . BlockStatement ; if ( upperBlock . body [ upperBlock . body . length - 1 ] === ifStatement ) { reportIfLastStatement ( node ) ; } } return { [ `:matches(${ loops }) > BlockStatement > ContinueStatement` ] : ( node ) => { reportIfLastStatement ( node as TSESTree . ContinueStatement ) ; } , [ `:matches(${ loops }) > BlockStatement > IfStatement > BlockStatement > ContinueStatement` ] : ( node ) => { reportIfLastStatementInsideIf ( node as TSESTree . ContinueStatement ) ; } , ':function > BlockStatement > ReturnStatement' : ( node ) => { reportIfLastStatement ( node as TSESTree . ReturnStatement ) ; } , ':function > BlockStatement > IfStatement > BlockStatement > ReturnStatement' : ( node ) => { reportIfLastStatementInsideIf ( node as TSESTree . ReturnStatement ) ; } , } ; } , } ; export = rule ;