import * as ts from 'typescript' ; import * as Lint from 'tslint' ; import { ErrorTolerantWalker } from './utils/ErrorTolerantWalker' ; import { ExtendedMetadata } from './utils/ExtendedMetadata' ; export const FAILURE_STRING = 'Try-catch blocks must be at the top of the scope' ; /**
 * Implementation of the newspaper-order rule.
 */ export class Rule extends Lint . Rules . AbstractRule { public static metadata : ExtendedMetadata = { ruleName : 'try-catch-first' , type : 'maintainability' , description : 'Try-catch blocks must be first within the scope. ' + 'Try-catch blocks are transactions and should leave your program in a consistent state, no matter what happens in the try.' , options : null , optionsDescription : '' , typescriptOnly : true , issueClass : 'Non-SDL' , issueType : 'Warning' , severity : 'Important' , level : 'Opportunity for Excellence' , group : 'Correctness' , recommendation : 'true,' , commonWeaknessEnumeration : '' , } ; public apply ( sourceFile ) { return this . applyWithWalker ( new TryCatchFirstRuleWalker ( sourceFile , this . getOptions ( ) ) ) ; } } class TryCatchFirstRuleWalker extends ErrorTolerantWalker { private scopeKinds : ts . SyntaxKind [ ] = [ ts . SyntaxKind . FunctionDeclaration , ts . SyntaxKind . ArrowFunction , ts . SyntaxKind . SourceFile , ts . SyntaxKind . MethodDeclaration , ts . SyntaxKind . GetAccessor , ts . SyntaxKind . SetAccessor , ] ; protected visitTryStatement ( node ) { this . checkAndReport ( node ) ; super . visitTryStatement ( node ) ; } private checkAndReport ( node ) { const block = node . parent ; const { parent } = block ; const isFirst = this . scopeKinds . indexOf ( ( parent || block ) . kind ) !== - 1 ; if ( ! isFirst ) { const failureMessage = this . makeFailureMessage ( ) ; this . addFailureAt ( node . getStart ( ) , node . getWidth ( ) , failureMessage ) ; } } private makeFailureMessage ( ) { return FAILURE_STRING ; } }