Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Commit 12fe3b3

Browse files
Merge pull request #110 from MikhailArkhipov/master
Fix wait for analysis complete, fix tests and avoid reload on all config changes
2 parents 1eb6839 + 546952d commit 12fe3b3

20 files changed

+2239
-2206
lines changed

src/Analysis/Engine/Impl/Definitions/IModuleAnalysis.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
namespace Microsoft.PythonTools.Analysis {
2222
public interface IModuleAnalysis {
23+
int Version { get; }
2324
IModuleContext InterpreterContext { get; }
2425
PythonAnalyzer ProjectState { get; }
2526
IScope Scope { get; }
@@ -146,7 +147,7 @@ public interface IModuleAnalysis {
146147
/// <param name="location">
147148
/// The location in the file where the available members should be looked up.
148149
/// </param>
149-
IEnumerable<IMemberResult> GetAllAvailableMembers(SourceLocation location, GetMemberOptions options = GetMemberOptions.IntersectMultipleResults);
150+
IEnumerable<IMemberResult> GetAllMembers(SourceLocation location, GetMemberOptions options = GetMemberOptions.IntersectMultipleResults);
150151

151152
/// <summary>
152153
/// Gets the AST for the given text as if it appeared at the specified location.

src/Analysis/Engine/Impl/ModuleAnalysis.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,21 @@ namespace Microsoft.PythonTools.Analysis {
3434
///
3535
/// Can be queried for various information about the resulting analysis.
3636
/// </summary>
37-
public sealed class ModuleAnalysis: IModuleAnalysis {
37+
public sealed class ModuleAnalysis : IModuleAnalysis {
3838
private readonly AnalysisUnit _unit;
3939
private static Regex _otherPrivateRegex = new Regex("^_[a-zA-Z_]\\w*__[a-zA-Z_]\\w*$");
4040

4141
private static readonly IEnumerable<IOverloadResult> GetSignaturesError =
4242
new[] { new OverloadResult(new ParameterResult[0], "Unknown", "IntellisenseError_Sigs", null) };
4343

44-
internal ModuleAnalysis(AnalysisUnit unit, InterpreterScope scope) {
44+
internal ModuleAnalysis(AnalysisUnit unit, InterpreterScope scope, int version) {
4545
_unit = unit;
4646
Scope = scope;
47+
Version = version;
4748
}
4849

4950
#region Public API
50-
51+
public int Version { get; }
5152
/// <summary>
5253
/// Evaluates the given expression in at the provided line number and returns the values
5354
/// that the expression can evaluate to.
@@ -350,7 +351,7 @@ public IEnumerable<IMemberResult> GetMembers(
350351
GetMemberOptions options = GetMemberOptions.IntersectMultipleResults
351352
) {
352353
if (string.IsNullOrEmpty(exprText)) {
353-
return GetAllAvailableMembers(location, options);
354+
return GetAllMembers(location, options);
354355
}
355356

356357
var expr = GetExpressionForText(exprText, location, out var scope, out var ast);
@@ -526,7 +527,7 @@ expr is TupleExpression ||
526527
/// specified location.
527528
/// </summary>
528529
/// <param name="index">The 0-based absolute index into the file.</param>
529-
internal IEnumerable<IMemberResult> GetDefinitionTreeByIndex(int index)
530+
internal IEnumerable<IMemberResult> GetDefinitionTreeByIndex(int index)
530531
=> GetDefinitionTree(_unit.Tree.IndexToLocation(index));
531532

532533
/// <summary>
@@ -630,7 +631,11 @@ public IEnumerable<IOverloadResult> GetOverrideable(SourceLocation location) {
630631
internal IEnumerable<IMemberResult> GetAllAvailableMembersByIndex(
631632
int index,
632633
GetMemberOptions options = GetMemberOptions.IntersectMultipleResults
633-
) => GetAllAvailableMembers(_unit.Tree.IndexToLocation(index), options);
634+
) => GetAllMembers(_unit.Tree.IndexToLocation(index), options);
635+
636+
[Obsolete]
637+
public IEnumerable<MemberResult> GetAllAvailableMembers(SourceLocation location, GetMemberOptions options = GetMemberOptions.IntersectMultipleResults)
638+
=> GetAllMembers(location, options).OfType<MemberResult>();
634639

635640
/// <summary>
636641
/// Gets the available names at the given location. This includes
@@ -641,7 +646,7 @@ internal IEnumerable<IMemberResult> GetAllAvailableMembersByIndex(
641646
/// looked up.
642647
/// </param>
643648
/// <remarks>New in 2.2</remarks>
644-
public IEnumerable<IMemberResult> GetAllAvailableMembers(SourceLocation location, GetMemberOptions options = GetMemberOptions.IntersectMultipleResults) {
649+
public IEnumerable<IMemberResult> GetAllMembers(SourceLocation location, GetMemberOptions options = GetMemberOptions.IntersectMultipleResults) {
645650
var result = new Dictionary<string, IEnumerable<AnalysisValue>>();
646651

647652
// collect builtins
@@ -989,9 +994,9 @@ private static bool IsInFunctionParameter(InterpreterScope scope, PythonAst tree
989994
}
990995

991996
return function.Parameters.Any(p => {
992-
var paramName = p.GetVerbatimImage(tree) ?? p.Name;
993-
return index >= p.StartIndex && index <= p.StartIndex + paramName.Length;
994-
});
997+
var paramName = p.GetVerbatimImage(tree) ?? p.Name;
998+
return index >= p.StartIndex && index <= p.StartIndex + paramName.Length;
999+
});
9951000
}
9961001

9971002
private static int GetParentScopeIndent(InterpreterScope scope, PythonAst tree) {

src/Analysis/Engine/Impl/ProjectEntry.cs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)