namespace ts . server { export class ThrottledOperations { private readonly pendingTimeouts = new Map < string , any > ( ) ; private readonly logger ? : Logger | undefined ; constructor ( private readonly host , logger ) { this . logger = logger . hasLevel ( LogLevel . verbose ) ? logger : undefined ; } /**
         * Wait `number` milliseconds and then invoke `cb`.  If, while waiting, schedule
         * is called again with the same `operationId`, cancel this operation in favor
         * of the new one.  (Note that the amount of time the canceled operation had been
         * waiting does not affect the amount of time that the new operation waits.)
         */ public schedule ( operationId , delay , cb ) { const pendingTimeout = this . pendingTimeouts . get ( operationId ) ; if ( pendingTimeout ) { this . host . clearTimeout ( pendingTimeout ) ; } this . pendingTimeouts . set ( operationId , this . host . setTimeout ( ThrottledOperations . run , delay , this , operationId , cb ) ) ; if ( this . logger ) { this . logger . info ( `Scheduled: ${ operationId }${ pendingTimeout ? ", Cancelled earlier one" : "" }` ) ; } } public cancel ( operationId ) { const pendingTimeout = this . pendingTimeouts . get ( operationId ) ; if ( ! pendingTimeout ) return false ; this . host . clearTimeout ( pendingTimeout ) ; return this . pendingTimeouts . delete ( operationId ) ; } private static run ( self , operationId , cb ) { perfLogger . logStartScheduledOperation ( operationId ) ; self . pendingTimeouts . delete ( operationId ) ; if ( self . logger ) { self . logger . info ( `Running: ${ operationId }` ) ; } cb ( ) ; perfLogger . logStopScheduledOperation ( ) ; } } export class GcTimer { private timerId : any ; constructor ( private readonly host , private readonly delay , private readonly logger ) { } public scheduleCollect ( ) { if ( ! this . host . gc || this . timerId !== undefined ) { return ; } this . timerId = this . host . setTimeout ( GcTimer . run , this . delay , this ) ; } private static run ( self ) { self . timerId = undefined ; perfLogger . logStartScheduledOperation ( "GC collect" ) ; const log = self . logger . hasLevel ( LogLevel . requestTime ) ; const before = log && self . host . getMemoryUsage ! ( ) ; self . host . gc ! ( ) ; if ( log ) { const after = self . host . getMemoryUsage ! ( ) ; self . logger . perftrc ( `GC::before ${ before }, after ${ after }` ) ; } perfLogger . logStopScheduledOperation ( ) ; } } export function getBaseConfigFileName ( configFilePath ) { const base = getBaseFileName ( configFilePath ) ; return base === "tsconfig.json" || base === "jsconfig.json" ? base : undefined ; } export function removeSorted < T > ( array , remove , compare ) { if ( ! array || array . length === 0 ) { return ; } if ( array [ 0 ] === remove ) { array . splice ( 0 , 1 ) ; return ; } const removeIndex = binarySearch ( array , remove , identity , compare ) ; if ( removeIndex >= 0 ) { array . splice ( removeIndex , 1 ) ; } } const indentStr = "\n    " ; export function indent ( str ) { return indentStr + str . replace ( /\n/g , indentStr ) ; } /** Put stringified JSON on the next line, indented. */ export function stringifyIndented ( json ) { return indentStr + JSON . stringify ( json ) ; } }