Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure we always get up to date diagnostics when getting pull diagnostics. #49256

Merged
13 commits merged into from
Nov 12, 2020

Conversation

CyrusNajmabadi
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi commented Nov 10, 2020

This splits our LSP diagnostics into two effective 'worlds'. A client can get diagnostics for open documents (specifically, documents they sent 'didOpen' for, and for closed diagnostics (aka. Workspace-Diagnostics). For open diagnostics we always grab the diagnostics for the current contents of hte file, ensuring that we never have to worry about syncing mismatches, albeit with the cost of computing the diagnostics right htere, and not with the rest of the diagnostics subsystem.

For Workspce-Diagnostics, we still defer to the normal diagnostics subsystem, meaning we can get stale data. This is ok though as that's for closed files and in general we don't need the diagnostics to strictly be up to date, as long as they eventually get up to date.

@CyrusNajmabadi CyrusNajmabadi changed the title Experiment with getting live diagnostics Ensure we always get up to date diagnostics when getting pull diagnostics. Nov 11, 2020
@CyrusNajmabadi CyrusNajmabadi marked this pull request as ready for review November 11, 2020 23:01
@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner November 11, 2020 23:01
// prioritize the files from currently active projects, but then also include all other docs in all projects
// (depending on current FSA settings).

// Oen docs will not be included as those are handled by DocumentPullDiagnosticHandler.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Oen docs will not be included as those are handled by DocumentPullDiagnosticHandler.
// Open docs will not be included as those are handled by DocumentPullDiagnosticHandler.

// For closed files, go to the IDiagnosticService for results. These won't necessarily be totally up to
// date. However, that's fine as these are closed files and won't be in the process of being edited. So
// any deviations in the spans of diagnostics shouldn't be impactful for the user.
var diagnostics = this.DiagnosticService.GetPullDiagnostics(document, includeSuppressedDiagnostics: false, diagnosticMode, cancellationToken);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this split actually makes a fair amount of sense to me then. Workspace diagnostics use whatever is in the workspace (which the server owns as these are closed files) whereas files with content managed via LSP (open) force a calculation based on the client's known content.

The only issue I can see is if the content in the open file changes the workspace diagnostics (e.g. delete a method in an open file that's used elsewhere). I guess in that case the experience would that the error list could show stale errors until the next workspace/diagnostic message comes in that acts on the new workspace content.

But squiggles are always fine as they act on open documents (and therefore LSP content)

@@ -47,29 +47,28 @@ public abstract class AbstractLanguageServerProtocolTests
internal class TestLspSolutionProvider : ILspSolutionProvider
{
[DisallowNull]
private Solution? _currentSolution;
private TestWorkspace? _workspace;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for fixing this!

Document document, Option2<DiagnosticMode> diagnosticMode, CancellationToken cancellationToken)
{
// We only support doc diagnostics for open files.
if (!document.IsOpen())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this is using the workspace notion of a document being opened, which is currently tied to the textbuffer being opened via VS. It is currently true that document textbuffers are opened on the server via VS, but may not be forever (and may not be exactly sync'd with LSP open events similarly to didChange).

Perhaps instead for the LSP handlers, we should check if we've received a didOpen event for the document (basically if it's a member of this - https://github.com/dotnet/roslyn/blob/master/src/Features/LanguageServer/Protocol/Handler/RequestExecutionQueue.DocumentChangeTracker.cs#L24 ). Same in the workspace handler

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup. i've changed this now.

// we're passing in. If information is already cached for that snapshot, it will be returned. Otherwise,
// it will be computed on demand. Because it is always accurate as per this snapshot, all spans are correct
// and do not need to be adjusted.
return _analyzerService.GetDiagnosticsAsync(document.Project.Solution, documentId: document.Id, cancellationToken: cancellationToken);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will re-calculate every time until we fix the fork on every request behavior right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes.

@@ -4,6 +4,7 @@

#nullable disable

using System;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed? Looks like there aren't other changes in this file

Copy link
Contributor

@davidwengier davidwengier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me. Am I right in guessing that the don't-fork-on-every-request doesn't require any changes here, it just makes it faster/more efficient?

Document document, Option2<DiagnosticMode> diagnosticMode, CancellationToken cancellationToken)
{
// We only support doc diagnostics for open files.
if (!document.IsOpen())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to work for Razor? Does the LSP didOpen handler need to do something to tell the workspace the document is open (as part of the server per workspace changes, not this PR)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i've switched this to be based on LSP semantics now.

{
var result = new Dictionary<Document, DiagnosticParams>();
foreach (var diagnosticParams in previousResults)
{
if (diagnosticParams.TextDocument != null)
{
var document = _solutionProvider.GetDocument(diagnosticParams.TextDocument);
var document = context.Solution.GetDocument(diagnosticParams.TextDocument);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best change ever <3

@CyrusNajmabadi
Copy link
Member Author

This makes sense to me. Am I right in guessing that the don't-fork-on-every-request doesn't require any changes here, it just makes it faster/more efficient?

Yup.

@ghost
Copy link

ghost commented Nov 12, 2020

Hello @CyrusNajmabadi!

Because this pull request has the auto-merge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-approval

@ghost ghost merged commit a351a14 into dotnet:master Nov 12, 2020
@ghost ghost added this to the Next milestone Nov 12, 2020
@CyrusNajmabadi CyrusNajmabadi deleted the liveDiag branch November 12, 2020 16:53
@allisonchou allisonchou modified the milestones: Next, 16.9.P2 Nov 24, 2020
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants