@@ -58,6 +58,7 @@ public bool IsCompleted {
58
58
}
59
59
60
60
public int Version { get ; }
61
+ public int AffectedEntriesCount { get ; }
61
62
62
63
public PythonAnalyzerSession ( IServiceManager services ,
63
64
IProgressReporter progress ,
@@ -73,6 +74,7 @@ public PythonAnalyzerSession(IServiceManager services,
73
74
_analysisCompleteEvent = analysisCompleteEvent ;
74
75
_startNextSession = startNextSession ;
75
76
Version = version ;
77
+ AffectedEntriesCount = walker . AffectedValues . Count ;
76
78
_walker = walker ;
77
79
_entry = entry ;
78
80
_state = State . NotStarted ;
@@ -99,7 +101,7 @@ public void Start(bool analyzeEntry) {
99
101
if ( analyzeEntry && _entry != null ) {
100
102
Task . Run ( ( ) => Analyze ( _entry , Version , _cts . Token ) , _cts . Token ) . DoNotWait ( ) ;
101
103
} else {
102
- StartAsync ( _walker ) . ContinueWith ( _startNextSession ) . DoNotWait ( ) ;
104
+ StartAsync ( ) . ContinueWith ( _startNextSession ) . DoNotWait ( ) ;
103
105
}
104
106
}
105
107
@@ -109,11 +111,11 @@ public void Cancel() {
109
111
}
110
112
}
111
113
112
- private async Task StartAsync ( IDependencyChainWalker < AnalysisModuleKey , PythonAnalyzerEntry > walker ) {
113
- _progress . ReportRemaining ( walker . Remaining ) ;
114
+ private async Task StartAsync ( ) {
115
+ _progress . ReportRemaining ( _walker . Remaining ) ;
114
116
115
117
lock ( _syncObj ) {
116
- var notAnalyzed = walker . AffectedValues . Count ( e => e . NotAnalyzed ) ;
118
+ var notAnalyzed = _walker . AffectedValues . Count ( e => e . NotAnalyzed ) ;
117
119
118
120
if ( _isCanceled && notAnalyzed < _maxTaskRunning ) {
119
121
_state = State . Completed ;
@@ -124,15 +126,15 @@ private async Task StartAsync(IDependencyChainWalker<AnalysisModuleKey, PythonAn
124
126
125
127
var cancellationToken = _cts . Token ;
126
128
var stopWatch = Stopwatch . StartNew ( ) ;
127
- foreach ( var affectedEntry in walker . AffectedValues ) {
129
+ foreach ( var affectedEntry in _walker . AffectedValues ) {
128
130
affectedEntry . Invalidate ( Version ) ;
129
131
}
130
132
131
- var originalRemaining = walker . Remaining ;
133
+ var originalRemaining = _walker . Remaining ;
132
134
var remaining = originalRemaining ;
133
135
try {
134
- _log ? . Log ( TraceEventType . Verbose , $ "Analysis version { walker . Version } of { originalRemaining } entries has started.") ;
135
- remaining = await AnalyzeAffectedEntriesAsync ( walker , stopWatch , cancellationToken ) ;
136
+ _log ? . Log ( TraceEventType . Verbose , $ "Analysis version { _walker . Version } of { originalRemaining } entries has started.") ;
137
+ remaining = await AnalyzeAffectedEntriesAsync ( stopWatch , cancellationToken ) ;
136
138
} finally {
137
139
_cts . Dispose ( ) ;
138
140
stopWatch . Stop ( ) ;
@@ -150,8 +152,8 @@ private async Task StartAsync(IDependencyChainWalker<AnalysisModuleKey, PythonAn
150
152
151
153
var elapsed = stopWatch . Elapsed . TotalMilliseconds ;
152
154
153
- SendTelemetry ( elapsed , originalRemaining , remaining , walker . Version ) ;
154
- LogResults ( elapsed , originalRemaining , remaining , walker . Version ) ;
155
+ SendTelemetry ( elapsed , originalRemaining , remaining , _walker . Version ) ;
156
+ LogResults ( elapsed , originalRemaining , remaining , _walker . Version ) ;
155
157
}
156
158
157
159
private void SendTelemetry ( double elapsed , int originalRemaining , int remaining , int version ) {
@@ -201,10 +203,12 @@ private void LogResults(double elapsed, int originalRemaining, int remaining, in
201
203
}
202
204
}
203
205
204
- private async Task < int > AnalyzeAffectedEntriesAsync ( IDependencyChainWalker < AnalysisModuleKey , PythonAnalyzerEntry > walker , Stopwatch stopWatch , CancellationToken cancellationToken ) {
206
+ private async Task < int > AnalyzeAffectedEntriesAsync ( Stopwatch stopWatch , CancellationToken cancellationToken ) {
205
207
IDependencyChainNode < PythonAnalyzerEntry > node ;
206
208
var remaining = 0 ;
207
- while ( ( node = await walker . GetNextAsync ( cancellationToken ) ) != null ) {
209
+ var ace = new AsyncCountdownEvent ( 0 ) ;
210
+
211
+ while ( ( node = await _walker . GetNextAsync ( cancellationToken ) ) != null ) {
208
212
bool isCanceled ;
209
213
lock ( _syncObj ) {
210
214
isCanceled = _isCanceled ;
@@ -216,14 +220,16 @@ private async Task<int> AnalyzeAffectedEntriesAsync(IDependencyChainWalker<Analy
216
220
continue ;
217
221
}
218
222
219
- if ( Interlocked . Increment ( ref _runningTasks ) >= _maxTaskRunning || walker . Remaining == 1 ) {
220
- Analyze ( walker , node , stopWatch , cancellationToken ) ;
223
+ if ( Interlocked . Increment ( ref _runningTasks ) >= _maxTaskRunning || _walker . Remaining == 1 ) {
224
+ Analyze ( node , null , stopWatch , cancellationToken ) ;
221
225
} else {
222
- StartAnalysis ( walker , node , stopWatch , cancellationToken ) . DoNotWait ( ) ;
226
+ StartAnalysis ( node , ace , stopWatch , cancellationToken ) . DoNotWait ( ) ;
223
227
}
224
228
}
225
229
226
- if ( walker . MissingKeys . All ( k => k . IsTypeshed ) ) {
230
+ await ace . WaitAsync ( cancellationToken ) ;
231
+
232
+ if ( _walker . MissingKeys . All ( k => k . IsTypeshed ) ) {
227
233
Interlocked . Exchange ( ref _runningTasks , 0 ) ;
228
234
bool isCanceled ;
229
235
lock ( _syncObj ) {
@@ -239,36 +245,37 @@ private async Task<int> AnalyzeAffectedEntriesAsync(IDependencyChainWalker<Analy
239
245
}
240
246
241
247
242
- private Task StartAnalysis ( IDependencyChainWalker < AnalysisModuleKey , PythonAnalyzerEntry > walker , IDependencyChainNode < PythonAnalyzerEntry > node , Stopwatch stopWatch , CancellationToken cancellationToken )
243
- => Task . Run ( ( ) => Analyze ( walker , node , stopWatch , cancellationToken ) , cancellationToken ) ;
248
+ private Task StartAnalysis ( IDependencyChainNode < PythonAnalyzerEntry > node , AsyncCountdownEvent ace , Stopwatch stopWatch , CancellationToken cancellationToken )
249
+ => Task . Run ( ( ) => Analyze ( node , ace , stopWatch , cancellationToken ) , cancellationToken ) ;
244
250
245
251
/// <summary>
246
252
/// Performs analysis of the document. Returns document global scope
247
253
/// with declared variables and inner scopes. Does not analyze chain
248
254
/// of dependencies, it is intended for the single file analysis.
249
255
/// </summary>
250
- private void Analyze ( IDependencyChainWalker < AnalysisModuleKey , PythonAnalyzerEntry > walker , IDependencyChainNode < PythonAnalyzerEntry > node , Stopwatch stopWatch , CancellationToken cancellationToken ) {
256
+ private void Analyze ( IDependencyChainNode < PythonAnalyzerEntry > node , AsyncCountdownEvent ace , Stopwatch stopWatch , CancellationToken cancellationToken ) {
251
257
IPythonModule module ;
252
258
try {
259
+ ace ? . AddOne ( ) ;
253
260
var entry = node . Value ;
254
- if ( ! entry . IsValidVersion ( walker . Version , out module , out var ast ) ) {
261
+ if ( ! entry . IsValidVersion ( _walker . Version , out module , out var ast ) ) {
255
262
_log ? . Log ( TraceEventType . Verbose , $ "Analysis of { module . Name } ({ module . ModuleType } ) canceled.") ;
256
263
node . Skip ( ) ;
257
264
return ;
258
265
}
259
266
var startTime = stopWatch . Elapsed ;
260
- AnalyzeEntry ( entry , module , ast , walker . Version , cancellationToken ) ;
267
+ AnalyzeEntry ( entry , module , ast , _walker . Version , cancellationToken ) ;
261
268
node . Commit ( ) ;
262
269
263
270
_log ? . Log ( TraceEventType . Verbose , $ "Analysis of { module . Name } ({ module . ModuleType } ) completed in { ( stopWatch . Elapsed - startTime ) . TotalMilliseconds } ms.") ;
264
271
} catch ( OperationCanceledException oce ) {
265
- node . Value . TryCancel ( oce , walker . Version ) ;
272
+ node . Value . TryCancel ( oce , _walker . Version ) ;
266
273
node . Skip ( ) ;
267
274
module = node . Value . Module ;
268
275
_log ? . Log ( TraceEventType . Verbose , $ "Analysis of { module . Name } ({ module . ModuleType } ) canceled.") ;
269
276
} catch ( Exception exception ) {
270
277
module = node . Value . Module ;
271
- node . Value . TrySetException ( exception , walker . Version ) ;
278
+ node . Value . TrySetException ( exception , _walker . Version ) ;
272
279
node . Commit ( ) ;
273
280
_log ? . Log ( TraceEventType . Verbose , $ "Analysis of { module . Name } ({ module . ModuleType } ) failed.") ;
274
281
} finally {
@@ -278,8 +285,9 @@ private void Analyze(IDependencyChainWalker<AnalysisModuleKey, PythonAnalyzerEnt
278
285
}
279
286
280
287
if ( ! isCanceled ) {
281
- _progress . ReportRemaining ( walker . Remaining ) ;
288
+ _progress . ReportRemaining ( _walker . Remaining ) ;
282
289
}
290
+ ace ? . Signal ( ) ;
283
291
Interlocked . Decrement ( ref _runningTasks ) ;
284
292
}
285
293
}
0 commit comments