fileoverview import * as ts from 'typescript' ; /**
 * Triggers increased verbosity in the rules.
 */ let DEBUG = false ; /**
 * Turns on or off logging for ConformancePatternRules.
 */ export function setDebug ( state ) { DEBUG = state ; } /**
 * Debug helper.
 */ export function debugLog ( msg ) { if ( DEBUG ) { console . log ( msg ( ) ) ; } } /**
 * Returns `n`'s parents in order.
 */ export function parents ( n ) { const p = [ ] ; while ( n . parent ) { n = n . parent ; p . push ( n ) ; } return p ; } /**
 * Searches for something satisfying the given test in `n` or its children.
 */ export function findInChildren ( n , test ) { let toExplore = [ n ] ; let cur ; while ( cur = toExplore . pop ( ) ) { if ( test ( cur ) ) { return true ; } toExplore = toExplore . concat ( cur . getChildren ( ) ) ; } return false ; } /**
 * Returns true if the pattern-based Rule should look at that node and consider
 * warning there. The goal is to make it easy to exclude on source files,
 * blocks, module declarations, JSDoc, lib.d.ts nodes, that kind of things.
 */ export function shouldExamineNode ( n ) { return ! ( ts . isBlock ( n ) || ts . isModuleBlock ( n ) || ts . isModuleDeclaration ( n ) || ts . isSourceFile ( n ) || ( n . parent && ts . isTypeNode ( n . parent ) ) || ts . isJSDoc ( n ) || isInStockLibraries ( n ) ) ; } /**
 * Return whether the given Node is (or is in) a library included as default.
 * We currently look for a node_modules/typescript/ prefix, but this could
 * be expanded if needed.
 */ export function isInStockLibraries ( n ) { const sourceFile = ts . isSourceFile ( n ) ? n : n . getSourceFile ( ) ; if ( sourceFile ) { return sourceFile . fileName . indexOf ( 'node_modules/typescript/' ) !== - 1 ; } else { return true ; } } /**
 * Turns the given Symbol into its non-aliased version (which could be itself).
 * Returns undefined if given an undefined Symbol (so you can call
 * `dealias(typeChecker.getSymbolAtLocation(node))`).
 */ export function dealias ( symbol , tc ) { if ( ! symbol ) { return undefined ; } if ( symbol . getFlags ( ) & ts . SymbolFlags . Alias ) { return dealias ( tc . getAliasedSymbol ( symbol ) , tc ) ; } return symbol ; } /**
 * Returns whether `n`'s parents are something indicating a type.
 */ export function isPartOfTypeDeclaration ( n ) { return [ n , ... parents ( n ) ] . some ( p => p . kind === ts . SyntaxKind . TypeReference || p . kind === ts . SyntaxKind . TypeLiteral ) ; } /**
 * Returns whether `n` is under an import statement.
 */ export function isPartOfImportStatement ( n ) { return [ n , ... parents ( n ) ] . some ( p => p . kind === ts . SyntaxKind . ImportDeclaration ) ; } function isAllowlistedNamedDeclaration ( n ) { return ts . isVariableDeclaration ( n ) || ts . isClassDeclaration ( n ) || ts . isFunctionDeclaration ( n ) || ts . isMethodDeclaration ( n ) || ts . isPropertyDeclaration ( n ) || ts . isInterfaceDeclaration ( n ) || ts . isTypeAliasDeclaration ( n ) || ts . isEnumDeclaration ( n ) || ts . isModuleDeclaration ( n ) || ts . isImportEqualsDeclaration ( n ) || ts . isExportDeclaration ( n ) || ts . isMissingDeclaration ( n ) || ts . isImportClause ( n ) || ts . isExportSpecifier ( n ) || ts . isImportSpecifier ( n ) ; } /** Returns whether `n` is being declared in a declaration statement. */ export function isNameInDeclaration ( n ) { const p = n . parent ; if ( p === undefined ) return false ; return ( isAllowlistedNamedDeclaration ( p ) && p . name === n ) || ts . isVariableDeclarationList ( p ) || ts . isImportDeclaration ( p ) ; } /**
 * If verbose, logs the given error that happened while walking n, with a
 * stacktrace.
 */ export function logASTWalkError ( verbose , n , e ) { let nodeText = `[error getting name for ${ JSON . stringify ( n ) }]` ; try { nodeText = '"' + n . getFullText ( ) . trim ( ) + '"' ; } catch { } debugLog ( ( ) => `Walking node ${ nodeText } failed with error ${ e }.\n` + `Stacktrace:\n${ e . stack }` ) ; }