Skip to content

Commit

Permalink
[Rgen] Add code to parse the NativeAttribute.
Browse files Browse the repository at this point in the history
Not to be confused with the NativeNameAttribute, which is different.
  • Loading branch information
mandel-macaque committed Jan 25, 2025
1 parent fba23cf commit 56e42ab
Show file tree
Hide file tree
Showing 2 changed files with 189 additions and 0 deletions.
89 changes: 89 additions & 0 deletions src/rgen/Microsoft.Macios.Transformer/Attributes/NativeData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

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

namespace Microsoft.Macios.Transformer.Attributes;

readonly struct NativeData : IEquatable<NativeData> {

public string? NativeName { get; }

public NativeData () {}

public NativeData (string? nativeName)
{
NativeName = nativeName;
}


public static bool TryParse (AttributeData attributeData,
[NotNullWhen (true)] out NativeData? data)
{
data = null;
var count = attributeData.ConstructorArguments.Length;
string? nativeName;

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

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

foreach (var (argumentName, value) in attributeData.NamedArguments) {
switch (argumentName) {
case "NativeName":
nativeName = (string) value.Value!;
break;
default:
data = null;
return false;
}
}

data = new(nativeName);
return true;
}

public bool Equals (NativeData other)
=> NativeName == other.NativeName;

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

/// <inheritdoc />
public override int GetHashCode ()
=> HashCode.Combine (NativeName);


public static bool operator == (NativeData x, NativeData y)
{
return x.Equals (y);
}

public static bool operator != (NativeData x, NativeData y)
{
return !(x == y);
}

/// <inheritdoc />
public override string ToString ()
{
return $"{{ NativeName: '{NativeName}' }}";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// 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 NativeDataTests : BaseTransformerTestClass {

class TestDataTryCreate : IEnumerable<object []> {
public IEnumerator<object []> GetEnumerator ()
{
var path = "/some/random/path.cs";
var simnpleNativeEnum = @"
using System;
using Foundation;
using ObjCRuntime;
[Native]
public enum AVAudioQuality : long {
Min = 0,
Low = 0x20,
Medium = 0x40,
High = 0x60,
Max = 0x7F,
}
";

yield return [(Sorunce: simnpleNativeEnum, Path: path), new NativeData ()];

var nativeEnumWithName = @"
using System;
using Foundation;
using ObjCRuntime;
[Native (""Test"")]
public enum AVAudioQuality : long {
Min = 0,
Low = 0x20,
Medium = 0x40,
High = 0x60,
Max = 0x7F,
}
";

yield return [(Sorunce: nativeEnumWithName, Path: path), new NativeData ("Test")];

var nativeEnumWithNameNamed = @"
using System;
using Foundation;
using ObjCRuntime;
[Native (NativeName = ""Test"")]
public enum AVAudioQuality : long {
Min = 0,
Low = 0x20,
Medium = 0x40,
High = 0x60,
Max = 0x7F,
}
";

yield return [(Sorunce: nativeEnumWithNameNamed, Path: path), new NativeData ("Test")];
}

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

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

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

var declaration = syntaxTree.GetRoot ()
.DescendantNodes ().OfType<EnumDeclarationSyntax> ()
.LastOrDefault ();
Assert.NotNull (declaration);

var symbol = semanticModel.GetDeclaredSymbol (declaration);
Assert.NotNull (symbol);
var exportData = symbol.GetAttribute<NativeData> (
AttributesNames.NativeAttribute, NativeData.TryParse);
Assert.Equal (expectedData, exportData);
}

}

0 comments on commit 56e42ab

Please sign in to comment.