@@ -40,7 +40,7 @@ export class TokenCalculator implements vscode.Disposable {
4040 private _notified_roots : Set < string > = new Set ( )
4141
4242 private _progress_stack : {
43- progress : vscode . Progress < { message ?: string ; increment ?: number } >
43+ progress ? : vscode . Progress < { message ?: string ; increment ?: number } >
4444 total_files : number
4545 processed_files : number
4646 } [ ] = [ ]
@@ -171,7 +171,9 @@ export class TokenCalculator implements vscode.Disposable {
171171 if ( state . total_files > 0 ) {
172172 state . processed_files ++
173173 const increment = ( 1 / state . total_files ) * 100
174- state . progress . report ( { increment } )
174+ if ( state . progress ) {
175+ state . progress . report ( { increment } )
176+ }
175177 }
176178 }
177179 }
@@ -274,30 +276,75 @@ export class TokenCalculator implements vscode.Disposable {
274276 return params . task ( )
275277 }
276278
277- return vscode . window . withProgress (
278- {
279- location : vscode . ProgressLocation . Notification ,
280- title : t ( 'context.crunching-token-counts' ) ,
281- cancellable : false
282- } ,
283- async ( progress ) => {
284- const progress_state = {
285- progress,
286- total_files : total_uncached ,
287- processed_files : 0
288- }
289- this . _progress_stack . push ( progress_state )
290-
291- try {
292- return await params . task ( )
293- } finally {
294- const index = this . _progress_stack . indexOf ( progress_state )
295- if ( index !== - 1 ) {
296- this . _progress_stack . splice ( index , 1 )
279+ const progress_state : {
280+ progress ?: vscode . Progress < { message ?: string ; increment ?: number } >
281+ total_files : number
282+ processed_files : number
283+ } = {
284+ total_files : total_uncached ,
285+ processed_files : 0
286+ }
287+ this . _progress_stack . push ( progress_state )
288+
289+ const task_promise = params . task ( )
290+
291+ let timeout_handle : NodeJS . Timeout
292+ const timeout_promise = new Promise < void > ( ( resolve ) => {
293+ timeout_handle = setTimeout ( ( ) => resolve ( ) , 3000 )
294+ } )
295+
296+ let is_completed = false
297+ task_promise . finally ( ( ) => {
298+ is_completed = true
299+ clearTimeout ( timeout_handle )
300+ } )
301+
302+ try {
303+ await Promise . race ( [ task_promise , timeout_promise ] )
304+ } catch ( error ) {
305+ const index = this . _progress_stack . indexOf ( progress_state )
306+ if ( index !== - 1 ) {
307+ this . _progress_stack . splice ( index , 1 )
308+ }
309+ throw error
310+ }
311+
312+ if ( ! is_completed ) {
313+ return vscode . window . withProgress (
314+ {
315+ location : vscode . ProgressLocation . Notification ,
316+ title : t ( 'context.crunching-token-counts' ) ,
317+ cancellable : false
318+ } ,
319+ async ( progress ) => {
320+ progress_state . progress = progress
321+ if (
322+ progress_state . total_files > 0 &&
323+ progress_state . processed_files > 0
324+ ) {
325+ progress . report ( {
326+ increment :
327+ ( progress_state . processed_files / progress_state . total_files ) *
328+ 100
329+ } )
330+ }
331+ try {
332+ return await task_promise
333+ } finally {
334+ const index = this . _progress_stack . indexOf ( progress_state )
335+ if ( index !== - 1 ) {
336+ this . _progress_stack . splice ( index , 1 )
337+ }
297338 }
298339 }
340+ )
341+ } else {
342+ const index = this . _progress_stack . indexOf ( progress_state )
343+ if ( index !== - 1 ) {
344+ this . _progress_stack . splice ( index , 1 )
299345 }
300- )
346+ return task_promise
347+ }
301348 }
302349
303350 public invalidate_token_counts_for_file ( changed_file_path : string ) {
0 commit comments