diff --git a/src/rgen/Microsoft.Macios.Bindings.Analyzer/Microsoft.Macios.Bindings.Analyzer.csproj b/src/rgen/Microsoft.Macios.Bindings.Analyzer/Microsoft.Macios.Bindings.Analyzer.csproj
index 50e69ddd6a51..ca1f355f8e9d 100644
--- a/src/rgen/Microsoft.Macios.Bindings.Analyzer/Microsoft.Macios.Bindings.Analyzer.csproj
+++ b/src/rgen/Microsoft.Macios.Bindings.Analyzer/Microsoft.Macios.Bindings.Analyzer.csproj
@@ -60,6 +60,9 @@
Generator/Attributes/UnsupportedOSPlatformData.cs
+
+ Generator/Extensions/ApplePlatformExtensions.cs
+
Generator/Extensions/CompilationExtensions.cs
@@ -72,17 +75,8 @@
Generator/Extensions/StringExtensions.cs
-
- Generator/Availability/PlatformAvailability.cs
-
-
- Generator/Availability/PlatformAvailabilityBuilder.cs
-
-
- Generator/Availability/SymbolAvailability.cs
-
-
- Generator/Availability/SymbolAvailabilityBuilder.cs
+
+ Generator/Availability/*.cs
True
diff --git a/src/rgen/Microsoft.Macios.Generator/Availability/AvailabilityTrivia.cs b/src/rgen/Microsoft.Macios.Generator/Availability/AvailabilityTrivia.cs
new file mode 100644
index 000000000000..ce8c43729e33
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/Availability/AvailabilityTrivia.cs
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Generic;
+using Microsoft.Macios.Generator.Extensions;
+using Xamarin.Utils;
+
+namespace Microsoft.Macios.Generator.Availability;
+
+readonly struct AvailabilityTrivia {
+
+ ///
+ /// Retrieve the trivia to add before the symbol declaration.
+ ///
+ public string? Start { get; }
+
+ ///
+ /// Retrieve the trivia to add after the symbol declaration.
+ ///
+ public string? End { get; }
+
+ public AvailabilityTrivia (SymbolAvailability availability)
+ {
+ // trivia is calculated based on the availability of the symbol in each platform
+ // we will check each of the platforms and decide for the shorts #if possible
+ var supportedPlatforms = new HashSet ();
+ var unsupportedPlatforms = new HashSet ();
+ foreach (var platformAvailability in availability.PlatformAvailabilities) {
+ var platformDefine = platformAvailability.Platform.ToPlatformDefine ();
+ if (platformDefine is null)
+ continue;
+
+ if (platformAvailability.IsSupported)
+ supportedPlatforms.Add (platformDefine);
+ else
+ unsupportedPlatforms.Add (platformDefine);
+ }
+
+ // if all platforms are supported, we don't need any trivia
+ if (unsupportedPlatforms.Count == 0) {
+ // all platforms are supported
+ Start = null;
+ End = null;
+ return;
+ }
+
+ if (supportedPlatforms.Count > unsupportedPlatforms.Count) {
+ // we have more supported platforms than unsupported ones
+ // we will use #if to exclude the unsupported platforms
+ Start = $"#if !{string.Join (" && !", unsupportedPlatforms)}";
+ End = "#endif";
+ } else {
+ // we have more unsupported platforms than supported ones
+ // we will use #if to include the supported platforms
+ Start = $"#if {string.Join (" || ", supportedPlatforms)}";
+ End = "#endif";
+ }
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailability.cs b/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailability.cs
index ba83bb51bed1..da94d3bf971a 100644
--- a/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailability.cs
+++ b/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailability.cs
@@ -36,14 +36,26 @@ namespace Microsoft.Macios.Generator.Availability;
///
/// Dictionary that contains all the obsoleted versions and their optional data.
///
- public readonly IReadOnlyDictionary UnsupportedVersions => unsupported;
+ public IReadOnlyDictionary UnsupportedVersions => unsupported;
readonly SortedDictionary obsoleted = new ();
///
/// The Dictionary which contains all the unsupported versions and their optional data.
///
- public readonly IReadOnlyDictionary ObsoletedVersions => obsoleted;
+ public IReadOnlyDictionary ObsoletedVersions => obsoleted;
+
+ ///
+ /// Return if the platform is supported.
+ ///
+ public bool IsSupported {
+ get {
+ // a platform is supported if:
+ // 1. The supported version is not null, either the default version or a specific one
+ // 2. The default version is not in the unsupported list
+ return SupportedVersion is not null && !unsupported.ContainsKey (defaultVersion);
+ }
+ }
///
@@ -53,6 +65,7 @@ namespace Microsoft.Macios.Generator.Availability;
/// True if the version is default.
public static bool IsDefaultVersion (Version version) => version == defaultVersion;
+
PlatformAvailability (ApplePlatform platform, Version? supportedVersion,
SortedDictionary unsupportedVersions,
SortedDictionary obsoletedVersions)
diff --git a/src/rgen/Microsoft.Macios.Generator/Availability/SymbolAvailability.cs b/src/rgen/Microsoft.Macios.Generator/Availability/SymbolAvailability.cs
index 29c3ab988327..da7983a06f52 100644
--- a/src/rgen/Microsoft.Macios.Generator/Availability/SymbolAvailability.cs
+++ b/src/rgen/Microsoft.Macios.Generator/Availability/SymbolAvailability.cs
@@ -33,6 +33,19 @@ public SymbolAvailability () { }
}
}
+ ///
+ /// Return the symbol trivia if it has any.
+ ///
+ public AvailabilityTrivia? Trivia {
+ get {
+ // just returns the trivia if it has any, null otherwise
+ var trivia = new AvailabilityTrivia (this);
+ if (trivia.Start is not null || trivia.End is not null)
+ return trivia;
+ return null;
+ }
+ }
+
///
/// Copy constructor.
///
diff --git a/src/rgen/Microsoft.Macios.Generator/Extensions/ApplePlatformExtensions.cs b/src/rgen/Microsoft.Macios.Generator/Extensions/ApplePlatformExtensions.cs
new file mode 100644
index 000000000000..d15da844a0d4
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/Extensions/ApplePlatformExtensions.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Xamarin.Utils;
+
+namespace Microsoft.Macios.Generator.Extensions;
+
+public static class ApplePlatformExtensions {
+
+ ///
+ /// Return the platform define for the given ApplePlatform for use in #if directives.
+ ///
+ /// Apple platform.
+ /// the platform define
+ public static string? ToPlatformDefine (this ApplePlatform self) => self switch {
+ ApplePlatform.iOS => "IOS",
+ ApplePlatform.TVOS => "TVOS",
+ ApplePlatform.MacOSX => "MONOMAC",
+ ApplePlatform.MacCatalyst => "__MACCATALYST__",
+ _ => null
+ };
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj b/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj
index d60881115b74..077f463f4f9d 100644
--- a/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj
+++ b/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj
@@ -45,6 +45,9 @@
Availability/*.cs
+
+ Extensions/ApplePlatformExtensions.cs
+
Extensions/ParameterSyntaxExtensions.cs
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/AvailabilityTriviaTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/AvailabilityTriviaTests.cs
new file mode 100644
index 000000000000..fe70fbfc74c4
--- /dev/null
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/AvailabilityTriviaTests.cs
@@ -0,0 +1,89 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.Macios.Generator.Attributes;
+using Microsoft.Macios.Generator.Availability;
+using Xunit;
+
+namespace Microsoft.Macios.Generator.Tests.Availability;
+
+public class AvailabilityTriviaTests {
+
+ [Fact]
+ public void AllSupportedPlatforms ()
+ {
+ SymbolAvailability.Builder builder = SymbolAvailability.CreateBuilder ();
+ builder.Add (new SupportedOSPlatformData ("ios12.0"));
+ builder.Add (new SupportedOSPlatformData ("tvos12.0"));
+ builder.Add (new SupportedOSPlatformData ("macos10.14"));
+ builder.Add (new SupportedOSPlatformData ("macCatalyst13.0"));
+ var availability = builder.ToImmutable ();
+ var trivia = new AvailabilityTrivia (availability);
+ Assert.Null (trivia.Start);
+ Assert.Null (trivia.End);
+ Assert.Null (availability.Trivia);
+ }
+
+ [Fact]
+ public void SomeUnsupportedVersions ()
+ {
+ SymbolAvailability.Builder builder = SymbolAvailability.CreateBuilder ();
+ builder.Add (new SupportedOSPlatformData ("ios12.0"));
+ builder.Add (new UnsupportedOSPlatformData ("ios9.0"));
+ builder.Add (new SupportedOSPlatformData ("tvos12.0"));
+ builder.Add (new SupportedOSPlatformData ("macos10.14"));
+ builder.Add (new SupportedOSPlatformData ("maccatalyst13.0"));
+ var availability = builder.ToImmutable ();
+ var trivia = new AvailabilityTrivia (availability);
+ Assert.Null (trivia.Start);
+ Assert.Null (trivia.End);
+ Assert.Null (availability.Trivia);
+ }
+
+ [Fact]
+ public void SingleFullyUnsupportedPlatform ()
+ {
+ SymbolAvailability.Builder builder = SymbolAvailability.CreateBuilder ();
+ builder.Add (new UnsupportedOSPlatformData ("ios"));
+ builder.Add (new SupportedOSPlatformData ("tvos12.0"));
+ builder.Add (new SupportedOSPlatformData ("macos10.14"));
+ builder.Add (new SupportedOSPlatformData ("maccatalyst13.0"));
+ var availability = builder.ToImmutable ();
+ var trivia = new AvailabilityTrivia (availability);
+ Assert.Equal ("#if !IOS", trivia.Start);
+ Assert.Equal ("#endif", trivia.End);
+ Assert.NotNull (availability.Trivia);
+ }
+
+ [Fact]
+ public void DoubleUnsupportedPlatform ()
+ {
+ SymbolAvailability.Builder builder = SymbolAvailability.CreateBuilder ();
+ builder.Add (new SupportedOSPlatformData ("ios"));
+ builder.Add (new SupportedOSPlatformData ("tvos12.0"));
+ builder.Add (new UnsupportedOSPlatformData ("macos"));
+ builder.Add (new UnsupportedOSPlatformData ("maccatalyst"));
+ var availability = builder.ToImmutable ();
+ var trivia = new AvailabilityTrivia (availability);
+ Assert.Equal ("#if IOS || TVOS", trivia.Start);
+ Assert.Equal ("#endif", trivia.End);
+ Assert.NotNull (availability.Trivia);
+ }
+
+ [Fact]
+ public void SingleSupportedPlatform ()
+ {
+ SymbolAvailability.Builder builder = SymbolAvailability.CreateBuilder ();
+ builder.Add (new SupportedOSPlatformData ("ios"));
+ builder.Add (new UnsupportedOSPlatformData ("tvos"));
+ builder.Add (new UnsupportedOSPlatformData ("macos"));
+ builder.Add (new UnsupportedOSPlatformData ("maccatalyst"));
+ var availability = builder.ToImmutable ();
+ var trivia = new AvailabilityTrivia (availability);
+ Assert.Equal ("#if IOS", trivia.Start);
+ Assert.Equal ("#endif", trivia.End);
+ Assert.NotNull (availability.Trivia);
+ }
+
+}