import * as ts from 'typescript' ; import * as Lint from 'tslint' ; import { ErrorTolerantWalker } from './utils/ErrorTolerantWalker' ; import { ExtendedMetadata } from './utils/ExtendedMetadata' ; export const FAILURE_STRING = 'Flag (boolean) arguments are not allowed: ' ; /**
 * Implementation of the newspaper-order rule.
 */ export class Rule extends Lint . Rules . AbstractRule { public static metadata : ExtendedMetadata = { ruleName : 'no-flag-args' , type : 'maintainability' , description : 'Passing a boolean into a function is a truly terrible practice. ' + 'It immediately complicates the signature of the method, loudly proclaiming that this function does more than one thing.' , 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 NoFlagArgsRuleWalker ( sourceFile , this . getOptions ( ) ) ) ; } } class NoFlagArgsRuleWalker extends ErrorTolerantWalker { protected visitParameterDeclaration ( node ) { if ( this . isBooleanParameter ( node ) && ! this . belongsToSetAssessor ( node ) ) { const failureMessage = this . makeFailureMessage ( node , FAILURE_STRING ) ; this . addFailureAt ( node . getStart ( ) , node . getWidth ( ) , failureMessage ) ; } super . visitParameterDeclaration ( node ) ; } private isBooleanParameter ( node ) { const { type } = node ; return type && type . kind === ts . SyntaxKind . BooleanKeyword ; } private belongsToSetAssessor ( node ) { const { parent } = node ; return parent && parent . kind === ts . SyntaxKind . SetAccessor ; } private makeFailureMessage ( node , failureString ) { const paramName = node . name . getText ( ) ; const pascalCaseParamName = this . toPascalCase ( paramName ) ; const functionName = node . parent . name && node . parent . name . getText ( ) ; const recommendation = functionName ? '\nSplit the function into two, such as ' + `${ functionName }When${ pascalCaseParamName }` + ' and ' + `${ functionName }WhenNot${ pascalCaseParamName }.` : '\nSplit the function into two.' ; return failureString + paramName + recommendation ; } private toPascalCase ( str ) { if ( typeof str !== 'string' || str . length === 0 ) { return str ; } return str [ 0 ] . toUpperCase ( ) + str . slice ( 1 ) ; } }