import ts from 'typescript' ; import * as utils from './utils' ; type NamedNode = ts . Node & { readonly name : ts . Identifier ; } ; type NameableNode = ts . Node & { readonly name ? : ts . Identifier ; } ; export type PropertyNamedNode = ts . Node & { readonly name : ts . PropertyName ; } ; type PropertyNameableNode = ts . Node & { readonly name ? : ts . PropertyName ; } ; type BindingNamedNode = ts . Node & { readonly name : ts . BindingName ; } ; type BindingNameableNode = ts . Node & { readonly name ? : ts . BindingName ; } ; export type AnyNameableNode = NameableNode | PropertyNameableNode | BindingNameableNode ; export function getNameNode ( node ) ; export function getNameNode ( node ) ; export function getNameNode ( node ) ; export function getNameNode ( node ) ; export function getNameNode ( node ) ; export function getNameNode ( node ) ; export function getNameNode ( node ) ; export function getNameNode ( node ) { return utils . getValueOrUndefined ( node . name ) ; } export function getNameNodeOrThrow ( node ) ; export function getNameNodeOrThrow ( node ) ; export function getNameNodeOrThrow ( node ) ; export function getNameNodeOrThrow ( node ) { return utils . throwIfNullOrUndefined ( getNameNode ( node ) , 'name' ) ; } export function getName ( node ) ; export function getName ( node ) ; export function getName ( node ) { const name = getNameNode ( node ) as ts . Identifier | ts . PropertyName | ts . BindingName | undefined ; if ( name === undefined || ts . isObjectBindingPattern ( name ) || ts . isArrayBindingPattern ( name ) ) { return undefined ; } return name . getText ( ) ; } export function getNameOrThrow ( node ) { return utils . throwIfNullOrUndefined ( getName ( node as any ) , 'name' ) ; } type PropertyNameNameableNode < T extends ts . PropertyName > = ts . Node & { readonly propertyName ? : T ; } ; export function getPropertyNameNode < T extends ts . PropertyName > ( node ) { return utils . getValueOrUndefined ( node . propertyName ) ; } type DotDotDotTokenNode = ts . Node & { readonly dotDotDotToken ? : ts . DotDotDotToken ; } ; export function getDotDotDotToken ( node ) { return utils . getValueOrUndefined ( node . dotDotDotToken ) ; } export function getText ( node ) { return node . getText ( ) ; } export function getParentSyntaxList ( node ) { const parent = utils . getValueOrUndefined ( node . parent ) ; if ( parent === undefined ) { return undefined ; } const { pos , end } = node ; for ( const child of parent . getChildren ( ) ) { if ( child . pos > end || child === node ) { return undefined ; } if ( child . kind === ts . SyntaxKind . SyntaxList && child . pos <= pos && child . end >= end ) { return child ; } } return undefined ; } export function getParent < TNode extends ts . Node > ( node ) { const parent = utils . getValueOrUndefined ( node . parent ) ; return parent === undefined ? undefined : ( node . parent as any ) ; } export function * getAncestors ( node ) { let parent = getParent ( node ) as ts . Node | undefined ; while ( parent !== undefined ) { yield parent ; parent = getParent ( parent ) ; } } export function * getDescendants ( node ) { let children = getChildren ( node ) ; while ( children . length > 0 ) { const mutableNextChildren = [ ] ; for ( const child of children ) { yield child ; mutableNextChildren . push ( ... getChildren ( child ) ) ; } children = mutableNextChildren ; } } export function * getDescendantsByKind < TNode extends ts . Node > ( node , kind ) { for ( const descendant of getDescendants ( node ) ) { if ( descendant . kind === kind ) { yield descendant as TNode ; } } } function getTarget ( symbol ) { const target = ( symbol as any ) . target ; return target === undefined ? symbol : target ; } export function getSymbol ( typeChecker , node ) { const symbol = utils . getValueOrUndefined ( ( node as any ) . symbol ) ; if ( symbol !== undefined ) { return getTarget ( symbol ) ; } const typeCheckerSymbol = utils . getValueOrUndefined ( typeChecker . getSymbolAtLocation ( node ) ) ; if ( typeCheckerSymbol !== undefined ) { return getTarget ( typeCheckerSymbol ) ; } const nameNode = getNameNode ( node ) ; if ( nameNode !== undefined ) { return getSymbol ( typeChecker , nameNode ) ; } return undefined ; } export function getSymbolOrThrow ( typeChecker , node ) { return utils . throwIfNullOrUndefined ( getSymbol ( typeChecker , node ) , 'symbol' ) ; } function getChildren ( node ) { return node . getChildren ( ) ; } export function getFirstChild ( node ) { const children = getChildren ( node ) ; return utils . getValueOrUndefined ( children [ 0 ] ) ; } export function getFirstChildByKind < TNode extends ts . Node > ( node , kind ) { const children = getChildren ( node ) ; return children . find ( ( value ) : value is TNode => value . kind === kind ) ; } export function getFirstAncestorByKind < TNode extends ts . Node > ( node , kind ) { for ( const ancestor of getAncestors ( node ) ) { if ( ancestor . kind === kind ) { return ancestor as TNode ; } } return undefined ; } export function getFirstAncestorByKindOrThrow < TNode extends ts . Node > ( node , kind ) { return utils . throwIfNullOrUndefined ( getFirstAncestorByKind < TNode > ( node , kind as any ) , 'ancestor' ) ; } export function getFirstAncestorByTest < TNode extends ts . Node > ( node , isNode ) { for ( const ancestor of getAncestors ( node ) ) { if ( isNode ( ancestor ) ) { return ancestor ; } } return undefined ; } export function getFirstAncestorByTestOrThrow < TNode extends ts . Node > ( node , isNode ) { return utils . throwIfNullOrUndefined ( getFirstAncestorByTest < TNode > ( node , isNode ) , 'ancestor' ) ; } export function getFirstDescendantByKind < TNode extends ts . Node > ( node , kind ) { for ( const ancestor of getDescendants ( node ) ) { if ( ancestor . kind === kind ) { return ancestor as TNode ; } } return undefined ; } function hasNodeFlag ( node , flag ) { return ( node . flags & flag ) !== 0 ; } export function isGlobalAugmentation ( node ) { return hasNodeFlag ( node , ts . NodeFlags . GlobalAugmentation ) ; } export function getSourceFile ( node ) { return node . getSourceFile ( ) ; } export function getPos ( node ) { return node . pos ; } export function getEnd ( node ) { return node . end ; } export function getChildAtPos ( node , pos ) { if ( pos < getPos ( node ) || pos >= getEnd ( node ) ) { return undefined ; } return getChildren ( node ) . find ( ( child ) => pos >= getPos ( child ) && pos < getEnd ( child ) ) ; } export function getDescendantAtPos ( nodeIn , pos ) { let node ; while ( true ) { const nextNode = getChildAtPos ( node === undefined ? nodeIn : node , pos ) ; if ( nextNode === undefined ) { return node ; } node = nextNode ; } } export function isPartOfTypeNode ( node ) { return ( ts as any ) . isPartOfTypeNode ( node ) ; }