Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Rgen] Keep track of properties/methods/ctrs that use smart enums. #21876

Merged
merged 11 commits into from
Dec 31, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public static bool TryCreate (ConstructorDeclarationSyntax declaration, Semantic
IsParams = parameter.IsParams,
IsThis = parameter.IsThis,
IsNullable = parameter.NullableAnnotation == NullableAnnotation.Annotated,
IsSmartEnum = parameter.Type.IsSmartEnum (),
DefaultValue = (parameter.HasExplicitDefaultValue) ? parameter.ExplicitDefaultValue?.ToString () : null,
ReferenceKind = parameter.RefKind.ToReferenceKind (),
Attributes = parameterDeclaration.GetAttributeCodeChanges (semanticModel),
Expand Down
1 change: 1 addition & 0 deletions src/rgen/Microsoft.Macios.Generator/DataModel/Method.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public static bool TryCreate (MethodDeclarationSyntax declaration, SemanticModel
IsParams = parameter.IsParams,
IsThis = parameter.IsThis,
IsNullable = parameter.NullableAnnotation == NullableAnnotation.Annotated,
IsSmartEnum = parameter.Type.IsSmartEnum (),
DefaultValue = (parameter.HasExplicitDefaultValue) ? parameter.ExplicitDefaultValue?.ToString () : null,
ReferenceKind = parameter.RefKind.ToReferenceKind (),
Attributes = parameterDeclaration.GetAttributeCodeChanges (semanticModel),
Expand Down
9 changes: 9 additions & 0 deletions src/rgen/Microsoft.Macios.Generator/DataModel/Parameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ namespace Microsoft.Macios.Generator.DataModel;
/// </summary>
public bool IsNullable { get; init; }

/// <summary>
/// Returns if the parameter type is a smart enum.
/// </summary>
public bool IsSmartEnum { get; init; }

/// <summary>
/// Optional default value.
/// </summary>
Expand Down Expand Up @@ -82,6 +87,8 @@ public bool Equals (Parameter other)
return false;
if (IsNullable != other.IsNullable)
return false;
if (IsSmartEnum != other.IsSmartEnum)
return false;
if (DefaultValue != other.DefaultValue)
return false;
if (ReferenceKind != other.ReferenceKind)
Expand All @@ -107,6 +114,7 @@ public override int GetHashCode ()
hashCode.Add (IsParams);
hashCode.Add (IsThis);
hashCode.Add (IsNullable);
hashCode.Add (IsSmartEnum);
hashCode.Add (DefaultValue);
hashCode.Add ((int) ReferenceKind);
return hashCode.ToHashCode ();
Expand Down Expand Up @@ -135,6 +143,7 @@ public override string ToString ()
sb.Append ($"IsParams {IsParams}, ");
sb.Append ($"IsThis: {IsThis}, ");
sb.Append ($"IsNullable: {IsNullable}, ");
sb.Append ($"IsSmartEnum: {IsSmartEnum}, ");
sb.Append ($"DefaultValue: {DefaultValue}, ");
sb.Append ($"ReferenceKind: {ReferenceKind} }}");
return sb.ToString ();
Expand Down
14 changes: 12 additions & 2 deletions src/rgen/Microsoft.Macios.Generator/DataModel/Property.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ namespace Microsoft.Macios.Generator.DataModel;
/// </summary>
public string Type { get; } = string.Empty;

/// <summary>
/// Returns if the parameter type is a smart enum.
/// </summary>
public bool IsSmartEnum { get; }

/// <summary>
/// The platform availability of the property.
/// </summary>
Expand Down Expand Up @@ -67,12 +72,14 @@ namespace Microsoft.Macios.Generator.DataModel;
public ImmutableArray<Accessor> Accessors { get; } = [];

internal Property (string name, string type,
bool isSmartEnum,
SymbolAvailability symbolAvailability,
ImmutableArray<AttributeCodeChange> attributes,
ImmutableArray<SyntaxToken> modifiers, ImmutableArray<Accessor> accessors)
{
Name = name;
Type = type;
IsSmartEnum = isSmartEnum;
SymbolAvailability = symbolAvailability;
Attributes = attributes;
Modifiers = modifiers;
Expand All @@ -87,6 +94,8 @@ public bool Equals (Property other)
return false;
if (Type != other.Type)
return false;
if (IsSmartEnum != other.IsSmartEnum)
return false;
if (SymbolAvailability != other.SymbolAvailability)
return false;
if (ExportFieldData != other.ExportFieldData)
Expand Down Expand Up @@ -115,7 +124,7 @@ public override bool Equals (object? obj)
/// <inheritdoc />
public override int GetHashCode ()
{
return HashCode.Combine (Name, Type, Attributes, Modifiers, Accessors);
return HashCode.Combine (Name, Type, IsSmartEnum, Attributes, Modifiers, Accessors);
}

public static bool operator == (Property left, Property right)
Expand Down Expand Up @@ -169,6 +178,7 @@ public static bool TryCreate (PropertyDeclarationSyntax declaration, SemanticMod
change = new (
name: memberName,
type: type,
isSmartEnum: propertySymbol.Type.IsSmartEnum (),
symbolAvailability: propertySupportedPlatforms,
attributes: attributes,
modifiers: [.. declaration.Modifiers],
Expand All @@ -183,7 +193,7 @@ public static bool TryCreate (PropertyDeclarationSyntax declaration, SemanticMod
public override string ToString ()
{
var sb = new StringBuilder (
$"Name: '{Name}', Type: '{Type}', Supported Platforms: {SymbolAvailability}, ExportFieldData: '{ExportFieldData?.ToString () ?? "null"}', ExportPropertyData: '{ExportPropertyData?.ToString () ?? "null"}' Attributes: [");
$"Name: '{Name}', Type: '{Type}', IsSmartEnum: {IsSmartEnum}, Supported Platforms: {SymbolAvailability}, ExportFieldData: '{ExportFieldData?.ToString () ?? "null"}', ExportPropertyData: '{ExportPropertyData?.ToString () ?? "null"}' Attributes: [");
sb.AppendJoin (",", Attributes);
sb.Append ("], Modifiers: [");
sb.AppendJoin (",", Modifiers.Select (x => x.Text));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.Macios.Generator.Attributes;
using Microsoft.Macios.Generator.Availability;
Expand Down Expand Up @@ -125,6 +126,29 @@ public static SymbolAvailability GetSupportedPlatforms (this ISymbol symbol)
return availability;
}

public static bool HasAttribute (this ISymbol symbol, string attribute)
{
var boundAttributes = symbol.GetAttributes ();
if (boundAttributes.Length == 0) {
return false;
}
foreach (var attributeData in boundAttributes) {
var attrName = attributeData.AttributeClass?.ToDisplayString ();
if (attrName == attribute) {
return true;
}
}
return false;
}

public static bool IsSmartEnum (this ITypeSymbol symbol)
{
// a type is a smart enum if its type is a enum one AND it was decorated with the
// binding type attribute
return symbol.TypeKind == TypeKind.Enum
&& symbol.HasAttribute (AttributesNames.BindingAttribute);
}

/// <summary>
/// Retrieve the data of an export attribute on a symbol.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ public partial class MyClass {
new (
name: "Name",
type: "string",
isSmartEnum: false,
symbolAvailability: new (),
attributes: [
new ("ObjCBindings.ExportAttribute<ObjCBindings.Property>", ["name"])
Expand All @@ -276,7 +277,119 @@ public partial class MyClass {
new (AccessorKind.Setter, new (), [], []),
]
) {
ExportPropertyData = new ("name")
}
]
}
];

const string singlePropertySmartEnumClass = @"
using ObjCBindings;

namespace NS;

[BindingType]
public enum MyEnum {
None = 0,
}

[BindingType]
public partial class MyClass {
[Export<Property> (""name"")]
public partial MyEnum Name { get; set; }
}
";

yield return [
singlePropertySmartEnumClass,
new CodeChanges (
bindingType: BindingType.Class,
name: "MyClass",
@namespace: ["NS"],
fullyQualifiedSymbol: "NS.MyClass",
symbolAvailability: new ()
) {
Attributes = [
new ("ObjCBindings.BindingTypeAttribute")
],
Modifiers = [
SyntaxFactory.Token (SyntaxKind.PublicKeyword),
SyntaxFactory.Token (SyntaxKind.PartialKeyword)
],
Properties = [
new (
name: "Name",
type: "NS.MyEnum",
isSmartEnum: true,
symbolAvailability: new (),
attributes: [
new ("ObjCBindings.ExportAttribute<ObjCBindings.Property>", ["name"])
],
modifiers: [
SyntaxFactory.Token (SyntaxKind.PublicKeyword),
SyntaxFactory.Token (SyntaxKind.PartialKeyword),
],
accessors: [
new (AccessorKind.Getter, new (), [], []),
new (AccessorKind.Setter, new (), [], []),
]
) {
ExportPropertyData = new ("name")
}
]
}
];

const string singlePropertyEnumClass = @"
using ObjCBindings;

namespace NS;

public enum MyEnum {
None = 0,
}

[BindingType]
public partial class MyClass {
[Export<Property> (""name"")]
public partial MyEnum Name { get; set; }
}
";

yield return [
singlePropertyEnumClass,
new CodeChanges (
bindingType: BindingType.Class,
name: "MyClass",
@namespace: ["NS"],
fullyQualifiedSymbol: "NS.MyClass",
symbolAvailability: new ()
) {
Attributes = [
new ("ObjCBindings.BindingTypeAttribute")
],
Modifiers = [
SyntaxFactory.Token (SyntaxKind.PublicKeyword),
SyntaxFactory.Token (SyntaxKind.PartialKeyword)
],
Properties = [
new (
name: "Name",
type: "NS.MyEnum",
isSmartEnum: false,
symbolAvailability: new (),
attributes: [
new ("ObjCBindings.ExportAttribute<ObjCBindings.Property>", ["name"])
],
modifiers: [
SyntaxFactory.Token (SyntaxKind.PublicKeyword),
SyntaxFactory.Token (SyntaxKind.PartialKeyword),
],
accessors: [
new (AccessorKind.Getter, new (), [], []),
new (AccessorKind.Setter, new (), [], []),
]
) {
ExportPropertyData = new ("name")
}
]
Expand Down Expand Up @@ -315,6 +428,7 @@ public partial class MyClass {
new (
name: "Name",
type: "string",
isSmartEnum: false,
symbolAvailability: new (),
attributes: [
new ("ObjCBindings.ExportAttribute<ObjCBindings.Property>", ["name", "ObjCBindings.Property.Notification"])
Expand Down Expand Up @@ -367,6 +481,7 @@ public partial class MyClass {
new (
name: "Name",
type: "string",
isSmartEnum: false,
symbolAvailability: new (),
attributes: [
new ("ObjCBindings.ExportAttribute<ObjCBindings.Field>", ["CONSTANT"])
Expand Down Expand Up @@ -422,6 +537,7 @@ public partial class MyClass {
new (
name: "Name",
type: "string",
isSmartEnum: false,
symbolAvailability: new (),
attributes: [
new ("ObjCBindings.ExportAttribute<ObjCBindings.Property>", ["name"])
Expand Down Expand Up @@ -476,6 +592,7 @@ public partial class MyClass {
new (
name: "Name",
type: "string",
isSmartEnum: false,
symbolAvailability: new (),
attributes: [
new ("ObjCBindings.ExportAttribute<ObjCBindings.Property>", ["name"])
Expand All @@ -494,6 +611,7 @@ public partial class MyClass {
new (
name: "Surname",
type: "string",
isSmartEnum: false,
symbolAvailability: new (),
attributes: [
new ("ObjCBindings.ExportAttribute<ObjCBindings.Property>", ["surname"])
Expand Down
Loading
Loading