diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.Generator.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.Generator.cs
new file mode 100644
index 00000000000..9462f7a4fe8
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.Generator.cs
@@ -0,0 +1,75 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis;
+using Microsoft.Macios.Generator.Attributes;
+using Microsoft.Macios.Generator.Availability;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct Accessor {
+
+ ///
+ /// The data of the field attribute used to mark the value as a property binding.
+ ///
+ public ExportData? ExportPropertyData { get; init; }
+
+ public bool MarshalNativeExceptions
+ => ExportPropertyData is not null && ExportPropertyData.Value.Flags.HasFlag (ObjCBindings.Property.MarshalNativeExceptions);
+
+ ///
+ /// Create a new code change in a property accessor.
+ ///
+ /// The kind of accessor.
+ /// The os availability of the symbol.
+ /// The data of the export attribute found in the accessor.
+ /// The list of attributes attached to the accessor.
+ /// The list of visibility modifiers of the accessor.
+ public Accessor (AccessorKind accessorKind,
+ SymbolAvailability symbolAvailability,
+ ExportData? exportPropertyData,
+ ImmutableArray attributes,
+ ImmutableArray modifiers)
+ {
+ Kind = accessorKind;
+ SymbolAvailability = symbolAvailability;
+ ExportPropertyData = exportPropertyData;
+ Attributes = attributes;
+ Modifiers = modifiers;
+ }
+
+ ///
+ /// Retrieve the selector to be used with the associated property.
+ ///
+ /// The property associated with the accessor.
+ /// The selector to use for the accessor.
+ public string? GetSelector (in Property associatedProperty)
+ {
+ // this is not a property but a field, we cannot retrieve a selector.
+ if (!associatedProperty.IsProperty)
+ return null;
+
+ // There are two possible cases, the current accessor has an export attribute, if that
+ // is the case, we will use the selector in that attribute. Otherwise, we have:
+ //
+ // * getter: return the property selector.
+ // * setter: use the registrar code (it has the right logic) to get the setter.
+ if (ExportPropertyData is null) {
+ return Kind == AccessorKind.Getter
+ ? associatedProperty.ExportPropertyData.Value.Selector
+ : Registrar.Registrar.CreateSetterSelector (associatedProperty.ExportPropertyData.Value.Selector);
+ }
+
+ return ExportPropertyData.Value.Selector;
+ }
+
+ ///
+ /// Returns if the accessor should marshal native exceptions with the associated property.
+ ///
+ /// The property associated with the accessor.
+ /// True if either the accessor or the property were marked with the MarshalNativeExceptions flag.
+ public bool ShouldMarshalNativeExceptions (in Property property)
+ => MarshalNativeExceptions || property.MarshalNativeExceptions;
+
+}
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.cs
index 5199718f4bd..bc4c0731bef 100644
--- a/src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.cs
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.cs
@@ -3,14 +3,15 @@
using System;
using System.Collections.Immutable;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Text;
using Microsoft.CodeAnalysis;
-using Microsoft.Macios.Generator.Attributes;
using Microsoft.Macios.Generator.Availability;
namespace Microsoft.Macios.Generator.DataModel;
-readonly struct Accessor : IEquatable {
+[StructLayout (LayoutKind.Auto)]
+readonly partial struct Accessor : IEquatable {
///
/// The kind of accessor.
///
@@ -21,14 +22,6 @@ namespace Microsoft.Macios.Generator.DataModel;
///
public SymbolAvailability SymbolAvailability { get; }
- ///
- /// The data of the field attribute used to mark the value as a property binding.
- ///
- public ExportData? ExportPropertyData { get; init; }
-
- public bool MarshalNativeExceptions
- => ExportPropertyData is not null && ExportPropertyData.Value.Flags.HasFlag (ObjCBindings.Property.MarshalNativeExceptions);
-
///
/// List of attribute code changes of the accessor.
///
@@ -39,60 +32,6 @@ public bool MarshalNativeExceptions
///
public ImmutableArray Modifiers { get; }
- ///
- /// Create a new code change in a property accessor.
- ///
- /// The kind of accessor.
- /// The os availability of the symbol.
- /// The data of the export attribute found in the accessor.
- /// The list of attributes attached to the accessor.
- /// The list of visibility modifiers of the accessor.
- public Accessor (AccessorKind accessorKind,
- SymbolAvailability symbolAvailability,
- ExportData? exportPropertyData,
- ImmutableArray attributes,
- ImmutableArray modifiers)
- {
- Kind = accessorKind;
- SymbolAvailability = symbolAvailability;
- ExportPropertyData = exportPropertyData;
- Attributes = attributes;
- Modifiers = modifiers;
- }
-
- ///
- /// Retrieve the selector to be used with the associated property.
- ///
- /// The property associated with the accessor.
- /// The selector to use for the accessor.
- public string? GetSelector (in Property associatedProperty)
- {
- // this is not a property but a field, we cannot retrieve a selector.
- if (!associatedProperty.IsProperty)
- return null;
-
- // There are two possible cases, the current accessor has an export attribute, if that
- // is the case, we will use the selector in that attribute. Otherwise, we have:
- //
- // * getter: return the property selector.
- // * setter: use the registrar code (it has the right logic) to get the setter.
- if (ExportPropertyData is null) {
- return Kind == AccessorKind.Getter
- ? associatedProperty.ExportPropertyData.Value.Selector
- : Registrar.Registrar.CreateSetterSelector (associatedProperty.ExportPropertyData.Value.Selector);
- }
-
- return ExportPropertyData.Value.Selector;
- }
-
- ///
- /// Returns if the accessor should marshal native exceptions with the associated property.
- ///
- /// The property associated with the accessor.
- /// True if either the accessor or the property were marked with the MarshalNativeExceptions flag.
- public bool ShouldMarshalNativeExceptions (in Property property)
- => MarshalNativeExceptions || property.MarshalNativeExceptions;
-
///
public bool Equals (Accessor other)
{
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/CodeChanges.Generator.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/CodeChanges.Generator.cs
new file mode 100644
index 00000000000..7f63af7a425
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/CodeChanges.Generator.cs
@@ -0,0 +1,287 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.Macios.Generator.Availability;
+using Microsoft.Macios.Generator.Context;
+using Microsoft.Macios.Generator.Extensions;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct CodeChanges {
+
+ ///
+ /// Represents the type of binding that the code changes are for.
+ ///
+ public BindingType BindingType => BindingInfo.BindingType;
+
+ readonly BindingInfo bindingInfo = default;
+ ///
+ /// Represents the binding data that will be used to generate the code.
+ ///
+ public BindingInfo BindingInfo => bindingInfo;
+
+ ///
+ /// Returns all the library names and paths that are needed by the native code represented by the code change.
+ ///
+ public IEnumerable<(string LibraryName, string? LibraryPath)> LibraryPaths {
+ get {
+ // we want to return unique values, A library name should always point to the
+ // same library path (either null or with a value). We keep track of the ones we already
+ // returned in a set and skip if we already returned it.
+ var visited = new HashSet ();
+
+ // return those libs needed by smart enums
+ foreach (var enumMember in EnumMembers) {
+ if (enumMember.FieldInfo is null)
+ continue;
+ var (_, libraryName, libraryPath) = enumMember.FieldInfo.Value;
+ if (visited.Add (libraryName)) // if already visited, we cannot add it
+ yield return (libraryName, libraryPath);
+ }
+
+ // return those libs needed by field properties
+ foreach (var property in Properties) {
+ if (property.ExportFieldData is null)
+ continue;
+ var (_, libraryName, libraryPath) = property.ExportFieldData.Value;
+ if (visited.Add (libraryName)) // if already visited, we cannot add it
+ yield return (libraryName, libraryPath);
+ }
+ }
+ }
+
+ ///
+ /// Decide if an enum value should be ignored as a change.
+ ///
+ /// The enum declaration under test.
+ /// The semantic model of the compilation.
+ /// True if the enum value should be ignored. False otherwise.
+ internal static bool Skip (EnumMemberDeclarationSyntax enumMemberDeclarationSyntax, SemanticModel semanticModel)
+ {
+ // for smart enums, we are only interested in the field that has a Field attribute
+ return !enumMemberDeclarationSyntax.HasAttribute (semanticModel, AttributesNames.EnumFieldAttribute);
+ }
+
+ ///
+ /// Decide if a property should be ignored as a change.
+ ///
+ /// The property declaration under test.
+ /// The semantic model of the compilation.
+ /// True if the property should be ignored. False otherwise.
+ internal static bool Skip (PropertyDeclarationSyntax propertyDeclarationSyntax, SemanticModel semanticModel)
+ {
+ // valid properties are:
+ // 1. Partial
+ // 2. One of the following:
+ // 1. Field properties
+ // 2. Exported properties
+ if (propertyDeclarationSyntax.Modifiers.Any (SyntaxKind.PartialKeyword)) {
+ return !propertyDeclarationSyntax.HasAtLeastOneAttribute (semanticModel,
+ AttributesNames.FieldPropertyAttribute, AttributesNames.ExportPropertyAttribute);
+ }
+
+ return true;
+ }
+
+ internal static bool Skip (ConstructorDeclarationSyntax constructorDeclarationSyntax, SemanticModel semanticModel)
+ {
+ // TODO: we need to confirm this when we have support from the roslyn team.
+ return false;
+ }
+
+ internal static bool Skip (EventDeclarationSyntax eventDeclarationSyntax, SemanticModel semanticModel)
+ {
+ // TODO: we need to confirm this when we have support from the roslyn team.
+ return false;
+ }
+
+ internal static bool Skip (MethodDeclarationSyntax methodDeclarationSyntax, SemanticModel semanticModel)
+ {
+ // Valid methods are:
+ // 1. Partial
+ // 2. Contain the export attribute
+ if (methodDeclarationSyntax.Modifiers.Any (SyntaxKind.PartialKeyword)) {
+ return !methodDeclarationSyntax.HasAttribute (semanticModel, AttributesNames.ExportMethodAttribute);
+ }
+
+ return true;
+ }
+
+ delegate bool SkipDelegate (T declarationSyntax, SemanticModel semanticModel);
+
+ delegate bool TryCreateDelegate (T declaration, RootBindingContext context,
+ [NotNullWhen (true)] out TR? change)
+ where T : MemberDeclarationSyntax
+ where TR : struct;
+
+ static void GetMembers (TypeDeclarationSyntax baseDeclarationSyntax, RootBindingContext context,
+ SkipDelegate skip, TryCreateDelegate tryCreate, out ImmutableArray
members)
+ where T : MemberDeclarationSyntax
+ where TR : struct
+ {
+ var bucket = ImmutableArray.CreateBuilder
();
+ var declarations = baseDeclarationSyntax.Members.OfType ();
+ foreach (var declaration in declarations) {
+ if (skip (declaration, context.SemanticModel))
+ continue;
+ if (tryCreate (declaration, context, out var change))
+ bucket.Add (change.Value);
+ }
+
+ members = bucket.ToImmutable ();
+ }
+
+ ///
+ /// Internal constructor added for testing purposes.
+ ///
+ /// The binding data of binding for the given code changes.
+ /// The name of the named type that created the code change.
+ /// The namespace that contains the named type.
+ /// The fully qualified name of the symbol.
+ /// The platform availability of the named symbol.
+ internal CodeChanges (BindingInfo bindingInfo, string name, ImmutableArray @namespace,
+ string fullyQualifiedSymbol, SymbolAvailability symbolAvailability)
+ {
+ this.bindingInfo = bindingInfo;
+ this.name = name;
+ this.namespaces = @namespace;
+ FullyQualifiedSymbol = fullyQualifiedSymbol;
+ this.availability = symbolAvailability;
+ }
+
+ ///
+ /// Creates a new instance of the struct for a given enum declaration.
+ ///
+ /// The enum declaration that triggered the change.
+ /// The root binding context of the current compilation.
+ CodeChanges (EnumDeclarationSyntax enumDeclaration, RootBindingContext context)
+ {
+ context.SemanticModel.GetSymbolData (
+ declaration: enumDeclaration,
+ bindingType: BindingType.SmartEnum,
+ name: out name,
+ baseClass: out baseClass,
+ interfaces: out interfaces,
+ namespaces: out namespaces,
+ symbolAvailability: out availability,
+ bindingInfo: out bindingInfo);
+ FullyQualifiedSymbol = enumDeclaration.GetFullyQualifiedIdentifier ();
+ Attributes = enumDeclaration.GetAttributeCodeChanges (context.SemanticModel);
+ UsingDirectives = enumDeclaration.SyntaxTree.CollectUsingStatements ();
+ Modifiers = [.. enumDeclaration.Modifiers];
+ var bucket = ImmutableArray.CreateBuilder ();
+ // loop over the fields and add those that contain a FieldAttribute
+ var enumValueDeclarations = enumDeclaration.Members.OfType ();
+ foreach (var enumValueDeclaration in enumValueDeclarations) {
+ if (Skip (enumValueDeclaration, context.SemanticModel))
+ continue;
+ if (context.SemanticModel.GetDeclaredSymbol (enumValueDeclaration) is not IFieldSymbol enumValueSymbol) {
+ continue;
+ }
+
+ var fieldData = enumValueSymbol.GetFieldData ();
+ // try and compute the library for this enum member
+ if (fieldData is null || !context.TryComputeLibraryName (fieldData.Value.LibraryName, Namespace [^1],
+ out string? libraryName, out string? libraryPath))
+ // could not calculate the library for the enum, do not add it
+ continue;
+ var enumMember = new EnumMember (
+ name: enumValueDeclaration.Identifier.ToFullString ().Trim (),
+ libraryName: libraryName,
+ libraryPath: libraryPath,
+ fieldData: enumValueSymbol.GetFieldData (),
+ symbolAvailability: enumValueSymbol.GetSupportedPlatforms (),
+ attributes: enumValueDeclaration.GetAttributeCodeChanges (context.SemanticModel)
+ );
+ bucket.Add (enumMember);
+ }
+
+ EnumMembers = bucket.ToImmutable ();
+ }
+
+ ///
+ /// Creates a new instance of the struct for a given class declaration.
+ ///
+ /// The class declaration that triggered the change.
+ /// The root binding context of the current compilation.
+ CodeChanges (ClassDeclarationSyntax classDeclaration, RootBindingContext context)
+ {
+ context.SemanticModel.GetSymbolData (
+ declaration: classDeclaration,
+ bindingType: BindingType.Class,
+ name: out name,
+ baseClass: out baseClass,
+ interfaces: out interfaces,
+ namespaces: out namespaces,
+ symbolAvailability: out availability,
+ bindingInfo: out bindingInfo);
+ FullyQualifiedSymbol = classDeclaration.GetFullyQualifiedIdentifier ();
+ Attributes = classDeclaration.GetAttributeCodeChanges (context.SemanticModel);
+ UsingDirectives = classDeclaration.SyntaxTree.CollectUsingStatements ();
+ Modifiers = [.. classDeclaration.Modifiers];
+
+ // use the generic method to get the members, we are using an out param to try an minimize the number of times
+ // the value types are copied
+ GetMembers (classDeclaration, context, Skip,
+ Constructor.TryCreate, out constructors);
+ GetMembers (classDeclaration, context, Skip, Property.TryCreate,
+ out properties);
+ GetMembers (classDeclaration, context, Skip, Event.TryCreate, out events);
+ GetMembers (classDeclaration, context, Skip, Method.TryCreate,
+ out methods);
+ }
+
+ ///
+ /// Creates a new instance of the struct for a given interface declaration.
+ ///
+ /// The interface declaration that triggered the change.
+ /// The root binding context of the current compilation.
+ CodeChanges (InterfaceDeclarationSyntax interfaceDeclaration, RootBindingContext context)
+ {
+ context.SemanticModel.GetSymbolData (
+ declaration: interfaceDeclaration,
+ bindingType: BindingType.Protocol,
+ name: out name,
+ baseClass: out baseClass,
+ interfaces: out interfaces,
+ namespaces: out namespaces,
+ symbolAvailability: out availability,
+ bindingInfo: out bindingInfo);
+ FullyQualifiedSymbol = interfaceDeclaration.GetFullyQualifiedIdentifier ();
+ Attributes = interfaceDeclaration.GetAttributeCodeChanges (context.SemanticModel);
+ UsingDirectives = interfaceDeclaration.SyntaxTree.CollectUsingStatements ();
+ Modifiers = [.. interfaceDeclaration.Modifiers];
+ // we do not init the constructors, we use the default empty array
+
+ GetMembers (interfaceDeclaration, context.SemanticModel, Skip, Property.TryCreate,
+ out properties);
+ GetMembers (interfaceDeclaration, context.SemanticModel, Skip, Event.TryCreate,
+ out events);
+ GetMembers (interfaceDeclaration, context.SemanticModel, Skip, Method.TryCreate,
+ out methods);
+ }
+
+ ///
+ /// Create a CodeChange from the provide base type declaration syntax. If the syntax is not supported,
+ /// it will return null.
+ ///
+ /// The declaration syntax whose change we want to calculate.
+ /// The root binding context of the current compilation.
+ /// A code change or null if it could not be calculated.
+ public static CodeChanges? FromDeclaration (BaseTypeDeclarationSyntax baseTypeDeclarationSyntax,
+ RootBindingContext context)
+ => baseTypeDeclarationSyntax switch {
+ EnumDeclarationSyntax enumDeclarationSyntax => new CodeChanges (enumDeclarationSyntax, context),
+ InterfaceDeclarationSyntax interfaceDeclarationSyntax => new CodeChanges (interfaceDeclarationSyntax,
+ context),
+ ClassDeclarationSyntax classDeclarationSyntax => new CodeChanges (classDeclarationSyntax, context),
+ _ => null
+ };
+}
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/CodeChanges.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/CodeChanges.cs
index c5a52c1fad2..a2e827c22db 100644
--- a/src/rgen/Microsoft.Macios.Generator/DataModel/CodeChanges.cs
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/CodeChanges.cs
@@ -2,15 +2,12 @@
// Licensed under the MIT License.
using System.Collections.Generic;
using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Macios.Generator.Availability;
-using Microsoft.Macios.Generator.Context;
-using Microsoft.Macios.Generator.Extensions;
namespace Microsoft.Macios.Generator.DataModel;
@@ -18,17 +15,8 @@ namespace Microsoft.Macios.Generator.DataModel;
/// Structure that represents a set of changes that were made by the user that need to be applied to the
/// generated code.
///
-readonly struct CodeChanges {
- ///
- /// Represents the type of binding that the code changes are for.
- ///
- public BindingType BindingType => BindingInfo.BindingType;
-
- readonly BindingInfo bindingInfo = default;
- ///
- /// Represents the binding data that will be used to generate the code.
- ///
- public BindingInfo BindingInfo => bindingInfo;
+[StructLayout (LayoutKind.Auto)]
+readonly partial struct CodeChanges {
readonly string name = string.Empty;
///
@@ -167,264 +155,6 @@ public ImmutableArray Methods {
init => methods = value;
}
- ///
- /// Returns all the library names and paths that are needed by the native code represented by the code change.
- ///
- public IEnumerable<(string LibraryName, string? LibraryPath)> LibraryPaths {
- get {
- // we want to return unique values, A library name should always point to the
- // same library path (either null or with a value). We keep track of the ones we already
- // returned in a set and skip if we already returned it.
- var visited = new HashSet ();
-
- // return those libs needed by smart enums
- foreach (var enumMember in EnumMembers) {
- if (enumMember.FieldInfo is null)
- continue;
- var (_, libraryName, libraryPath) = enumMember.FieldInfo.Value;
- if (visited.Add (libraryName)) // if already visited, we cannot add it
- yield return (libraryName, libraryPath);
- }
-
- // return those libs needed by field properties
- foreach (var property in Properties) {
- if (property.ExportFieldData is null)
- continue;
- var (_, libraryName, libraryPath) = property.ExportFieldData.Value;
- if (visited.Add (libraryName)) // if already visited, we cannot add it
- yield return (libraryName, libraryPath);
- }
- }
- }
-
- ///
- /// Decide if an enum value should be ignored as a change.
- ///
- /// The enum declaration under test.
- /// The semantic model of the compilation.
- /// True if the enum value should be ignored. False otherwise.
- internal static bool Skip (EnumMemberDeclarationSyntax enumMemberDeclarationSyntax, SemanticModel semanticModel)
- {
- // for smart enums, we are only interested in the field that has a Field attribute
- return !enumMemberDeclarationSyntax.HasAttribute (semanticModel, AttributesNames.EnumFieldAttribute);
- }
-
- ///
- /// Decide if a property should be ignored as a change.
- ///
- /// The property declaration under test.
- /// The semantic model of the compilation.
- /// True if the property should be ignored. False otherwise.
- internal static bool Skip (PropertyDeclarationSyntax propertyDeclarationSyntax, SemanticModel semanticModel)
- {
- // valid properties are:
- // 1. Partial
- // 2. One of the following:
- // 1. Field properties
- // 2. Exported properties
- if (propertyDeclarationSyntax.Modifiers.Any (SyntaxKind.PartialKeyword)) {
- return !propertyDeclarationSyntax.HasAtLeastOneAttribute (semanticModel,
- AttributesNames.FieldPropertyAttribute, AttributesNames.ExportPropertyAttribute);
- }
-
- return true;
- }
-
- internal static bool Skip (ConstructorDeclarationSyntax constructorDeclarationSyntax, SemanticModel semanticModel)
- {
- // TODO: we need to confirm this when we have support from the roslyn team.
- return false;
- }
-
- internal static bool Skip (EventDeclarationSyntax eventDeclarationSyntax, SemanticModel semanticModel)
- {
- // TODO: we need to confirm this when we have support from the roslyn team.
- return false;
- }
-
- internal static bool Skip (MethodDeclarationSyntax methodDeclarationSyntax, SemanticModel semanticModel)
- {
- // Valid methods are:
- // 1. Partial
- // 2. Contain the export attribute
- if (methodDeclarationSyntax.Modifiers.Any (SyntaxKind.PartialKeyword)) {
- return !methodDeclarationSyntax.HasAttribute (semanticModel, AttributesNames.ExportMethodAttribute);
- }
-
- return true;
- }
-
- delegate bool SkipDelegate (T declarationSyntax, SemanticModel semanticModel);
-
- delegate bool TryCreateDelegate (T declaration, RootBindingContext context,
- [NotNullWhen (true)] out TR? change)
- where T : MemberDeclarationSyntax
- where TR : struct;
-
- static void GetMembers (TypeDeclarationSyntax baseDeclarationSyntax, RootBindingContext context,
- SkipDelegate skip, TryCreateDelegate tryCreate, out ImmutableArray
members)
- where T : MemberDeclarationSyntax
- where TR : struct
- {
- var bucket = ImmutableArray.CreateBuilder
();
- var declarations = baseDeclarationSyntax.Members.OfType ();
- foreach (var declaration in declarations) {
- if (skip (declaration, context.SemanticModel))
- continue;
- if (tryCreate (declaration, context, out var change))
- bucket.Add (change.Value);
- }
-
- members = bucket.ToImmutable ();
- }
-
- ///
- /// Internal constructor added for testing purposes.
- ///
- /// The binding data of binding for the given code changes.
- /// The name of the named type that created the code change.
- /// The namespace that contains the named type.
- /// The fully qualified name of the symbol.
- /// The platform availability of the named symbol.
- internal CodeChanges (BindingInfo bindingInfo, string name, ImmutableArray @namespace,
- string fullyQualifiedSymbol, SymbolAvailability symbolAvailability)
- {
- this.bindingInfo = bindingInfo;
- this.name = name;
- this.namespaces = @namespace;
- FullyQualifiedSymbol = fullyQualifiedSymbol;
- this.availability = symbolAvailability;
- }
-
- ///
- /// Creates a new instance of the struct for a given enum declaration.
- ///
- /// The enum declaration that triggered the change.
- /// The root binding context of the current compilation.
- CodeChanges (EnumDeclarationSyntax enumDeclaration, RootBindingContext context)
- {
- context.SemanticModel.GetSymbolData (
- declaration: enumDeclaration,
- bindingType: BindingType.SmartEnum,
- name: out name,
- baseClass: out baseClass,
- interfaces: out interfaces,
- namespaces: out namespaces,
- symbolAvailability: out availability,
- bindingInfo: out bindingInfo);
- FullyQualifiedSymbol = enumDeclaration.GetFullyQualifiedIdentifier ();
- Attributes = enumDeclaration.GetAttributeCodeChanges (context.SemanticModel);
- UsingDirectives = enumDeclaration.SyntaxTree.CollectUsingStatements ();
- Modifiers = [.. enumDeclaration.Modifiers];
- var bucket = ImmutableArray.CreateBuilder ();
- // loop over the fields and add those that contain a FieldAttribute
- var enumValueDeclarations = enumDeclaration.Members.OfType ();
- foreach (var enumValueDeclaration in enumValueDeclarations) {
- if (Skip (enumValueDeclaration, context.SemanticModel))
- continue;
- if (context.SemanticModel.GetDeclaredSymbol (enumValueDeclaration) is not IFieldSymbol enumValueSymbol) {
- continue;
- }
-
- var fieldData = enumValueSymbol.GetFieldData ();
- // try and compute the library for this enum member
- if (fieldData is null || !context.TryComputeLibraryName (fieldData.Value.LibraryName, Namespace [^1],
- out string? libraryName, out string? libraryPath))
- // could not calculate the library for the enum, do not add it
- continue;
- var enumMember = new EnumMember (
- name: enumValueDeclaration.Identifier.ToFullString ().Trim (),
- libraryName: libraryName,
- libraryPath: libraryPath,
- fieldData: enumValueSymbol.GetFieldData (),
- symbolAvailability: enumValueSymbol.GetSupportedPlatforms (),
- attributes: enumValueDeclaration.GetAttributeCodeChanges (context.SemanticModel)
- );
- bucket.Add (enumMember);
- }
-
- EnumMembers = bucket.ToImmutable ();
- }
-
- ///
- /// Creates a new instance of the struct for a given class declaration.
- ///
- /// The class declaration that triggered the change.
- /// The root binding context of the current compilation.
- CodeChanges (ClassDeclarationSyntax classDeclaration, RootBindingContext context)
- {
- context.SemanticModel.GetSymbolData (
- declaration: classDeclaration,
- bindingType: BindingType.Class,
- name: out name,
- baseClass: out baseClass,
- interfaces: out interfaces,
- namespaces: out namespaces,
- symbolAvailability: out availability,
- bindingInfo: out bindingInfo);
- FullyQualifiedSymbol = classDeclaration.GetFullyQualifiedIdentifier ();
- Attributes = classDeclaration.GetAttributeCodeChanges (context.SemanticModel);
- UsingDirectives = classDeclaration.SyntaxTree.CollectUsingStatements ();
- Modifiers = [.. classDeclaration.Modifiers];
-
- // use the generic method to get the members, we are using an out param to try an minimize the number of times
- // the value types are copied
- GetMembers (classDeclaration, context, Skip,
- Constructor.TryCreate, out constructors);
- GetMembers (classDeclaration, context, Skip, Property.TryCreate,
- out properties);
- GetMembers (classDeclaration, context, Skip, Event.TryCreate, out events);
- GetMembers (classDeclaration, context, Skip, Method.TryCreate,
- out methods);
- }
-
- ///
- /// Creates a new instance of the struct for a given interface declaration.
- ///
- /// The interface declaration that triggered the change.
- /// The root binding context of the current compilation.
- CodeChanges (InterfaceDeclarationSyntax interfaceDeclaration, RootBindingContext context)
- {
- context.SemanticModel.GetSymbolData (
- declaration: interfaceDeclaration,
- bindingType: BindingType.Protocol,
- name: out name,
- baseClass: out baseClass,
- interfaces: out interfaces,
- namespaces: out namespaces,
- symbolAvailability: out availability,
- bindingInfo: out bindingInfo);
- FullyQualifiedSymbol = interfaceDeclaration.GetFullyQualifiedIdentifier ();
- Attributes = interfaceDeclaration.GetAttributeCodeChanges (context.SemanticModel);
- UsingDirectives = interfaceDeclaration.SyntaxTree.CollectUsingStatements ();
- Modifiers = [.. interfaceDeclaration.Modifiers];
- // we do not init the constructors, we use the default empty array
-
- GetMembers (interfaceDeclaration, context.SemanticModel, Skip, Property.TryCreate,
- out properties);
- GetMembers (interfaceDeclaration, context.SemanticModel, Skip, Event.TryCreate,
- out events);
- GetMembers (interfaceDeclaration, context.SemanticModel, Skip, Method.TryCreate,
- out methods);
- }
-
- ///
- /// Create a CodeChange from the provide base type declaration syntax. If the syntax is not supported,
- /// it will return null.
- ///
- /// The declaration syntax whose change we want to calculate.
- /// The root binding context of the current compilation.
- /// A code change or null if it could not be calculated.
- public static CodeChanges? FromDeclaration (BaseTypeDeclarationSyntax baseTypeDeclarationSyntax,
- RootBindingContext context)
- => baseTypeDeclarationSyntax switch {
- EnumDeclarationSyntax enumDeclarationSyntax => new CodeChanges (enumDeclarationSyntax, context),
- InterfaceDeclarationSyntax interfaceDeclarationSyntax => new CodeChanges (interfaceDeclarationSyntax,
- context),
- ClassDeclarationSyntax classDeclarationSyntax => new CodeChanges (classDeclarationSyntax, context),
- _ => null
- };
-
///
public override string ToString ()
{
@@ -453,4 +183,5 @@ public override string ToString ()
sb.Append ("] }");
return sb.ToString ();
}
+
}
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Constructor.Generator.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Constructor.Generator.cs
new file mode 100644
index 00000000000..a3b14cce0c0
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Constructor.Generator.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.Macios.Generator.Context;
+using Microsoft.Macios.Generator.Extensions;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct Constructor {
+
+ public static bool TryCreate (ConstructorDeclarationSyntax declaration, RootBindingContext context,
+ [NotNullWhen (true)] out Constructor? change)
+ {
+ if (context.SemanticModel.GetDeclaredSymbol (declaration) is not IMethodSymbol constructor) {
+ change = null;
+ return false;
+ }
+
+ var attributes = declaration.GetAttributeCodeChanges (context.SemanticModel);
+ var parametersBucket = ImmutableArray.CreateBuilder ();
+ // loop over the parameters of the construct since changes on those implies a change in the generated code
+ foreach (var parameter in constructor.Parameters) {
+ var parameterDeclaration = declaration.ParameterList.Parameters [parameter.Ordinal];
+ if (!Parameter.TryCreate (parameter, parameterDeclaration, context.SemanticModel, out var parameterChange))
+ continue;
+ parametersBucket.Add (parameterChange.Value);
+ }
+
+ change = new (
+ type: constructor.ContainingSymbol.Name, // we DO NOT want the full name
+ symbolAvailability: constructor.GetSupportedPlatforms (),
+ attributes: attributes,
+ modifiers: [.. declaration.Modifiers],
+ parameters: parametersBucket.ToImmutable ());
+ return true;
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Constructor.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Constructor.cs
index 57e9f19cb5e..eee7d6a9104 100644
--- a/src/rgen/Microsoft.Macios.Generator/DataModel/Constructor.cs
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Constructor.cs
@@ -2,18 +2,14 @@
// Licensed under the MIT License.
using System;
using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Macios.Generator.Availability;
-using Microsoft.Macios.Generator.Context;
-using Microsoft.Macios.Generator.Extensions;
namespace Microsoft.Macios.Generator.DataModel;
-readonly struct Constructor : IEquatable {
+readonly partial struct Constructor : IEquatable {
///
/// Type name that owns the constructor.
///
@@ -52,33 +48,6 @@ public Constructor (string type,
Parameters = parameters;
}
- public static bool TryCreate (ConstructorDeclarationSyntax declaration, RootBindingContext context,
- [NotNullWhen (true)] out Constructor? change)
- {
- if (context.SemanticModel.GetDeclaredSymbol (declaration) is not IMethodSymbol constructor) {
- change = null;
- return false;
- }
-
- var attributes = declaration.GetAttributeCodeChanges (context.SemanticModel);
- var parametersBucket = ImmutableArray.CreateBuilder ();
- // loop over the parameters of the construct since changes on those implies a change in the generated code
- foreach (var parameter in constructor.Parameters) {
- var parameterDeclaration = declaration.ParameterList.Parameters [parameter.Ordinal];
- if (!Parameter.TryCreate (parameter, parameterDeclaration, context.SemanticModel, out var parameterChange))
- continue;
- parametersBucket.Add (parameterChange.Value);
- }
-
- change = new (
- type: constructor.ContainingSymbol.Name, // we DO NOT want the full name
- symbolAvailability: constructor.GetSupportedPlatforms (),
- attributes: attributes,
- modifiers: [.. declaration.Modifiers],
- parameters: parametersBucket.ToImmutable ());
- return true;
- }
-
///
public bool Equals (Constructor other)
{
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/EnumMember.Generator.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/EnumMember.Generator.cs
new file mode 100644
index 00000000000..252192f8b83
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/EnumMember.Generator.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Immutable;
+using Microsoft.Macios.Generator.Attributes;
+using Microsoft.Macios.Generator.Availability;
+using ObjCBindings;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct EnumMember {
+
+ ///
+ /// The data of the field attribute used to mark the value as a binding.
+ ///
+ public FieldInfo? FieldInfo { get; }
+
+ ///
+ /// Create a new change that happened on a member.
+ ///
+ /// The name of the changed member.
+ /// The library name of the smart enum.
+ /// The library path to the library, null if it is a known frameworl.
+ /// The binding data attached to this enum value.
+ /// The symbol availability of the member.
+ /// The list of attribute changes in the member.
+ public EnumMember (string name,
+ string libraryName,
+ string? libraryPath,
+ FieldData? fieldData,
+ SymbolAvailability symbolAvailability,
+ ImmutableArray attributes)
+ {
+ Name = name;
+ FieldInfo = fieldData is null ? null : new (fieldData.Value, libraryName, libraryPath);
+ SymbolAvailability = symbolAvailability;
+ Attributes = attributes;
+ }
+
+}
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/EnumMember.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/EnumMember.cs
index 003ac01b4a9..783650fa187 100644
--- a/src/rgen/Microsoft.Macios.Generator/DataModel/EnumMember.cs
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/EnumMember.cs
@@ -2,6 +2,8 @@
// Licensed under the MIT License.
using System;
using System.Collections.Immutable;
+using System.Reflection;
+using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Macios.Generator.Attributes;
using Microsoft.Macios.Generator.Availability;
@@ -13,7 +15,8 @@ namespace Microsoft.Macios.Generator.DataModel;
/// Structure that represents a change that was made by the user on enum members that has to be
/// reflected in the generated code.
///
-readonly struct EnumMember : IEquatable {
+[StructLayout (LayoutKind.Auto)]
+readonly partial struct EnumMember : IEquatable {
///
/// Get the name of the member.
///
@@ -24,38 +27,11 @@ namespace Microsoft.Macios.Generator.DataModel;
///
public SymbolAvailability SymbolAvailability { get; }
- ///
- /// The data of the field attribute used to mark the value as a binding.
- ///
- public FieldInfo? FieldInfo { get; }
-
///
/// Get the attributes added to the member.
///
public ImmutableArray Attributes { get; }
- ///
- /// Create a new change that happened on a member.
- ///
- /// The name of the changed member.
- /// The library name of the smart enum.
- /// The library path to the library, null if it is a known frameworl.
- /// The binding data attached to this enum value.
- /// The symbol availability of the member.
- /// The list of attribute changes in the member.
- public EnumMember (string name,
- string libraryName,
- string? libraryPath,
- FieldData? fieldData,
- SymbolAvailability symbolAvailability,
- ImmutableArray attributes)
- {
- Name = name;
- FieldInfo = fieldData is null ? null : new (fieldData.Value, libraryName, libraryPath);
- SymbolAvailability = symbolAvailability;
- Attributes = attributes;
- }
-
///
/// Create a new change that happened on a member.
///
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Event.Generator.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Event.Generator.cs
new file mode 100644
index 00000000000..ebbcd469e0d
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Event.Generator.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.Macios.Generator.Context;
+using Microsoft.Macios.Generator.Extensions;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct Event {
+
+ public static bool TryCreate (EventDeclarationSyntax declaration, RootBindingContext context,
+ [NotNullWhen (true)] out Event? change)
+ {
+ var memberName = declaration.Identifier.ToFullString ().Trim ();
+ // get the symbol from the property declaration
+ if (context.SemanticModel.GetDeclaredSymbol (declaration) is not IEventSymbol eventSymbol) {
+ change = null;
+ return false;
+ }
+
+ var type = eventSymbol.Type.ToDisplayString ().Trim ();
+ var attributes = declaration.GetAttributeCodeChanges (context.SemanticModel);
+ ImmutableArray accessorCodeChanges = [];
+ if (declaration.AccessorList is not null && declaration.AccessorList.Accessors.Count > 0) {
+ // calculate any possible changes in the accessors of the property
+ var accessorsBucket = ImmutableArray.CreateBuilder ();
+ foreach (var accessorDeclaration in declaration.AccessorList.Accessors) {
+ if (context.SemanticModel.GetDeclaredSymbol (accessorDeclaration) is not ISymbol accessorSymbol)
+ continue;
+ var kind = accessorDeclaration.Kind ().ToAccessorKind ();
+ var accessorAttributeChanges = accessorDeclaration.GetAttributeCodeChanges (context.SemanticModel);
+ accessorsBucket.Add (new (
+ accessorKind: kind,
+ symbolAvailability: accessorSymbol.GetSupportedPlatforms (),
+ exportPropertyData: null,
+ attributes: accessorAttributeChanges,
+ modifiers: [.. accessorDeclaration.Modifiers]));
+ }
+
+ accessorCodeChanges = accessorsBucket.ToImmutable ();
+ }
+
+ change = new (memberName, type, eventSymbol.GetSupportedPlatforms (), attributes,
+ [.. declaration.Modifiers], accessorCodeChanges);
+ return true;
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Event.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Event.cs
index 38f7e5e10b8..3b53660c7a3 100644
--- a/src/rgen/Microsoft.Macios.Generator/DataModel/Event.cs
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Event.cs
@@ -2,18 +2,14 @@
// Licensed under the MIT License.
using System;
using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Macios.Generator.Availability;
-using Microsoft.Macios.Generator.Context;
-using Microsoft.Macios.Generator.Extensions;
namespace Microsoft.Macios.Generator.DataModel;
-readonly struct Event : IEquatable {
+readonly partial struct Event : IEquatable {
///
/// Name of the property.
///
@@ -101,43 +97,6 @@ public override int GetHashCode ()
return !left.Equals (right);
}
- public static bool TryCreate (EventDeclarationSyntax declaration, RootBindingContext context,
- [NotNullWhen (true)] out Event? change)
- {
- var memberName = declaration.Identifier.ToFullString ().Trim ();
- // get the symbol from the property declaration
- if (context.SemanticModel.GetDeclaredSymbol (declaration) is not IEventSymbol eventSymbol) {
- change = null;
- return false;
- }
-
- var type = eventSymbol.Type.ToDisplayString ().Trim ();
- var attributes = declaration.GetAttributeCodeChanges (context.SemanticModel);
- ImmutableArray accessorCodeChanges = [];
- if (declaration.AccessorList is not null && declaration.AccessorList.Accessors.Count > 0) {
- // calculate any possible changes in the accessors of the property
- var accessorsBucket = ImmutableArray.CreateBuilder ();
- foreach (var accessorDeclaration in declaration.AccessorList.Accessors) {
- if (context.SemanticModel.GetDeclaredSymbol (accessorDeclaration) is not ISymbol accessorSymbol)
- continue;
- var kind = accessorDeclaration.Kind ().ToAccessorKind ();
- var accessorAttributeChanges = accessorDeclaration.GetAttributeCodeChanges (context.SemanticModel);
- accessorsBucket.Add (new (
- accessorKind: kind,
- symbolAvailability: accessorSymbol.GetSupportedPlatforms (),
- exportPropertyData: null,
- attributes: accessorAttributeChanges,
- modifiers: [.. accessorDeclaration.Modifiers]));
- }
-
- accessorCodeChanges = accessorsBucket.ToImmutable ();
- }
-
- change = new (memberName, type, eventSymbol.GetSupportedPlatforms (), attributes,
- [.. declaration.Modifiers], accessorCodeChanges);
- return true;
- }
-
///
public override string ToString ()
{
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Method.Generator.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Method.Generator.cs
new file mode 100644
index 00000000000..fefb41c4f79
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Method.Generator.cs
@@ -0,0 +1,81 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.Macios.Generator.Attributes;
+using Microsoft.Macios.Generator.Availability;
+using Microsoft.Macios.Generator.Context;
+using Microsoft.Macios.Generator.Extensions;
+using ObjCRuntime;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct Method {
+
+ ///
+ /// The data of the export attribute used to mark the value as a property binding.
+ ///
+ public ExportData ExportMethodData { get; }
+
+ ///
+ /// True if the method was exported with the MarshalNativeExceptions flag allowing it to support native exceptions.
+ ///
+ public bool MarshalNativeExceptions => ExportMethodData.Flags.HasFlag (ObjCBindings.Method.MarshalNativeExceptions);
+
+ public Method (string type, string name, TypeInfo returnType,
+ SymbolAvailability symbolAvailability,
+ ExportData exportMethodData,
+ ImmutableArray attributes,
+ ImmutableArray modifiers,
+ ImmutableArray parameters)
+ {
+ Type = type;
+ Name = name;
+ ReturnType = returnType;
+ SymbolAvailability = symbolAvailability;
+ ExportMethodData = exportMethodData;
+ Attributes = attributes;
+ Modifiers = modifiers;
+ Parameters = parameters;
+ }
+
+ public static bool TryCreate (MethodDeclarationSyntax declaration, RootBindingContext context,
+ [NotNullWhen (true)] out Method? change)
+ {
+ if (context.SemanticModel.GetDeclaredSymbol (declaration) is not IMethodSymbol method) {
+ change = null;
+ return false;
+ }
+
+ var attributes = declaration.GetAttributeCodeChanges (context.SemanticModel);
+ var parametersBucket = ImmutableArray.CreateBuilder ();
+ // loop over the parameters of the construct since changes on those implies a change in the generated code
+ foreach (var parameter in method.Parameters) {
+ var parameterDeclaration = declaration.ParameterList.Parameters [parameter.Ordinal];
+ if (!Parameter.TryCreate (parameter, parameterDeclaration, context.SemanticModel, out var parameterChange))
+ continue;
+ parametersBucket.Add (parameterChange.Value);
+ }
+
+ // DO NOT USE default if null, the reason is that it will set the ArgumentSemantics to be value 0, when
+ // none is value 1. The reason for that is that the default of an enum is 0, that was a mistake
+ // in the old binding code.
+ var exportData = method.GetExportData ()
+ ?? new (null, ArgumentSemantic.None, ObjCBindings.Method.Default);
+
+ change = new (
+ type: method.ContainingSymbol.ToDisplayString ().Trim (), // we want the full name
+ name: method.Name,
+ returnType: new TypeInfo (method.ReturnType),
+ symbolAvailability: method.GetSupportedPlatforms (),
+ exportMethodData: exportData,
+ attributes: attributes,
+ modifiers: [.. declaration.Modifiers],
+ parameters: parametersBucket.ToImmutableArray ());
+
+ return true;
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Method.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Method.cs
index 476d9f2b53c..4be3968ba03 100644
--- a/src/rgen/Microsoft.Macios.Generator/DataModel/Method.cs
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Method.cs
@@ -2,20 +2,16 @@
// Licensed under the MIT License.
using System;
using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Text;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.Macios.Generator.Attributes;
using Microsoft.Macios.Generator.Availability;
-using Microsoft.Macios.Generator.Context;
-using Microsoft.Macios.Generator.Extensions;
-using ObjCRuntime;
namespace Microsoft.Macios.Generator.DataModel;
-readonly struct Method : IEquatable {
+[StructLayout (LayoutKind.Auto)]
+readonly partial struct Method : IEquatable {
///
/// Type name that owns the method.
@@ -37,16 +33,6 @@ namespace Microsoft.Macios.Generator.DataModel;
///
public SymbolAvailability SymbolAvailability { get; }
- ///
- /// The data of the export attribute used to mark the value as a property binding.
- ///
- public ExportData ExportMethodData { get; }
-
- ///
- /// True if the method was exported with the MarshalNativeExceptions flag allowing it to support native exceptions.
- ///
- public bool MarshalNativeExceptions => ExportMethodData.Flags.HasFlag (ObjCBindings.Method.MarshalNativeExceptions);
-
///
/// Get the attributes added to the constructor.
///
@@ -62,58 +48,6 @@ namespace Microsoft.Macios.Generator.DataModel;
///
public ImmutableArray Parameters { get; } = [];
- public Method (string type, string name, TypeInfo returnType,
- SymbolAvailability symbolAvailability,
- ExportData exportMethodData,
- ImmutableArray attributes,
- ImmutableArray modifiers,
- ImmutableArray parameters)
- {
- Type = type;
- Name = name;
- ReturnType = returnType;
- SymbolAvailability = symbolAvailability;
- ExportMethodData = exportMethodData;
- Attributes = attributes;
- Modifiers = modifiers;
- Parameters = parameters;
- }
-
- public static bool TryCreate (MethodDeclarationSyntax declaration, RootBindingContext context,
- [NotNullWhen (true)] out Method? change)
- {
- if (context.SemanticModel.GetDeclaredSymbol (declaration) is not IMethodSymbol method) {
- change = null;
- return false;
- }
-
- var attributes = declaration.GetAttributeCodeChanges (context.SemanticModel);
- var parametersBucket = ImmutableArray.CreateBuilder ();
- // loop over the parameters of the construct since changes on those implies a change in the generated code
- foreach (var parameter in method.Parameters) {
- var parameterDeclaration = declaration.ParameterList.Parameters [parameter.Ordinal];
- if (!Parameter.TryCreate (parameter, parameterDeclaration, context.SemanticModel, out var parameterChange))
- continue;
- parametersBucket.Add (parameterChange.Value);
- }
-
- // DO NOT USE default if null, the reason is that it will set the ArgumentSemantics to be value 0, when
- // none is value 1. The reason for that is that the default of an enum is 0, that was a mistake
- // in the old binding code.
- var exportData = method.GetExportData ()
- ?? new (null, ArgumentSemantic.None, ObjCBindings.Method.Default);
- change = new (
- type: method.ContainingSymbol.ToDisplayString ().Trim (), // we want the full name
- name: method.Name,
- returnType: new (method.ReturnType),
- symbolAvailability: method.GetSupportedPlatforms (),
- exportMethodData: exportData,
- attributes: attributes,
- modifiers: [.. declaration.Modifiers],
- parameters: parametersBucket.ToImmutableArray ());
- return true;
- }
-
///
public bool Equals (Method other)
{
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Property.Generator.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Property.Generator.cs
new file mode 100644
index 00000000000..0320eb67da3
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Property.Generator.cs
@@ -0,0 +1,119 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.Macios.Generator.Attributes;
+using Microsoft.Macios.Generator.Context;
+using Microsoft.Macios.Generator.Extensions;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct Property {
+
+ ///
+ /// The data of the field attribute used to mark the value as a field binding.
+ ///
+ public FieldInfo? ExportFieldData { get; init; }
+
+ ///
+ /// True if the property represents a Objc field.
+ ///
+ [MemberNotNullWhen (true, nameof (ExportFieldData))]
+ public bool IsField => ExportFieldData is not null;
+
+ public bool IsNotification
+ => IsField && ExportFieldData.Value.FieldData.Flags.HasFlag (ObjCBindings.Property.Notification);
+
+ ///
+ /// The data of the field attribute used to mark the value as a property binding.
+ ///
+ public ExportData? ExportPropertyData { get; init; }
+
+ ///
+ /// True if the property represents a Objc property.
+ ///
+ [MemberNotNullWhen (true, nameof (ExportPropertyData))]
+ public bool IsProperty => ExportPropertyData is not null;
+
+ ///
+ /// True if the method was exported with the MarshalNativeExceptions flag allowing it to support native exceptions.
+ ///
+ public bool MarshalNativeExceptions
+ => IsProperty && ExportPropertyData.Value.Flags.HasFlag (ObjCBindings.Property.MarshalNativeExceptions);
+
+ static FieldInfo? GetFieldInfo (RootBindingContext context, IPropertySymbol propertySymbol)
+ {
+ // grab the last port of the namespace
+ var ns = propertySymbol.ContainingNamespace.Name.Split ('.') [^1];
+ var fieldData = propertySymbol.GetFieldData ();
+ FieldInfo? fieldInfo = null;
+ if (fieldData is not null && context.TryComputeLibraryName (fieldData.Value.LibraryName, ns,
+ out string? libraryName, out string? libraryPath)) {
+ fieldInfo = new FieldInfo (fieldData.Value, libraryName, libraryPath);
+ }
+
+ return fieldInfo;
+ }
+
+ public static bool TryCreate (PropertyDeclarationSyntax declaration, RootBindingContext context,
+ [NotNullWhen (true)] out Property? change)
+ {
+ var memberName = declaration.Identifier.ToFullString ().Trim ();
+ // get the symbol from the property declaration
+ if (context.SemanticModel.GetDeclaredSymbol (declaration) is not IPropertySymbol propertySymbol) {
+ change = null;
+ return false;
+ }
+
+ var propertySupportedPlatforms = propertySymbol.GetSupportedPlatforms ();
+ var attributes = declaration.GetAttributeCodeChanges (context.SemanticModel);
+
+ ImmutableArray accessorCodeChanges = [];
+ if (declaration.AccessorList is not null && declaration.AccessorList.Accessors.Count > 0) {
+ // calculate any possible changes in the accessors of the property
+ var accessorsBucket = ImmutableArray.CreateBuilder ();
+ foreach (var accessorDeclaration in declaration.AccessorList.Accessors) {
+ if (context.SemanticModel.GetDeclaredSymbol (accessorDeclaration) is not ISymbol accessorSymbol)
+ continue;
+ var kind = accessorDeclaration.Kind ().ToAccessorKind ();
+ var accessorAttributeChanges =
+ accessorDeclaration.GetAttributeCodeChanges (context.SemanticModel);
+ accessorsBucket.Add (new (
+ accessorKind: kind,
+ exportPropertyData: accessorSymbol.GetExportData (),
+ symbolAvailability: accessorSymbol.GetSupportedPlatforms (),
+ attributes: accessorAttributeChanges,
+ modifiers: [.. accessorDeclaration.Modifiers]));
+ }
+
+ accessorCodeChanges = accessorsBucket.ToImmutable ();
+ }
+
+ if (declaration.ExpressionBody is not null) {
+ // an expression body == a getter with no attrs or modifiers; that means that the accessor does not have
+ // extra availability, but the ones form the property
+ accessorCodeChanges = [new (
+ accessorKind: AccessorKind.Getter,
+ symbolAvailability: propertySupportedPlatforms,
+ exportPropertyData: null,
+ attributes: [],
+ modifiers: [])
+ ];
+ }
+
+ change = new (
+ name: memberName,
+ returnType: new (propertySymbol.Type),
+ symbolAvailability: propertySupportedPlatforms,
+ attributes: attributes,
+ modifiers: [.. declaration.Modifiers],
+ accessors: accessorCodeChanges) {
+ ExportFieldData = GetFieldInfo (context, propertySymbol),
+ ExportPropertyData = propertySymbol.GetExportData (),
+ };
+ return true;
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/Property.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/Property.cs
index bc1f4d1e45a..cef7185bf36 100644
--- a/src/rgen/Microsoft.Macios.Generator/DataModel/Property.cs
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/Property.cs
@@ -2,22 +2,19 @@
// Licensed under the MIT License.
using System;
using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Text;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.Macios.Generator.Attributes;
using Microsoft.Macios.Generator.Availability;
-using Microsoft.Macios.Generator.Context;
-using Microsoft.Macios.Generator.Extensions;
namespace Microsoft.Macios.Generator.DataModel;
///
/// Readonly struct that represent the changes that a user has made in a property.
///
-readonly struct Property : IEquatable {
+[StructLayout (LayoutKind.Auto)]
+readonly partial struct Property : IEquatable {
///
/// Name of the property.
///
@@ -50,42 +47,11 @@ namespace Microsoft.Macios.Generator.DataModel;
///
public SymbolAvailability SymbolAvailability { get; }
- ///
- /// The data of the field attribute used to mark the value as a field binding.
- ///
- public FieldInfo? ExportFieldData { get; init; }
-
- ///
- /// True if the property represents a Objc field.
- ///
- [MemberNotNullWhen (true, nameof (ExportFieldData))]
- public bool IsField => ExportFieldData is not null;
-
- public bool IsNotification
- => IsField && ExportFieldData.Value.FieldData.Flags.HasFlag (ObjCBindings.Property.Notification);
-
- ///
- /// The data of the field attribute used to mark the value as a property binding.
- ///
- public ExportData? ExportPropertyData { get; init; }
-
- ///
- /// True if the property represents a Objc property.
- ///
- [MemberNotNullWhen (true, nameof (ExportPropertyData))]
- public bool IsProperty => ExportPropertyData is not null;
-
///
/// Get the attributes added to the member.
///
public ImmutableArray Attributes { get; } = [];
- ///
- /// True if the method was exported with the MarshalNativeExceptions flag allowing it to support native exceptions.
- ///
- public bool MarshalNativeExceptions
- => IsProperty && ExportPropertyData.Value.Flags.HasFlag (ObjCBindings.Property.MarshalNativeExceptions);
-
///
/// Get the modifiers of the property.
///
@@ -175,79 +141,6 @@ public override int GetHashCode ()
return !left.Equals (right);
}
- static FieldInfo? GetFieldInfo (RootBindingContext context, IPropertySymbol propertySymbol)
- {
- // grab the last port of the namespace
- var ns = propertySymbol.ContainingNamespace.Name.Split ('.') [^1];
- var fieldData = propertySymbol.GetFieldData ();
- FieldInfo? fieldInfo = null;
- if (fieldData is not null && context.TryComputeLibraryName (fieldData.Value.LibraryName, ns,
- out string? libraryName, out string? libraryPath)) {
- fieldInfo = new FieldInfo (fieldData.Value, libraryName, libraryPath);
- }
-
- return fieldInfo;
- }
-
- public static bool TryCreate (PropertyDeclarationSyntax declaration, RootBindingContext context,
- [NotNullWhen (true)] out Property? change)
- {
- var memberName = declaration.Identifier.ToFullString ().Trim ();
- // get the symbol from the property declaration
- if (context.SemanticModel.GetDeclaredSymbol (declaration) is not IPropertySymbol propertySymbol) {
- change = null;
- return false;
- }
-
- var propertySupportedPlatforms = propertySymbol.GetSupportedPlatforms ();
- var attributes = declaration.GetAttributeCodeChanges (context.SemanticModel);
-
- ImmutableArray accessorCodeChanges = [];
- if (declaration.AccessorList is not null && declaration.AccessorList.Accessors.Count > 0) {
- // calculate any possible changes in the accessors of the property
- var accessorsBucket = ImmutableArray.CreateBuilder ();
- foreach (var accessorDeclaration in declaration.AccessorList.Accessors) {
- if (context.SemanticModel.GetDeclaredSymbol (accessorDeclaration) is not ISymbol accessorSymbol)
- continue;
- var kind = accessorDeclaration.Kind ().ToAccessorKind ();
- var accessorAttributeChanges =
- accessorDeclaration.GetAttributeCodeChanges (context.SemanticModel);
- accessorsBucket.Add (new (
- accessorKind: kind,
- exportPropertyData: accessorSymbol.GetExportData (),
- symbolAvailability: accessorSymbol.GetSupportedPlatforms (),
- attributes: accessorAttributeChanges,
- modifiers: [.. accessorDeclaration.Modifiers]));
- }
-
- accessorCodeChanges = accessorsBucket.ToImmutable ();
- }
-
- if (declaration.ExpressionBody is not null) {
- // an expression body == a getter with no attrs or modifiers; that means that the accessor does not have
- // extra availability, but the ones form the property
- accessorCodeChanges = [new (
- accessorKind: AccessorKind.Getter,
- symbolAvailability: propertySupportedPlatforms,
- exportPropertyData: null,
- attributes: [],
- modifiers: [])
- ];
- }
-
- change = new (
- name: memberName,
- returnType: new (propertySymbol.Type),
- symbolAvailability: propertySupportedPlatforms,
- attributes: attributes,
- modifiers: [.. declaration.Modifiers],
- accessors: accessorCodeChanges) {
- ExportFieldData = GetFieldInfo (context, propertySymbol),
- ExportPropertyData = propertySymbol.GetExportData (),
- };
- return true;
- }
-
///
public override string ToString ()
{
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.Generator.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.Generator.cs
new file mode 100644
index 00000000000..2c2d4984ca0
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.Generator.cs
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.CodeAnalysis;
+using Microsoft.Macios.Generator.Extensions;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct TypeInfo {
+
+ internal TypeInfo (ITypeSymbol symbol) :
+ this (
+ symbol is IArrayTypeSymbol arrayTypeSymbol
+ ? arrayTypeSymbol.ElementType.ToDisplayString ()
+ : symbol.ToDisplayString ().Trim ('?', '[', ']'),
+ symbol.SpecialType)
+ {
+ IsNullable = symbol.NullableAnnotation == NullableAnnotation.Annotated;
+ IsBlittable = symbol.IsBlittable ();
+ IsSmartEnum = symbol.IsSmartEnum ();
+ IsArray = symbol is IArrayTypeSymbol;
+ IsReferenceType = symbol.IsReferenceType;
+ IsInterface = symbol.TypeKind == TypeKind.Interface;
+ IsNativeIntegerType = symbol.IsNativeIntegerType;
+ IsNativeEnum = symbol.HasAttribute (AttributesNames.NativeEnumAttribute);
+
+ // data that we can get from the symbol without being INamedType
+ symbol.GetInheritance (
+ isNSObject: out isNSObject,
+ isNativeObject: out isINativeObject,
+ parents: out parents,
+ interfaces: out interfaces);
+
+ // try to get the named type symbol to have more educated decisions
+ var namedTypeSymbol = symbol as INamedTypeSymbol;
+
+ // store the enum special type, useful when generate code that needs to cast
+ EnumUnderlyingType = namedTypeSymbol?.EnumUnderlyingType?.SpecialType;
+
+ if (!IsReferenceType && IsNullable && namedTypeSymbol is not null) {
+ // get the type argument for nullable, which we know is the data that was boxed and use it to
+ // overwrite the SpecialType
+ var typeArgument = namedTypeSymbol.TypeArguments [0];
+ SpecialType = typeArgument.SpecialType;
+ MetadataName = SpecialType is SpecialType.None or SpecialType.System_Void
+ ? null : typeArgument.MetadataName;
+ } else {
+ MetadataName = SpecialType is SpecialType.None or SpecialType.System_Void
+ ? null : symbol.MetadataName;
+ }
+
+ }
+
+}
diff --git a/src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.cs b/src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.cs
index ae4d1a23d05..6377c09451e 100644
--- a/src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.cs
+++ b/src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.cs
@@ -5,14 +5,13 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Microsoft.CodeAnalysis;
-using Microsoft.Macios.Generator.Extensions;
namespace Microsoft.Macios.Generator.DataModel;
///
/// Readonly structure that represents a change in a method return type.
///
-readonly struct TypeInfo : IEquatable {
+readonly partial struct TypeInfo : IEquatable {
///
/// Type of the parameter.
@@ -136,49 +135,6 @@ internal TypeInfo (string name,
IsReferenceType = isReferenceType;
}
- internal TypeInfo (ITypeSymbol symbol) :
- this (
- symbol is IArrayTypeSymbol arrayTypeSymbol
- ? arrayTypeSymbol.ElementType.ToDisplayString ()
- : symbol.ToDisplayString ().Trim ('?', '[', ']'),
- symbol.SpecialType)
- {
- IsNullable = symbol.NullableAnnotation == NullableAnnotation.Annotated;
- IsBlittable = symbol.IsBlittable ();
- IsSmartEnum = symbol.IsSmartEnum ();
- IsArray = symbol is IArrayTypeSymbol;
- IsReferenceType = symbol.IsReferenceType;
- IsInterface = symbol.TypeKind == TypeKind.Interface;
- IsNativeIntegerType = symbol.IsNativeIntegerType;
- IsNativeEnum = symbol.HasAttribute (AttributesNames.NativeEnumAttribute);
-
- // data that we can get from the symbol without being INamedType
- symbol.GetInheritance (
- isNSObject: out isNSObject,
- isNativeObject: out isINativeObject,
- parents: out parents,
- interfaces: out interfaces);
-
- // try to get the named type symbol to have more educated decisions
- var namedTypeSymbol = symbol as INamedTypeSymbol;
-
- // store the enum special type, useful when generate code that needs to cast
- EnumUnderlyingType = namedTypeSymbol?.EnumUnderlyingType?.SpecialType;
-
- if (!IsReferenceType && IsNullable && namedTypeSymbol is not null) {
- // get the type argument for nullable, which we know is the data that was boxed and use it to
- // overwrite the SpecialType
- var typeArgument = namedTypeSymbol.TypeArguments [0];
- SpecialType = typeArgument.SpecialType;
- MetadataName = SpecialType is SpecialType.None or SpecialType.System_Void
- ? null : typeArgument.MetadataName;
- } else {
- MetadataName = SpecialType is SpecialType.None or SpecialType.System_Void
- ? null : symbol.MetadataName;
- }
-
- }
-
///
public bool Equals (TypeInfo other)
{
diff --git a/src/rgen/Microsoft.Macios.Transformer/Attributes/ExportData.cs b/src/rgen/Microsoft.Macios.Transformer/Attributes/ExportData.cs
new file mode 100644
index 00000000000..264ac1ce961
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/Attributes/ExportData.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Microsoft.Macios.Transformer.Attributes;
+
+public struct ExportData : IEquatable {
+
+ public bool Equals (ExportData other)
+ {
+ throw new NotImplementedException ();
+ }
+
+ ///
+ public override bool Equals (object? obj)
+ {
+ return obj is ExportData other && Equals (other);
+ }
+
+ ///
+ public override int GetHashCode ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static bool operator == (ExportData x, ExportData y)
+ {
+ return x.Equals (y);
+ }
+
+ public static bool operator != (ExportData x, ExportData y)
+ {
+ return !(x == y);
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Attributes/FieldData.cs b/src/rgen/Microsoft.Macios.Transformer/Attributes/FieldData.cs
new file mode 100644
index 00000000000..3f7c0e824d8
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/Attributes/FieldData.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Microsoft.Macios.Transformer.Attributes;
+
+public struct FieldData : IEquatable {
+
+ public bool Equals (FieldData other)
+ {
+ throw new NotImplementedException ();
+ }
+
+ ///
+ public override bool Equals (object? obj)
+ {
+ return obj is ExportData other && Equals (other);
+ }
+
+ ///
+ public override int GetHashCode ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static bool operator == (FieldData x, FieldData y)
+ {
+ return x.Equals (y);
+ }
+
+ public static bool operator != (FieldData x, FieldData y)
+ {
+ return !(x == y);
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/DataModel/Accessor.Transformer.cs b/src/rgen/Microsoft.Macios.Transformer/DataModel/Accessor.Transformer.cs
new file mode 100644
index 00000000000..3220114a142
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/DataModel/Accessor.Transformer.cs
@@ -0,0 +1,11 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.Macios.Transformer.Attributes;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct Accessor {
+
+ public ExportData? ExportPropertyData { get; init; }
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/DataModel/BindingInfo.cs b/src/rgen/Microsoft.Macios.Transformer/DataModel/BindingInfo.cs
new file mode 100644
index 00000000000..049e67c427e
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/DataModel/BindingInfo.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+///
+/// This struct works as a union to store the possible BindingTypeData that can be present in the bindings.
+///
+readonly struct BindingInfo : IEquatable {
+
+ ///
+ public bool Equals (BindingInfo other)
+ {
+ throw new NotImplementedException ();
+ }
+
+ ///
+ public override bool Equals (object? obj)
+ {
+ return obj is BindingInfo other && Equals (other);
+ }
+
+ ///
+ public override int GetHashCode ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static bool operator == (BindingInfo x, BindingInfo y)
+ {
+ return x.Equals (y);
+ }
+
+ public static bool operator != (BindingInfo x, BindingInfo y)
+ {
+ return !(x == y);
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/DataModel/CodeChanges.Transformer.cs b/src/rgen/Microsoft.Macios.Transformer/DataModel/CodeChanges.Transformer.cs
new file mode 100644
index 00000000000..703f48f9eb4
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/DataModel/CodeChanges.Transformer.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct CodeChanges {
+
+ ///
+ /// Represents the type of binding that the code changes are for.
+ ///
+ public BindingType BindingType => throw new NotImplementedException ();
+
+ public BindingInfo BindingInfo => throw new NotImplementedException ();
+
+ public CodeChanges ()
+ {
+ FullyQualifiedSymbol = "";
+ IsStatic = false;
+ IsPartial = false;
+ IsAbstract = false;
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/DataModel/EnumMember.Transformer.cs b/src/rgen/Microsoft.Macios.Transformer/DataModel/EnumMember.Transformer.cs
new file mode 100644
index 00000000000..6f5548abc72
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/DataModel/EnumMember.Transformer.cs
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Immutable;
+using Microsoft.Macios.Generator.Availability;
+using Microsoft.Macios.Transformer.Attributes;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct EnumMember {
+
+ ///
+ /// The data of the field attribute used to mark the value as a binding.
+ ///
+ public FieldData? FieldInfo { get; }
+
+ ///
+ /// Create a new change that happened on a member.
+ ///
+ /// The name of the changed member.
+ /// The library name of the smart enum.
+ /// The library path to the library, null if it is a known frameworl.
+ /// The binding data attached to this enum value.
+ /// The symbol availability of the member.
+ /// The list of attribute changes in the member.
+ public EnumMember (string name,
+ string libraryName,
+ string? libraryPath,
+ FieldData? fieldData,
+ SymbolAvailability symbolAvailability,
+ ImmutableArray attributes)
+ {
+ throw new NotImplementedException ();
+ }
+
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/DataModel/Method.Transformer.cs b/src/rgen/Microsoft.Macios.Transformer/DataModel/Method.Transformer.cs
new file mode 100644
index 00000000000..fd2db969254
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/DataModel/Method.Transformer.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis;
+using Microsoft.Macios.Generator.Availability;
+using Microsoft.Macios.Transformer.Attributes;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct Method {
+
+ ///
+ /// The data of the export attribute used to mark the value as a property binding.
+ ///
+ public ExportData ExportMethodData { get; }
+
+ ///
+ /// True if the method was exported with the MarshalNativeExceptions flag allowing it to support native exceptions.
+ ///
+ public bool MarshalNativeExceptions => throw new NotImplementedException ();
+
+ public Method (string type, string name, TypeInfo returnType,
+ SymbolAvailability symbolAvailability,
+ ExportData exportMethodData,
+ ImmutableArray attributes,
+ ImmutableArray modifiers,
+ ImmutableArray parameters)
+ {
+ Type = type;
+ Name = name;
+ ReturnType = returnType;
+ SymbolAvailability = symbolAvailability;
+ ExportMethodData = exportMethodData;
+ Attributes = attributes;
+ Modifiers = modifiers;
+ Parameters = parameters;
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/DataModel/Property.Transformer.cs b/src/rgen/Microsoft.Macios.Transformer/DataModel/Property.Transformer.cs
new file mode 100644
index 00000000000..682ca922622
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/DataModel/Property.Transformer.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.Macios.Transformer.Attributes;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct Property {
+
+ ///
+ /// The data of the field attribute used to mark the value as a field binding.
+ ///
+ public FieldData? ExportFieldData { get; init; }
+
+ ///
+ /// True if the property represents a Objc field.
+ ///
+ [MemberNotNullWhen (true, nameof (ExportFieldData))]
+ public bool IsField => ExportFieldData is not null;
+
+ public bool IsNotification => throw new NotImplementedException ();
+
+ ///
+ /// The data of the field attribute used to mark the value as a property binding.
+ ///
+ public ExportData? ExportPropertyData { get; init; }
+
+ ///
+ /// True if the property represents a Objc property.
+ ///
+ [MemberNotNullWhen (true, nameof (ExportPropertyData))]
+ public bool IsProperty => ExportPropertyData is not null;
+
+ ///
+ /// True if the method was exported with the MarshalNativeExceptions flag allowing it to support native exceptions.
+ ///
+ public bool MarshalNativeExceptions => throw new NotImplementedException ();
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/DataModel/TypeInfo.Transformer.cs b/src/rgen/Microsoft.Macios.Transformer/DataModel/TypeInfo.Transformer.cs
new file mode 100644
index 00000000000..a0d4ea7ef22
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/DataModel/TypeInfo.Transformer.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.Macios.Generator.DataModel;
+
+readonly partial struct TypeInfo {
+
+ internal TypeInfo (ITypeSymbol symbol) :
+ this (
+ symbol is IArrayTypeSymbol arrayTypeSymbol
+ ? arrayTypeSymbol.ElementType.ToDisplayString ()
+ : symbol.ToDisplayString ().Trim ('?', '[', ']'),
+ symbol.SpecialType)
+ {
+ throw new NotImplementedException ();
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Extensions/TypeSymbolExtensions.Transformer.cs b/src/rgen/Microsoft.Macios.Transformer/Extensions/TypeSymbolExtensions.Transformer.cs
new file mode 100644
index 00000000000..0b1b6a70cb9
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/Extensions/TypeSymbolExtensions.Transformer.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.Macios.Generator.Extensions;
+
+static partial class TypeSymbolExtensions {
+
+ public static bool IsSmartEnum (this ITypeSymbol symbol)
+ {
+ throw new NotImplementedException ();
+ }
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj b/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj
index 3d0ac820d62..e86488747c8 100644
--- a/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj
+++ b/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj
@@ -25,6 +25,9 @@
DictionaryComparer.cs
+
+ CollectionComparer.cs
+
Attributes/ObsoletedOSPlatformData.cs
@@ -37,6 +40,9 @@
Availability/*.cs
+
+ Extensions/ParameterSyntaxExtensions.cs
+
Extensions/StringExtensions.cs
@@ -45,6 +51,19 @@
+
+
+ DataModel/*.cs
+
+
+
+
+
+
+
+
+
+