diff --git a/src/Features/LanguageServer/Protocol/Handler/IRequestHandlerMetadata.cs b/src/Features/LanguageServer/Protocol/Handler/IRequestHandlerMetadata.cs
index 69616711d942ffe9e4b76d0cd59b8916bbda6ca5..1b7c3fab7b3fc1ce21e5aa3ee78b99a942c4cf63 100644
--- a/src/Features/LanguageServer/Protocol/Handler/IRequestHandlerMetadata.cs
+++ b/src/Features/LanguageServer/Protocol/Handler/IRequestHandlerMetadata.cs
@@ -19,7 +19,9 @@ internal interface IRequestHandlerMetadata
string? LanguageName { get; }
///
- /// Whether or not handling this method results in changes to the current solution state
+ /// Whether or not handling this method results in changes to the current solution state.
+ /// Mutating requests will block subsequent requests from starting until after they have
+ /// completed and mutations have been applied. See .
///
bool MutatesSolutionState { get; }
}
diff --git a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs
index de5810dddb8cd37f20b2a0c9c7ef7eed4219acd2..5f9fc99131c54925fc274c119c3e79c10949b81e 100644
--- a/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs
+++ b/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.cs
@@ -33,7 +33,7 @@ public RequestExecutionQueue(ILspSolutionProvider solutionProvider)
}
///
- /// Queues a request to be handled by the specified handler, with mutating requests blocking future requests
+ /// Queues a request to be handled by the specified handler, with mutating requests blocking subsequent requests
/// from starting until the mutation is complete.
///
/// Whether or not the specified request needs to mutate the solution.
@@ -56,6 +56,9 @@ public RequestExecutionQueue(ILspSolutionProvider solutionProvider)
if (cancellationToken.IsCancellationRequested)
{
completion.SetCanceled();
+
+ // Tell the queue to ignore any mutations from this request, not that we've given it a chance
+ // to make any
return false;
}
@@ -63,6 +66,7 @@ public RequestExecutionQueue(ILspSolutionProvider solutionProvider)
{
var result = await handler.HandleRequestAsync(request, context, cancellationToken).ConfigureAwait(false);
completion.SetResult(result);
+ // Tell the queue that this was successful so that mutations (if any) can be applied
return true;
}
catch (OperationCanceledException)
@@ -72,9 +76,11 @@ public RequestExecutionQueue(ILspSolutionProvider solutionProvider)
catch (Exception exception)
{
// Pass the exception to the task completion source, so the caller of the ExecuteAsync method can observe but
- // don't let it escape from this callback, so it doens't affect the queue processing.
+ // don't let it escape from this callback, so it doesn't affect the queue processing.
completion.SetException(exception);
}
+
+ // Tell the queue to ignore any mutations from this request
return false;
});
_queue.Enqueue(item);
@@ -88,6 +94,8 @@ private async Task ProcessQueueAsync()
{
var work = await _queue.DequeueAsync().ConfigureAwait(false);
+ // The "current" solution can be updated by non-LSP actions, so we need it, but we also need
+ // to merge in the changes from any mutations that have been applied to open documents
var solution = GetCurrentSolution();
solution = MergeChanges(solution, _lastMutatedSolution);