-
Notifications
You must be signed in to change notification settings - Fork 466
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
CA1416 handle call-site empty sets causing warnings when TFM attributes applied #4740
Conversation
|
||
public PlatformAttributes(Callsite callsite, SmallDictionary<string, Versions> platforms) | ||
{ | ||
Callsite = callsite; |
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.
Because of attributes kept in the cache i needed to add Call-site info for subsequent calls made within that call site
...tAnalyzers/Core/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzer.cs
Show resolved
Hide resolved
...tAnalyzers/Core/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzer.cs
Outdated
Show resolved
Hide resolved
Codecov Report
@@ Coverage Diff @@
## master #4740 +/- ##
==========================================
- Coverage 95.71% 95.68% -0.04%
==========================================
Files 1196 1193 -3
Lines 271237 271512 +275
Branches 16386 16411 +25
==========================================
+ Hits 259611 259788 +177
- Misses 9477 9620 +143
+ Partials 2149 2104 -45 |
@buyaa-n just trying to understand the expected semantics for the below example you provided: [SupportedOSPlatform("windows")]
[SupportedOSPlatform("macos")]
class Test2
{
[SupportedOSPlatform("macos")]
class Test2MacOs
{
[SupportedOSPlatform("windows")]
void WindowsOnly()
{
// No valid call sites; no warnings no matter what
}
[SupportedOSPlatform("linux")]
void LinuxOnly()
{
// No valid call sites; no warnings no matter what
}
}
} Applying |
...yzers/Core/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzer.Data.cs
Outdated
Show resolved
Hide resolved
...tAnalyzers/Core/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzer.cs
Outdated
Show resolved
Hide resolved
Yes that is correct, it is equivalent to |
...tAnalyzers/Core/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzer.cs
Show resolved
Hide resolved
...tAnalyzers/Core/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzer.cs
Outdated
Show resolved
Hide resolved
...tAnalyzers/Core/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzer.cs
Show resolved
Hide resolved
.../UnitTests/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzerTests.cs
Outdated
Show resolved
Hide resolved
.../UnitTests/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzerTests.cs
Show resolved
Hide resolved
...yzers/Core/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzer.Data.cs
Show resolved
Hide resolved
@buyaa-n Do I interpret this change correctly in that there's no assembly-level special-casing of the empty set behavior and that this is the desired "correct" fix to achieve empty set detection? With these changes, how many of the |
Yes it does not include my previous solution with
All are cleaned up, no one left |
💯 /cc @terrajobst -- the correct fix is in here, so no need for a follow-up item
Great! |
...tAnalyzers/Core/Microsoft.NetCore.Analyzers/InteropServices/PlatformCompatibilityAnalyzer.cs
Outdated
Show resolved
Hide resolved
[SupportedOSPlatform(""Browser"")] | ||
public class Test | ||
{ | ||
[UnsupportedOSPlatform(""browser"")] |
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 curious - does the reverse annotation work? i.e. if I mark the containing assembly or type as unsupported for a platform A and just a single method/property inside it as supported, will we get warnings inside that method/property if it has guarded runtime checks within it?
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 curious - does the reverse annotation work? i.e. if I mark the containing assembly or type as unsupported for a platform A and just a single method/property inside it as supported
Only parent attribute would work, as a child cannot extend parent support supported attribute on M2 will be ignored
[UnsupportedOSPlatform(""Browser"")] // Deny list => unsupported only on browser but supported on all others
public class Test
{
[SupportedOSPlatform(""browser"")] // child cannot extend parent support, annotation willl be ignored
public void M2 () // the above annotation doesn't produce empty set as parent only unsupported on browser but supported on all other
{
// All platforms except browser can access here, so we would warn for platform-specific APIs usage
}
}
will we get warnings inside that method/property if it has guarded runtime checks within it?
Good question, this combination is not producing the empty set, so we should warn
Console.Beep(10, 20); | ||
} | ||
|
||
[SupportedOSPlatform(""Linux"")] // Not valid because Linux is not in parent list of platforms |
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.
Why is this the case? If I had a type such that only one of the method supported a platform, why would I be required to add the supported attribute on the whole type as opposed to just the method?
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.
Right, as you mentioned it is not a meaningful or realistic scenario, but it is happening in multitargeted builds for runtime repo. We have assemblies for multiple platforms where some APIs annotated as platform-specific, the assembly doesn't have any platform attributes but it does build for each platform specified:
<TargetFrameworks>net5.0-windows;net5.0-Unix;net5.0-tvOS;net5.0-Browser</TargetFrameworks>
For example, when it builds for windows net5.0-windows
target MSBuild adds assembly-level [SupportedOSPlatform("windows")] attributes then the individual APIs having different platforms support would produce this scenario and we see warnings within their body for those targeted builds, this is the main reason we are doing this change, we don't want to warn in this case
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.
LGTM. Have some minor questions, but none of those seem blocking.
Related to dotnet/runtime#44231
By design, SDK adds SuuportedOSPlatform attribute with the targeted OS platform from TFMs, which works well for normal condition but for multitargeted env like
runtime
repo it is causing warnings mentioned in dotnet/runtime#44231 and requiring clear separation of platform-specific APIs which forcing developers to duplicate their code to conform to the strict supported-platform name rules. After evaluating of possible solution and several discussions we have decided to resolve it at the analyzer level. The TFM target attributes are causing inconsistent scenarios in the call site and the real attributes within that assembly are being ignored or malfunctioned which causing the warnings, this shouldn't happen in normal development. By the main rule of "Child API attributes cannot widen parent or containing type attributes" when the inconsistency happens in the call site and call site evaluated to an empty set of support not gonna warn within that empty set context.cc @jeffhandley @terrajobst
Examples: