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

Rename API handles refactor notify #41126

Closed
wants to merge 12 commits into from

Conversation

ryzngard
Copy link
Contributor

@ryzngard ryzngard commented Jan 21, 2020

This change makes it so that the rename API we surface pubilicly marks symbol definitions with an annotation.

An editor workspace implementation can use those annotations as hints to what has been refactored, and handle these changes if needed. For the case of VS, that includes calling IVsRefactorNotify on TryApplyChanges

This allows IVsRefactorNotify to be handled automatically when calling
Solution.TryApplyChanges
@ryzngard ryzngard force-pushed the rename_does_refactor_notify branch from 4abad93 to 17c380e Compare January 23, 2020 00:36
@ryzngard ryzngard marked this pull request as ready for review January 28, 2020 18:52
@ryzngard ryzngard requested a review from a team as a code owner January 28, 2020 18:52
@jasonmalinowski jasonmalinowski changed the base branch from master to release/dev16.6-preview1 January 31, 2020 21:08
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.

Overall the direction here looks great. A few general thoughts:

  1. It'd be nice if the various code action tests just tested the existence of the annotation, and we had a single test that tested that the Workspace does the right thing when it encouters it; this keeps all the individual features from having to set up the refactor notify stuff directly.
  2. We may need to refactor the stuff into TryApplyChanges better -- right now there's duplicate code between TestWorkspace and VisualStudioWorkspace. It also looks like there's a bug in the VisualStudioWorkspace variant that might prevent it from working, so that's worrisome -- the unit tests may pass but it'll fail in the actual product.
  3. We might be able to clean up more in Rename tracking too -- that also is directly invoking IRefactorNotify which might now be unnecessary. It actually might mean we're firing the events twice now.
  4. Ditto for ContainedLanguageCodeSupport.cs which isn't here: that's also firing events directly. At this point with this PR I'd guess you can just search on IRefactorNotifySymbol and only see the workspace stuff directly interacting with it -- anybody else still firing it manually is probably a duplicate invocation.

@@ -1217,17 +1231,42 @@ public async Task TestRefactorNotify()
var testParameters = new TestParameters(options: options.ClassNamesArePascalCase);

using var workspace = CreateWorkspaceFromOptions(markup, testParameters);

var refactorNotify = workspace.GetService<IRefactorNotifyService>() as TestRefactorNotify;
Copy link
Member

Choose a reason for hiding this comment

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

At this point, is there some way to make these tests not have to grovel with IRefactorNotifyService and just have a helper that asserts the rename annotation was added? And have a standalone test that does all the refactor notify stuff directly?

@@ -21,7 +22,7 @@ public class MoveToNamespaceTests : AbstractMoveToNamespaceTests
{
private static readonly IExportProviderFactory ExportProviderFactory =
ExportProviderCache.GetOrCreateExportProviderFactory(
TestExportProvider.EntireAssemblyCatalogWithCSharpAndVisualBasic.WithPart(typeof(TestMoveToNamespaceOptionsService)));
TestExportProvider.EntireAssemblyCatalogWithCSharpAndVisualBasic.WithPart(typeof(TestMoveToNamespaceOptionsService)).WithPart(typeof(TestRefactorNotify)));
Copy link
Member

Choose a reason for hiding this comment

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

Why? What happens if it's not there?

var currentSemanticModel = await oldDocument.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

var oldSymbol = ResolveSymbol(annotation, currentSemanticModel.Compilation);
var newSymbol = newSemanticModel.GetDeclaredSymbol(node);
Copy link
Member

Choose a reason for hiding this comment

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

GetDeclaredSymbol could return null, why did it let you pass that to changedSymbols.Add?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It can, but shouldn't in this case right? Assuming we're always annotating something that declares a symbol (which is the useful point of this). Maybe just add a contract throw?

Copy link
Member

Choose a reason for hiding this comment

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

I'm more worried why the compiler didn't yell at you. Is this a bug in nullable somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm... the extension method is annotated as return a non-null value. Potentially by design but not desired...

SemanticModel.GetDeclaredSymbolForNode might be annotated wrong?

@jasonmalinowski
Copy link
Member

Tagging @dpoeschl to also look at this, since he has background in both rename tracking and IRefactorNotifyService; there might be some other nice cleanups that happen too. I could also imagine things breaking too: if the rename tracking is now running through the common code, that might also trigger the dismissal of the session in some way that might interact poorly.

@ryzngard
Copy link
Contributor Author

ryzngard commented Feb 6, 2020

It'd be nice if the various code action tests just tested the existence of the annotation, and we had a single test that tested that the Workspace does the right thing when it encouters it; this keeps all the individual features from having to set up the refactor notify stuff directly.

Agreed. I'll work on a test helper for this. I think having a mock refactornotify test is worthwhile still, but more general use would be to check annotation.

We may need to refactor the stuff into TryApplyChanges better -- right now there's duplicate code between TestWorkspace and VisualStudioWorkspace. It also looks like there's a bug in the VisualStudioWorkspace variant that might prevent it from working, so that's worrisome -- the unit tests may pass but it'll fail in the actual product.

hmm... maybe good chance to add more integration tests?

We might be able to clean up more in Rename tracking too -- that also is directly invoking IRefactorNotify which might now be unnecessary. It actually might mean we're firing the events twice now.

Same as above :)

Ditto for ContainedLanguageCodeSupport.cs which isn't here: that's also firing events directly. At this point with this PR I'd guess you can just search on IRefactorNotifySymbol and only see the workspace stuff directly interacting with it -- anybody else still firing it manually is probably a duplicate invocation.

I'll dig into these implementations. Having multiple IRefactorNotifySymbol is not necessarily bad, but they shouldn't all be calling into the VS layer. We should have 1 per endpoint that needs to be called.

@ryzngard ryzngard requested review from a team as code owners February 6, 2020 20:35
@ryzngard ryzngard requested a review from a team as a code owner February 6, 2020 20:36
@ryzngard ryzngard changed the base branch from release/dev16.6-preview1 to master February 6, 2020 20:37
@CyrusNajmabadi
Copy link
Member

@ryzngard What would you like to do with this PR?

@ryzngard ryzngard closed this Sep 9, 2020
@ryzngard ryzngard deleted the rename_does_refactor_notify branch September 9, 2020 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants