import { Node , SourceFile , transform , TransformationContext , Transformer , TransformerFactory , visitEachChild , visitNode } from 'typescript' ; import { query } from './query' ; import { TSQueryNodeTransformer , TSQueryOptions } from './tsquery-types' ; export function map ( ast , selector , nodeTransformer , options = { } ) { const matches = query ( ast , selector , options ) ; const transformer = createTransformer ( matches , nodeTransformer ) ; const [ transformed ] = transform ( ast , [ transformer ] ) . transformed ; return transformed as SourceFile ; } function createTransformer ( results , nodeTransformer ) { return function ( context ) : Transformer < Node > { return function ( rootNode ) : Node { function visit ( node ) { if ( results . includes ( node ) ) { const replacement = nodeTransformer ( node ) ; return replacement ? replacement : node ; } return visitEachChild ( node , visit , context ) ; } return visitNode ( rootNode , visit ) ; } ; } ; }