-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Fixed incorrect offer to interpolate string if used string.Format with named arguments. #20832
Conversation
return null; | ||
} | ||
|
||
return argument.NameColon.Name.Identifier.Text; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: consider : => argument?.NameColon?.Name.Identifier.Text
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, use ISyntaxFactsService. It already has GetNameForArgument
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(can be used directly from base class).
|
||
private TArgumentSyntax GetArgument(SeparatedSyntaxList<TArgumentSyntax> arguments, int index) | ||
{ | ||
if (arguments.Count > 4) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs explanation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if argument more than 4 it means that it is used the following overload String.Format(String format, params Object[] args)
without using named arguments. So we 100% sure in that case that we have no named arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i meant: needs explanation in the code (i.e. add a comment) :)
@CyrusNajmabadi, should we suggest refactoring in this case: void Foo()
{
string.Format("{0} string", "test");
} ? |
I would be ok with that. I would also be ok with it not being shown :) |
We could always emit this as |
|
||
public const string ArgsArgumentName = "args"; | ||
|
||
public static readonly Dictionary<int, string> ParamsArgumentNames = new Dictionary<int, string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 If you are just going to index into it (which the code currently is doing), we can benefit from both immutability and performance by changing this to ImmutableArray<string>
:
public static readonly ImmutableArray<string> ParamsArgumentNames =
ImmutableArray.Create("", "arg0", "arg1", "arg2");
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
private SyntaxNode GetParamsArgument(SeparatedSyntaxList<TArgumentSyntax> arguments, ISyntaxFactsService syntaxFactsService) | ||
{ | ||
var i = arguments.IndexOf(argument => GetArgumentName(argument, syntaxFactsService) == StringFormatArguments.ArgsArgumentName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will this work in a case-insensitive language like Visual Basic?
|
||
private TArgumentSyntax GetFormatArgument(SeparatedSyntaxList<TArgumentSyntax> arguments, ISyntaxFactsService syntaxFactsService) | ||
{ | ||
var index = arguments.IndexOf(argument => GetArgumentName(argument, syntaxFactsService) == StringFormatArguments.FormatArgumentName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will this work in a case-insensitive language like Visual Basic?
return arguments[index]; | ||
} | ||
|
||
return arguments.FirstOrDefault(argument => GetArgumentName(argument, syntaxFactsService) == StringFormatArguments.ParamsArgumentNames[index]) ?? arguments[index]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will this work in a case-insensitive language like Visual Basic?
=> arguments.FirstOrDefault(argument => string.Equals(GetArgumentName(argument, syntaxFactsService), StringFormatArguments.FormatArgumentName, StringComparison.OrdinalIgnoreCase)) ?? arguments[1]; | ||
|
||
private TArgumentSyntax GetFormatArgument(SeparatedSyntaxList<TArgumentSyntax> arguments, ISyntaxFactsService syntaxFactsService) | ||
=> arguments.FirstOrDefault(argument => string.Equals(GetArgumentName(argument, syntaxFactsService), StringFormatArguments.FormatArgumentName, StringComparison.OrdinalIgnoreCase)) ?? arguments[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In VB we want the comparison to be case-insensitive, but I believe we want a case sensitive comparison for C# correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jmarolf Since String.Format("{0}", ARg0: 1)
is incorrect syntax 'convert to interpolate string' refactoring wouldn't be suggested
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just tried it with your changes. You are correct.
Customer scenario
Incorrect offer to interpolate string if used string.Format with named arguments.
Bugs this fixes:
Fixes #19162
Workarounds, if any
Don't use this refactoring for string.Format with named arguments.
Risk
Low
Performance impact
Is this a regression from a previous update?
No
Root cause analysis:
Doesn't implemented support for string.Format with named arguments
How was the bug found?
customer reported