[tests] Fix CA1416 root cause in test projects instead of suppressing it#11761
[tests] Fix CA1416 root cause in test projects instead of suppressing it#11761simonrozsival wants to merge 3 commits into
Conversation
Our test projects exercise Mono.Android APIs that are annotated with
[SupportedOSPlatform("android24.0")] from helper/instrumentation code
that the platform-compatibility analyzer treats as reachable on all
platforms. This produces ~1300 CA1416 warnings per build that add no
value: the tests only ever run on Android, so the platform guards the
analyzer wants are meaningless here.
Add a tests/Directory.Build.props that chains to the repository-root
Directory.Build.props and appends CA1416 to $(NoWarn) for all test
projects.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a tests/Directory.Build.props to suppress CA1416 (platform compatibility analyzer) warnings across all projects under tests/, reducing build log noise while preserving the repository-root build settings via an explicit import chain.
Changes:
- Add
tests/Directory.Build.propsthat explicitly imports the repo-rootDirectory.Build.props(since MSBuild only auto-imports the nearest one). - Append
CA1416to$(NoWarn)for all test projects undertests/.
Show a summary per file
| File | Description |
|---|---|
| tests/Directory.Build.props | Chains to repo-root Directory.Build.props and suppresses CA1416 for all projects under tests/. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 1
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Replace the blanket NoWarn suppression with the actual fix: declare the
assembly's supported platform.
The android-targeted test projects that set <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
lose the SDK-generated [assembly: SupportedOSPlatform("android24.0")]
attribute. Without it the platform-compatibility analyzer treats the
whole assembly as platform-neutral ("reachable on all platforms") and
emits CA1416 for every call to a Mono.Android API (which, with minimum
API level 24, is essentially the entire API surface).
Add [assembly: SupportedOSPlatform("android24.0")] to the affected
projects so the analyzer knows the assemblies only run on Android 24+,
silencing CA1416 without hiding genuine portability warnings:
- Mono.Android.NET-Tests
- TestRunner.Core
- CodeBehind/BuildTests
StartupHook also sets GenerateAssemblyInfo=false but calls no Mono.Android
APIs, so it needs no change. MSBuildDeviceIntegration and the Mc/JcwGen
test projects use the default GenerateAssemblyInfo=true and already get
the attribute from the SDK.
Verified with the real Mono.Android reference assembly that the same API
calls produce CA1416 without the attribute and build cleanly (0 warnings)
with it.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| // This test assembly only ever runs on Android (minimum API level 24). Without this | ||
| // attribute the platform-compatibility analyzer treats the assembly as platform-neutral | ||
| // (because GenerateAssemblyInfo is disabled) and emits spurious CA1416 warnings for every | ||
| // call to an [SupportedOSPlatform("android24.0")] API. | ||
| [assembly: SupportedOSPlatform ("android24.0")] |
There was a problem hiding this comment.
Can you set the SupportedOSPlatformVersion MSBuild property instead?
There was a problem hiding this comment.
SupportedOSPlatformVersion is actually already set on this project (<SupportedOSPlatformVersion>$(AndroidMinimumDotNetApiLevel)</SupportedOSPlatformVersion>, currently 24) — but it doesn't produce the attribute here.
The .NET SDK only turns SupportedOSPlatformVersion into [assembly: SupportedOSPlatform] inside the GenerateAssemblyInfo target, which is gated on GenerateAssemblyInfo == true (Microsoft.NET.GenerateAssemblyInfo.targets). These test projects set <GenerateAssemblyInfo>false</GenerateAssemblyInfo> to avoid clashing with the hand-written Properties/AssemblyInfo.cs, so the property is inert and no attribute is emitted. The Android SDK consumes SupportedOSPlatformVersion only for typemap/runtime generation, not for the assembly attribute.
So to drive it from the property we'd have to either:
- stop setting
GenerateAssemblyInfo=falseand move everything inProperties/AssemblyInfo.cs(including[assembly: UsesPermission]inTestRunner.Core) into MSBuild, or - add a small target that emits the attribute from
$(SupportedOSPlatformVersion)viaWriteCodeFragment.
Do you prefer one of those over the explicit [assembly: SupportedOSPlatform]? Happy to wire up (2) if you'd like to keep it property-driven.
There was a problem hiding this comment.
Ok, yeah we can remove GenerateAssemblyInfo=false, I remember this problem.
We'd have to migrate attributes to the relevant MSBuild properties -- or you get duplicates.
The MSBuild properties seem better, in general.
Summary
Our Android-targeted test projects emit a large volume of
CA1416warnings — roughly 1300 per build in theMono.Android.NET-Testsbuild alone. Rather than suppress the rule, this PR fixes the root cause by declaring each affected assembly's supported platform.Root cause
The telltale wording is "This call site is reachable on all platforms. 'X' is only supported on: 'Android' 24.0 and later." — the platform-compatibility analyzer thinks the assembly is platform-neutral, not Android-only.
Normally the .NET SDK auto-emits an assembly-level attribute that tells the analyzer the assembly only runs on Android:
But these test projects set
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>(to avoid clashing with their hand-writtenProperties/AssemblyInfo.cs). In the .NET SDK, theSupportedOSPlatformAttributeis only emitted insideCoreGenerateAssemblyInfo, which is gated entirely byGenerateAssemblyInfo == true. With it disabled, the attribute is never produced, the analyzer has no Android floor, and every call to aMono.AndroidAPI (with minimum API level 24, essentially the entire API surface is annotatedandroid24.0) raisesCA1416.Fix
Add
[assembly: SupportedOSPlatform("android24.0")]to the affected assemblies. This states the literal truth — these test apps only ever run on Android 24+ — so the analyzer stops warning, without hiding genuine portability diagnostics the way a blanketNoWarnwould.Projects changed
Only Android-targeted test projects that both set
GenerateAssemblyInfo=falseand callMono.AndroidAPIs need this:Mono.Android.NET-TestsTestRunner.CoreCodeBehind/BuildTestsProjects intentionally left alone
StartupHook— also setsGenerateAssemblyInfo=false, but calls noMono.AndroidAPIs, so it never trips CA1416.MSBuildDeviceIntegration,Xamarin.Android.McwGen-Tests,Xamarin.Android.JcwGen-Tests— use the defaultGenerateAssemblyInfo=true, so the SDK already emits the platform attribute.Verification
Verified against the real
Mono.Androidreference assembly (Microsoft.Android.Ref.37) with a minimalnet*-androidproject mirroring the test projects' settings (GenerateAssemblyInfo=false,SupportedOSPlatformVersion=24) and the same kinds of API calls (Object.Handle,JavaSystem.IdentityHashCode,JNIEnv.GetMethodID,Activity.OnCreate,Instrumentation,Log.Error,TextView/Button, …):CA1416warnings ("reachable on all platforms", android 24.0)