Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@dibarbet
Copy link
Member

@dibarbet dibarbet commented Oct 1, 2025

Resolves https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2576168

When the diagnostics handler was looking up documentIds to compare the previous results, it uses GetTextDocumentAsync on the LSP text doc identifier. However, in document pull, the diagnostics originally get computed against the requestContext.Document, as determined by the LspWorkspaceManager.

Generally this is not an issue, the lookup from document URI -> document is intended to be stable, regardless of if a project context is provided or not.

However this was broken with file based programs. Consider the following sequence:

  1. VSCode is opened with a file open that looks like a file based program, but is actually part of a solution.
  2. Before the solution loads, Roslyn sees the file and loads it as an FBP. This creates a project in the host workspace for the FBP.
  3. Eventually the solution loads and adds the file to a real project in the solution. At this point in time both the FBP file and the regular file exist in the host solution.
  4. The LspWorkspaceManager attempts to preferentially return the main solution file.
  5. The document pull handler compares the DocumentId from requestContext.Document and requestContext.Solution.GetTextDocumentAsync. Because of 4), these are now different and the handler attempts to report diagnostics for the document and the document as being removed in the same call.

The fix I made here is to remove the document from the misc provider, and re-lookup the document. This ensures the misc document is not part of the solution that is given to the handler. The queue was already blocked on removing the file from misc anyway, so we might as well read that result.

@dibarbet dibarbet changed the title Add test demonstrating issue with document context in FBP Fix LSP GetTextDocumentAsync returning different document from request context Oct 1, 2025
@dibarbet
Copy link
Member Author

dibarbet commented Oct 1, 2025

@jasonmalinowski @RikkiGibson ptal

@RikkiGibson RikkiGibson self-assigned this Oct 1, 2025
@dibarbet dibarbet marked this pull request as ready for review October 2, 2025 20:32
@dibarbet dibarbet requested a review from a team as a code owner October 2, 2025 20:32
@jasonmalinowski jasonmalinowski self-requested a review October 7, 2025 20:21
@dibarbet dibarbet changed the title Fix LSP GetTextDocumentAsync returning different document from request context Ensure LspWorkspaceManager returns solutions without misc document when file moved Oct 9, 2025
Comment on lines 91 to 95
// The first call should return a document in the misc files workspace.
var (_, miscDocument) = await GetLspWorkspaceAndDocumentAsync(newDocumentUri, testLspServer).ConfigureAwait(false);
Assert.NotNull(miscDocument);
Assert.True(await testLspServer.GetManagerAccessor().IsMiscellaneousFilesDocumentAsync(miscDocument));
Assert.Equal(WorkspaceKind.MiscellaneousFiles, miscDocument.Project.Solution.Workspace.Kind);
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 technically a race if the project system were to load it first? It seems terribly unlikely, but still.

Copy link
Member Author

Choose a reason for hiding this comment

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

Not currently, no. This is what happens

  1. Nothing happens when the document is opened, the text is just saved.
  2. GetLspWorkspaceAndDocumentAsync searches the workspaces, doesn't find the doc and then calls into the misc provider AddMiscellaneousDocumentAsync.
  3. FBP misc provider creates the 'primordial' document in the misc workspace and triggers the load of the FBP program (adds to the batch).
  4. FBP misc provider always returns the primordial document.

So even if the FBP project load completed instantly, the FBP misc provider still just returns the primordial document from AddMiscellaneousDocumentAsync.

Copy link
Member

Choose a reason for hiding this comment

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

Ah right! Makes sense...does that deserve a comment?

Copy link
Member

@jasonmalinowski jasonmalinowski left a comment

Choose a reason for hiding this comment

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

Code change is great; not sure if the test can be unified with another one in the base or moved down to the base, but that's not critical.

}

[Theory, CombinatorialData]
public async Task TestLspTransfersFromFileBasedProgramToHostWorkspaceDocumentOrderingAsync(bool mutatingLspWorkspace)
Copy link
Member

Choose a reason for hiding this comment

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

It's not entirely clear to me how this test is much different than TestLspTransfersFromMiscellaneousFilesToHostWorkspaceAsync test already in the base. I'd expect we should be able to push it to the base class anyways.

Comment on lines 91 to 95
// The first call should return a document in the misc files workspace.
var (_, miscDocument) = await GetLspWorkspaceAndDocumentAsync(newDocumentUri, testLspServer).ConfigureAwait(false);
Assert.NotNull(miscDocument);
Assert.True(await testLspServer.GetManagerAccessor().IsMiscellaneousFilesDocumentAsync(miscDocument));
Assert.Equal(WorkspaceKind.MiscellaneousFiles, miscDocument.Project.Solution.Workspace.Kind);
Copy link
Member

Choose a reason for hiding this comment

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

Ah right! Makes sense...does that deserve a comment?

@dibarbet dibarbet enabled auto-merge (squash) October 14, 2025 17:57
@dibarbet dibarbet merged commit 225ca71 into dotnet:main Oct 14, 2025
24 of 25 checks passed
@dibarbet dibarbet deleted the fbp_issue branch October 14, 2025 18:16
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.

4 participants