@@ -41,11 +41,15 @@ namespace Microsoft.PythonTools.Analysis {
41
41
[ SuppressMessage ( "Microsoft.Design" , "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable" ,
42
42
Justification = "Unclear ownership makes it unlikely this object will be disposed correctly" ) ]
43
43
internal sealed class ProjectEntry : IPythonProjectEntry , IAggregateableProjectEntry , IDocument {
44
- private AnalysisUnit _unit ;
45
- private TaskCompletionSource < IModuleAnalysis > _analysisTcs = new TaskCompletionSource < IModuleAnalysis > ( ) ;
46
44
private readonly SortedDictionary < int , DocumentBuffer > _buffers ;
47
45
private readonly ConcurrentQueue < WeakReference < ReferenceDict > > _backReferences = new ConcurrentQueue < WeakReference < ReferenceDict > > ( ) ;
48
- internal readonly HashSet < AggregateProjectEntry > _aggregates = new HashSet < AggregateProjectEntry > ( ) ;
46
+ private readonly HashSet < AggregateProjectEntry > _aggregates = new HashSet < AggregateProjectEntry > ( ) ;
47
+
48
+ private TaskCompletionSource < IModuleAnalysis > _analysisTcs = new TaskCompletionSource < IModuleAnalysis > ( ) ;
49
+ private AnalysisUnit _unit ;
50
+ private readonly ManualResetEventSlim _pendingParse = new ManualResetEventSlim ( true ) ;
51
+ private long _expectedParseVersion ;
52
+ private long _expectedAnalysisVersion ;
49
53
50
54
internal ProjectEntry (
51
55
PythonAnalyzer state ,
@@ -84,17 +88,14 @@ internal static Uri MakeDocumentUri(string filePath) {
84
88
public event EventHandler < EventArgs > NewParseTree ;
85
89
public event EventHandler < EventArgs > NewAnalysis ;
86
90
87
- private readonly ManualResetEventSlim _pendingParse = new ManualResetEventSlim ( true ) ;
88
- private long _expectedParse ;
89
-
90
91
private class ActivePythonParse : IPythonParse {
91
92
private readonly ProjectEntry _entry ;
92
- private readonly long _expected ;
93
+ private readonly long _expectedVersion ;
93
94
private bool _completed ;
94
95
95
- public ActivePythonParse ( ProjectEntry entry , long expected ) {
96
+ public ActivePythonParse ( ProjectEntry entry , long expectedVersion ) {
96
97
_entry = entry ;
97
- _expected = expected ;
98
+ _expectedVersion = expectedVersion ;
98
99
}
99
100
100
101
public PythonAst Tree { get ; set ; }
@@ -105,7 +106,7 @@ public void Dispose() {
105
106
return ;
106
107
}
107
108
lock ( _entry ) {
108
- if ( _entry . _expectedParse == _expected ) {
109
+ if ( _entry . _expectedParseVersion == _expectedVersion ) {
109
110
_entry . _pendingParse . Set ( ) ;
110
111
}
111
112
}
@@ -114,7 +115,7 @@ public void Dispose() {
114
115
public void Complete ( ) {
115
116
_completed = true ;
116
117
lock ( _entry ) {
117
- if ( _entry . _expectedParse == _expected ) {
118
+ if ( _entry . _expectedParseVersion == _expectedVersion ) {
118
119
_entry . SetCurrentParse ( Tree , Cookie ) ;
119
120
_entry . _pendingParse . Set ( ) ;
120
121
}
@@ -125,8 +126,8 @@ public void Complete() {
125
126
public IPythonParse BeginParse ( ) {
126
127
_pendingParse . Reset ( ) ;
127
128
lock ( this ) {
128
- _expectedParse += 1 ;
129
- return new ActivePythonParse ( this , _expectedParse ) ;
129
+ _expectedParseVersion += 1 ;
130
+ return new ActivePythonParse ( this , _expectedParseVersion ) ;
130
131
}
131
132
}
132
133
@@ -157,14 +158,18 @@ public IPythonParse GetCurrentParse() {
157
158
158
159
internal void SetCompleteAnalysis ( ) {
159
160
lock ( this ) {
161
+ if ( _expectedAnalysisVersion != Analysis . Version ) {
162
+ return ;
163
+ }
160
164
_analysisTcs . TrySetResult ( Analysis ) ;
161
165
}
162
166
RaiseNewAnalysis ( ) ;
163
167
}
164
168
165
169
internal void ResetCompleteAnalysis ( ) {
166
- TaskCompletionSource < IModuleAnalysis > analysisTcs ;
170
+ TaskCompletionSource < IModuleAnalysis > analysisTcs = null ;
167
171
lock ( this ) {
172
+ _expectedAnalysisVersion = AnalysisVersion + 1 ;
168
173
analysisTcs = _analysisTcs ;
169
174
_analysisTcs = new TaskCompletionSource < IModuleAnalysis > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
170
175
}
@@ -188,14 +193,9 @@ public void SetCurrentParse(PythonAst tree, IAnalysisCookie cookie, bool notify
188
193
return GetCurrentParse ( ) ;
189
194
}
190
195
196
+ internal bool IsVisible ( ProjectEntry assigningScope ) => true ;
191
197
192
- internal bool IsVisible ( ProjectEntry assigningScope ) {
193
- return true ;
194
- }
195
-
196
- public void Analyze ( CancellationToken cancel ) {
197
- Analyze ( cancel , false ) ;
198
- }
198
+ public void Analyze ( CancellationToken cancel ) => Analyze ( cancel , false ) ;
199
199
200
200
public void Analyze ( CancellationToken cancel , bool enqueueOnly ) {
201
201
if ( cancel . IsCancellationRequested ) {
@@ -290,7 +290,7 @@ private void Parse(bool enqueueOnly, CancellationToken cancel) {
290
290
string pathPrefix = PathUtils . EnsureEndSeparator ( Path . GetDirectoryName ( FilePath ) ) ;
291
291
var children =
292
292
from pair in ProjectState . ModulesByFilename
293
- // Is the candidate child package in a subdirectory of our package?
293
+ // Is the candidate child package in a subdirectory of our package?
294
294
let fileName = pair . Key
295
295
where fileName . StartsWithOrdinal ( pathPrefix , ignoreCase : true )
296
296
let moduleName = pair . Value . Name
@@ -314,7 +314,8 @@ where lastDot > 0
314
314
// publish the analysis now that it's complete/running
315
315
Analysis = new ModuleAnalysis (
316
316
_unit ,
317
- ( ( ModuleScope ) _unit . Scope ) . CloneForPublish ( )
317
+ ( ( ModuleScope ) _unit . Scope ) . CloneForPublish ( ) ,
318
+ AnalysisVersion
318
319
) ;
319
320
}
320
321
0 commit comments