Skip to content

Commit

Permalink
[RGen] Add the code to parse the field attribute in the transformer. (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
mandel-macaque authored Jan 21, 2025
1 parent 1480b5d commit 727a00f
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Microsoft.Macios.Transformer.Attributes;

public struct ExportData : IEquatable<ExportData> {
struct ExportData : IEquatable<ExportData> {

/// <summary>
/// The exported native selector.
Expand All @@ -31,7 +31,7 @@ public ExportData (string? selector, ArgumentSemantic argumentSemantic)
}

/// <summary>
/// Try to parse the attribute data to retrieve the information of an ExportAttribute&lt;T&gt;.
/// Try to parse the attribute data to retrieve the information of an ExportAttribute.
/// </summary>
/// <param name="attributeData">The attribute data to be parsed.</param>
/// <param name="data">The parsed data. Null if we could not parse the attribute data.</param>
Expand Down
70 changes: 66 additions & 4 deletions src/rgen/Microsoft.Macios.Transformer/Attributes/FieldData.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,82 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis;

namespace Microsoft.Macios.Transformer.Attributes;

public struct FieldData : IEquatable<FieldData> {
struct FieldData : IEquatable<FieldData> {

public string SymbolName { get; }
public string? LibraryName { get; }

internal FieldData (string symbolName, string? libraryName)
{
SymbolName = symbolName;
LibraryName = libraryName;
}

internal FieldData (string symbolName) : this (symbolName, null) { }

public static bool TryParse (AttributeData attributeData,
[NotNullWhen (true)] out FieldData? data)
{
data = default;

var count = attributeData.ConstructorArguments.Length;
string? symbolName;
string? libraryName = null;
switch (count) {
case 1:
symbolName = (string?) attributeData.ConstructorArguments [0].Value!;
break;
case 2:
symbolName = (string?) attributeData.ConstructorArguments [0].Value!;
libraryName = (string?) attributeData.ConstructorArguments [1].Value!;
break;
default:
// 0 should not be an option.
return false;
}

if (attributeData.NamedArguments.Length == 0) {
data = new (symbolName, libraryName);
return true;
}

// LibraryName can be a param value
foreach (var (name, value) in attributeData.NamedArguments) {
switch (name) {
case "LibraryName":
libraryName = (string?) value.Value!;
break;
default:
data = null;
return false;
}
}
data = new (symbolName, libraryName);
return true;
}

public bool Equals (FieldData other)
{
throw new NotImplementedException ();
if (SymbolName != other.SymbolName)
return false;
return LibraryName == other.LibraryName;
}

/// <inheritdoc />
public override bool Equals (object? obj)
{
return obj is ExportData other && Equals (other);
return obj is FieldData other && Equals (other);
}

/// <inheritdoc />
public override int GetHashCode ()
{
throw new NotImplementedException ();
return HashCode.Combine (SymbolName, LibraryName);
}

public static bool operator == (FieldData x, FieldData y)
Expand All @@ -31,4 +88,9 @@ public override int GetHashCode ()
{
return !(x == y);
}

public override string ToString ()
{
return $"{{ SymbolName: '{SymbolName}' LibraryName: '{LibraryName ?? "null"}' }}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
using System.Collections;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Macios.Generator.Extensions;
using Microsoft.Macios.Transformer.Attributes;
using ObjCRuntime;
using Xamarin.Tests;
using Xamarin.Utils;
using Microsoft.Macios.Generator.Extensions;
using ObjCRuntime;

namespace Microsoft.Macios.Transformer.Tests.DataModel;
namespace Microsoft.Macios.Transformer.Tests.Attributes;

public class ExportDataTests : BaseTransformerTestClass {

Expand Down Expand Up @@ -67,7 +67,7 @@ interface UIFeedbackGenerator : UIInteraction {

[Theory]
[AllSupportedPlatformsClassData<TestDataTryCreate>]
public void TryeCreateTests (ApplePlatform platform, (string Source, string Path) source, ExportData expectedData)
void TryCreateTests (ApplePlatform platform, (string Source, string Path) source, ExportData expectedData)
{
// create a compilation used to create the transformer
var compilation = CreateCompilation (platform, sources: source);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Collections;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Macios.Generator.Extensions;
using Microsoft.Macios.Transformer.Attributes;
using Xamarin.Tests;
using Xamarin.Utils;

namespace Microsoft.Macios.Transformer.Tests.Attributes;

public class FieldDataTests : BaseTransformerTestClass {

class TestDataTryCreate : IEnumerable<object []> {
public IEnumerator<object []> GetEnumerator ()
{
const string symbolOnly = @"
using System;
using Foundation;
using ObjCRuntime;
using UIKit;
namespace Test;
[NoTV]
[MacCatalyst (13, 1)]
[DisableDefaultCtor]
[Abstract]
[BaseType (typeof (NSObject))]
interface UIFeedbackGenerator : UIInteraction {
[Field (""prepare"")]
void Prepare { get; }
}
";
yield return [(Source: symbolOnly, Path: "/some/random/path.cs"), new FieldData ("prepare")];

const string symbolAndLibrary = @"
using System;
using Foundation;
using ObjCRuntime;
using UIKit;
namespace Test;
[NoTV]
[MacCatalyst (13, 1)]
[DisableDefaultCtor]
[Abstract]
[BaseType (typeof (NSObject))]
interface UIFeedbackGenerator : UIInteraction {
[Field (""prepare"", ""LibraryName"")]
void Prepare { get; }
}
";
yield return [(Source: symbolAndLibrary, Path: "/some/random/path.cs"), new FieldData ("prepare", "LibraryName")];

const string symbolAndLibraryNamed = @"
using System;
using Foundation;
using ObjCRuntime;
using UIKit;
namespace Test;
[NoTV]
[MacCatalyst (13, 1)]
[DisableDefaultCtor]
[Abstract]
[BaseType (typeof (NSObject))]
interface UIFeedbackGenerator : UIInteraction {
[Field (""prepare"", LibraryName = ""LibraryName"")]
void Prepare { get; }
}
";
yield return [(Source: symbolAndLibraryNamed, Path: "/some/random/path.cs"), new FieldData ("prepare", "LibraryName")];
}

IEnumerator IEnumerable.GetEnumerator () => GetEnumerator ();
}

[Theory]
[AllSupportedPlatformsClassData<TestDataTryCreate>]
void TryCreateTests (ApplePlatform platform, (string Source, string Path) source, FieldData expectedData)
{
// create a compilation used to create the transformer
var compilation = CreateCompilation (platform, sources: source);
var syntaxTree = compilation.SyntaxTrees.FirstOrDefault ();
Assert.NotNull (syntaxTree);

var semanticModel = compilation.GetSemanticModel (syntaxTree);
Assert.NotNull (semanticModel);

var declaration = syntaxTree.GetRoot ()
.DescendantNodes ().OfType<PropertyDeclarationSyntax> ()
.FirstOrDefault ();
Assert.NotNull (declaration);

var symbol = semanticModel.GetDeclaredSymbol (declaration);
Assert.NotNull (symbol);
var fieldData = symbol.GetAttribute<FieldData> (AttributesNames.FieldAttribute, FieldData.TryParse);
Assert.Equal (expectedData, fieldData);
}
}

0 comments on commit 727a00f

Please sign in to comment.