diff --git a/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailabilityBuilder.cs b/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailabilityBuilder.cs
index 0c9905c9d014..0b1677cbf1bb 100644
--- a/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailabilityBuilder.cs
+++ b/src/rgen/Microsoft.Macios.Generator/Availability/PlatformAvailabilityBuilder.cs
@@ -84,6 +84,11 @@ internal void AddUnsupportedVersion (Version version, string? message)
if (unsupported.ContainsKey (defaultVersion))
return;
unsupported [version] = message;
+ // we need to ensure that if we unsupported a version that the supported version is not null, if
+ // it is, we need to set it to the version before the unsupported one
+ if (supportedVersion is null) {
+ supportedVersion = defaultVersion;
+ }
}
}
diff --git a/src/rgen/Microsoft.Macios.Generator/Availability/SymbolAvailability.cs b/src/rgen/Microsoft.Macios.Generator/Availability/SymbolAvailability.cs
index da7983a06f52..fc97c14c94bb 100644
--- a/src/rgen/Microsoft.Macios.Generator/Availability/SymbolAvailability.cs
+++ b/src/rgen/Microsoft.Macios.Generator/Availability/SymbolAvailability.cs
@@ -129,6 +129,16 @@ public SymbolAvailability MergeWithParent (SymbolAvailability? parent)
return new (merged);
}
+ ///
+ /// Returns true if the symbol is supported in the given platform.
+ ///
+ public bool IsSupported (ApplePlatform platform)
+ {
+ // if the platform is not present, it is supported by default
+ var availability = this [platform];
+ return availability is null || availability.Value.IsSupported;
+ }
+
///
public bool Equals (SymbolAvailability other)
{
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Binding.Generator.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Binding.Generator.cs
index 772ed10ed40d..420c4474f493 100644
--- a/src/rgen/Microsoft.Macios.Generator/DataModel/Binding.Generator.cs
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Binding.Generator.cs
@@ -11,6 +11,7 @@
using Microsoft.Macios.Generator.Availability;
using Microsoft.Macios.Generator.Context;
using Microsoft.Macios.Generator.Extensions;
+using Xamarin.Utils;
namespace Microsoft.Macios.Generator.DataModel;
@@ -263,7 +264,7 @@ internal static bool Skip (MethodDeclarationSyntax methodDeclarationSyntax, Sema
/// The fully qualified name of the symbol.
/// The platform availability of the named symbol.
internal Binding (BindingInfo bindingInfo, string name, ImmutableArray @namespace,
- string fullyQualifiedSymbol, SymbolAvailability symbolAvailability)
+ string fullyQualifiedSymbol, SymbolAvailability symbolAvailability) : this (StructState.Initialized)
{
this.bindingInfo = bindingInfo;
this.name = name;
@@ -278,7 +279,8 @@ internal Binding (BindingInfo bindingInfo, string name, ImmutableArray @
/// The enum declaration that triggered the change.
/// The root binding context of the current compilation.
/// If the struct should validate the members from the declarations. Defaults to true.
- Binding (EnumDeclarationSyntax enumDeclaration, RootContext context, bool validateMembers = true)
+ Binding (EnumDeclarationSyntax enumDeclaration, RootContext context,
+ bool validateMembers = true) : this (StructState.Initialized)
{
context.SemanticModel.GetSymbolData (
declaration: enumDeclaration,
@@ -346,7 +348,8 @@ internal Binding (BindingInfo bindingInfo, string name, ImmutableArray @
/// The class declaration that triggered the change.
/// The root binding context of the current compilation.
/// If the struct should validate the members from the declarations. Defaults to true.
- Binding (ClassDeclarationSyntax classDeclaration, RootContext context, bool validateMembers = true)
+ Binding (ClassDeclarationSyntax classDeclaration, RootContext context,
+ bool validateMembers = true) : this (StructState.Initialized)
{
context.SemanticModel.GetSymbolData (
declaration: classDeclaration,
@@ -392,7 +395,8 @@ internal Binding (BindingInfo bindingInfo, string name, ImmutableArray @
/// The interface declaration that triggered the change.
/// The root binding context of the current compilation.
/// If the struct should validate the members from the declarations. Defaults to true.
- Binding (InterfaceDeclarationSyntax interfaceDeclaration, RootContext context, bool validateMembers = true)
+ Binding (InterfaceDeclarationSyntax interfaceDeclaration, RootContext context,
+ bool validateMembers = true) : this (StructState.Initialized)
{
context.SemanticModel.GetSymbolData (
declaration: interfaceDeclaration,
@@ -471,6 +475,7 @@ internal Binding (BindingInfo bindingInfo, string name, ImmutableArray @
public override string ToString ()
{
var sb = new StringBuilder ("Changes: {");
+ sb.Append ($"State: {State}, ");
sb.Append ($"BindingData: '{BindingInfo}', Name: '{Name}', Namespace: [");
sb.AppendJoin (", ", Namespace);
sb.Append ($"], FullyQualifiedSymbol: '{FullyQualifiedSymbol}', Base: '{Base ?? "null"}', SymbolAvailability: {SymbolAvailability}, ");
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Binding.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Binding.cs
index daf4f916ee2b..5f97150c84ba 100644
--- a/src/rgen/Microsoft.Macios.Generator/DataModel/Binding.cs
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Binding.cs
@@ -9,8 +9,10 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.Macios.Generator.Attributes;
using Microsoft.Macios.Generator.Availability;
using Microsoft.Macios.Generator.Context;
+using Xamarin.Utils;
namespace Microsoft.Macios.Generator.DataModel;
@@ -21,6 +23,22 @@ namespace Microsoft.Macios.Generator.DataModel;
[StructLayout (LayoutKind.Auto)]
readonly partial struct Binding {
+ ///
+ /// The initialization state of the struct.
+ ///
+ StructState State { get; init; } = StructState.Default;
+
+
+ ///
+ /// Gets the default, uninitialized instance of .
+ ///
+ public static Binding Default { get; } = new (StructState.Default);
+
+ ///
+ /// Gets a value indicating whether the instance is the default, uninitialized instance.
+ ///
+ public bool IsNullOrDefault => State == StructState.Default;
+
readonly string name = string.Empty;
///
/// The name of the named type that generated the code change.
@@ -417,4 +435,44 @@ public bool TryGetEvent (string selector, out Event? @event)
/// True if the method was found. False otherwise.
public bool TryGetMethod (string selector, out Method? method)
=> TryGetFromIndex (selector, methods, methodIndex, out method);
+
+ ///
+ /// Initializes a new instance of the struct with a specific state.
+ ///
+ /// The initialization state of the struct.
+ public Binding (StructState state)
+ {
+ State = state;
+ FullyQualifiedSymbol = string.Empty;
+ }
+
+ ///
+ /// Creates a new binding containing only the members available for a specific platform.
+ ///
+ /// The Apple platform to filter members for.
+ ///
+ /// A new instance with members filtered for the specified platform,
+ /// or the default binding if the type itself is not available on the platform.
+ ///
+ public Binding TrimForPlatform (ApplePlatform platform)
+ {
+ // if the binding is not available in the given platform, return an empty binding
+ if (!SymbolAvailability.IsSupported (platform))
+ return Default;
+
+ // collect all the different members that we are going to keep and return the same data but
+ // without those members that are not available in the given platform
+ return this with {
+ EnumMembers = [.. enumMembers.Where (m => m.SymbolAvailability.IsSupported (platform))],
+ Properties = [.. properties.Where (p => p.SymbolAvailability.IsSupported (platform))],
+ ParentProtocolProperties = [.. parentProperties.Where (p => p.SymbolAvailability.IsSupported (platform))],
+ StrongDictionaryProperties = [.. strongDictproperties.Where (p => p.SymbolAvailability.IsSupported (platform))],
+ Constructors = [.. constructors.Where (c => c.SymbolAvailability.IsSupported (platform))],
+ Events = [.. events.Where (e => e.SymbolAvailability.IsSupported (platform))],
+ Methods = [.. methods.Where (m => m.SymbolAvailability.IsSupported (platform))],
+ ParentProtocolMethods = [.. parentMethods.Where (m => m.SymbolAvailability.IsSupported (platform))],
+ };
+
+ }
+
}
diff --git a/src/rgen/Microsoft.Macios.Transformer/DataModel/Binding.Transformer.cs b/src/rgen/Microsoft.Macios.Transformer/DataModel/Binding.Transformer.cs
index 4028746fd0eb..5f49e9231a62 100644
--- a/src/rgen/Microsoft.Macios.Transformer/DataModel/Binding.Transformer.cs
+++ b/src/rgen/Microsoft.Macios.Transformer/DataModel/Binding.Transformer.cs
@@ -57,7 +57,7 @@ internal Binding (string name,
string fullyQualifiedSymbol,
BindingInfo bindingInfo,
SymbolAvailability symbolAvailability,
- Dictionary> attributes)
+ Dictionary> attributes) : this (StructState.Initialized)
{
this.name = name;
namespaces = @namespace;
@@ -67,7 +67,8 @@ internal Binding (string name,
FullyQualifiedSymbol = fullyQualifiedSymbol;
}
- internal Binding (EnumDeclarationSyntax enumDeclaration, INamedTypeSymbol symbol, in RootContext context)
+ internal Binding (EnumDeclarationSyntax enumDeclaration, INamedTypeSymbol symbol,
+ in RootContext context) : this (StructState.Initialized)
{
SemanticModelExtensions.GetSymbolData (
symbol: symbol,
@@ -269,7 +270,8 @@ internal static bool Skip (MethodDeclarationSyntax methodDeclarationSyntax, Sema
/// An interface that declares a binding.
///
/// The current compilation context.
- internal Binding (InterfaceDeclarationSyntax interfaceDeclarationSyntax, INamedTypeSymbol symbol, in RootContext context)
+ internal Binding (InterfaceDeclarationSyntax interfaceDeclarationSyntax, INamedTypeSymbol symbol,
+ in RootContext context) : this (StructState.Initialized)
{
BaseDeclarationSyntax = interfaceDeclarationSyntax;
// basic properties of the binding
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityTests.cs
index 9b4a78eeec10..f0ddad2dec94 100644
--- a/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityTests.cs
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityTests.cs
@@ -112,6 +112,7 @@ public void UnsupportPlatform (ApplePlatform platform, string attributePlatformN
Assert.Contains (defaultVersion, availability.UnsupportedVersions.Keys);
Assert.Single (availability.UnsupportedVersions);
Assert.Null (availability.UnsupportedVersions [defaultVersion]);
+ Assert.Null (availability.SupportedVersion);
}
[Theory]
@@ -129,6 +130,7 @@ public void UnsupportPlatformWithMessage (ApplePlatform platform, string attribu
Assert.Contains (defaultVersion, availability.UnsupportedVersions.Keys);
Assert.Single (availability.UnsupportedVersions);
Assert.Equal (message, availability.UnsupportedVersions [defaultVersion]);
+ Assert.Null (availability.SupportedVersion);
}
[Theory]
@@ -150,6 +152,8 @@ public void UnsupportVersionAndPlatform (ApplePlatform platform, string attribut
Assert.Contains (defaultVersion, availability.UnsupportedVersions.Keys);
Assert.Single (availability.UnsupportedVersions);
Assert.Equal (message, availability.UnsupportedVersions [defaultVersion]);
+ // we fully unsupported the platform
+ Assert.Null (availability.SupportedVersion);
}
[Theory]
diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityToStringTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityToStringTests.cs
index 1072fd9fca2e..524d4848dc23 100644
--- a/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityToStringTests.cs
+++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/PlatformAvailabilityToStringTests.cs
@@ -26,16 +26,16 @@ public IEnumerator