Skip to content

Commit

Permalink
[Rgen] Keep track if a type is a dictionary container. (#22042)
Browse files Browse the repository at this point in the history
  • Loading branch information
mandel-macaque authored Jan 25, 2025
1 parent 341abb3 commit 1195014
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ symbol is IArrayTypeSymbol arrayTypeSymbol
symbol.GetInheritance (
isNSObject: out isNSObject,
isNativeObject: out isINativeObject,
isDictionaryContainer: out isDictionaryContainer,
parents: out parents,
interfaces: out interfaces);

Expand Down
8 changes: 8 additions & 0 deletions src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ public bool IsINativeObject {
init => isINativeObject = value;
}

readonly bool isDictionaryContainer = false;

public bool IsDictionaryContainer {
get => isDictionaryContainer;
init => isDictionaryContainer = value;
}

readonly ImmutableArray<string> parents = [];
public ImmutableArray<string> Parents {
get => parents;
Expand Down Expand Up @@ -284,6 +291,7 @@ public override string ToString ()
sb.Append ($"IsStruct: {IsStruct}, ");
sb.Append ($"IsVoid : {IsVoid}, ");
sb.Append ($"IsNSObject : {IsNSObject}, ");
sb.Append ($"IsDictionaryContainer: {IsDictionaryContainer}, ");
sb.Append ($"IsNativeObject: {IsINativeObject}, ");
sb.Append ($"IsInterface: {IsInterface}, ");
sb.Append ($"IsNativeIntegerType: {IsNativeIntegerType}, ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,18 +402,22 @@ internal static int GetValueTypeSize (this ITypeSymbol type, List<ITypeSymbol> f
/// </summary>
/// <param name="symbol">The symbol whose inheritance we want to retrieve.</param>
/// <param name="isNativeObject">If the type implements the INativeObject interface.</param>
/// <param name="isDictionaryContainer">If the type inherits from Foundation.DictionaryContainer.</param>
/// <param name="parents">An immutable array of the parents in order from closest to furthest.</param>
/// <param name="interfaces">All implemented interfaces by the type and its parents.</param>
/// <param name="isNSObject">If the type inherits from NSObject.</param>
public static void GetInheritance (
this ITypeSymbol symbol, out bool isNSObject, out bool isNativeObject, out ImmutableArray<string> parents,
this ITypeSymbol symbol, out bool isNSObject, out bool isNativeObject, out bool isDictionaryContainer,
out ImmutableArray<string> parents,
out ImmutableArray<string> interfaces)
{
const string nativeObjectInterface = "ObjCRuntime.INativeObject";
const string nsObjectClass = "Foundation.NSObject";
const string dictionaryContainerClass = "Foundation.DictionaryContainer";

isNSObject = false;
isNativeObject = false;
isDictionaryContainer = false;

// parents will be returned directly in a Immutable array via a builder since the order is important
// interfaces will use a hash set because we do not want duplicates.
Expand All @@ -426,6 +430,7 @@ public static void GetInheritance (
// check if we reach the NSObject as a parent
var parentName = currentType.ToDisplayString ().Trim ();
isNSObject |= parentName == nsObjectClass;
isDictionaryContainer |= parentName == dictionaryContainerClass;
parentsBuilder.Add (parentName);

// union with the current interfaces
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@ namespace NS;
public class TestClass {}
";
yield return [simpleClass, false, false, new [] { "object" }, new string [] { }];
yield return [
simpleClass,
false,
false,
false,
new [] { "object" },
new string [] { }];

const string genericClass = @"
using System;
Expand All @@ -36,7 +42,13 @@ namespace NS;
public class TestClass<T> where T Enum {}
";
yield return [genericClass, false, false, new [] { "object" }, new string [] { }];
yield return [
genericClass,
false,
false,
false,
new [] { "object" },
new string [] { }];

const string singleParent = @"
using System;
Expand All @@ -47,7 +59,13 @@ public class Parent {}
public class TestClass : Parent {}
";

yield return [singleParent, false, false, new [] { "NS.Parent", "object" }, new string [] { }];
yield return [
singleParent,
false,
false,
false,
new [] { "NS.Parent", "object" },
new string [] { }];

const string genericParent = @"
using System;
Expand All @@ -58,7 +76,13 @@ public class Parent<T> where T object {}
public class TestClass : Parent<string> {}
";

yield return [genericParent, false, false, new [] { "NS.Parent<string>", "object" }, new string [] { }];
yield return [
genericParent,
false,
false,
false,
new [] { "NS.Parent<string>", "object" },
new string [] { }];

const string multiParent = @"
using System;
Expand All @@ -70,7 +94,12 @@ public class Parent1 : Parent0 {}
public class TestClass : Parent1 {}
";

yield return [multiParent, false, false, new [] { "NS.Parent1", "NS.Parent0", "object" }, new string [] { }];
yield return [multiParent,
false,
false,
false,
new [] { "NS.Parent1", "NS.Parent0", "object" },
new string [] { }];

const string singleInterface = @"
using System;
Expand All @@ -81,7 +110,13 @@ public interface IInterface {}
public class TestClass : IInterface {}
";

yield return [singleInterface, false, false, new [] { "object" }, new [] { "NS.IInterface" }];
yield return [
singleInterface,
false,
false,
false,
new [] { "object" },
new [] { "NS.IInterface" }];

const string genericInterface = @"
using System;
Expand All @@ -92,7 +127,13 @@ public interface IInterface<T> where T : object {}
public class TestClass : IInterface<string> {}
";

yield return [genericInterface, false, false, new [] { "object" }, new [] { "NS.IInterface<string>" }];
yield return [
genericInterface,
false,
false,
false,
new [] { "object" },
new [] { "NS.IInterface<string>" }];

const string severalInterfaces = @"
using System;
Expand All @@ -104,7 +145,13 @@ public interface IInterface2 {}
public class TestClass : IInterface1, IInterface2 {}
";

yield return [severalInterfaces, false, false, new [] { "object" }, new [] { "NS.IInterface1", "NS.IInterface2" }];
yield return [
severalInterfaces,
false,
false,
false,
new [] { "object" },
new [] { "NS.IInterface1", "NS.IInterface2" }];

const string severalGenericInterfaces = @"
using System;
Expand All @@ -115,7 +162,12 @@ public interface IInterface1<T> where T : object {}
public class TestClass : IInterface1<string>, IInterface1<int> {}
";

yield return [severalGenericInterfaces, false, false, new [] { "object" }, new [] { "NS.IInterface1<string>", "NS.IInterface1<int>" }];
yield return [severalGenericInterfaces,
false,
false,
false,
new [] { "object" },
new [] { "NS.IInterface1<string>", "NS.IInterface1<int>" }];

const string parentSingleInterface = @"
using System;
Expand All @@ -127,7 +179,13 @@ public class Parent : IInterface {}
public class TestClass : Parent {}
";

yield return [parentSingleInterface, false, false, new [] { "NS.Parent", "object" }, new [] { "NS.IInterface" }];
yield return [
parentSingleInterface,
false,
false,
false,
new [] { "NS.Parent", "object" },
new [] { "NS.IInterface" }];

const string nsObjectChild = @"
using System;
Expand All @@ -149,6 +207,7 @@ protected AVCaptureDataOutputSynchronizer (NSObjectFlag t) : base (t)
yield return [nsObjectChild,
true,
true,
false,
new [] { "Foundation.NSObject", "object" },
new [] {
"ObjCRuntime.INativeObject",
Expand Down Expand Up @@ -180,6 +239,7 @@ public partial class Child : AVCaptureDataOutputSynchronizer {}
yield return [nsObjectNestedChild,
true,
true,
false,
new [] { "NS.AVCaptureDataOutputSynchronizer", "Foundation.NSObject", "object" },
new [] {
"ObjCRuntime.INativeObject",
Expand Down Expand Up @@ -209,10 +269,27 @@ protected AVCaptureDataOutputSynchronizer (NSObjectFlag t) : base (t)
yield return [nativeObjectInterface,
false,
true,
false,
new [] { "object" },
new [] {
"ObjCRuntime.INativeObject",
}];

const string dictionaryContainer = @"
using System;
using Foundation;
using ObjCRuntime;
namespace NS;
public partial class SKCloudServiceSetupOptions : DictionaryContainer { }
";

yield return [dictionaryContainer,
false,
false,
true,
new [] { "Foundation.DictionaryContainer", "object" },
new string [] { }];
}

IEnumerator IEnumerable.GetEnumerator () => GetEnumerator ();
Expand All @@ -221,7 +298,8 @@ protected AVCaptureDataOutputSynchronizer (NSObjectFlag t) : base (t)
[Theory]
[AllSupportedPlatformsClassData<TestDataInheritanceClasses>]
void GetInheritance (ApplePlatform platform, string inputText,
bool expectedIsNSObject, bool expectedIsNativeObject, string [] expectedParents, string [] expectedInterfaces)
bool expectedIsNSObject, bool expectedIsNativeObject, bool expectedDictionaryContainer,
string [] expectedParents, string [] expectedInterfaces)
{
var (compilation, syntaxTrees) = CreateCompilation (platform, sources: inputText);
Assert.Single (syntaxTrees);
Expand All @@ -237,11 +315,13 @@ void GetInheritance (ApplePlatform platform, string inputText,
symbol.GetInheritance (
isNSObject: out var isNsObject,
isNativeObject: out var isNativeObject,
isDictionaryContainer: out var isDictionaryContainer,
parents: out var parents,
interfaces: out var interfaces);
Assert.Equal (expectedIsNSObject, isNsObject);
Assert.Equal (expectedIsNativeObject, isNativeObject);
Assert.Equal (expectedParents, parents);
Assert.Equal (expectedInterfaces, interfaces);
Assert.Equal (expectedDictionaryContainer, isDictionaryContainer);
}
}

0 comments on commit 1195014

Please sign in to comment.