Skip to content

Commit 7c09ca1

Browse files
dotnet-botdibarbet
andauthored
Merge pull request #57824 from dibarbet/fix_lsp_rps (#57871)
[LSP] Use test accessor task instead of async operation to wait for LSP server shutdown in tests Co-authored-by: David Barbet <dabarbet@microsoft.com>
1 parent 1591d71 commit 7c09ca1

File tree

6 files changed

+24
-21
lines changed

6 files changed

+24
-21
lines changed

src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,7 @@ private static RequestExecutionQueue CreateRequestQueue(TestWorkspace workspace)
404404
var registrationService = workspace.GetService<LspWorkspaceRegistrationService>();
405405
var globalOptions = workspace.GetService<IGlobalOptionService>();
406406
var lspMiscFilesWorkspace = new LspMiscellaneousFilesWorkspace(NoOpLspLogger.Instance);
407-
var listenerProvider = workspace.ExportProvider.GetExportedValue<IAsynchronousOperationListenerProvider>();
408-
return new RequestExecutionQueue(NoOpLspLogger.Instance, registrationService, lspMiscFilesWorkspace, globalOptions, listenerProvider, ProtocolConstants.RoslynLspLanguages, serverName: "Tests", "TestClient");
407+
return new RequestExecutionQueue(NoOpLspLogger.Instance, registrationService, lspMiscFilesWorkspace, globalOptions, ProtocolConstants.RoslynLspLanguages, serverName: "Tests", "TestClient");
409408
}
410409

411410
private static string GetDocumentFilePathFromName(string documentName)

src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ public ImmutableArray<SourceText> GetTrackedTexts()
6161

6262
public bool IsComplete() => _queue._queue.IsCompleted && _queue._queue.IsEmpty;
6363

64+
public async Task WaitForProcessingToStopAsync()
65+
{
66+
await _queue._queueProcessingTask.ConfigureAwait(false);
67+
}
68+
6469
/// <summary>
6570
/// Test only method to validate that remaining items in the queue are cancelled.
6671
/// This directly mutates the queue in an unsafe way, so ensure that all relevant queue operations

src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,16 @@ internal partial class RequestExecutionQueue
6565
private readonly CancellationTokenSource _cancelSource = new CancellationTokenSource();
6666
private readonly RequestTelemetryLogger _requestTelemetryLogger;
6767
private readonly IGlobalOptionService _globalOptions;
68-
private readonly IAsynchronousOperationListener _asynchronousOperationListener;
6968

7069
private readonly ILspLogger _logger;
7170
private readonly LspWorkspaceManager _lspWorkspaceManager;
7271

72+
/// <summary>
73+
/// For test purposes only.
74+
/// A task that completes when the queue processing stops.
75+
/// </summary>
76+
private readonly Task _queueProcessingTask;
77+
7378
public CancellationToken CancellationToken => _cancelSource.Token;
7479

7580
/// <summary>
@@ -87,7 +92,6 @@ public RequestExecutionQueue(
8792
LspWorkspaceRegistrationService lspWorkspaceRegistrationService,
8893
LspMiscellaneousFilesWorkspace? lspMiscellaneousFilesWorkspace,
8994
IGlobalOptionService globalOptions,
90-
IAsynchronousOperationListenerProvider listenerProvider,
9195
ImmutableArray<string> supportedLanguages,
9296
string serverName,
9397
string serverTypeName)
@@ -106,9 +110,7 @@ public RequestExecutionQueue(
106110
_lspWorkspaceManager = new LspWorkspaceManager(logger, lspMiscellaneousFilesWorkspace, lspWorkspaceRegistrationService, _requestTelemetryLogger);
107111

108112
// Start the queue processing
109-
_asynchronousOperationListener = listenerProvider.GetListener(FeatureAttribute.LanguageServer);
110-
var token = _asynchronousOperationListener.BeginAsyncOperation($"{nameof(ProcessQueueAsync)}_{serverTypeName}");
111-
_ = ProcessQueueAsync().CompletesAsyncOperation(token);
113+
_queueProcessingTask = ProcessQueueAsync();
112114
}
113115

114116
/// <summary>

src/Features/LanguageServer/Protocol/LanguageServerTarget.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ internal LanguageServerTarget(
8787
workspaceRegistrationService,
8888
lspMiscellaneousFilesWorkspace,
8989
globalOptions,
90-
listenerProvider,
9190
supportedLanguages,
9291
userVisibleServerName,
9392
TelemetryServerName);

src/Features/LanguageServer/ProtocolUnitTests/LanguageServerTargetTests.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,34 +27,34 @@ public class LanguageServerTargetTests : AbstractLanguageServerProtocolTests
2727
[Fact]
2828
public async Task LanguageServerQueueEmptyOnShutdownMessage()
2929
{
30-
await using var languageServerTarget = CreateLanguageServer(out var jsonRpc, out var listenerProvider);
30+
await using var languageServerTarget = CreateLanguageServer(out var jsonRpc);
3131
AssertServerAlive(languageServerTarget);
3232

3333
await languageServerTarget.ShutdownAsync(CancellationToken.None).ConfigureAwait(false);
34-
await AssertServerQueueClosed(languageServerTarget, listenerProvider).ConfigureAwait(false);
34+
await AssertServerQueueClosed(languageServerTarget).ConfigureAwait(false);
3535
Assert.False(jsonRpc.IsDisposed);
3636
}
3737

3838
[Fact]
3939
public async Task LanguageServerCleansUpOnExitMessage()
4040
{
41-
await using var languageServerTarget = CreateLanguageServer(out var jsonRpc, out var listenerProvider);
41+
await using var languageServerTarget = CreateLanguageServer(out var jsonRpc);
4242
AssertServerAlive(languageServerTarget);
4343

4444
await languageServerTarget.ShutdownAsync(CancellationToken.None).ConfigureAwait(false);
4545
await languageServerTarget.ExitAsync(CancellationToken.None).ConfigureAwait(false);
46-
await AssertServerQueueClosed(languageServerTarget, listenerProvider).ConfigureAwait(false);
46+
await AssertServerQueueClosed(languageServerTarget).ConfigureAwait(false);
4747
Assert.True(jsonRpc.IsDisposed);
4848
}
4949

5050
[Fact]
5151
public async Task LanguageServerCleansUpOnUnexpectedJsonRpcDisconnectAsync()
5252
{
53-
await using var languageServerTarget = CreateLanguageServer(out var jsonRpc, out var listenerProvider);
53+
await using var languageServerTarget = CreateLanguageServer(out var jsonRpc);
5454
AssertServerAlive(languageServerTarget);
5555

5656
jsonRpc.Dispose();
57-
await AssertServerQueueClosed(languageServerTarget, listenerProvider).ConfigureAwait(false);
57+
await AssertServerQueueClosed(languageServerTarget).ConfigureAwait(false);
5858
Assert.True(jsonRpc.IsDisposed);
5959
}
6060

@@ -64,14 +64,14 @@ private static void AssertServerAlive(LanguageServerTarget server)
6464
Assert.False(server.GetTestAccessor().GetQueueAccessor().IsComplete());
6565
}
6666

67-
private static async Task AssertServerQueueClosed(LanguageServerTarget server, IAsynchronousOperationListenerProvider listenerProvider)
67+
private static async Task AssertServerQueueClosed(LanguageServerTarget server)
6868
{
69-
await listenerProvider.GetWaiter(FeatureAttribute.LanguageServer).ExpeditedWaitAsync();
69+
await server.GetTestAccessor().GetQueueAccessor().WaitForProcessingToStopAsync().ConfigureAwait(false);
7070
Assert.True(server.HasShutdownStarted);
7171
Assert.True(server.GetTestAccessor().GetQueueAccessor().IsComplete());
7272
}
7373

74-
private LanguageServerTarget CreateLanguageServer(out JsonRpc serverJsonRpc, out IAsynchronousOperationListenerProvider listenerProvider)
74+
private LanguageServerTarget CreateLanguageServer(out JsonRpc serverJsonRpc)
7575
{
7676
using var workspace = TestWorkspace.CreateCSharp("", composition: Composition);
7777

@@ -80,7 +80,7 @@ private LanguageServerTarget CreateLanguageServer(out JsonRpc serverJsonRpc, out
8080
var lspWorkspaceRegistrationService = workspace.GetService<LspWorkspaceRegistrationService>();
8181
var capabilitiesProvider = workspace.GetService<DefaultCapabilitiesProvider>();
8282
var globalOptions = workspace.GetService<IGlobalOptionService>();
83-
listenerProvider = workspace.GetService<IAsynchronousOperationListenerProvider>();
83+
var listenerProvider = workspace.GetService<IAsynchronousOperationListenerProvider>();
8484

8585
serverJsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(serverStream, serverStream))
8686
{

src/Features/LanguageServer/ProtocolUnitTests/Ordering/RequestOrderingTests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,7 @@ public async Task FailingMutableTaskShutsDownQueue()
173173

174174
// The failed request returns to the client before the shutdown completes.
175175
// Wait for the queue to finish handling the failed request and shutdown.
176-
var operations = testLspServer.TestWorkspace.ExportProvider.GetExportedValue<AsynchronousOperationListenerProvider>();
177-
var waiter = operations.GetWaiter(FeatureAttribute.LanguageServer);
178-
await waiter.ExpeditedWaitAsync();
176+
await testLspServer.GetQueueAccessor().WaitForProcessingToStopAsync().ConfigureAwait(false);
179177

180178
// remaining tasks should be canceled
181179
var areAllItemsCancelled = await testLspServer.GetQueueAccessor().AreAllItemsCancelledUnsafeAsync();

0 commit comments

Comments
 (0)