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 GetEnumerator () builder.Clear (); builder.AddUnsupportedVersion (new Version (16, 0), null); - yield return [builder.ToImmutable (), "{ Platform: 'iOS', Supported: '', Unsupported: ['16.0': 'null'], Obsoleted: [] }"]; + yield return [builder.ToImmutable (), "{ Platform: 'iOS', Supported: '0.0', Unsupported: ['16.0': 'null'], Obsoleted: [] }"]; builder.Clear (); builder.AddUnsupportedVersion (new Version (16, 0), "Not supported."); - yield return [builder.ToImmutable (), "{ Platform: 'iOS', Supported: '', Unsupported: ['16.0': 'Not supported.'], Obsoleted: [] }"]; + yield return [builder.ToImmutable (), "{ Platform: 'iOS', Supported: '0.0', Unsupported: ['16.0': 'Not supported.'], Obsoleted: [] }"]; builder.Clear (); builder.AddUnsupportedVersion (new Version (16, 0), "Not supported."); builder.AddUnsupportedVersion (new Version (18, 0), "Not supported."); - yield return [builder.ToImmutable (), "{ Platform: 'iOS', Supported: '', Unsupported: ['16.0': 'Not supported.', '18.0': 'Not supported.'], Obsoleted: [] }"]; + yield return [builder.ToImmutable (), "{ Platform: 'iOS', Supported: '0.0', Unsupported: ['16.0': 'Not supported.', '18.0': 'Not supported.'], Obsoleted: [] }"]; builder.Clear (); builder.AddObsoletedVersion (new Version (16, 0), null, null); diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/SymbolAvailabilityToStringTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/SymbolAvailabilityToStringTests.cs index 626164ddf1eb..be5968311e0b 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/SymbolAvailabilityToStringTests.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Availability/SymbolAvailabilityToStringTests.cs @@ -43,7 +43,7 @@ public IEnumerator GetEnumerator () builder.AddSupportedVersion (ApplePlatform.iOS, new (16, 0)); builder.AddUnsupportedVersion (ApplePlatform.MacOSX, new (11, 0), null); builder.AddSupportedVersion (ApplePlatform.MacCatalyst, new (16, 0)); - yield return [builder.ToImmutable (), "[{ Platform: 'MacOSX', Supported: '', Unsupported: ['11.0': 'null'], Obsoleted: [] }, { Platform: 'iOS', Supported: '16.0', Unsupported: [], Obsoleted: [] }, { Platform: 'MacCatalyst', Supported: '16.0', Unsupported: [], Obsoleted: [] }]"]; + yield return [builder.ToImmutable (), "[{ Platform: 'MacOSX', Supported: '0.0', Unsupported: ['11.0': 'null'], Obsoleted: [] }, { Platform: 'iOS', Supported: '16.0', Unsupported: [], Obsoleted: [] }, { Platform: 'MacCatalyst', Supported: '16.0', Unsupported: [], Obsoleted: [] }]"]; } IEnumerator IEnumerable.GetEnumerator () diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/DataModel/BindingTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/DataModel/BindingTests.cs index bdf47b321f12..33d59c6b4052 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/DataModel/BindingTests.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/DataModel/BindingTests.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.Macios.Generator.Attributes; +using Microsoft.Macios.Generator.Context; using Microsoft.Macios.Generator.DataModel; using Xamarin.Tests; using Xamarin.Utils; @@ -259,6 +260,362 @@ public void SkipMethodDeclaration (ApplePlatform platform, string inputText, boo Assert.Equal (expected, Binding.Skip (node, semanticModel)); } + class TestDataTrimForPlatform : IEnumerable { + public IEnumerator GetEnumerator () + { + // Binding not supported in platform - should return Default + var bindingNotSupported = @" +using System; +using System.Runtime.Versioning; +using Foundation; +using ObjCBindings; +using ObjCRuntime; + +namespace NS { + [UnsupportedOSPlatform (""tvos"")] + [BindingType] + public partial class MyClass { + [Export (""method1"")] + public virtual partial void Method1 (); + } +} +"; + yield return [bindingNotSupported, ApplePlatform.TVOS, true, 0, 0, 0]; + + // All members supported - should return all + var allMembersSupported = @" +using System; +using System.Runtime.Versioning; +using Foundation; +using ObjCBindings; +using ObjCRuntime; + +namespace NS { + [BindingType] + public partial class MyClass { + [Export (""init"")] + public MyClass () {} + + [Export (""method1"")] + public virtual partial void Method1 (); + + [Export (""property1"")] + public virtual partial string Property1 { get; set; } + } +} +"; + yield return [allMembersSupported, ApplePlatform.iOS, false, 1, 1, 1]; + + // Mixed platform support - some members excluded + var mixedSupport = @" +using System; +using System.Runtime.Versioning; +using Foundation; +using ObjCBindings; +using ObjCRuntime; + +namespace NS { + [BindingType] + public partial class MyClass { + [Export (""init"")] + public MyClass (); + + [UnsupportedOSPlatform (""tvos"")] + [Export (""init2"")] + public MyClass (string value); + + [Export (""method1"")] + public virtual partial void Method1 (); + + [UnsupportedOSPlatform (""tvos"")] + [Export (""method2"")] + public virtual partial void Method2 (); + + [Export (""property1"")] + public virtual partial string Property1 { get; set; } + + [UnsupportedOSPlatform (""tvos"")] + [Export (""property2"")] + public virtual partial string Property2 { get; set; } + } +} +"; + yield return [mixedSupport, ApplePlatform.TVOS, false, 1, 1, 1]; + yield return [mixedSupport, ApplePlatform.iOS, false, 2, 2, 2]; + + // No constructors supported in platform + var noConstructorsSupported = @" +using System; +using System.Runtime.Versioning; +using Foundation; +using ObjCBindings; +using ObjCRuntime; + +namespace NS { + [BindingType] + public partial class MyClass { + [UnsupportedOSPlatform (""tvos"")] + [Export (""init"")] + public MyClass (); + + [UnsupportedOSPlatform (""tvos"")] + [Export (""init2"")] + public MyClass (string value); + + [Export (""method1"")] + public virtual partial void Method1 (); + + [Export (""property1"")] + public virtual partial string Property1 { get; set; } + } +} +"; + yield return [noConstructorsSupported, ApplePlatform.TVOS, false, 0, 1, 1]; + + // No methods supported in platform + var noMethodsSupported = @" +using System; +using System.Runtime.Versioning; +using Foundation; +using ObjCBindings; +using ObjCRuntime; + +namespace NS { + [BindingType] + public partial class MyClass { + [Export (""init"")] + public MyClass (); + + [UnsupportedOSPlatform (""tvos"")] + [Export (""method1"")] + public virtual partial void Method1 (); + + [UnsupportedOSPlatform (""tvos"")] + [Export (""method2"")] + public virtual partial void Method2 (); + + [Export (""property1"")] + public virtual partial string Property1 { get; set; } + } +} +"; + yield return [noMethodsSupported, ApplePlatform.TVOS, false, 1, 0, 1]; + + // No properties supported in platform + var noPropertiesSupported = @" +using System; +using System.Runtime.Versioning; +using Foundation; +using ObjCBindings; +using ObjCRuntime; + +namespace NS { + [BindingType] + public partial class MyClass { + [Export (""init"")] + public MyClass (); + + [Export (""method1"")] + public virtual partial void Method1 (); + + [UnsupportedOSPlatform (""tvos"")] + [Export (""property1"")] + public virtual partial string Property1 { get; set; } + + [UnsupportedOSPlatform (""tvos"")] + [Export (""property2"")] + public virtual partial string Property2 { get; set; } + } +} +"; + yield return [noPropertiesSupported, ApplePlatform.TVOS, false, 1, 1, 0]; + + // Platform-specific availability with iOS version constraints + var versionConstraints = @" +using System; +using System.Runtime.Versioning; +using Foundation; +using ObjCBindings; +using ObjCRuntime; + +namespace NS { + [BindingType] + public partial class MyClass { + [Export (""init"")] + public MyClass (); + + [SupportedOSPlatform (""ios15.0"")] + [Export (""newMethod"")] + public virtual partial void NewMethod (); + + [SupportedOSPlatform (""ios14.0"")] + [Export (""newProperty"")] + public virtual partial string NewProperty { get; set; } + } +} +"; + yield return [versionConstraints, ApplePlatform.iOS, false, 1, 1, 1]; + yield return [versionConstraints, ApplePlatform.TVOS, false, 1, 0, 0]; + + // not supported platform + var notSupportedPlatform = @" +using System; +using System.Runtime.Versioning; +using Foundation; +using ObjCBindings; +using ObjCRuntime; + +namespace NS { + [BindingType] + [UnsupportedOSPlatform (""tvos""] + public partial class MyClass { + [Export (""init"")] + public MyClass (); + + [SupportedOSPlatform (""ios15.0"")] + [Export (""newMethod"")] + public virtual partial void NewMethod (); + + [SupportedOSPlatform (""ios14.0"")] + [Export (""newProperty"")] + public virtual partial string NewProperty { get; set; } + } +} +"; + yield return [notSupportedPlatform, ApplePlatform.TVOS, true, 0, 0, 0]; + + // not supported platform version. It means that we do not return the default binding, just + // that we have a unsupported version. + var notSupportedPlatformVersion = @" +using System; +using System.Runtime.Versioning; +using Foundation; +using ObjCBindings; +using ObjCRuntime; + +namespace NS { + [BindingType] + [UnsupportedOSPlatform (""tvos14.0""] + public partial class MyClass { + [Export (""init"")] + public MyClass (); + + [SupportedOSPlatform (""ios15.0"")] + [Export (""newMethod"")] + public virtual partial void NewMethod (); + + [SupportedOSPlatform (""ios14.0"")] + [Export (""newProperty"")] + public virtual partial string NewProperty { get; set; } + } +} +"; + yield return [notSupportedPlatformVersion, ApplePlatform.TVOS, false, 1, 1, 1]; + + var complexExample = @" +using System; +using System.Runtime.Versioning; +using Foundation; +using ObjCBindings; +using ObjCRuntime; + +namespace NS { + [BindingType] + [SupportedOSPlatform (""ios""] + [SupportedOSPlatform (""macos""] + [SupportedOSPlatform (""maccatalyst13.0""] + [UnsupportedOSPlatform (""tvos""] + public partial class MyClass { + + [SupportedOSPlatform (""tvos14.0""] + [Export (""init"")] + public MyClass (); + + [SupportedOSPlatform (""tvos14.0""] + [SupportedOSPlatform (""ios15.0"")] + [UnsupportedOSPlatform (""maccatalyst""] + [Export (""newMethod"")] + public virtual partial void NewMethod (); + + [SupportedOSPlatform (""tvos14.0""] + [SupportedOSPlatform (""ios14.0"")] + [UnsupportedOSPlatform (""macos""] + [Export (""newProperty"")] + public virtual partial string NewProperty { get; set; } + } +} +"; + // tvos should return default + yield return [complexExample, ApplePlatform.TVOS, true, 0, 0, 0]; + // contains all of the constructors, methods andproperties + yield return [complexExample, ApplePlatform.iOS, false, 1, 1, 1]; + // missing method + yield return [complexExample, ApplePlatform.MacCatalyst, false, 1, 0, 1]; + // missing property + yield return [complexExample, ApplePlatform.MacOSX, false, 1, 1, 0]; + } + + IEnumerator IEnumerable.GetEnumerator () => GetEnumerator (); + } + + [Theory] + [AllSupportedPlatformsClassData] + public void TrimForPlatformTest (ApplePlatform platform, string inputText, ApplePlatform targetPlatform, + bool shouldReturnDefault, int expectedConstructors, int expectedMethods, int expectedProperties) + { + var (compilation, sourceTrees) = CreateCompilation (platform, sources: inputText); + Assert.Single (sourceTrees); + + var semanticModel = compilation.GetSemanticModel (sourceTrees [0]); + var declaration = sourceTrees [0].GetRoot () + .DescendantNodes ().OfType () + .FirstOrDefault (); + Assert.NotNull (declaration); + var context = new RootContext (semanticModel); + + var binding = Binding.FromDeclaration (declaration, context); + Assert.NotNull (binding); + + var trimmedBinding = binding.Value.TrimForPlatform (targetPlatform); + + if (shouldReturnDefault) { + Assert.True (trimmedBinding.IsNullOrDefault); + return; + } + + Assert.False (trimmedBinding.IsNullOrDefault); + + // Validate constructors + Assert.Equal (expectedConstructors, trimmedBinding.Constructors.Length); + foreach (var constructor in trimmedBinding.Constructors) { + Assert.True (constructor.SymbolAvailability.IsSupported (targetPlatform), + $"Constructor {constructor.Type} should be supported on {targetPlatform}"); + } + + // Validate methods + Assert.Equal (expectedMethods, trimmedBinding.Methods.Length); + foreach (var method in trimmedBinding.Methods) { + Assert.True (method.SymbolAvailability.IsSupported (targetPlatform), + $"Method {method.Name} should be supported on {targetPlatform}"); + } + + // Validate properties + Assert.Equal (expectedProperties, trimmedBinding.Properties.Length); + foreach (var property in trimmedBinding.Properties) { + Assert.True (property.SymbolAvailability.IsSupported (targetPlatform), + $"Property {property.Name} should be supported on {targetPlatform}"); + } + + // Ensure no extra members are included by checking original binding + var originalConstructorsCount = binding.Value.Constructors.Count (c => c.SymbolAvailability.IsSupported (targetPlatform)); + var originalMethodsCount = binding.Value.Methods.Count (m => m.SymbolAvailability.IsSupported (targetPlatform)); + var originalPropertiesCount = binding.Value.Properties.Count (p => p.SymbolAvailability.IsSupported (targetPlatform)); + + Assert.Equal (originalConstructorsCount, trimmedBinding.Constructors.Length); + Assert.Equal (originalMethodsCount, trimmedBinding.Methods.Length); + Assert.Equal (originalPropertiesCount, trimmedBinding.Properties.Length); + } + [Fact] public void EnumIndexTest () { @@ -467,3 +824,4 @@ public void MethodIndexTest () Assert.NotNull (member); } } + diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/IO/TabbedStringBuilderTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/IO/TabbedStringBuilderTests.cs index 2aeb9ad07db0..65baa0dd0663 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/IO/TabbedStringBuilderTests.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/IO/TabbedStringBuilderTests.cs @@ -461,7 +461,7 @@ public static IEnumerable AppendMemberAvailabilityTestData { builder.Add (new UnsupportedOSPlatformData ("ios12.0")); builder.Add (new UnsupportedOSPlatformData ("tvos12.0")); builder.Add (new UnsupportedOSPlatformData ("macos")); - yield return [builder.ToImmutable (), "[UnsupportedOSPlatform (\"macos\")]\n[UnsupportedOSPlatform (\"ios12.0\")]\n[UnsupportedOSPlatform (\"tvos12.0\")]\n"]; + yield return [builder.ToImmutable (), "[UnsupportedOSPlatform (\"macos\")]\n[SupportedOSPlatform (\"ios\")]\n[UnsupportedOSPlatform (\"ios12.0\")]\n[SupportedOSPlatform (\"tvos\")]\n[UnsupportedOSPlatform (\"tvos12.0\")]\n"]; builder.Clear (); } } diff --git a/tests/rgen/Microsoft.Macios.Transformer.Tests/IO/TabbedStreamWriterTests.cs b/tests/rgen/Microsoft.Macios.Transformer.Tests/IO/TabbedStreamWriterTests.cs index 573cc8603423..2b53faeb76bd 100644 --- a/tests/rgen/Microsoft.Macios.Transformer.Tests/IO/TabbedStreamWriterTests.cs +++ b/tests/rgen/Microsoft.Macios.Transformer.Tests/IO/TabbedStreamWriterTests.cs @@ -259,7 +259,7 @@ public static IEnumerable AppendMemberAvailabilityTestData () builder.Add (new UnsupportedOSPlatformData ("ios12.0")); builder.Add (new UnsupportedOSPlatformData ("tvos12.0")); builder.Add (new UnsupportedOSPlatformData ("macos")); - yield return [builder.ToImmutable (), "[UnsupportedOSPlatform (\"macos\")]\n[UnsupportedOSPlatform (\"ios12.0\")]\n[UnsupportedOSPlatform (\"tvos12.0\")]\n"]; + yield return [builder.ToImmutable (), "[UnsupportedOSPlatform (\"macos\")]\n[SupportedOSPlatform (\"ios\")]\n[UnsupportedOSPlatform (\"ios12.0\")]\n[SupportedOSPlatform (\"tvos\")]\n[UnsupportedOSPlatform (\"tvos12.0\")]\n"]; builder.Clear (); }