Docs: Breaking change: Roslyn analyzer CA1416 - Platform Compatibility Analyzer

Created on 26 Aug 2020  路  11Comments  路  Source: dotnet/docs

Breaking change: Roslyn analyzer CA1416 - Platform Compatibility Analyzer

In .NET 5.0 we have added new attributes to annotate platform-specific APIs. This works as follows:

  • An unmarked API is considered to work on all OS platforms.
  • An API marked with [SupportedOSPlatform("...")] is considered only portable to the specified OS platforms (the attribute can be applied multiple times).
  • An API marked with [UnsupportedOSPlatform("...")] is considered unsupported only to the specified OS platforms (the attribute can be applied multiple times).

We have applied [SupportedOSPlatform("windows")] attribute for some windows specific APIs. We also applied [UnsupportedOSPlatform("windows")] to the System.Security.Cryptography.OpenSsl assembly. We are applying [UnsupportedOSPlatform("browser")] for APIs that are not supported in Blazor WebAssembly (still in progress).

We have a Roslyn analyzer that informs you when you're using platform-specific APIs from a call site where the API might not be available. Because the analyzer is turned on by default, you might see additional diagnostics in your build, in case your code references any platform-specific API.

Version introduced

This analyzer is included in .NET 5 RC1 SDK and turned on by default.

Old behavior

Referencing platform-specific APIs without a proper platform context would not use any diagnostics.

New behavior

Referencing platform-specific APIs without a proper platform context will produce diagnostics. Examples are below.

Reason for change

Using platform-dependent APIs on a component makes the code no longer work across all platforms.

  • Accessing any of the APIs annotated as windows only ([SupportedOSPlatform("windows")]) from platform-neutral or non-windows context will produce a diagnostic.
public void PlayCMajor()
{
    // CA1416: 'Console.Beep(int, int)' is supported on 'windows'
    Console.Beep(261, 1000);
}

Note: A diagnostic is only raised if the project is targeting net5.0 and has an AnalysisLevel of 5 (the default for net5.0 projects). This also applies to multi-targeted projects. No diagnostic is raised if the project is targeting windows only (net5.0-windows), or if you are targeting netstandard or netcoreapp. Therefore, existing projects will not encounter these diagnostics until they are updated to target net5.0.

  • Accessing any of the APIs annotated as not supported on browser ([UnsupportedOSPlatform("browser")]) when building a Blazor WebAssembly will produce diagnostics.
public void CreateImage()
{
    // CA1416: 'Image.FromFile(string)' is unsupported on 'browser'
    Image newImage = Image.FromFile("SampImag.jpg");
}

Note: This only raises a diagnostic if the project is use the Blazor WebAssembly SDK (or has manually included browser in the MSBuild <SupportedPlatform> item group. If you're building a regular class library (targeting .NET Standard or .NET 5) you won't get any diagnostics for APIs that are unsupported by browser unless you explicitly opt-in by adding this to your project:

<ItemGroup>
    <SupportedPlatform Include="browser" />
</ItemGroup>

Recommended action

The recommend way to deal with these diagnostics is by making sure you only call these APIs when running on the appropriate platforms. You can either achieve this by excluding the code at build time using #if and multi-targeting or by conditionally calling the code at runtime. The analyzer will recognize the new platform guards we added to System.OperatingSystem that you can use for checking.

  • Diagnostics can be suppressed by surrounding the call site with a platform guard
public void PlayCMajor() 
{ 
    if (OperatingSystem.IsWindows())
    { 
        // No diagnostic
        Console.Beep(261, 1000); 
    } 
} 

You can also choose to mark your own APIs as being platform-specific, thus effectively just forwarding the requirements to your callers. You can only mark specific methods or types or the entire assembly.

  • Use [SupportedOSPlatform("platformName")] attribute to indicate that your API is platform-specific
[SupportedOSPlatform("windows")]
public void PlayCMajor () 
{ 
    // No diagnostics
    Console.Beep(261, 1000); 
} 
  • The analyzer also respects Debug.Assert as a means for preventing the code from being reached on unsupported platforms. Using Debug.Assert allows the check to be trimmed out of release builds if desired.
public void PlayCMajor() 
{ 
    Debug.Assert(OperatingSystem.IsWindows());

    // No diagnostic
    Console.Beep(261, 1000); 
} 
  • And lastly, you can also suppress these diagnostics by the usual means (<NoWarn>, editor config, or #pragma):
public void PlayCMajor () 
{ 
#pragma warning disable CA1416
    Console.Beep(261, 1000); 
#pragma warning restore CA1416
} 

Category

Core .NET libraries

Affected APIs

We have applied [SupportedOSPlatform("windows")] attribute for some windows specific APIs. We also applied [UnsupportedOSPlatform("windows")] to the System.Security.Cryptography.OpenSsl assembly. We are applying [UnsupportedOSPlatform("browser")] for APIs that are not supported in Blazor WebAssembly (still in progress).


Issue metadata

  • Issue type: breaking-change
.NET 5 breaking-change doc-idea

Most helpful comment

I believe you're correct, by default only net5.0 and net5.0-windows are opted into the new analysis level.

I just verified that switching from net5.0 to netstandard2.1 made the diagnostic go away. I'll edit the description to fix that.

All 11 comments

CC @jmarolf @mavasani @jeffhandley @terrajobst

I've slightly edited the wording, but it looks great. Thanks!

I've slightly edited the wording, but it looks great. Thanks!

Looks great, thanks!

@buyaa-n I edited to:

  • Mention OpenSsl being unsupported on Windows
  • Change some quotes from back-tick quotes to single-quotes
  • Fix a typo
  • Add the approach for using Debug.Assert. Can you specifically review that section please?

@jmarolf One question for you... is it correct that the diagnostics could show up when targeting netstandard, or would targeting netstandard put you in Analysis Level 4 such that you wouldn't get diagnostics from this analyzer unless you opt in?

I'm referring to this part:

Note: No diagnostic is raised if the project is targeting windows (net5.0-windows), a diagnostic is raised if the project is targeting net5.0 or netstandard

Add the approach for using Debug.Assert. Can you specifically review that section please?

Looks good, thanks!

@jmarolf One question for you... is it correct that the diagnostics could show up when targeting netstandard, or would targeting netstandard put you in Analysis Level 4 such that you wouldn't get diagnostics from this analyzer unless you opt in?

I'm referring to this part:

Note: No diagnostic is raised if the project is targeting windows (net5.0-windows), a diagnostic is raised if the project is targeting net5.0 or netstandard

I believe you're correct, by default only net5.0 and net5.0-windows are opted into the new analysis level.

I believe you're correct, by default only net5.0 and net5.0-windows are opted into the new analysis level.

I just verified that switching from net5.0 to netstandard2.1 made the diagnostic go away. I'll edit the description to fix that.

I updated the target framework block to be:

Note: A diagnostic is only raised if the project is targeting net5.0 and has an AnalysisLevel of 5 (the default for net5.0 projects). This also applies to multi-targeted projects. No diagnostic is raised if the project is targeting windows only (net5.0-windows), or if you are targeting netstandard or netcoreapp. Therefore, existing projects will not encounter these diagnostics until they are updated to target net5.0.

@terrajobst / @jmarolf - Feel free to further wordsmith that if you'd like.

The remaining work is to list the APIs individually.

I think listing the APIs out individually has low value for the effort required, so I'm going to close this issue out now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mekomlusa picture mekomlusa  路  3Comments

LJ9999 picture LJ9999  路  3Comments

Manoj-Prabhakaran picture Manoj-Prabhakaran  路  3Comments

LJ9999 picture LJ9999  路  3Comments

sdmaclea picture sdmaclea  路  3Comments