Skip to content

Commit

Permalink
[Rgen] Add the platform availability as part of the enum field change…
Browse files Browse the repository at this point in the history
…s struct. (#21843)

This way we keep track of the different changes of the availability not
only from the current enum value but from any possible changes in the
parent containers. This can be the enum itself or a class in case we
have a nested enum declaration.

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: GitHub Actions Autoformatter <[email protected]>
  • Loading branch information
3 people authored Dec 20, 2024
1 parent c9d052a commit 4af3d21
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ namespace Microsoft.Macios.Generator.Availability;
static readonly HashSet<ApplePlatform> supportedPlatforms =
[ApplePlatform.iOS, ApplePlatform.TVOS, ApplePlatform.MacOSX, ApplePlatform.MacCatalyst];

readonly SortedDictionary<ApplePlatform, PlatformAvailability?> availabilities;
readonly SortedDictionary<ApplePlatform, PlatformAvailability?> availabilities = new ();

public SymbolAvailability () { }

SymbolAvailability (Dictionary<ApplePlatform, PlatformAvailability?> platforms)
{
Expand Down
15 changes: 9 additions & 6 deletions src/rgen/Microsoft.Macios.Generator/DataModel/CodeChanges.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,16 @@ internal CodeChanges (BindingType bindingType, string fullyQualifiedSymbol)
Attributes = enumDeclaration.GetAttributeCodeChanges (semanticModel);
var bucket = ImmutableArray.CreateBuilder<EnumMember> ();
// loop over the fields and add those that contain a FieldAttribute
var enumValueDeclaration = enumDeclaration.Members.OfType<EnumMemberDeclarationSyntax> ();
foreach (var val in enumValueDeclaration) {
if (Skip (val, semanticModel))
var enumValueDeclarations = enumDeclaration.Members.OfType<EnumMemberDeclarationSyntax> ();
foreach (var declaration in enumValueDeclarations) {
if (Skip (declaration, semanticModel))
continue;
var memberName = val.Identifier.ToFullString ().Trim ();
var attributes = val.GetAttributeCodeChanges (semanticModel);
bucket.Add (new (memberName, attributes));
if (semanticModel.GetDeclaredSymbol (declaration) is not ISymbol symbol) {
continue;
}
var memberName = declaration.Identifier.ToFullString ().Trim ();
var attributes = declaration.GetAttributeCodeChanges (semanticModel);
bucket.Add (new (memberName, symbol.GetSupportedPlatforms (), attributes));
}

EnumMembers = bucket.ToImmutable ();
Expand Down
20 changes: 16 additions & 4 deletions src/rgen/Microsoft.Macios.Generator/DataModel/EnumMember.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.Macios.Generator.Availability;

namespace Microsoft.Macios.Generator.DataModel;

Expand All @@ -9,12 +10,16 @@ namespace Microsoft.Macios.Generator.DataModel;
/// reflected in the generated code.
/// </summary>
readonly struct EnumMember : IEquatable<EnumMember> {

/// <summary>
/// Get the name of the member.
/// </summary>
public string Name { get; }

/// <summary>
/// The platform availability of the enum value.
/// </summary>
public SymbolAvailability SymbolAvailability { get; }

/// <summary>
/// Get the attributes added to the member.
/// </summary>
Expand All @@ -24,24 +29,31 @@ namespace Microsoft.Macios.Generator.DataModel;
/// Create a new change that happened on a member.
/// </summary>
/// <param name="name">The name of the changed member.</param>
/// <param name="symbolAvailability">The symbol availability of the member.</param>
/// <param name="attributes">The list of attribute changes in the member.</param>
public EnumMember (string name, ImmutableArray<AttributeCodeChange> attributes)
public EnumMember (string name, SymbolAvailability symbolAvailability,
ImmutableArray<AttributeCodeChange> attributes)
{
Name = name;
SymbolAvailability = symbolAvailability;
Attributes = attributes;
}

/// <summary>
/// Create a new change that happened on a member.
/// </summary>
/// <param name="name">The name of the changed member.</param>
public EnumMember (string name) : this (name, []) { }
public EnumMember (string name) : this (name, new SymbolAvailability (), ImmutableArray<AttributeCodeChange>.Empty)
{
}

/// <inheritdoc />
public bool Equals (EnumMember other)
{
if (Name != other.Name)
return false;
if (SymbolAvailability != other.SymbolAvailability)
return false;
var attrComparer = new AttributesEqualityComparer ();
return attrComparer.Equals (Attributes, other.Attributes);
}
Expand All @@ -55,7 +67,7 @@ public override bool Equals (object? obj)
/// <inheritdoc />
public override int GetHashCode ()
{
return HashCode.Combine (Name, Attributes);
return HashCode.Combine (Name, SymbolAvailability, Attributes);
}

public static bool operator == (EnumMember x, EnumMember y)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public void CompareDifferentMembersLength ()
var changes1 = new CodeChanges (BindingType.SmartEnum, "name");
var changes2 = new CodeChanges (BindingType.SmartEnum, "name") {
EnumMembers = [
new EnumMember ("name", [])
new EnumMember ("name", new (), [])
],
};
Assert.False (comparer.Equals (changes1, changes2));
Expand All @@ -72,12 +72,12 @@ public void CompareDifferentMembers ()
{
var changes1 = new CodeChanges (BindingType.SmartEnum, "name") {
EnumMembers = [
new EnumMember ("name", [])
new EnumMember ("name", new (), [])
],
};
var changes2 = new CodeChanges (BindingType.SmartEnum, "name") {
EnumMembers = [
new EnumMember ("name2", [])
new EnumMember ("name2", new (), [])
],
};
Assert.False (comparer.Equals (changes1, changes2));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public void CompareDifferentMembersLength ()
var changes1 = new CodeChanges (BindingType.SmartEnum, "name");
var changes2 = new CodeChanges (BindingType.SmartEnum, "name") {
EnumMembers = [
new EnumMember ("name", [])
new EnumMember ("name", new (), [])
],
};
Assert.False (equalityComparer.Equals (changes1, changes2));
Expand All @@ -72,12 +72,12 @@ public void CompareDifferentMembers ()
{
var changes1 = new CodeChanges (BindingType.SmartEnum, "name") {
EnumMembers = [
new EnumMember ("name", [])
new EnumMember ("name", new (), [])
],
};
var changes2 = new CodeChanges (BindingType.SmartEnum, "name") {
EnumMembers = [
new EnumMember ("name2", [])
new EnumMember ("name2", new (), [])
],
};
Assert.False (equalityComparer.Equals (changes1, changes2));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Microsoft.Macios.Generator.Attributes;
using Microsoft.Macios.Generator.Availability;
using Microsoft.Macios.Generator.DataModel;
using Xunit;

Expand All @@ -7,8 +9,8 @@ public class EnumMemberCodeChangesTests {
[Fact]
public void EqualsNoParams ()
{
var memberCodeChange1 = new EnumMember ("name", []);
var memberCodeChange2 = new EnumMember ("name", []);
var memberCodeChange1 = new EnumMember ("name", new (), []);
var memberCodeChange2 = new EnumMember ("name", new (), []);
Assert.True (memberCodeChange1.Equals (memberCodeChange2));
Assert.True (memberCodeChange1 == memberCodeChange2);
Assert.False (memberCodeChange1 != memberCodeChange2);
Expand All @@ -17,10 +19,10 @@ public void EqualsNoParams ()
[Fact]
public void EqualsWithArgumentParams ()
{
var memberCodeChange1 = new EnumMember ("name", [
var memberCodeChange1 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name", ["arg1", "arg2"])
]);
var memberCodeChange2 = new EnumMember ("name", [
var memberCodeChange2 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name", ["arg1", "arg2"])
]);
Assert.True (memberCodeChange1.Equals (memberCodeChange2));
Expand All @@ -31,20 +33,20 @@ public void EqualsWithArgumentParams ()
[Fact]
public void NotEqualsDifferentName ()
{
var memberCodeChange1 = new EnumMember ("name", []);
var memberCodeChange2 = new EnumMember ("name2", []);
var memberCodeChange1 = new EnumMember ("name", new (), []);
var memberCodeChange2 = new EnumMember ("name2", new (), []);
Assert.False (memberCodeChange1.Equals (memberCodeChange2));
Assert.False (memberCodeChange1 == memberCodeChange2);
Assert.True (memberCodeChange1 != memberCodeChange2);
}

[Fact]
public void NotEqualsDiffenretAttributeNames ()
public void NotEqualsDifferentAttributeNames ()
{
var memberCodeChange1 = new EnumMember ("name", [
var memberCodeChange1 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name", ["arg1", "arg2"])
]);
var memberCodeChange2 = new EnumMember ("name", [
var memberCodeChange2 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name2", ["arg1", "arg2"])
]);
Assert.False (memberCodeChange1.Equals (memberCodeChange2));
Expand All @@ -55,10 +57,10 @@ public void NotEqualsDiffenretAttributeNames ()
[Fact]
public void NotEqualsDifferentAttributeParams ()
{
var memberCodeChange1 = new EnumMember ("name", [
var memberCodeChange1 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name", ["arg1", "arg2"])
]);
var memberCodeChange2 = new EnumMember ("name", [
var memberCodeChange2 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name", ["arg1", "arg3"])
]);
Assert.False (memberCodeChange1.Equals (memberCodeChange2));
Expand All @@ -69,10 +71,10 @@ public void NotEqualsDifferentAttributeParams ()
[Fact]
public void NotEqualsDifferentAttributeParamsOrder ()
{
var memberCodeChange1 = new EnumMember ("name", [
var memberCodeChange1 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name", ["arg1", "arg2"])
]);
var memberCodeChange2 = new EnumMember ("name", [
var memberCodeChange2 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name", ["arg2", "arg1"])
]);
Assert.False (memberCodeChange1.Equals (memberCodeChange2));
Expand All @@ -83,12 +85,32 @@ public void NotEqualsDifferentAttributeParamsOrder ()
[Fact]
public void NotEqualsDifferentAttributesCount ()
{
var memberCodeChange1 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name", ["arg1", "arg2"]),
new AttributeCodeChange ("name2", [])
]);
var memberCodeChange2 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name", ["arg2", "arg1"])
]);
Assert.False (memberCodeChange1.Equals (memberCodeChange2));
Assert.False (memberCodeChange1 == memberCodeChange2);
Assert.True (memberCodeChange1 != memberCodeChange2);
}

[Fact]
public void NotEqualsDifferentPlatformAvailability ()
{
var builder = SymbolAvailability.CreateBuilder ();
builder.Add (new SupportedOSPlatformData ("ios"));
builder.Add (new SupportedOSPlatformData ("tvos"));
builder.Add (new UnsupportedOSPlatformData ("tvos"));
var availability = builder.ToImmutable ();

var memberCodeChange1 = new EnumMember ("name", [
var memberCodeChange1 = new EnumMember ("name", availability, [
new AttributeCodeChange ("name", ["arg1", "arg2"]),
new AttributeCodeChange ("name2", [])
]);
var memberCodeChange2 = new EnumMember ("name", [
var memberCodeChange2 = new EnumMember ("name", new (), [
new AttributeCodeChange ("name", ["arg2", "arg1"])
]);
Assert.False (memberCodeChange1.Equals (memberCodeChange2));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Immutable;
using Microsoft.Macios.Generator.Availability;
using Microsoft.Macios.Generator.DataModel;
using Xunit;

Expand All @@ -16,32 +17,32 @@ public EnumMembersEqualityComparerTests ()
[Fact]
public void NotEqualsDiffLength ()
{
ImmutableArray<EnumMember> x = [new ("name", []), new ("name1")];
ImmutableArray<EnumMember> y = [new ("name", [])];
ImmutableArray<EnumMember> x = [new ("name", new (), []), new ("name1")];
ImmutableArray<EnumMember> y = [new ("name", new (), [])];
Assert.False (comparer.Equals (x, y));
}

[Fact]
public void NotEqualsDiffAttributes ()
{
ImmutableArray<EnumMember> x = [new ("name", []), new ("name1")];
ImmutableArray<EnumMember> y = [new ("name1", []), new ("name1")];
ImmutableArray<EnumMember> x = [new ("name", new (), []), new ("name1")];
ImmutableArray<EnumMember> y = [new ("name1", new (), []), new ("name1")];
Assert.False (comparer.Equals (x, y));
}

[Fact]
public void EqualsSameOrder ()
{
ImmutableArray<EnumMember> x = [new ("name", []), new ("name1")];
ImmutableArray<EnumMember> y = [new ("name", []), new ("name1")];
ImmutableArray<EnumMember> x = [new ("name", new SymbolAvailability (), []), new ("name1")];
ImmutableArray<EnumMember> y = [new ("name", new SymbolAvailability (), []), new ("name1")];
Assert.True (comparer.Equals (x, y));
}

[Fact]
public void EqualsDiffOrder ()
{
ImmutableArray<EnumMember> x = [new ("name1", []), new ("name")];
ImmutableArray<EnumMember> y = [new ("name", []), new ("name1")];
ImmutableArray<EnumMember> x = [new ("name1", new (), []), new ("name")];
ImmutableArray<EnumMember> y = [new ("name", new (), []), new ("name1")];
Assert.True (comparer.Equals (x, y));
}
}

10 comments on commit 4af3d21

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.