44import { Progress , ProgressLocation , window } from 'vscode' ;
55import { Disposable , LanguageClient } from 'vscode-languageclient' ;
66import { createDeferred , Deferred } from '../../utils/async' ;
7+ import { StopWatch } from '../../utils/stopWatch' ;
8+ import { sendTelemetryEvent } from '../telemetry' ;
9+ import { PYTHON_LANGUAGE_SERVER_ANALYSISTIME } from '../telemetry/constants' ;
10+
11+ // Draw the line at Language Server analysis 'timing out'
12+ // and becoming a failure-case at 1 minute:
13+ const ANALYSIS_TIMEOUT_MS : number = 60000 ;
714
815export class ProgressReporting {
916 private statusBarMessage : Disposable | undefined ;
1017 private progress : Progress < { message ?: string ; increment ?: number } > | undefined ;
1118 private progressDeferred : Deferred < void > | undefined ;
19+ private progressTimer ?: StopWatch ;
20+ // tslint:disable-next-line:no-unused-variable
21+ private progressTimeout ?: NodeJS . Timer ;
1222
1323 constructor ( private readonly languageClient : LanguageClient ) {
1424 this . languageClient . onNotification ( 'python/setStatusBarMessage' , ( m : string ) => {
@@ -19,7 +29,17 @@ export class ProgressReporting {
1929 } ) ;
2030
2131 this . languageClient . onNotification ( 'python/beginProgress' , async _ => {
32+ if ( this . progressDeferred ) {
33+ return ;
34+ }
35+
2236 this . progressDeferred = createDeferred < void > ( ) ;
37+ this . progressTimer = new StopWatch ( ) ;
38+ this . progressTimeout = setTimeout (
39+ this . handleTimeout . bind ( this ) ,
40+ ANALYSIS_TIMEOUT_MS
41+ ) ;
42+
2343 window . withProgress ( {
2444 location : ProgressLocation . Window ,
2545 title : ''
@@ -40,7 +60,26 @@ export class ProgressReporting {
4060 if ( this . progressDeferred ) {
4161 this . progressDeferred . resolve ( ) ;
4262 this . progressDeferred = undefined ;
63+ this . progress = undefined ;
64+ this . completeAnalysisTracking ( true ) ;
4365 }
4466 } ) ;
4567 }
68+
69+ private completeAnalysisTracking ( success : boolean ) : void {
70+ if ( this . progressTimer ) {
71+ sendTelemetryEvent (
72+ PYTHON_LANGUAGE_SERVER_ANALYSISTIME ,
73+ this . progressTimer . elapsedTime ,
74+ { success }
75+ ) ;
76+ }
77+ this . progressTimer = undefined ;
78+ this . progressTimeout = undefined ;
79+ }
80+
81+ // tslint:disable-next-line:no-any
82+ private handleTimeout ( _args : any [ ] ) : void {
83+ this . completeAnalysisTracking ( false ) ;
84+ }
4685}
0 commit comments