-
Notifications
You must be signed in to change notification settings - Fork 480
Update CA2241 to handle cases from IDE0043 #4226
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
Conversation
| if (missingIndexes.Any()) | ||
| { | ||
| // can't deal with this for now. | ||
| context.ReportDiagnostic(invocation.CreateDiagnostic(Rule)); |
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.
We may want to report with a different diagnostic (message + desc).
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 think, since we are saying we want to break with legacy FxCop behavior that introducing a new, more specific warning message would be nice.
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 would still keep the same rule ID except if you think that's valuable to let users disable some part of the rule (I don't see the need as I don't expect much FPs).
...yzers/Core/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs
Outdated
Show resolved
Hide resolved
| {|#1:" + invocation + @"(""{0} {1} {2}"", 1)|}; | ||
| {|#2:" + invocation + @"(""{0} {1} {2}"", 1, 2)|}; | ||
| // These cases are not handled as we cannot find a parameter named format |
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 was tempted to update the code to handle these cases but I was a bit worried about the perf impact of analyzing the extra overloads. Let me know what you think.
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 would go ahead and handle them.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #4226 +/- ##
==========================================
+ Coverage 95.81% 95.83% +0.02%
==========================================
Files 1170 1170
Lines 266447 266951 +504
Branches 16050 16051 +1
==========================================
+ Hits 255293 255836 +543
+ Misses 9102 9087 -15
+ Partials 2052 2028 -24 🚀 New features to boost your workflow:
|
|
@jmarolf You have the most context on this analyzer. Can you please review? |
...yzers/Core/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs
Outdated
Show resolved
Hide resolved
| } | ||
|
|
||
| private static int GetFormattingArguments(string format) | ||
| private static HashSet<int>? GetStringFormatItemIndexes(string format) |
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 would extract this to a helper class and add unit tests explicitly for it. If we are going to maintain our own fork of the mscorlib parser code we should have tests to document its behavior.
...Tests/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethodsTests.cs
Show resolved
Hide resolved
|
|
||
| namespace Microsoft.NetCore.Analyzers.Runtime.UnitTests | ||
| { | ||
| public class ProvideCorrectArgumentsToFormattingMethodsTests |
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 we add a test for __arglist?
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.
Do you mean an empty arglist? We have some tests with __arglist(5)
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.
yep
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 am not sure how to get it to work, I was expecting the following to be good but that's not the case:
public void M(__arglist)
{
System.Console.WriteLine("", __arglist);
}
jmarolf
left a comment
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.
looks good! I would appreciate it if we could add a few more tests while we are here and I think having a separate, more descriptive diagnostic message would be nice
# Conflicts: # src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethodsTests.cs
| <data name="ProvideCorrectArgumentsToFormattingMethodsMessage" xml:space="preserve"> | ||
| <value>Provide correct arguments to formatting methods</value> | ||
| <data name="ProvideCorrectArgumentsToFormattingMethodsMessageArgs" xml:space="preserve"> | ||
| <value>Incorrect number of arguments passed to this formatting method call</value> |
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.
Do we want to add how many params are expected and how many were passed?
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.
This sounds like a great idea
| <value>Replace with 'string.Contains'</value> | ||
| </data> | ||
| <data name="ProvideCorrectArgumentsToFormattingMethodsMessageFormatItem" xml:space="preserve"> | ||
| <value>Some string format items are missing from this formatting method call</value> |
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 don't know if it brings much to add the missing indexes, WDYT?
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.
Considering we will "squiggle" the entire thing I think some text explaining how to fix what is wrong would help. Saying
"Some string format items are missing from this formatting method call. Nothing was passed for index '0'"
| isDataflowRule: false); | ||
|
|
||
| internal static DiagnosticDescriptor MissingFormatItemRule = DiagnosticDescriptorHelper.Create( | ||
| RuleId, |
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 don't think there is a need for a different ID (i.e. being able to activate one behavior without the other).
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 think that users may want to configure different severities for these rules which would necessitate a different ID.
- having too few parameters, run time error, should be a warning
- having too many parameters, not a runtime error, should probably be info by default
| /// <summary> | ||
| /// This regex is used to remove escaped brackets from the format string before looking for valid {} pairs. | ||
| /// </summary> | ||
| private static readonly Regex s_removeEscapedBracketsRegex = new("{{"); |
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.
Not sure if it's better to use the compiled regex here. It's not present in IDE0043 so I am assuming this was a conscious call.
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.
compiling the regex has binary size implications in visual studio which we are very paranoid about. Having the regex be precompiled here is fine.
...yzers/Core/Microsoft.NetCore.Analyzers/Runtime/ProvideCorrectArgumentsToFormattingMethods.cs
Show resolved
Hide resolved
| // but we want to skip it only in C# since VB doesn't support __arglist | ||
| if (info.ExpectedStringFormatArgumentCount >= 0 && | ||
| invocation.TargetMethod.IsVararg && | ||
| invocation.Language == LanguageNames.CSharp) |
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.
This filter was suggested but not present in the original implementation. Let me know if you prefer to revert this.
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 am fine with this change
| if (missingIndexes.Any()) | ||
| { | ||
| // can't deal with this for now. | ||
| context.ReportDiagnostic(invocation.CreateDiagnostic(MissingFormatItemRule)); |
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.
Do we want to report only on the string parameter?
|
There is an extra user option available in IDE0043, do we want to integrate it? |
If you have the time, I would love that. I think each of these options should be a different diagnostic Id that the user can configure independently. |
|
@mavasani I would like providing too few parameters (which will cause a runtime error) to be enabled as a warning for analysis level 6. Do you have any objections? |
Sounds reasonable. However, lets follow a process for promoting any CA rule to a warning:
|
|
@mavasani sounds like a plan. Looking over my notes from the last meeting I believe this has already been approved, but I agree let's not put foist those additional requirements on this PR. I'll create a follow up PR after this is merged. |
As part of that we should also bump the analyzer to warning in dotnet/roslyn and dotnet/runtime and confirm no false positives and acceptable performance. I think that should be our miniumn quality gate before bumping up a rule to a warning. |
|
I am working on the various open comment but I have a side question regarding the descriptors we want to create, basically we have the following use-cases:
In addition to the previous cases, there is a user option to provide additional string format methods, shall we reuse the previous descriptors or create a new set of them? Especially for case 1, where we are not sure if these additional methods will cause the runtime error so we might not want them to be raised as Regarding the user-option available in roslyn - IDE0043 looking at the tests it seems that this is used to validate what I have called missing format item here. Do we want to keep this as a separate option? |
|
I am wondering what can be done in term of diagnostic ID, I mean could we depreciate an old ID? I'd like to avoid having a too big gap between the 2 analyzers ID. The next available ID is CA2250. Except if we want to have 2 separate categories too. I am also wondering if we want to simply bail-out for C# varargs or if we still want to report for missing format indexes? Related to this subject, I would need help for the syntax of the empty I will push a WIP soon, here are the remaining steps:
|
|
@Evangelink Let's not deprecate CA2241 ID, let's just repurpose it for one of the new buckets. Microsoft.CodeAnalysis.FxCopAnalyzers is soon going to be deprecated in favor of Microsoft.CodeAnalysis.NetAnalyzers, and we do not need to preserve any backcompat behavior from FxCop in the latter, so I wouldn't worry about breaking changes in CA2241. |
|
It just feels a little weird as a user to have two really related rules so separated while I don't see much people who wouldn't both running. |
We already have multiple such cases, so it should be fine. Rule IDs should essentially be considered opaque. |
| csharpTest.ExpectedDiagnostics.Add( | ||
| // Test0.cs(8,17): warning CA2241: Provide correct arguments to formatting methods | ||
| GetCSharpResultAt(8, 17)); | ||
| // TODO: Make sure to report only the right diagnostic not both |
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.
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.
@sharwell as he is the expert on test framework helpers. I am not aware of one.
| // Not enough args | ||
| var s3 = MyFormat(""{0} {1}"", 1); | ||
| // Not enough args and missing format index | ||
| var s4 = MyFormat(""{0} {2}"", 1); |
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 am tempted to have a separate set of descriptors for these cases (they will use CA2241 as the too many cases) because we are not sure these will lead to runtime failure as this is a custom implementation.
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 would be fine with not issuing these diagnostics at all to start. Yes, historically we've done this but and I can see the utility but I would not turn these on for folks by default. This is always going to be something that you need to opt into. I like the idea of having a separate ID for custom methods so folks can still get these warnings on their custom loggers.
| // Not enough args | ||
| var s3 = MyFormat(""{0} {1}"", 1); | ||
| // Not enough args and missing format index | ||
| var s4 = MyFormat(""{0} {2}"", 1); |
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.
Same comment regarding the separate descriptors.
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.
yep, lets add a new descriptor for this case.
| var g = String.Format(p, ""{0}"", 1, 2); | ||
| var h = String.Format(p, ""{0} {1}"", 1, 2, 3); | ||
| var i = String.Format(p, ""{0} {1} {2}"", 1, 2, 3, 4); | ||
| {|#0:" + invocation + @"("""", 1)|}; |
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 so on these cases I need to report on all extra args, is it right?
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 think thats what we want. Once we get the preview out for .NET 6 well see if feedback directs us to change this.
| Console.Write(""{0} {1}"", 1, 2, 3); | ||
| Console.Write(""{0} {1} {2}"", 1, 2, 3, 4); | ||
| Console.Write(""{0} {1} {2} {3}"", 1, 2, 3, 4, 5); | ||
| {|#0:" + invocation + @"(""{1}"", 1, 2, 3)|}; |
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 here I need to report on all extra args + somewhere for the missing format indexes (any suggestion?)
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.
for this case I think the most useful location would be 1, and 3 indicating that these are unused.
| var s = String.Format(""{0} {1} {2} {3}"", new object[] {1, 2}); | ||
| Console.Write(""{0} {1} {2} {3}"", new object[] {1, 2, 3, 4, 5}); | ||
| Console.WriteLine(""{0} {1} {2} {3}"", new object[] {1, 2, 3, 4, 5}); | ||
| {|#0:" + invocation + @"(""{0} {1}"", 1)|}; |
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.
Here I highlight all format indexes without associated args, right?
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.
That would be my preference
| { | ||
| Console.Write(""{0} {1} {2} {3} {4}"", 1, 2, 3, 4, __arglist(5)); | ||
| Console.WriteLine(""{0} {1} {2} {3} {4}"", 1, 2, 3, 4, __arglist(5)); | ||
| {|#0:" + invocation + @"(""{1}"", 1)|}; |
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 to highlight the missing indexes?
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 this case I think we want to have a diagnostic on , 1 and say that is will not be used.
|
@jmarolf Would be you able to review the latest commit and answer @Evangelink's questions? |
|
@mavasani I'll review this after lunch, thanks for the ping |
|
@Evangelink done with review pass, please ping me if I missed something. |
|
@jmarolf Thank you for the various feedback! I will try to work on the pending changes by the end of the week (I might need a bit of time to get back to what's done and what's left to do, it's no longer really fresh in my mind). |
mavasani
left a comment
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.
Please retarget this PR to https://github.com/dotnet/roslyn-analyzers/tree/release/6.0.1xx-preview1
|
@Evangelink gentle ping, do you have time to retarget this? |
|
@jmarolf I will try to finish this PR by the end of next week. Looking back at it, there is still a lot of work to do. |
|
@Evangelink Would you have time to proceed further on this PR? Thanks! |
| DiagnosticCategory.Usage, | ||
| RuleLevel.BuildWarningCandidate, | ||
| description: s_localizableDescription, | ||
| isPortedFxCopRule: true, |
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.
Were all rules supported by FxCop?
|
Ping @Evangelink |
Fix #1254