Skip to content

Commit 76ab8b2

Browse files
authored
[Mono.Android] Use PublicApiAnalyzers to ensure we do not break API. (#8171)
Fixes: #7421 Context: #1118 Context: 07e7477 We currently have our internal `<CheckApiCompatibility/>` task (07e7477), which ensures that we do not break backwards compatibility between Android API levels. Now that we are in the .NET `TargetFramework` world we also need to ensure we do not *add* any new API to a Target Framework once it has shipped. A `TargetFramework` is essentially a contract that we cannot change. (Imagine if you had different minor versions of .NET on your local machine and CI machine, what works on one should work on the other.) Enable Microsoft's [PublicApiAnalyzers][0] for `Mono.Android.dll`. ([PublicApiAnalyzers documentation][1].) This ensures that we don't add new API once we've shipped `Mono.Android.dll` for a given .NET version. Running the `PublicApiAnalyzer` adds about 25 seconds to a local build. One can use our existing `$(DisableApiCompatibilityCheck)` property to also disable them to facilitate faster local build if desired. Additionally, disable [`RS0041`][2] ("Public members should not use oblivious types"). We should look at getting `Android.Runtime.JniEnv.g.cs` properly annotated with nullable reference types, and then we could enable this analyzer. ***Note***: PublicApiAnalyzers cannot be the *only* mechanism that is used to track API compatibility for `Mono.Android.dll`, because some binding constructs can result in compatible APIs while breaking *semantics*. See also Issue #1118. We thus need to continue using `<CheckApiCompatibility/>` (or some equivalent) to ensure that our `[Register]` attribute values do not change without review. [0]: https://github.com/dotnet/roslyn-analyzers/tree/40a3ec17a7507b8767b4ac806f29b6df179cf627/src/PublicApiAnalyzers [1]: https://github.com/dotnet/roslyn-analyzers/blob/40a3ec17a7507b8767b4ac806f29b6df179cf627/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md [2]: https://github.com/dotnet/roslyn-analyzers/blob/40a3ec17a7507b8767b4ac806f29b6df179cf627/src/PublicApiAnalyzers/Microsoft.CodeAnalysis.PublicApiAnalyzers.md#rs0041-public-members-should-not-use-oblivious-types
1 parent 6836818 commit 76ab8b2

File tree

9 files changed

+124293
-3
lines changed

9 files changed

+124293
-3
lines changed

build-tools/automation/guardian/PoliCheck.Exclusions.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<PoliCheckExclusions>
2+
<!-- Reminder: you are only allowed one exclusion element of each type, to have multiple values you must pipe separate them in a single element -->
23
<!-- Each of these exclusions is a folder name - if \[name]\ exists in the file path, it will be skipped -->
34
<Exclusion Type="FolderPathFull">LICENSE-DATA|NREFACTORY|LOCALIZE</Exclusion>
4-
<Exclusion Type="FolderPathStart">src\Mono.Android\Profiles</Exclusion>
55
<!-- Each of these exclusions is a folder name - if any folder or file starts with "\[name]", it will be skipped -->
6-
<!--<Exclusion Type="FolderPathStart">ABC|XYZ</Exclusion>-->
6+
<Exclusion Type="FolderPathStart">src\Mono.Android\Profiles|src\Mono.Android\PublicAPI</Exclusion>
77
<!-- Each of these file types will be completely skipped for the entire scan -->
88
<!--<Exclusion Type="FileType">.ABC|.XYZ</Exclusion>-->
99
<!-- The specified file names will be skipped during the scan regardless which folder they are in -->

src/Mono.Android/Android.Runtime/JNIEnv.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,9 @@ static unsafe void _GetDoubleArrayRegion (IntPtr array, int start, int length, d
835835
JniEnvironment.Arrays.GetDoubleArrayRegion (new JniObjectReference (array), start, length, p);
836836
}
837837

838+
#pragma warning disable RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads
838839
public static void CopyArray (IntPtr src, Array dest, Type? elementType = null)
840+
#pragma warning restore RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads
839841
{
840842
if (dest == null)
841843
throw new ArgumentNullException ("dest");

src/Mono.Android/Android/IncludeAndroidResourcesFromAttribute.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ namespace Android {
66
[Obsolete ("This attribute is no longer supported.", error: true)]
77
public class IncludeAndroidResourcesFromAttribute : ReferenceFilesAttribute
88
{
9+
#pragma warning disable RS0022 // Constructor make noninheritable base class inheritable
910
public IncludeAndroidResourcesFromAttribute (string path)
11+
#pragma warning restore RS0022 // Constructor make noninheritable base class inheritable
1012
{
1113
ResourceDirectory = path;
1214
}

src/Mono.Android/Java.Interop/JavaLibraryReferenceAttribute.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ namespace Java.Interop {
66
[Obsolete ("This attribute is no longer supported.", error: true)]
77
public class JavaLibraryReferenceAttribute : Android.ReferenceFilesAttribute
88
{
9+
#pragma warning disable RS0022 // Constructor make noninheritable base class inheritable
910
public JavaLibraryReferenceAttribute (string filename)
11+
#pragma warning restore RS0022 // Constructor make noninheritable base class inheritable
1012
{
1113
LibraryFileName = filename;
1214
}

src/Mono.Android/Java.Interop/JavaTypeParametersAttribute.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
#if NET
44
using System.Runtime.CompilerServices;
55

6+
// PublicApiAnalyzers doesn't like TypeForwards
7+
#pragma warning disable RS0016 // Symbol is not part of the declared API
68
[assembly: TypeForwardedTo (typeof (Java.Interop.JavaTypeParametersAttribute))]
9+
#pragma warning restore RS0016 // Symbol is not part of the declared API
710

811
#else // !NET
912

src/Mono.Android/Mono.Android.csproj

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<RootNamespace>Android</RootNamespace>
1010
<SignAssembly>true</SignAssembly>
1111
<AssemblyOriginatorKeyFile>..\..\product.snk</AssemblyOriginatorKeyFile>
12-
<NoWarn>0618;0809;0108;0114;0465;8609;8610;8614;8617;8613;8764;8765;8766;8767</NoWarn>
12+
<NoWarn>0618;0809;0108;0114;0465;8609;8610;8614;8617;8613;8764;8765;8766;8767;RS0041</NoWarn>
1313
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
1414
<DefineConstants>$(DefineConstants);JAVA_INTEROP</DefineConstants>
1515
<IntermediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)\$(TargetFramework)\android-$(AndroidPlatformId)\</IntermediateOutputPath>
@@ -27,6 +27,7 @@
2727
<PropertyGroup>
2828
<DefineConstants Condition=" '$(AndroidApiLevel)' &gt; '$(AndroidLatestStableApiLevel)' ">$(DefineConstants);ANDROID_UNSTABLE</DefineConstants>
2929
<OutputPath>$(_MonoAndroidNETDefaultOutDir)</OutputPath>
30+
<RunAnalyzers Condition=" '$(DisableApiCompatibilityCheck)' == 'True' ">false</RunAnalyzers>
3031
</PropertyGroup>
3132

3233
<PropertyGroup Condition=" '$(IncludeAndroidJavadoc)' == 'True' ">
@@ -39,6 +40,11 @@
3940
<NoWarn>$(NoWarn);CA1422;CA1416</NoWarn>
4041
</PropertyGroup>
4142

43+
<ItemGroup>
44+
<AdditionalFiles Include="PublicAPI\API-$(AndroidApiLevel)\PublicAPI.Shipped.txt" />
45+
<AdditionalFiles Include="PublicAPI\API-$(AndroidApiLevel)\PublicAPI.Unshipped.txt" />
46+
</ItemGroup>
47+
4248
<PropertyGroup>
4349
<JavaCallableWrapperAbsAssembly>$([System.IO.Path]::GetFullPath ('$(OutputPath)$(AssemblyName).dll'))</JavaCallableWrapperAbsAssembly>
4450
</PropertyGroup>
@@ -338,6 +344,13 @@
338344
<Compile Include="Xamarin.Android.Net\NegotiateAuthenticationHelper.cs" />
339345
</ItemGroup>
340346

347+
<ItemGroup>
348+
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4">
349+
<PrivateAssets>all</PrivateAssets>
350+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
351+
</PackageReference>
352+
</ItemGroup>
353+
341354
<ItemGroup>
342355
<ProjectReference Include="..\..\build-tools\create-android-api\create-android-api.csproj" ReferenceOutputAssembly="false" />
343356
<!-- Explicitly pass the target framework of the project so we don't have conflicts with the multiple targets in this file. -->

src/Mono.Android/Properties/AssemblyInfo.cs.in

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// Copyright 2014 Xamarin, Inc.
88
// Copyright 2016 Microsoft Corporation.
99

10+
using System.Diagnostics.CodeAnalysis;
1011
using System.Reflection;
1112
using System.Runtime.CompilerServices;
1213
using System.Runtime.Versioning;
@@ -26,6 +27,8 @@ using System.Runtime.Versioning;
2627
[assembly: SupportedOSPlatform("Android@[email protected]")]
2728
#endif
2829

30+
// PublicApiAnalyzers doesn't like TypeForwards
31+
#pragma warning disable RS0016 // Symbol is not part of the declared API
2932
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Drawing.Color))]
3033
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Drawing.ColorConverter))]
3134
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Drawing.KnownColor))]
@@ -36,9 +39,13 @@ using System.Runtime.Versioning;
3639
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Drawing.Size))]
3740
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Drawing.SizeF))]
3841
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Drawing.SystemColors))]
42+
#pragma warning restore RS0016 // Symbol is not part of the declared API
43+
3944
[assembly: InternalsVisibleTo("Mono.Android.Export, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
4045
[assembly: InternalsVisibleTo("Mono.Android-Tests, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
4146
[assembly: InternalsVisibleTo("Java.Interop-Tests, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
4247
[assembly: InternalsVisibleTo("Mono.Android-TestsMultiDex, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
4348
[assembly: InternalsVisibleTo("Mono.Android-TestsAppBundle, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
4449
[assembly: InternalsVisibleTo("Mono.Android.NET-Tests, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
50+
51+
[assembly: SuppressMessage ("ApiDesign", "RS0016:Add public types and members to the declared API", Justification = "Analyzer fails due to extended characters.", Scope = "member", Target = "~F:Android.Util.Patterns.GoodIriChar")]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#nullable enable

0 commit comments

Comments
 (0)