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

Commit 2fbe616

Browse files
author
Mikhail Arkhipov
authored
Merge pull request #96 from MikhailArkhipov/master
Better progress reporting
2 parents 5a1db7a + 7380582 commit 2fbe616

File tree

12 files changed

+126
-46
lines changed

12 files changed

+126
-46
lines changed

src/Analysis/Engine/Impl/ProjectEntry.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ internal void SetCompleteAnalysis() {
159159
lock (this) {
160160
_analysisTcs.TrySetResult(Analysis);
161161
}
162+
RaiseNewAnalysis();
162163
}
163164

164165
internal void ResetCompleteAnalysis() {
@@ -216,7 +217,7 @@ public void Analyze(CancellationToken cancel, bool enqueueOnly) {
216217
}
217218
}
218219

219-
internal void RaiseNewAnalysis() => NewAnalysis?.Invoke(this, EventArgs.Empty);
220+
private void RaiseNewAnalysis() => NewAnalysis?.Invoke(this, EventArgs.Empty);
220221

221222
public int AnalysisVersion { get; private set; }
222223

src/Analysis/Engine/Impl/PythonAnalyzer.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,6 @@ public void AnalyzeQueuedEntries(CancellationToken cancel) {
925925
ddg.Analyze(Queue, cancel, _reportQueueSize, _reportQueueInterval);
926926
foreach (ProjectEntry entry in ddg.AnalyzedEntries) {
927927
entry.SetCompleteAnalysis();
928-
entry.RaiseNewAnalysis();
929928
}
930929
}
931930

src/Analysis/Engine/Impl/Values/Definitions/IAnalysisIterableValue.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
using System.Collections.Generic;
1818

1919
namespace Microsoft.PythonTools.Analysis.Values {
20-
interface IAnalysisIterableValue: IAnalysisValue {
20+
public interface IAnalysisIterableValue: IAnalysisValue {
2121
IEnumerable<IVariableDefinition> IndexTypes { get; }
2222
}
2323
}

src/Analysis/Engine/Test/AnalysisTest.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,6 @@ public async Task ImportTrailingComma() {
685685
}
686686

687687
[TestMethod, Priority(0)]
688-
[Ignore("https://github.com/Microsoft/python-language-server/issues/49")]
689688
public async Task ImportStarCorrectRefs() {
690689
var text1 = @"
691690
from mod2 import *
@@ -3212,7 +3211,6 @@ def f(a):
32123211
}
32133212

32143213
[TestMethod, Priority(0)]
3215-
[Ignore("https://github.com/Microsoft/python-language-server/issues/51")]
32163214
public async Task ReferencesCrossModule() {
32173215
var fobText = @"
32183216
from oar import abc
@@ -3239,7 +3237,6 @@ from oar import abc
32393237
}
32403238

32413239
[TestMethod, Priority(0)]
3242-
[Ignore("https://github.com/Microsoft/python-language-server/issues/53")]
32433240
public async Task SuperclassMemberReferencesCrossModule() {
32443241
// https://github.com/Microsoft/PTVS/issues/2271
32453242

src/LanguageServer/Impl/Definitions/ILanguageServerExtensionProvider.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@
1717
using System.Collections.Generic;
1818
using System.Threading;
1919
using System.Threading.Tasks;
20-
using Microsoft.Python.LanguageServer.Extensions;
2120

22-
namespace Microsoft.Python.LanguageServer {
21+
namespace Microsoft.Python.LanguageServer.Extensions {
2322
/// <summary>
2423
/// Implemented on a class that can create a language server extension.
2524
/// This class must have a default constructor.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Python Tools for Visual Studio
2+
// Copyright(c) Microsoft Corporation
3+
// All rights reserved.
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the License); you may not use
6+
// this file except in compliance with the License. You may obtain a copy of the
7+
// License at http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS
10+
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY
11+
// IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
12+
// MERCHANTABLITY OR NON-INFRINGEMENT.
13+
//
14+
// See the Apache Version 2.0 License for specific language governing
15+
// permissions and limitations under the License.
16+
17+
using System;
18+
using System.Threading.Tasks;
19+
using Microsoft.PythonTools.Analysis.Infrastructure;
20+
21+
namespace Microsoft.Python.LanguageServer.Implementation {
22+
sealed class AnalysisProgressReporter : IDisposable {
23+
private readonly DisposableBag _disposables = new DisposableBag(nameof(AnalysisProgressReporter));
24+
private readonly IProgressService _progressService;
25+
private readonly ILogger _logger;
26+
private readonly Server _server;
27+
private readonly object _lock = new object();
28+
private IProgress _progress;
29+
private Task _queueMonitoringTask;
30+
31+
public AnalysisProgressReporter(Server server, IProgressService progressService, ILogger logger) {
32+
_progressService = progressService;
33+
_logger = logger;
34+
35+
_server = server;
36+
_server.OnAnalysisQueued += OnAnalysisQueued;
37+
_server.OnAnalysisComplete += OnAnalysisComplete;
38+
_disposables
39+
.Add(() => _server.OnAnalysisQueued -= OnAnalysisQueued)
40+
.Add(() => _server.OnAnalysisComplete -= OnAnalysisComplete)
41+
.Add(() => _progress?.Dispose());
42+
}
43+
44+
public void Dispose() => _disposables.TryDispose();
45+
46+
private void OnAnalysisQueued(object sender, AnalysisQueuedEventArgs e) {
47+
lock (_lock) {
48+
UpdateProgressMessage();
49+
_queueMonitoringTask = _queueMonitoringTask ?? QueueMonitoringTask();
50+
}
51+
}
52+
private void OnAnalysisComplete(object sender, AnalysisCompleteEventArgs e) {
53+
lock (_lock) {
54+
UpdateProgressMessage();
55+
}
56+
}
57+
58+
private void UpdateProgressMessage() {
59+
var count = _server.EstimateRemainingWork();
60+
if (count > 0) {
61+
_progress = _progress ?? _progressService.BeginProgress();
62+
_progress.Report(count == 1
63+
? Resources.AnalysisProgress_SingleItemRemaining
64+
: Resources.AnalysisProgress_MultipleItemsRemaining.FormatInvariant(count)).DoNotWait();
65+
} else {
66+
EndProgress();
67+
}
68+
}
69+
70+
private async Task QueueMonitoringTask() {
71+
try {
72+
await _server.WaitForCompleteAnalysisAsync();
73+
} finally {
74+
EndProgress();
75+
}
76+
}
77+
78+
private void EndProgress() {
79+
lock (_lock) {
80+
_progress?.Dispose();
81+
_progress = null;
82+
_queueMonitoringTask = null;
83+
}
84+
}
85+
}
86+
}

src/LanguageServer/Impl/Implementation/Server.Extensions.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ private async Task InvokeExtensionsAsync(Func<ILanguageServerExtension, Cancella
7777
break;
7878
}
7979
await action(ext.Value, cancellationToken);
80-
} catch (Exception ex) when (!ex.IsCriticalException()) {
81-
// We do not replace res in this case.
80+
} catch (Exception ex) when (!ex.IsCriticalException() && !(ex is OperationCanceledException)) {
8281
LogMessage(MessageType.Error, $"Error invoking extension '{ext.Key}': {ex}");
8382
}
8483
}

src/LanguageServer/Impl/Implementation/Server.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,13 @@ private void Analysis_UnhandledException(object sender, UnhandledExceptionEventA
123123

124124
public void Dispose() => _disposableBag.TryDispose();
125125

126+
#region ILogger
126127
public void TraceMessage(IFormattable message) {
127128
if (_traceLogging) {
128129
LogMessage(MessageType.Log, message.ToString());
129130
}
130131
}
132+
#endregion
131133

132134
#region Client message handling
133135
internal InitializeResult GetInitializeResult() => new InitializeResult {

src/LanguageServer/Impl/LanguageServer.cs

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -43,31 +43,29 @@ public sealed partial class LanguageServer: IDisposable {
4343
private IServiceContainer _services;
4444
private IUIService _ui;
4545
private ITelemetryService _telemetry;
46-
private IProgressService _progress;
4746

4847
private JsonRpc _rpc;
4948
private bool _filesLoaded;
50-
private Task _progressReportingTask;
5149
private PathsWatcher _pathsWatcher;
5250
private IdleTimeTracker _idleTimeTracker;
51+
private AnalysisProgressReporter _analysisProgressReporter;
5352

5453
public CancellationToken Start(IServiceContainer services, JsonRpc rpc) {
5554
_services = services;
5655
_ui = services.GetService<IUIService>();
5756
_telemetry = services.GetService<ITelemetryService>();
58-
_progress = services.GetService<IProgressService>();
59-
6057
_rpc = rpc;
6158

59+
var progress = services.GetService<IProgressService>();
60+
_analysisProgressReporter = new AnalysisProgressReporter(_server, progress, _server);
61+
6262
_server.OnLogMessage += OnLogMessage;
6363
_server.OnShowMessage += OnShowMessage;
6464
_server.OnTelemetry += OnTelemetry;
6565
_server.OnPublishDiagnostics += OnPublishDiagnostics;
6666
_server.OnApplyWorkspaceEdit += OnApplyWorkspaceEdit;
6767
_server.OnRegisterCapability += OnRegisterCapability;
6868
_server.OnUnregisterCapability += OnUnregisterCapability;
69-
_server.OnAnalysisQueued += OnAnalysisQueued;
70-
_server.OnAnalysisComplete += OnAnalysisComplete;
7169

7270
_disposables
7371
.Add(() => _server.OnLogMessage -= OnLogMessage)
@@ -77,40 +75,14 @@ public CancellationToken Start(IServiceContainer services, JsonRpc rpc) {
7775
.Add(() => _server.OnApplyWorkspaceEdit -= OnApplyWorkspaceEdit)
7876
.Add(() => _server.OnRegisterCapability -= OnRegisterCapability)
7977
.Add(() => _server.OnUnregisterCapability -= OnUnregisterCapability)
80-
.Add(() => _server.OnAnalysisQueued -= OnAnalysisQueued)
81-
.Add(() => _server.OnAnalysisComplete -= OnAnalysisComplete)
82-
.Add(_prioritizer);
78+
.Add(_prioritizer)
79+
.Add(_analysisProgressReporter)
80+
.Add(() => _pathsWatcher?.Dispose());
8381

8482
return _sessionTokenSource.Token;
8583
}
8684

87-
private void OnAnalysisQueued(object sender, AnalysisQueuedEventArgs e) => HandleAnalysisQueueEvent();
88-
private void OnAnalysisComplete(object sender, AnalysisCompleteEventArgs e) => HandleAnalysisQueueEvent();
89-
90-
private void HandleAnalysisQueueEvent()
91-
=> _progressReportingTask = _progressReportingTask ?? ProgressWorker();
92-
93-
private async Task ProgressWorker() {
94-
await Task.Delay(1000);
95-
96-
var remaining = _server.EstimateRemainingWork();
97-
if (remaining > 0) {
98-
using (var p = _progress.BeginProgress()) {
99-
while (remaining > 0) {
100-
var items = remaining > 1 ? "items" : "item";
101-
// TODO: in localization this needs to be two different messages
102-
// since not all languages allow sentence construction.
103-
await p.Report($"Analyzing workspace, {remaining} {items} remaining...");
104-
await Task.Delay(100);
105-
remaining = _server.EstimateRemainingWork();
106-
}
107-
}
108-
}
109-
_progressReportingTask = null;
110-
}
111-
11285
public void Dispose() {
113-
_pathsWatcher?.Dispose();
11486
_disposables.TryDispose();
11587
_server.Dispose();
11688
}

src/LanguageServer/Impl/Resources.Designer.cs

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/LanguageServer/Impl/Resources.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@
117117
<resheader name="writer">
118118
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119119
</resheader>
120+
<data name="AnalysisProgress_MultipleItemsRemaining" xml:space="preserve">
121+
<value>Analyzing workspace, {0} items remaining...</value>
122+
</data>
123+
<data name="AnalysisProgress_SingleItemRemaining" xml:space="preserve">
124+
<value>Analyzing workspace, 1 item remaining...</value>
125+
</data>
120126
<data name="RenameVariable_CannotRename" xml:space="preserve">
121127
<value>Cannot rename</value>
122128
</data>

src/LanguageServer/Impl/Services/UIService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ public Task LogMessage(string message, MessageType messageType) {
6363
public Task SetStatusBarMessage(string message)
6464
=> _rpc.NotifyWithParameterObjectAsync("window/setStatusBarMessage", message);
6565

66-
public void TraceMessage(IFormattable message) => LogMessage(message.ToString(), MessageType.Info);
66+
public void TraceMessage(string message) => LogMessage(message.ToString(), MessageType.Info);
67+
public void TraceMessage(IFormattable message) => TraceMessage(message.ToString());
6768

6869
public void SetLogLevel(MessageType logLevel) => _logLevel = logLevel;
6970
}

0 commit comments

Comments
 (0)