Skip to content

Commit

Permalink
[Rgen] Implement the parsing of the backing field attr in the transfo…
Browse files Browse the repository at this point in the history
…rmer.
  • Loading branch information
mandel-macaque committed Jan 24, 2025
1 parent 0e52702 commit 8a1e32f
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

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

namespace Microsoft.Macios.Transformer.Attributes;

readonly struct BackingFieldTypeData : IEquatable<BackingFieldTypeData> {

public string TypeName { get; }

public BackingFieldTypeData (string typeName)
{
TypeName = typeName;
}

public static bool TryParse (AttributeData attributeData,
[NotNullWhen (true)] out BackingFieldTypeData? data)
{
data = null;
var count = attributeData.ConstructorArguments.Length;
string backingField;
// custom marshal directive values

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

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

foreach (var (argumentName, value) in attributeData.NamedArguments) {
switch (argumentName) {
case "BackingFieldType":
backingField = ((INamedTypeSymbol) value.Value!).ToDisplayString ();
break;
default:
data = null;
return false;
}
}

data = new(backingField);
return true;
}

public bool Equals (BackingFieldTypeData other)
{
return TypeName == other.TypeName;
}

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

/// <inheritdoc />
public override int GetHashCode ()
=> TypeName.GetHashCode ();


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

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

/// <inheritdoc />
public override string ToString ()
{
return $"{{ BackingFieldType: '{TypeName}' }}";
}
}
11 changes: 8 additions & 3 deletions src/rgen/Microsoft.Macios.Transformer/AttributesNames.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#pragma warning disable format
using Microsoft.Macios.Transformer.Generator;

namespace Microsoft.Macios.Transformer;
Expand All @@ -13,7 +15,8 @@ static class AttributesNames {
[BindingFlag (AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Interface)]
public const string AbstractAttribute = "AbstractAttribute";

[BindingFlag] public const string AdvancedAttribute = "AdvancedAttribute";
[BindingFlag]
public const string AdvancedAttribute = "AdvancedAttribute";
public const string AdviceAttribute = "Foundation.AdviceAttribute";

/// <summary>
Expand Down Expand Up @@ -41,7 +44,8 @@ static class AttributesNames {
[BindingFlag (AttributeTargets.Interface)]
public const string CategoryAttribute = "CategoryAttribute";

[BindingFlag] public const string CheckDisposedAttribute = "CheckDisposedAttribute";
[BindingFlag]
public const string CheckDisposedAttribute = "CheckDisposedAttribute";
public const string CoreImageFilterAttribute = "CoreImageFilterAttribute";
public const string DefaultCtorVisibilityAttribute = "DefaultCtorVisibilityAttribute";

Expand Down Expand Up @@ -74,7 +78,8 @@ static class AttributesNames {
public const string ExperimentalAttribute = "System.Diagnostics.CodeAnalysis.ExperimentalAttribute";
public const string ExportAttribute = "Foundation.ExportAttribute";

[BindingFlag] public const string FactoryAttribute = "FactoryAttribute";
[BindingFlag]
public const string FactoryAttribute = "FactoryAttribute";
public const string FieldAttribute = "Foundation.FieldAttribute";
public const string FlagsAttribute = "System.FlagsAttribute";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// 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 BackingFieldTypeDataTests : BaseTransformerTestClass {

class TestDataTryCreate : IEnumerable<object []> {
public IEnumerator<object []> GetEnumerator ()
{
var path = "/some/random/path.cs";
const string nsnumberBackingFieldType = @"
using System;
using Foundation;
using ObjCRuntime;
[NoTV, Mac (15, 0), NoiOS, NoMacCatalyst]
[BackingFieldType (typeof (NSNumber))]
public enum ASAuthorizationProviderExtensionEncryptionAlgorithm {
[Field (""ASAuthorizationProviderExtensionEncryptionAlgorithmECDHE_A256GCM"")]
EcdheA256Gcm,
[Field (""ASAuthorizationProviderExtensionEncryptionAlgorithmHPKE_P256_SHA256_AES_GCM_256"")]
HpkeP256Sha256AesGcm256,
[Field (""ASAuthorizationProviderExtensionEncryptionAlgorithmHPKE_P384_SHA384_AES_GCM_256"")]
HpkeP384Sha384AesGcm256,
[Field (""ASAuthorizationProviderExtensionEncryptionAlgorithmHPKE_Curve25519_SHA256_ChachaPoly"")]
HpkeCurve25519Sha256ChachaPoly,
}
";
yield return [(Source: nsnumberBackingFieldType, Path: path), new BackingFieldTypeData ("Foundation.NSNumber")];

const string nsstringBackingFieldType = @"
using System;
using Foundation;
using ObjCRuntime;
[NoTV, Mac (15, 0), NoiOS, NoMacCatalyst]
[BackingFieldType (typeof (NSString))]
public enum ASAuthorizationProviderExtensionEncryptionAlgorithm {
[Field (""ASAuthorizationProviderExtensionEncryptionAlgorithmECDHE_A256GCM"")]
EcdheA256Gcm,
[Field (""ASAuthorizationProviderExtensionEncryptionAlgorithmHPKE_P256_SHA256_AES_GCM_256"")]
HpkeP256Sha256AesGcm256,
[Field (""ASAuthorizationProviderExtensionEncryptionAlgorithmHPKE_P384_SHA384_AES_GCM_256"")]
HpkeP384Sha384AesGcm256,
[Field (""ASAuthorizationProviderExtensionEncryptionAlgorithmHPKE_Curve25519_SHA256_ChachaPoly"")]
HpkeCurve25519Sha256ChachaPoly,
}
";
yield return [(Source: nsstringBackingFieldType, Path: path), new BackingFieldTypeData ("Foundation.NSString")];

}

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

[Theory]
[AllSupportedPlatformsClassData<TestDataTryCreate>]
void TryeCreateTests (ApplePlatform platform, (string Source, string Path) source, BackingFieldTypeData 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<BaseTypeDeclarationSyntax> ()
.LastOrDefault ();
Assert.NotNull (declaration);

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

0 comments on commit 8a1e32f

Please sign in to comment.