-
Notifications
You must be signed in to change notification settings - Fork 470
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
CA2263: Prefer generic overload when type is known #6857
Conversation
This analyzer detects when a `System.Type` overload is called when a suitable generic overload is available. To validate if a generic overload is applicable, the arity, parameter count, containing symbol of the invocation (to avoid endless loops), return type, argument types and type constraints(using speculative binding) are checked. The fixer removes unnecessary casts and parentheses.
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #6857 +/- ##
=========================================
Coverage 96.44% 96.45%
=========================================
Files 1415 1422 +7
Lines 338229 340539 +2310
Branches 11191 11230 +39
=========================================
+ Hits 326192 328453 +2261
- Misses 9216 9247 +31
- Partials 2821 2839 +18 |
src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Usage/CSharpPreferGenericOverloads.Fixer.cs
Show resolved
Hide resolved
Good catch 👍
Shouldn't we restrict to exact match not compatible to avoid false positives? Is there a specific scenario that needs to be compatible?
By my understanding the analyzer compilation only have the current target info, could not give info for other targets. Now all similar analyzers cause this issue and in runtime repo we if-def the resolution in case the analyzer is set for warning. I'm not aware of any solution for this, @mavasani might know if there is any solution |
void M(System.Type type, object x) {} | ||
void M<T>(T x) {} |
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.
Wonder if this scenario cause more false positives, why do you think this should be covered?
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.
IIRC this test was motivated by the following (from roslyn-cs.txt):
W:\roslyn\src\Compilers\CSharp\Test\Semantic\SourceGeneration\GeneratorDriverTests.cs(3102,78): info CA2262: Prefer the generic overload 'System.Enum.GetName(TEnum)' instead of 'System.Enum.GetName(System.Type, object)'
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.
System.Enum.GetName<TEnum>(TEnum)
instead of System.Enum.GetName(System.Type, object)
is a good example, thank you! We can make it strict if a false positives reported, and the severity is info level, not breaking
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.
The PR looks great, thank you @mpidash!
Test coverage looks good, many hits in runtime, but with a quick check did not see a false positive, the fixer works as expected, good to go
Fixes dotnet/runtime#68243.
Category: Usage
Severity: Info
This analyzer detects when a
System.Type
overload is called when a suitable generic overload is available and the type is known at compile-time. The fixer replaces it with the generic call and removes redundant casts and parentheses.To validate if a generic overload is applicable, the following rules are checked:
Some notes and corner cases found during testing:
Rule 3. is due to the following case used in the runtime repository:
If we did not check the enclosing symbol, the fixer would generate an endless recursion.
Rule 4. is due to the following case:
Here, the intention is to create a
ImmutableArray<Type>
with one elementtypeof(NameSyntax)
. If the analyzer would not check the return value, this would lead to a diagnostic and would be fixed toImmutableArray.Create<NameSyntax>()
which returns an emptyImmutableArray<NameSyntax>
.Rule 6. prevents compile errors due to type constraints, for example:
We cannot change to
return Enum.GetValues<T>()
as there is only a struct type constraint, but the generic version ofEnum.GetValues
also constrainsT
to theEnum
type (in addition tostruct
).The tests show all other corner cases that I've encountered during testing.
I have one open question: How should we handle different runtime targets? For example the following
would produce a diagnostic when targeting
net7.0
, but not when targetingnet472
, as Enum.GetValues is only available sincenet5
. Is this ok because the default severity is info?I've also added all findings from
roslyn-analyzer
,roslyn
andruntime
(set severity tonone
for tests inruntime
, rule ID is still CA2262 in the files):roslyn-analyzer.txt
roslyn-cs.txt
roslyn-vb.txt
runtime-clr-mono-libs-libs.tests.txt