@@ -41,11 +41,15 @@ namespace Microsoft.PythonTools.Analysis {
4141 [ SuppressMessage ( "Microsoft.Design" , "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable" ,
4242 Justification = "Unclear ownership makes it unlikely this object will be disposed correctly" ) ]
4343 internal sealed class ProjectEntry : IPythonProjectEntry , IAggregateableProjectEntry , IDocument {
44- private AnalysisUnit _unit ;
45- private TaskCompletionSource < IModuleAnalysis > _analysisTcs = new TaskCompletionSource < IModuleAnalysis > ( ) ;
4644 private readonly SortedDictionary < int , DocumentBuffer > _buffers ;
4745 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 ;
4953
5054 internal ProjectEntry (
5155 PythonAnalyzer state ,
@@ -84,17 +88,14 @@ internal static Uri MakeDocumentUri(string filePath) {
8488 public event EventHandler < EventArgs > NewParseTree ;
8589 public event EventHandler < EventArgs > NewAnalysis ;
8690
87- private readonly ManualResetEventSlim _pendingParse = new ManualResetEventSlim ( true ) ;
88- private long _expectedParse ;
89-
9091 private class ActivePythonParse : IPythonParse {
9192 private readonly ProjectEntry _entry ;
92- private readonly long _expected ;
93+ private readonly long _expectedVersion ;
9394 private bool _completed ;
9495
95- public ActivePythonParse ( ProjectEntry entry , long expected ) {
96+ public ActivePythonParse ( ProjectEntry entry , long expectedVersion ) {
9697 _entry = entry ;
97- _expected = expected ;
98+ _expectedVersion = expectedVersion ;
9899 }
99100
100101 public PythonAst Tree { get ; set ; }
@@ -105,7 +106,7 @@ public void Dispose() {
105106 return ;
106107 }
107108 lock ( _entry ) {
108- if ( _entry . _expectedParse == _expected ) {
109+ if ( _entry . _expectedParseVersion == _expectedVersion ) {
109110 _entry . _pendingParse . Set ( ) ;
110111 }
111112 }
@@ -114,7 +115,7 @@ public void Dispose() {
114115 public void Complete ( ) {
115116 _completed = true ;
116117 lock ( _entry ) {
117- if ( _entry . _expectedParse == _expected ) {
118+ if ( _entry . _expectedParseVersion == _expectedVersion ) {
118119 _entry . SetCurrentParse ( Tree , Cookie ) ;
119120 _entry . _pendingParse . Set ( ) ;
120121 }
@@ -125,8 +126,8 @@ public void Complete() {
125126 public IPythonParse BeginParse ( ) {
126127 _pendingParse . Reset ( ) ;
127128 lock ( this ) {
128- _expectedParse += 1 ;
129- return new ActivePythonParse ( this , _expectedParse ) ;
129+ _expectedParseVersion += 1 ;
130+ return new ActivePythonParse ( this , _expectedParseVersion ) ;
130131 }
131132 }
132133
@@ -157,14 +158,18 @@ public IPythonParse GetCurrentParse() {
157158
158159 internal void SetCompleteAnalysis ( ) {
159160 lock ( this ) {
161+ if ( _expectedAnalysisVersion != Analysis . Version ) {
162+ return ;
163+ }
160164 _analysisTcs . TrySetResult ( Analysis ) ;
161165 }
162166 RaiseNewAnalysis ( ) ;
163167 }
164168
165169 internal void ResetCompleteAnalysis ( ) {
166- TaskCompletionSource < IModuleAnalysis > analysisTcs ;
170+ TaskCompletionSource < IModuleAnalysis > analysisTcs = null ;
167171 lock ( this ) {
172+ _expectedAnalysisVersion = AnalysisVersion + 1 ;
168173 analysisTcs = _analysisTcs ;
169174 _analysisTcs = new TaskCompletionSource < IModuleAnalysis > ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
170175 }
@@ -188,14 +193,9 @@ public void SetCurrentParse(PythonAst tree, IAnalysisCookie cookie, bool notify
188193 return GetCurrentParse ( ) ;
189194 }
190195
196+ internal bool IsVisible ( ProjectEntry assigningScope ) => true ;
191197
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 ) ;
199199
200200 public void Analyze ( CancellationToken cancel , bool enqueueOnly ) {
201201 if ( cancel . IsCancellationRequested ) {
@@ -290,7 +290,7 @@ private void Parse(bool enqueueOnly, CancellationToken cancel) {
290290 string pathPrefix = PathUtils . EnsureEndSeparator ( Path . GetDirectoryName ( FilePath ) ) ;
291291 var children =
292292 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?
294294 let fileName = pair . Key
295295 where fileName . StartsWithOrdinal ( pathPrefix , ignoreCase : true )
296296 let moduleName = pair . Value . Name
@@ -314,7 +314,8 @@ where lastDot > 0
314314 // publish the analysis now that it's complete/running
315315 Analysis = new ModuleAnalysis (
316316 _unit ,
317- ( ( ModuleScope ) _unit . Scope ) . CloneForPublish ( )
317+ ( ( ModuleScope ) _unit . Scope ) . CloneForPublish ( ) ,
318+ AnalysisVersion
318319 ) ;
319320 }
320321
0 commit comments