-
Notifications
You must be signed in to change notification settings - Fork 518
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Rgen] Add the needed code to parse a BindAsAttriubte. (#22083)
This change is a little more interesting than the others because I had to update the way we retrieve the attributes. Return attrbutes are only present on a special collection for IMethodSymbols, this meant that we had to add an extra pass for those attributes in the generic method in pur extensions. --------- Co-authored-by: GitHub Actions Autoformatter <[email protected]>
- Loading branch information
1 parent
0984d4d
commit 53cbff0
Showing
4 changed files
with
217 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
src/rgen/Microsoft.Macios.Transformer/Attributes/BindAsData.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System.Diagnostics.CodeAnalysis; | ||
using Microsoft.CodeAnalysis; | ||
|
||
namespace Microsoft.Macios.Transformer.Attributes; | ||
|
||
readonly record struct BindAsData { | ||
|
||
public string Type { get; init; } | ||
public string? OriginalType { get; init; } | ||
|
||
public BindAsData (string type) | ||
{ | ||
Type = type; | ||
} | ||
|
||
public BindAsData (string type, string? originalType) | ||
{ | ||
Type = type; | ||
OriginalType = originalType; | ||
|
||
} | ||
|
||
public static bool TryParse (AttributeData attributeData, | ||
[NotNullWhen (true)] out BindAsData? data) | ||
{ | ||
data = null; | ||
var count = attributeData.ConstructorArguments.Length; | ||
string type; | ||
string? originalType = null; | ||
|
||
switch (count) { | ||
case 1: | ||
type = ((ITypeSymbol) attributeData.ConstructorArguments [0].Value!).ToDisplayString (); | ||
break; | ||
default: | ||
// 0 should not be an option.. | ||
return false; | ||
} | ||
|
||
if (attributeData.NamedArguments.Length == 0) { | ||
data = new (type); | ||
return true; | ||
} | ||
|
||
foreach (var (argumentName, value) in attributeData.NamedArguments) { | ||
switch (argumentName) { | ||
case "Type": | ||
type = ((ITypeSymbol) value.Value!).ToDisplayString (); | ||
break; | ||
case "OriginalType": | ||
originalType = ((ITypeSymbol) value.Value!).ToDisplayString (); | ||
break; | ||
default: | ||
data = null; | ||
return false; | ||
} | ||
} | ||
|
||
data = new (type, originalType); | ||
return true; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
tests/rgen/Microsoft.Macios.Transformer.Tests/Attributes/BindAsDataTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System.Collections; | ||
using Microsoft.CodeAnalysis; | ||
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; | ||
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; | ||
|
||
namespace Microsoft.Macios.Transformer.Tests.Attributes; | ||
|
||
public class BindAsDataTests : BaseTransformerTestClass { | ||
|
||
class TestDataTryCreate : IEnumerable<object []> { | ||
public IEnumerator<object []> GetEnumerator () | ||
{ | ||
var path = "/some/random/path.cs"; | ||
|
||
const string bindAsProperty = @" | ||
using System; | ||
using Foundation; | ||
using ObjCRuntime; | ||
using CoreMedia; | ||
namespace Test; | ||
[NoTV] | ||
[MacCatalyst (13, 1)] | ||
[DisableDefaultCtor] | ||
[Abstract] | ||
[BaseType (typeof (NSObject))] | ||
interface UIFeedbackGenerator { | ||
[BindAs (typeof (CMVideoDimensions []))] | ||
[Export (""supportedMaxPhotoDimensions"")] | ||
NSValue [] SupportedMaxPhotoDimensions { get; } | ||
} | ||
"; | ||
|
||
yield return [ | ||
PropertyDeclaration (IdentifierName ("string"), Identifier ("Hello")), | ||
(Source: bindAsProperty, Path: path), | ||
new BindAsData ("CoreMedia.CMVideoDimensions[]")]; | ||
|
||
|
||
const string bindAsReturnMethod = @" | ||
using System; | ||
using Foundation; | ||
using ObjCRuntime; | ||
using CoreMedia; | ||
namespace Test; | ||
[NoTV] | ||
[MacCatalyst (13, 1)] | ||
[DisableDefaultCtor] | ||
[Abstract] | ||
[BaseType (typeof (NSObject))] | ||
interface UIFeedbackGenerator { | ||
[return: BindAs (typeof (NSLinguisticTag []))] | ||
[Export (""linguisticTagsInRange:scheme:options:orthography:tokenRanges:"")] | ||
NSString [] GetLinguisticTags (NSRange range, NSString scheme, NSLinguisticTaggerOptions options, [NullAllowed] NSOrthography orthography, [NullAllowed] out NSValue [] tokenRanges); | ||
} | ||
"; | ||
|
||
yield return [ | ||
MethodDeclaration (PredefinedType (Token (SyntaxKind.StringKeyword)), Identifier ("Hello")), | ||
(Source: bindAsReturnMethod, Path: path), | ||
new BindAsData ("Foundation.NSLinguisticTag[]")]; | ||
|
||
|
||
const string parameterBindAs = @" | ||
using System; | ||
using Foundation; | ||
using ObjCRuntime; | ||
using CoreMedia; | ||
namespace Test; | ||
[NoTV] | ||
[MacCatalyst (13, 1)] | ||
[DisableDefaultCtor] | ||
[Abstract] | ||
[BaseType (typeof (NSObject))] | ||
interface UIFeedbackGenerator { | ||
[Export (""linguisticTagsInRange:scheme:options:orthography:tokenRanges:"")] | ||
NSString [] GetLinguisticTags ([BindAs (typeof (ushort?))] NSString scheme); | ||
} | ||
"; | ||
var parameter = Parameter (Identifier ("variable")) | ||
.WithType (PredefinedType (Token (SyntaxKind.StringKeyword))); | ||
yield return [ | ||
parameter, | ||
(Source: parameterBindAs, Path: path), | ||
new BindAsData ("ushort?")]; | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator () => GetEnumerator (); | ||
} | ||
|
||
[Theory] | ||
[AllSupportedPlatformsClassData<TestDataTryCreate>] | ||
void TryCreateTests<T> (ApplePlatform platform, T _, (string Source, string Path) source, BindAsData expectedData) | ||
where T : CSharpSyntaxNode | ||
{ | ||
// create a compilation used to create the transformer | ||
var compilation = CreateCompilation (platform, sources: source); | ||
var syntaxTree = compilation.SyntaxTrees.ForSource (source); | ||
var trees = compilation.SyntaxTrees.Where (s => s.FilePath == source.Path).ToArray (); | ||
Assert.Single (trees); | ||
Assert.NotNull (syntaxTree); | ||
|
||
var semanticModel = compilation.GetSemanticModel (syntaxTree); | ||
Assert.NotNull (semanticModel); | ||
|
||
var declaration = syntaxTree.GetRoot () | ||
.DescendantNodes ().OfType<T> () | ||
.LastOrDefault (); | ||
|
||
Assert.NotNull (declaration); | ||
|
||
var symbol = semanticModel.GetDeclaredSymbol (declaration); | ||
Assert.NotNull (symbol); | ||
var attribute = symbol.GetAttribute<BindAsData> (AttributesNames.BindAsAttribute, BindAsData.TryParse); | ||
Assert.NotNull (attribute); | ||
Assert.Equal (expectedData, attribute.Value); | ||
} | ||
} |