/**
 * This file has code that is shared for all the ignore options.
 */ import * as ts from "typescript" ; import * as Lint from "tslint" ; import { escapeRegExp } from "tslint/lib/utils" ; import * as utils from "tsutils/typeguard/2.8" ; import * as CheckNode from "./check-node" ; import { hasExpression , isFunctionLikeDeclaration , isVariableLikeDeclaration } from "./typeguard" ; export type Options = IgnoreLocalOption & IgnoreOption & IgnoreRestParametersOption & IgnoreClassOption & IgnoreInterfaceOption & IgnoreMutationFollowingAccessorOption ; export interface IgnoreLocalOption { readonly ignoreLocal ? : boolean ; } export interface IgnoreOption { readonly ignorePattern ? : string | Array < string > | undefined ; readonly ignorePrefix ? : string | Array < string > | undefined ; readonly ignoreSuffix ? : string | Array < string > | undefined ; } export interface IgnoreRestParametersOption { readonly ignoreRestParameters ? : boolean ; } export interface IgnoreReturnType { readonly ignoreReturnType ? : boolean ; } export interface IgnoreClassOption { readonly ignoreClass ? : boolean ; } export interface IgnoreInterfaceOption { readonly ignoreInterface ? : boolean ; } export interface IgnoreNewArrayOption { readonly ignoreNewArray ? : boolean ; } deprecated export interface IgnoreMutationFollowingAccessorOption { readonly ignoreMutationFollowingAccessor ? : boolean ; } export function checkNodeWithIgnore ( checkNode ) { return ( node , ctx ) => { if ( ctx . options . ignoreLocal && isFunctionLikeDeclaration ( node ) ) { const invalidNodes = checkIgnoreLocalFunctionNode ( node , ctx , checkNode ) ; return { invalidNodes , skipChildren : true } ; } if ( ( ctx . options . ignoreClass && utils . isPropertyDeclaration ( node ) ) || ( ctx . options . ignoreInterface && utils . isPropertySignature ( node ) ) ) { return { invalidNodes : [ ] , skipChildren : true } ; } return checkNode ( node , ctx ) ; } ; } function checkIgnoreLocalFunctionNode ( functionNode , ctx , checkNode ) { let myInvalidNodes = [ ] ; const cb = ( node ) : void => { const { invalidNodes , skipChildren } = checkNode ( node , ctx ) ; if ( invalidNodes ) { myInvalidNodes = myInvalidNodes . concat ( ... invalidNodes ) ; } if ( skipChildren ) { return ; } return ts . forEachChild ( node , cb ) ; } ; for ( const n of functionNode . parameters . map ( p => ( p . type ? p . type : p ) ) ) { const { invalidNodes : invalidCheckNodes } = checkNode ( n , ctx ) ; if ( invalidCheckNodes ) { myInvalidNodes = myInvalidNodes . concat ( ... invalidCheckNodes ) ; } ts . forEachChild ( n , cb ) ; } const nt = functionNode . type ; if ( nt ) { const { invalidNodes : invalidCheckNodes } = checkNode ( nt , ctx ) ; if ( invalidCheckNodes ) { myInvalidNodes = myInvalidNodes . concat ( ... invalidCheckNodes ) ; } ts . forEachChild ( nt , cb ) ; } return myInvalidNodes ; } export function shouldIgnore ( node , options , sourceFile ) { if ( node && ( isVariableLikeDeclaration ( node ) || utils . isTypeAliasDeclaration ( node ) ) ) { const variableText = node . name . getText ( sourceFile ) ; if ( isIgnoredPattern ( variableText , options . ignorePattern ) ) { return true ; } if ( isIgnoredPrefix ( variableText , options . ignorePrefix ) ) { return true ; } if ( isIgnoredSuffix ( variableText , options . ignoreSuffix ) ) { return true ; } } return false ; } export function isIgnored ( node , ignorePattern , ignorePrefix , ignoreSuffix ) { const text = node . getText ( ) ; if ( isIgnoredPrefix ( text , ignorePrefix ) || isIgnoredSuffix ( text , ignoreSuffix ) || isIgnoredPattern ( node . getText ( ) , ignorePattern ) ) { return true ; } if ( hasExpression ( node ) ) { return isIgnored ( node . expression , undefined , ignorePrefix , ignoreSuffix ) ; } return false ; } function isIgnoredPrefix ( text , ignorePrefix ) { if ( ! ignorePrefix ) { return false ; } if ( Array . isArray ( ignorePrefix ) ) { if ( ignorePrefix . find ( pfx => text . indexOf ( pfx ) === 0 ) ) { return true ; } } else { if ( text . indexOf ( ignorePrefix ) === 0 ) { return true ; } } return false ; } function isIgnoredSuffix ( text , ignoreSuffix ) { if ( ! ignoreSuffix ) { return false ; } if ( Array . isArray ( ignoreSuffix ) ) { if ( ignoreSuffix . find ( sfx => { const indexToFindAt = text . length - sfx . length ; return indexToFindAt >= 0 && text . indexOf ( sfx ) === indexToFindAt ; } ) ) { return true ; } } else { const indexToFindAt = text . length - ignoreSuffix . length ; if ( indexToFindAt >= 0 && text . indexOf ( ignoreSuffix ) === indexToFindAt ) { return true ; } } return false ; } function isIgnoredPattern ( text , ignorePattern ) { if ( ! ignorePattern ) { return false ; } const patterns = Array . isArray ( ignorePattern ) ? ignorePattern : [ ignorePattern ] ; const findMatch = ( patternParts , textParts ) : boolean => { let index = 0 ; for ( ; index < patternParts . length ; index ++ ) { if ( index >= textParts . length ) { return false ; } switch ( patternParts [ index ] ) { case "**" : const subpattern = patternParts . slice ( index + 1 ) ; for ( let offset = index ; offset < textParts . length ; offset ++ ) { const submatch = findMatch ( subpattern , textParts . slice ( offset ) ) ; if ( submatch ) { return submatch ; } } return false ; case "*" : continue ; default : break ; } if ( new RegExp ( "^" + escapeRegExp ( patternParts [ index ] ) . replace ( /\\\*/g , ".*" ) + "$" ) . test ( textParts [ index ] ) ) { continue ; } return false ; } return textParts . length === index ; } ; return patterns . some ( pattern => findMatch ( pattern . split ( "." ) , text . split ( "." ) ) ) ; }