-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
Version Used:
Microsoft Visual Studio Professional
Version 17.14.16
Version 17.14.16 Preview 1.0
Version: 18.0.0 Insiders [11104.47]
Steps to Reproduce:
- Subscribe to WorkspaceChanged event either directly or via
RegisterWorkspaceChangedHandler
- Call
Microsoft.CodeAnalysis.Project.GetSourceGeneratedDocumentsAsync
on projects fromWorksspace.CurrentSolution
in response to some workspace events likeSolutionChanged
Expected Behavior:
You can safely request source generated files via the public Roslyn API
Actual Behavior:
Sometimes, calling Project.GetSourceGeneratedDocumentsAsync
causes Roslyn to cache an outdated version of source generators until some future event like solution build forces an updated.
All subsequent calls to Project.GetSourceGeneratedDocumentsAsync
return outdated version.
This affect VS's own code analysis as it will see outdated source generated documents, e.g. after navigating to a file that uses them
Notes:
I did some investigation and it looks like the following race happens inside Roslyn:
- There are 2 concurrent activities in Roslyn:
Workspace.EnqueueUpdateSourceGeneratorVersion
in response to finishing a buildProjectSystemProjectFactory.StartRefreshingAnalyzerReferenceForFileAsync
in response to a file system event about changed analyzer reference assembly
- During build,
Workspace.EnqueueUpdateSourceGeneratorVersion
tirggers first and updates source generators' version for the solution. - Here, if you call
Project.GetSourceGeneratedDocumentsAsync
Roslyn will use the old version of the generator but will cache it with the updatedSourceGeneratorExecutionVersion
since it was already incremented by the previous step - Afterwards, a file system watcher event triggers
ProjectSystemProjectFactory.StartRefreshingAnalyzerReferenceForFileAsync
which reloads the generator without incrementingSourceGeneratorExecutionVersion
- All future requests to
Project.GetSourceGeneratedDocumentsAsync
will return the cached outdated version of source generated documents
It looks impossible to tell when it's safe to call Project.GetSourceGeneratedDocumentsAsync
because
there's no guarantee when an async refresh of an analyzer reference file will happen and whether it will happen at all after some workspace change
It's also not possible to determine that such a reload happened. It sends a ProjectChanged
workspace change event, but checking changes between old and new solution returns empty diff as the project just removes and adds the same analyzer reference in a single modification.