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

Argument completion tweaks #51655

Conversation

jasonmalinowski
Copy link
Member

@jasonmalinowski jasonmalinowski commented Mar 4, 2021

This does several refactorings for argument completion:

  1. Rather than using snippet function providers, just embed the computed values into the snippet XML directly. This avoids having to have an argument provider "reach back" into the snippet state in the first place.
  2. Because of that prior simplification, remove the "preserve symbols" state management which was required to preserve state during the dismissal of a prior session and the start of a next one.

This doesn't fix one general issue about the experience right now, which is model changes that come from typing rather than up/down arrow cause a new snippet to apply, potentially with problematic effects. I did make two small tweaks though to generally mitigate the impact:

  1. Switch to using SymbolEquivalenceComparer when checking if the method we're applying is the same as the one already applied. Otherwise if we apply a snippet, signature help will update the model to select the same overload. If the symbols were from source (rather than metadata) this would result in an infinite loop of applications.
  2. If you start typing in an empty signature, copy what you've typed into the first parameter of the new method. Otherwise you start typing, a new overload is chosen, and then your typing is immediately overwritten.

Copy link
Member

@sharwell sharwell left a comment

Choose a reason for hiding this comment

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

Mainly waiting for updated integration tests

Comment on lines +139 to +138
// doing so will disrupt signature help.
if (_state.IsFullMethodCallSnippet)
Copy link
Member

Choose a reason for hiding this comment

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

❔ Was this changed as part of the wrong commit?

Copy link
Member

Choose a reason for hiding this comment

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

➡️ Yes, there were a few small cases of this

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 think I did screw up the commit rebasing at one point.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, for this one, it's intentionally part of the null annotation commit: the comment stated that we had to check _methods because _expansionSession isn't initialized, but the explicit null check being added means the comment is now stale. The null check was added because the null annotation revealed that if it was null, we'd end up throwing at line 177.

@@ -802,6 +802,17 @@ public void MoveToSpecificMethod(IMethodSymbol method, CancellationToken cancell

if (_state._method is not null)
{
// If we didn't have any previous parameters, then there is only the placeholder in the snippet.
// We'll use that as text of the first argument; failing to do so means starting to type in the placeholder
// will be overwritten once the signature help changes it's overload due to your typing.
Copy link
Member

Choose a reason for hiding this comment

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

💡 It should be possible to add an integration test for this by typing the following without waiting

  • ToString, Tab, Tab, 0

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 actually have to fix this, because this needs to be conditioned on either the method being not null or also there not being a method at all which is if you hit tab before signature help even caught up.

Copy link
Member

Choose a reason for hiding this comment

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

or also there not being a method at all which is if you hit tab before signature help even caught up

Signature help is only triggered by the second Tab key, so for the example here only 0 could be typed between this feature getting invoked and signature help appearing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, that's what I meant. Code is still broken though.

Copy link
Member Author

Choose a reason for hiding this comment

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

So I fixed up the code a bit better, but until we fix or address typing causing model changes, it's hard to really get a sense of what's necessary here. I'd say we fix that, and then sort out a good test for this.

@jasonmalinowski jasonmalinowski self-assigned this Mar 4, 2021
@jasonmalinowski jasonmalinowski force-pushed the argument-completion-tweaks branch 4 times, most recently from 353818e to 3cf764e Compare March 11, 2021 01:04
@jasonmalinowski jasonmalinowski marked this pull request as ready for review March 11, 2021 01:40
@jasonmalinowski jasonmalinowski requested a review from a team as a code owner March 11, 2021 01:40
@jasonmalinowski jasonmalinowski marked this pull request as draft March 11, 2021 01:40
@jasonmalinowski jasonmalinowski marked this pull request as ready for review March 11, 2021 02:06
@jasonmalinowski jasonmalinowski force-pushed the argument-completion-tweaks branch 2 times, most recently from 85e95d3 to 656ec3a Compare March 12, 2021 00:27
@dotnet dotnet deleted a comment from azure-pipelines bot Mar 15, 2021
Since we're only using this in snippets we generate ourselves, we can
just compute the value directly and insert that into the Snippet XML.
This takes advantage of the prior commit to simplify some state
management. When we were using snippet functions to populate each
parameter, it was necessary to ensure some state "survives" when we are
moving from one overload to the next. This is because there's some
reentrancy: the process of moving to a new overload would dismiss the
prior snippet, but it had to still be avialable before the call to
insert the new snippet returned. Now that the snippet is fully
pre-generated, that's not a requirement anymore; instead we can just
always clear state when one snippet is dismissed, and set it afterwards
again once the snippet is re-inserted. This removes the necessity of
having the "_preserveSymbols" flag, as well as removing the requirement
to call specific Clear() at various points when we were dismissing
sessions.

The other simplification is the list of methods that was stored once a
session began was only used to grab one thing: the name of the method
group. So just replace that with a string.
If the first overload displayed by signature help is a method with no
parameters, then we have a placeholder snippet field. If you type in
that snippet field, we would switch the active overload to something
else which would cause what you typed to disappear.
As long as an edit happens in the middle, the two methods can come from
different Compilations. If the methods are in source, they don't compare
the same.
Since we create snippets out of XML, ensure we don't mangle parameters
if they round-trip in some way.
@jasonmalinowski jasonmalinowski merged commit c953000 into dotnet:features/argument-completion Mar 16, 2021
@jasonmalinowski jasonmalinowski deleted the argument-completion-tweaks branch March 16, 2021 20:42
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.

3 participants