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

Inline Hints: More logic around handling named arguments #60184

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

akhera99
Copy link
Member

@akhera99 akhera99 commented Mar 15, 2022

Fixes: #59317

  1. Iterate through the arguments first
  2. Create a listing of ParameterSymbols that map back to named arguments
  3. Go through the arguments again
  4. Get the parameter symbol the argument maps back to
  5. If it is a parameter symbol contained in the list, don't add a hint for it

@akhera99 akhera99 marked this pull request as ready for review March 15, 2022 18:41
@akhera99 akhera99 requested a review from a team as a code owner March 15, 2022 18:41
@akhera99 akhera99 requested a review from CyrusNajmabadi March 15, 2022 18:42
foreach (var argument in argumentList.Arguments)
{
if (argument.NameColon != null)
continue;

var parameter = argument.DetermineParameter(semanticModel, cancellationToken: cancellationToken);

if (parametersOfNamedArguments.Contains(parameter))
Copy link
Contributor

Choose a reason for hiding this comment

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

Aren't we already skipping here because of line 80?

if (argument.NameColon != null)
    continue;

Copy link
Member Author

Choose a reason for hiding this comment

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

This is for this case:
image

In which DetermineParameter maps the argument "true" to the parameter "d". So GetParametersOfNamedArguments goes through and gets the parameters in those mappings and makes sure to skip them. The argument.NameColon is necessary for the named argument "d:" since we still want to skip it.

Copy link
Contributor

Choose a reason for hiding this comment

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

ahhhh.... I get it now. Thanks for the explanation

Copy link
Contributor

@ryzngard ryzngard left a comment

Choose a reason for hiding this comment

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

I'm confused by this fix so maybe I'm missing something. It looks like all the work you do in GetParametersOfNamedArguments is duplicate continue logic in the for. What is causing this to be different?

@akhera99
Copy link
Member Author

I'm confused by this fix so maybe I'm missing something. It looks like all the work you do in GetParametersOfNamedArguments is duplicate continue logic in the for. What is causing this to be different?

Previously, if there was a named argument that wasn't at the exact location as the parameter, then it was still being shown. This is to combat that case.

Copy link
Member

@Youssef1313 Youssef1313 left a comment

Choose a reason for hiding this comment

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

Why not update DetermineParameter to not return a symbol if there is an overload resolution error?

More specifically, remove this if entirely:

if (symbol == null && symbolInfo.CandidateSymbols.Length == 1)
{
symbol = symbolInfo.CandidateSymbols[0];
}

@akhera99
Copy link
Member Author

akhera99 commented Mar 15, 2022

Why not update DetermineParameter to not return a symbol if there is an overload resolution error?

More specifically, remove this if entirely:

if (symbol == null && symbolInfo.CandidateSymbols.Length == 1)
{
symbol = symbolInfo.CandidateSymbols[0];
}

I remember adding that bit of code back when I first implemented this feature, it had something to do with an overload case. I need to see if it can just be removed.

Edit:
I remember now, in incomplete function calls we still want to try and add a hint if we can.
For instance:

class A
{
    int testMethod(int x, object y)
    {
        return x;
    }
    void Main() 
    {
        testMethod(-(int)5.5,);
    }
}

Should still show a hint for the argument in testMethod and it doesn't if we don't try to use the candidate symbol.

@Youssef1313
Copy link
Member

@akhera99 Does disabling inline parameter hints completely when there are more arguments than the parameter count make sense? I don't think we can give any good result for this case.

@akhera99
Copy link
Member Author

@akhera99 Does disabling inline parameter hints completely when there are more arguments than the parameter count make sense? I don't think we can give any good result for this case.

Yeah, I have no qualms with that, though I think that is orthogonal to this issue about named arguments.

@Youssef1313
Copy link
Member

@akhera99 The issue with named arguments seems to be reproducible only when the given arguments are greater than the number of parameters. If this assumption is correct, then the suggestion will result in a less complex fix.

An alternative is to somehow tweak DetermineParameter such that we guarantee it doesn't return the same parameter for different arguments. Here:

image

It returns the symbol for parameter d for both the true and the named argument, I think.

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.

Inline parameter hint is off when incorrect number of arguments is passed
3 participants