Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
dibarbet committed Feb 14, 2023
1 parent 06a52ac commit 3a80693
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,19 @@ protected abstract ValueTask<ImmutableArray<IDiagnosticSource>> GetOrderedDiagno

protected abstract string? GetDiagnosticCategory(TDiagnosticsParams diagnosticsParams);

/// <summary>
/// Used by public workspace pull diagnostics to allow it to keep the connection open until
/// changes occur to avoid the client spamming the server with requests.
///
/// TODO - must be called at the end before closing the connection otherwise we'll have a stale request context.
///
/// </summary>
/// <returns></returns>
protected virtual Task WaitForChangesAsync()
{
return Task.CompletedTask;
}

public async Task<TReturn?> HandleRequestAsync(
TDiagnosticsParams diagnosticsParams, RequestContext context, CancellationToken cancellationToken)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,9 @@ public PublicWorkspacePullDiagnosticHandlerFactory(
}

public ILspService CreateILspService(LspServices lspServices, WellKnownLspServerKinds serverKind)
=> new PublicWorkspacePullDiagnosticsHandler(_analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions);
{
var workspaceManager = lspServices.GetRequiredService<LspWorkspaceManager>();
var workspaceRegistration = lspServices.GetRequiredService<LspWorkspaceRegistrationService>();
return new PublicWorkspacePullDiagnosticsHandler(workspaceManager, workspaceRegistration, _analyzerService, _editAndContinueDiagnosticUpdateSource, _globalOptions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.CodeAnalysis.EditAndContinue;
using Microsoft.CodeAnalysis.Options;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Public;

Expand All @@ -23,12 +24,37 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler.Diagnostics.Public;
[Method(Methods.WorkspaceDiagnosticName)]
internal class PublicWorkspacePullDiagnosticsHandler : AbstractPullDiagnosticHandler<WorkspaceDiagnosticParams, WorkspaceDiagnosticPartialReport, WorkspaceDiagnosticReport?>
{
private readonly LspWorkspaceRegistrationService _workspaceRegistrationService;
private readonly LspWorkspaceManager _workspaceManager;

/// <summary>
/// Lock guarding <see cref="_lspChanged"/>
/// This is concurrently accessed by workspace diagnostics requests and LSP solution change events.
/// </summary>
private readonly object _lspChangedLock = new();

/// <summary>
/// Updated by LSP change events to signal to this handler that the LSP view of the world
/// has changed in some way. It is totally fine for this to somewhat over-report changes
/// as it is an optimization used to delay workspace diagnostic requests.
/// </summary>
private bool _lspChanged;


public PublicWorkspacePullDiagnosticsHandler(
LspWorkspaceManager workspaceManager,
LspWorkspaceRegistrationService registrationService,
IDiagnosticAnalyzerService analyzerService,
EditAndContinueDiagnosticUpdateSource editAndContinueDiagnosticUpdateSource,
IGlobalOptionService globalOptions)
: base(analyzerService, editAndContinueDiagnosticUpdateSource, globalOptions)
{
_workspaceRegistrationService = registrationService;
_workspaceRegistrationService.LspSolutionChanged += OnLspSolutionChanged;

_workspaceManager = workspaceManager;
_workspaceManager.LspTextChanged += OnLspTextChanged;

}

/// <summary>
Expand Down Expand Up @@ -118,4 +144,41 @@ protected override ValueTask<ImmutableArray<IDiagnosticSource>> GetOrderedDiagno
}
}).ToImmutableArray();
}

private void OnLspSolutionChanged(object? sender, WorkspaceChangeEventArgs e)
{
UpdateLspChanged();
}

private void OnLspTextChanged(object? sender, EventArgs e)
{
UpdateLspChanged();
}

private void UpdateLspChanged()
{
lock (_lspChangedLock)
{
_lspChanged = true;
}
}

protected override async Task WaitForChangesAsync()
{
lock (_lspChangedLock)
{
if (_lspChanged)
{
// We've hit a change, so we close the current request.
// The client will automatically trigger a new request as soon as we close it, bringing us up to date on diagnostics changes that have happened or might happen after.
// Only if there are no changes between now and the next request completing, we will hold the connection open while we poll for changes.
_lspChanged = false;
return;
}
}

// Delay 100ms and check again for changes.
await Task.Delay(TimeSpan.FromMilliseconds(100))
.ContinueWith(async (_) => await WaitForChangesAsync().ConfigureAwait(false), TaskScheduler.Default).ConfigureAwait(false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ public LspWorkspaceManager(
_lspWorkspaceRegistrationService = lspWorkspaceRegistrationService;
}

public EventHandler<EventArgs>? LspTextChanged;

#region Implementation of IDocumentChangeTracker

/// <summary>
Expand All @@ -102,6 +104,8 @@ public void StartTracking(Uri uri, SourceText documentText)

// If LSP changed, we need to compare against the workspace again to get the updated solution.
_cachedLspSolutions.Clear();

LspTextChanged?.Invoke(this, EventArgs.Empty);
}

/// <summary>
Expand All @@ -120,6 +124,8 @@ public void StopTracking(Uri uri)

// Also remove it from our loose files workspace if it is still there.
_lspMiscellaneousFilesWorkspace.TryRemoveMiscellaneousDocument(uri);

LspTextChanged?.Invoke(this, EventArgs.Empty);
}

/// <summary>
Expand All @@ -135,6 +141,8 @@ public void UpdateTrackedDocument(Uri uri, SourceText newSourceText)

// If LSP changed, we need to compare against the workspace again to get the updated solution.
_cachedLspSolutions.Clear();

LspTextChanged?.Invoke(this, EventArgs.Empty);
}

public ImmutableDictionary<Uri, SourceText> GetTrackedLspText() => _trackedDocuments;
Expand Down

0 comments on commit 3a80693

Please sign in to comment.