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

Decouple FixAll from the workspace #1962

Merged
merged 11 commits into from
Oct 8, 2020

Conversation

333fred
Copy link
Contributor

@333fred 333fred commented Sep 28, 2020

Today, the RunFixAllInCodeActionService is tightly coupled to the current workspace, applying its changes to the workspace as it processes the request and counting on the updates from doing so to invalidate diagnostic caches. While this does work, it's has 2 major downsides:

  1. It's a race condition waiting to happen, where the propagation of the changed documents invalidating the diagnostic provider's caches races with the next fix all operation attempting to get the diagnostics it needs to fix.
  2. It has bad interations with the buffer updater from clients. The service returns the needed changes to clients, who then apply the changes. The client will then see that changes have been applied, and send them back to the server. The server's workspace has already been updated with these changes, so it ends up double applying the changes, leaving the server's workspace in a bad state with garbage in many files.

This commit breaks the dependency of the FixAll service on the current workspace. We now have the fixes occur on top of the previous fix's changed solution. At the end, if the client requested the changes be applied on the workspace side, then we apply the changes to the workspace at that point. In order for this work, I had to modify the diagnostic workers a bit to add an option to force a document to be analyzed, skipping the cache entirely. This is necessary because the cache is only invalidated on document add/remove/change in the workspace itself. The documents we work on linearly in the fix all provider do not get added/changed/removed in the workspace, so we need to analyze them again, right then and there. To support this, the AnalyzerWorkQueue is now based on documents, not document ids, though the caches in the workers are still based on ids.

In the process of doing this PR, I also fixed #1960.

@333fred 333fred mentioned this pull request Sep 28, 2020
Today, the RunFixAllInCodeActionService is tightly coupled to the current workspace, applying its changes to the workspace as it processes the request and counting on the updates from doing so to invalidate diagnostic caches. While this does work, it's has 2 major downsides:

1. It's a race condition waiting to happen, where the propagation of the changed documents invalidating the diagnostic provider's caches races with the next fix all operation attempting to get the diagnostics it needs to fix.
2. It has bad interations with the buffer updater from clients. The service returns the needed changes to clients, who then apply the changes. The client will then see that changes have been applied, and send them back to the server. The server's workspace has already been updated with these changes, so it ends up double applying the changes, leaving the server's workspace in a bad state with garbage in many files.

This commit breaks the dependency of the FixAll service on the current workspace. We now have the fixes occur on top of the previous fix's changed solution. At the end, if the client requested the changes be applied on the workspace side, then we apply the changes to the workspace at that point. In order for this work, I had to modify the diagnostic workers a bit to add an option to force a document to be analyzed, skipping the cache entirely. This is necessary because the cache is only invalidated on document add/remove/change in the workspace itself. The documents we work on linearly in the fix all provider do not get added/changed/removed in the workspace, so we need to analyze them again, right then and there. To support this, the AnalyzerWorkQueue is now based on documents, not document ids, though the caches in the workers are still based on ids.
333fred added a commit to 333fred/vscode-csharp that referenced this pull request Sep 28, 2020
@333fred
Copy link
Contributor Author

333fred commented Sep 29, 2020

@filipw I'm not sure if any of these test failures could be related to this change. Can you advise?

@filipw
Copy link
Member

filipw commented Sep 29, 2020

no, all three separate failures are "known" to be flaky already... let's see the retry

…n DocumentId->Diagnostics. This is done via a ConditionalWeakTable to ensure we don't root Documents and prevent garbage collection.
@333fred
Copy link
Contributor Author

333fred commented Oct 3, 2020

@david-driscoll I believe I've addressed your feedback.

Copy link
Member

@filipw filipw left a comment

Choose a reason for hiding this comment

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

:shipit:

@JoeRobich
Copy link
Member

@david-driscoll Would you like to give this PR your blessing? =)

Copy link
Member

@david-driscoll david-driscoll left a comment

Choose a reason for hiding this comment

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

:shipit:

@david-driscoll david-driscoll merged commit da4c92f into OmniSharp:master Oct 8, 2020
@333fred 333fred deleted the decouple-fixall branch October 8, 2020 23:52
JoeRobich pushed a commit to dotnet/vscode-csharp that referenced this pull request Oct 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix All always does the entire project, regardless of input
4 participants