import { BaseVisitorContext , VisitorContext } from "../visitor-context" ; import { TS } from "../../type/type" ; import { BeforeVisitorOptions } from "./before-visitor-options" ; import { visitNode } from "./visitor/visit-node" ; import { ImportedSymbol } from "../../type/imported-symbol" ; import { ensureNodeFactory } from "compatfactory" ; export function beforeTransformer ( context ) { return ( transformationContext ) => { const factory = ensureNodeFactory ( transformationContext . factory ?? context . typescript ) ; return ( sourceFile ) => transformSourceFile ( sourceFile , { ... context , transformationContext , factory , } ) ; } ; } function transformSourceFile ( sourceFile , context ) { const requiredImportedSymbolSet = new Set < ImportedSymbol > ( ) ; /**
     * An optimization in which every imported symbol is converted into
     * a string that can be matched against directly to guard against
     * duplicates
     */ const requiredImportedSymbolSetFlags = new Set < string > ( ) ; context . sourceFileToAddTslibDefinition . set ( sourceFile . fileName , false ) ; context . sourceFileToRequiredImportedSymbolSet . set ( sourceFile . fileName , requiredImportedSymbolSet ) ; const computeImportedSymbolFlag = ( symbol ) : string => [ "name" , "propertyName" , "moduleSpecifier" , "isNamespaceImport" , "isDefaultImport" , ] . map ( ( property ) => `${ property }:${ symbol [ property as keyof ImportedSymbol ] ?? false }` ) . join ( "|" ) ; const visitorOptions = { context , addTslibDefinition : ( ) : void => { context . sourceFileToAddTslibDefinition . set ( sourceFile . fileName , true ) ; } , requireImportedSymbol : ( importedSymbol ) : void => { const flag = computeImportedSymbolFlag ( importedSymbol ) ; if ( requiredImportedSymbolSetFlags . has ( flag ) ) return ; requiredImportedSymbolSetFlags . add ( flag ) ; requiredImportedSymbolSet . add ( importedSymbol ) ; } , continuation : ( node ) => visitNode ( { ... visitorOptions , sourceFile , node , } ) , childContinuation : ( node ) => context . typescript . visitEachChild ( node , ( cbNode ) => visitNode ( { ... visitorOptions , sourceFile , node : cbNode , } ) , context . transformationContext ) , } ; return visitorOptions . continuation ( sourceFile ) as TS . SourceFile ; }