Skip to content

Commit

Permalink
[Rgen] Add support for the Methods/Constructors in the transformer.
Browse files Browse the repository at this point in the history
Add the parsing of methods and constructor in the data model for the
transformer.
  • Loading branch information
mandel-macaque committed Feb 12, 2025
1 parent 489e47c commit 4442985
Show file tree
Hide file tree
Showing 6 changed files with 458 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@
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 Constructor {

/// <summary>
/// The data of the export attribute used to mark the value as a property binding.
/// </summary>
public ExportData<ObjCBindings.Constructor> ExportMethodData { get; }

public static bool TryCreate (ConstructorDeclarationSyntax declaration, RootContext context,
[NotNullWhen (true)] out Constructor? change)
{
Expand Down
8 changes: 6 additions & 2 deletions src/rgen/Microsoft.Macios.Generator/DataModel/Constructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ namespace Microsoft.Macios.Generator.DataModel;
/// <summary>
/// Modifiers list.
/// </summary>
public ImmutableArray<SyntaxToken> Modifiers { get; } = [];
public ImmutableArray<SyntaxToken> Modifiers { get; init; } = [];

/// <summary>
/// Parameters list.
/// </summary>
public ImmutableArray<Parameter> Parameters { get; } = [];
public ImmutableArray<Parameter> Parameters { get; init; } = [];

public Constructor (string type,
SymbolAvailability symbolAvailability,
Expand All @@ -55,6 +55,8 @@ public bool Equals (Constructor other)
{
if (Type != other.Type)
return false;
if (ExportMethodData != other.ExportMethodData)
return false;
if (SymbolAvailability != other.SymbolAvailability)
return false;

Expand Down Expand Up @@ -110,6 +112,8 @@ public override int GetHashCode ()
public override string ToString ()
{
var sb = new StringBuilder ($"{{ Ctr: Type: {Type}, ");
sb.Append ($"ExportMethodData: {ExportMethodData}, ");
sb.Append ($"SymbolAvailability: {SymbolAvailability}, ");
sb.Append ("Attributes: [");
sb.AppendJoin (", ", Attributes);
sb.Append ("], Modifiers: [");
Expand Down
2 changes: 1 addition & 1 deletion src/rgen/Microsoft.Macios.Generator/DataModel/Method.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public override string ToString ()
sb.Append ($"ReturnType: {ReturnType}, ");
sb.Append ($"SymbolAvailability: {SymbolAvailability}, ");
sb.Append ($"ExportMethodData: {ExportMethodData}, ");
sb.Append ($"BindAs: {BindAs}, ");
sb.Append ($"BindAs: {BindAs?.ToString () ?? "null"}, ");
sb.Append ("Attributes: [");
sb.AppendJoin (", ", Attributes);
sb.Append ("], Modifiers: [");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,9 @@ static BindingType GetBindingType (Dictionary<string, List<AttributeData>> attri
/// <summary>
/// Retrieve the base class for a given binding based on its binding infor.
/// </summary>
/// <param name="symbol">The symbol whose base class we want to retrieve..</param>
/// <param name="bindingInfo">The binding information.</param>
/// <returns>The base class to use for the new style SDK based on the binding information.</returns>
static string GetBaseClass (INamedTypeSymbol symbol, BindingInfo bindingInfo)
static string GetBaseClass (BindingInfo bindingInfo)
{
// collecting the base class and the interface is a little more complicated in the older SDK style because
// we have to make the difference between a class base and a protocol base
Expand Down Expand Up @@ -198,6 +197,23 @@ internal static bool Skip (PropertyDeclarationSyntax propertyDeclarationSyntax,
return !attributes.HasExportAttribute () && !attributes.HasFieldAttribute ();
}

/// <summary>
/// Decide if a method should be ignored as a change.
/// </summary>
/// <param name="methodDeclarationSyntax">The method declaration under test.</param>
/// <param name="semanticModel">The semantic model of the compilation.</param>
/// <returns>True if the method should be skipped, false otherwise.</returns>
internal static bool Skip (MethodDeclarationSyntax methodDeclarationSyntax, SemanticModel semanticModel)
{
var methodSymbol = semanticModel.GetDeclaredSymbol (methodDeclarationSyntax);
if (methodSymbol is null)
// skip if we cannot retrieve the symbol
return true;
var attributes = methodSymbol.GetAttributeData ();
// we will skip methods that do not have the export attribute
return !attributes.HasExportAttribute ();
}

/// <summary>
/// Create a new binding based on the interface declaration. Because in the old SDK old the bindings
/// are represented by an interface, this constructor will ensure that the correct binding type is set.
Expand All @@ -216,7 +232,7 @@ internal Binding (InterfaceDeclarationSyntax interfaceDeclarationSyntax, INamedT
name = symbol.Name;
availability = symbol.GetAvailabilityForSymbol ();
namespaces = symbol.GetNamespaceArray ();
baseClass = GetBaseClass (symbol, BindingInfo);
baseClass = GetBaseClass (BindingInfo);

// retrieve the interfaces and protocols, notice that this are two out params
GetInterfaceAndProtocols (symbol, out interfaces, out protocols);
Expand All @@ -234,6 +250,17 @@ internal Binding (InterfaceDeclarationSyntax interfaceDeclarationSyntax, INamedT
// loop over the different members and add them to the model
GetMembers<PropertyDeclarationSyntax, Property> (interfaceDeclarationSyntax, context, Skip, Property.TryCreate,
out properties);
// methods are a little diff, in the old SDK style, both methods and constructors are methods, we will get
// all exported methods and then filter accordingly
GetMembers<MethodDeclarationSyntax, Method> (interfaceDeclarationSyntax, context, Skip, Method.TryCreate,
out ImmutableArray<Method> allMethods);
methods = [.. allMethods.Where (m => !m.IsConstructor)];
constructors = allMethods.Where (m => m.IsConstructor)
.Select (m => m.ToConstructor ())
.Where (c => c is not null)
.Select (c => c!.Value)
.ToImmutableArray ();

}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,36 @@
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Macios.Generator.Availability;
using Microsoft.Macios.Transformer.Attributes;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

namespace Microsoft.Macios.Generator.DataModel;

readonly partial struct Constructor {

readonly ExportData? overrideExportData;

/// <summary>
/// The data of the export attribute used to mark the value as a property binding.
/// </summary>
public ExportData? ExportMethodData {
get => overrideExportData ?? ExportAttribute;
init => overrideExportData = value;
}

public Constructor (string type,
SymbolAvailability symbolAvailability,
Dictionary<string, List<AttributeData>> attributes,
ImmutableArray<Parameter> parameters)
{
Type = type;
SymbolAvailability = symbolAvailability;
Attributes = [];
AttributesDictionary = attributes;
Parameters = parameters;
ExportMethodData = null;
}

/// <summary>
/// Create a constructor from a method signature.
Expand All @@ -22,6 +46,7 @@ public Constructor (in Method method)
Attributes = method.Attributes;
Parameters = method.Parameters;
AttributesDictionary = method.AttributesDictionary;
ExportMethodData = method.ExportMethodData;

// modifiers cannot only be copied, we do not have a virtual/override constructor, it is either
// public, private or internal.
Expand Down
Loading

0 comments on commit 4442985

Please sign in to comment.