Skip to content

Commit bdfb8e3

Browse files
[RGen] Add extension method to know if a symbol is wrapped.
1 parent 8d57fe6 commit bdfb8e3

File tree

4 files changed

+210
-6
lines changed

4 files changed

+210
-6
lines changed

src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.Generator.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@
77
namespace Microsoft.Macios.Generator.DataModel;
88

99
readonly partial struct TypeInfo {
10+
11+
public bool IsWrapped { get; init; }
12+
13+
public bool ArrayElementTypeIsWrapped { get; init; }
14+
15+
public bool IsWrappedType {
16+
get {
17+
return true;
18+
}
19+
}
1020

1121
internal TypeInfo (ITypeSymbol symbol) :
1222
this (
@@ -18,7 +28,6 @@ symbol is IArrayTypeSymbol arrayTypeSymbol
1828
IsNullable = symbol.NullableAnnotation == NullableAnnotation.Annotated;
1929
IsBlittable = symbol.IsBlittable ();
2030
IsSmartEnum = symbol.IsSmartEnum ();
21-
IsArray = symbol is IArrayTypeSymbol;
2231
IsReferenceType = symbol.IsReferenceType;
2332
IsStruct = symbol.TypeKind == TypeKind.Struct;
2433
IsInterface = symbol.TypeKind == TypeKind.Interface;
@@ -33,6 +42,13 @@ symbol is IArrayTypeSymbol arrayTypeSymbol
3342
parents: out parents,
3443
interfaces: out interfaces);
3544

45+
IsWrapped = symbol.IsWrapped (isNSObject);
46+
if (symbol is IArrayTypeSymbol arraySymbol) {
47+
IsArray = true;
48+
ArrayElementTypeIsWrapped = arraySymbol.ElementType.IsWrapped ();
49+
}
50+
IsArray = symbol is IArrayTypeSymbol;
51+
3652
// try to get the named type symbol to have more educated decisions
3753
var namedTypeSymbol = symbol as INamedTypeSymbol;
3854

src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.Core.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
namespace Microsoft.Macios.Generator.Extensions;
1414

1515
static partial class TypeSymbolExtensions {
16+
17+
const string nativeObjectInterface = "ObjCRuntime.INativeObject";
18+
const string nsObjectClass = "Foundation.NSObject";
19+
const string dictionaryContainerClass = "Foundation.DictionaryContainer";
20+
1621
/// <summary>
1722
/// Retrieve a dictionary with the attribute data of all the attributes attached to a symbol. Because
1823
/// an attribute can appear more than once, the valus are a collection of attribute data.
@@ -417,11 +422,7 @@ public static void GetInheritance (
417422
out ImmutableArray<string> parents,
418423
out ImmutableArray<string> interfaces)
419424
{
420-
const string nativeObjectInterface = "ObjCRuntime.INativeObject";
421-
const string nsObjectClass = "Foundation.NSObject";
422-
const string dictionaryContainerClass = "Foundation.DictionaryContainer";
423-
424-
isNSObject = false;
425+
isNSObject = symbol.ToDisplayString ().Trim() == nsObjectClass;
425426
isNativeObject = false;
426427
isDictionaryContainer = false;
427428

src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.Generator.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Collections.Immutable;
7+
using System.Linq;
68
using Microsoft.CodeAnalysis;
79
using Microsoft.Macios.Generator.Attributes;
810
using Microsoft.Macios.Generator.Availability;
@@ -213,4 +215,32 @@ public static bool NeedsStret (this ITypeSymbol returnType, Compilation compilat
213215

214216
return ArmNeedStret (returnType, compilation);
215217
}
218+
219+
/// <summary>
220+
/// A type is considered wrapped if it is an Interface or is an child of the NSObject class or the NSObject
221+
/// itself.
222+
/// </summary>
223+
/// <param name="symbol">The symbol to check if it is wrapped.</param>
224+
/// <param name="isNSObject">If the symbol is a NSObject of inherits from an NSObject.</param>
225+
/// <returns>True if the ymbol is considered to be wrapped.</returns>
226+
public static bool IsWrapped (this ITypeSymbol symbol, bool isNSObject)
227+
=> symbol.TypeKind == TypeKind.Interface || isNSObject;
228+
229+
/// <summary>
230+
/// A type is considered wrapped if it is an Interface or is an child of the NSObject class or the NSObject
231+
/// itself.
232+
/// </summary>
233+
/// <param name="symbol">The symbol to check if it is wrapped.</param>
234+
/// <returns>True if the ymbol is considered to be wrapped.</returns>
235+
public static bool IsWrapped (this ITypeSymbol symbol)
236+
{
237+
symbol.GetInheritance (
238+
isNSObject: out bool isNSObject,
239+
isNativeObject: out bool _,
240+
isDictionaryContainer: out bool _,
241+
parents: out ImmutableArray<string> _,
242+
interfaces: out ImmutableArray<string> _);
243+
// either we are a NSObject or we are a subclass of it
244+
return IsWrapped (symbol, isNSObject);
245+
}
216246
}

tests/rgen/Microsoft.Macios.Generator.Tests/Extensions/TypeSymbolExtensionsTests.cs

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,5 +1702,162 @@ void IsBlittable (ApplePlatform platform, string inputText, bool expectedResult)
17021702
Assert.NotNull (symbol);
17031703
Assert.Equal (expectedResult, symbol.Type.IsBlittable ());
17041704
}
1705+
1706+
class TestDataIsWrapped : IEnumerable<object []> {
1707+
public IEnumerator<object []> GetEnumerator ()
1708+
{
1709+
const string stringProperty = @"
1710+
using System;
1711+
using ObjCBindings;
1712+
1713+
namespace NS;
1714+
1715+
[BindingType<Class>]
1716+
public partial class MyClass {
1717+
public string Property { get; set; }
1718+
}
1719+
";
1720+
yield return [stringProperty, false];
1721+
1722+
const string nsUuidProperty = @"
1723+
using System;
1724+
using Foundation;
1725+
using ObjCBindings;
1726+
1727+
namespace NS;
1728+
1729+
[BindingType<Class>]
1730+
public partial class MyClass {
1731+
public NSUuid Property { get; set; }
1732+
}
1733+
";
1734+
yield return [nsUuidProperty, true];
1735+
1736+
const string nmatrix4Property = @"
1737+
using System;
1738+
using CoreGraphics;
1739+
using ObjCBindings;
1740+
1741+
namespace NS;
1742+
1743+
[BindingType<Class>]
1744+
public partial class MyClass {
1745+
public NMatrix4 Property { get; set; }
1746+
}
1747+
";
1748+
1749+
yield return [nmatrix4Property, false];
1750+
1751+
const string nativeHandleProperty = @"
1752+
using System;
1753+
using ObjCRuntime;
1754+
using ObjCBindings;
1755+
1756+
namespace NS;
1757+
1758+
[BindingType<Class>]
1759+
public partial class MyClass {
1760+
public NativeHandle Property { get; set; }
1761+
}
1762+
";
1763+
yield return [nativeHandleProperty, false];
1764+
1765+
const string nsZoneProperty = @"
1766+
using System;
1767+
using Foundation;
1768+
using ObjCBindings;
1769+
1770+
namespace NS;
1771+
1772+
[BindingType<Class>]
1773+
public partial class MyClass {
1774+
public NSZone Property { get; set; }
1775+
}
1776+
";
1777+
yield return [nsZoneProperty, false];
1778+
1779+
const string nsobjectProperty = @"
1780+
using System;
1781+
using Foundation;
1782+
using ObjCBindings;
1783+
1784+
namespace NS;
1785+
1786+
[BindingType<Class>]
1787+
public partial class MyClass {
1788+
public NSObject Property { get; set; }
1789+
}
1790+
";
1791+
yield return [nsobjectProperty, true];
1792+
1793+
const string nssetProperty = @"
1794+
using System;
1795+
using Foundation;
1796+
using ObjCBindings;
1797+
1798+
namespace NS;
1799+
1800+
[BindingType<Class>]
1801+
public partial class MyClass {
1802+
public NSSet<NSObject> Property { get; set; }
1803+
}
1804+
";
1805+
yield return [nssetProperty, true];
1806+
1807+
1808+
const string mtlDeviceProperty = @"
1809+
using System;
1810+
using Metal;
1811+
using ObjCBindings;
1812+
1813+
namespace NS;
1814+
1815+
[BindingType<Class>]
1816+
public partial class MyClass {
1817+
public IMTLDevice Property { get; set; }
1818+
}
1819+
";
1820+
yield return [mtlDeviceProperty, true];
1821+
1822+
const string EnumProperty = @"
1823+
using System;
1824+
using System.Runtime.InteropServices;
1825+
using ObjCBindings;
1826+
1827+
namespace NS;
1828+
1829+
public enum MyEnum : ulong {
1830+
First,
1831+
Second,
1832+
}
1833+
1834+
[BindingType<Class>]
1835+
public partial class MyClass {
1836+
public MyEnum Property { get; set; }
1837+
}
1838+
";
1839+
yield return [EnumProperty, false];
1840+
}
1841+
1842+
IEnumerator IEnumerable.GetEnumerator () => GetEnumerator ();
1843+
}
1844+
1845+
[Theory]
1846+
[AllSupportedPlatformsClassData<TestDataIsWrapped>]
1847+
void IsWrapped (ApplePlatform platform, string inputText, bool expectedResult)
1848+
{
1849+
var (compilation, syntaxTrees) = CreateCompilation (platform, sources: inputText);
1850+
Assert.Single (syntaxTrees);
1851+
var declaration = syntaxTrees [0].GetRoot ()
1852+
.DescendantNodes ()
1853+
.OfType<PropertyDeclarationSyntax> ()
1854+
.FirstOrDefault ();
1855+
Assert.NotNull (declaration);
1856+
var semanticModel = compilation.GetSemanticModel (syntaxTrees [0]);
1857+
Assert.NotNull (semanticModel);
1858+
var symbol = semanticModel.GetDeclaredSymbol (declaration);
1859+
Assert.NotNull (symbol);
1860+
Assert.Equal (expectedResult, symbol.Type.IsWrapped ());
1861+
}
17051862

17061863
}

0 commit comments

Comments
 (0)