From 17f6057ec46ed613959c84f6e3f4a1590c5c9c7e Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Saenz Date: Thu, 6 Mar 2025 12:49:21 -0500 Subject: [PATCH 1/5] [Bgen] Improve the generated code for SmarEnum BindAs calls. Because we now have a GetValue method that takes a NativeHandle, we can simplify the code generated when we are dealing with a smart enum in a BindAs decorated property/method. The old generated code is: ```csharp ret = global::CoreAnimation.CACornerCurveExtensions.GetValue (Runtime.GetNSObject (global::ObjCRuntime.Messaging.NativeHandle_objc_msgSend (this.Handle, Selector.GetHandle ("cornerCurve")), false)!); ``` While the new one is: ```csharp ret = global::NaturalLanguage.NLLanguageExtensions.GetValue (global::ObjCRuntime.Messaging.NativeHandle_objc_msgSendSuper (this.SuperHandle, Selector.GetHandle ("language"))); ``` The code is simpler, but there is also a small memory imrpovement. In the old version of the binding, we were not callin the Dispose method in the NSString. On the other hand, the new code uses the GetValue method that is disposing the NSString as soon as it leaves the method and therefore it does not need the GC to take care of it. --- src/bgen/Generator.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bgen/Generator.cs b/src/bgen/Generator.cs index 9fbd2e73455..ec6fa3e547a 100644 --- a/src/bgen/Generator.cs +++ b/src/bgen/Generator.cs @@ -2910,9 +2910,8 @@ void GetReturnsWrappers (MethodInfo mi, MemberInformation minfo, Type declaringT var formattedReturnType = TypeManager.FormatType (minfo.type, mi.ReturnType); if (mi.ReturnType == TypeCache.NSString) { if (isNullable) { - print ("{0} retvaltmp;", NativeHandleType); - cast_a = "((retvaltmp = "; - cast_b = $") == IntPtr.Zero ? default ({formattedBindAsType}) : ({wrapper}Runtime.GetNSObject<{formattedReturnType}> (retvaltmp, {owns})!){suffix})"; + cast_a = $"{wrapper}"; + cast_b = $"{suffix}"; } else { cast_a = $"{wrapper}Runtime.GetNSObject<{formattedReturnType}> ("; cast_b = $", {owns})!{suffix}"; From 78eefefcae72f1a6615cbb159d3aa4968983bc7f Mon Sep 17 00:00:00 2001 From: GitHub Actions Autoformatter Date: Thu, 6 Mar 2025 17:58:49 +0000 Subject: [PATCH 2/5] Auto-format source code --- .../Emitters/BindingSyntaxFactory.Runtime.cs | 6 +++--- .../Emitters/BindingSyntaxFactoryRuntimeTests.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.Runtime.cs b/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.Runtime.cs index 779884edc79..55079649653 100644 --- a/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.Runtime.cs +++ b/src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.Runtime.cs @@ -173,7 +173,7 @@ internal static InvocationExpressionSyntax StringFromHandle (ImmutableArray /// Generates a call to the NSArray.ArrayFromHandleFunc with the given arguments. /// @@ -189,14 +189,14 @@ internal static InvocationExpressionSyntax NSArrayFromHandleFunc (string returnT // generate var genericsList = TypeArgumentList ( SingletonSeparatedList (IdentifierName (returnType))); - + // generate NSArray.ArrayFromHandleFunc (arg1, arg2, arg3) return InvocationExpression ( MemberAccessExpression ( SyntaxKind.SimpleMemberAccessExpression, IdentifierName ("NSArray"), GenericName ("ArrayFromHandleFunc") - .WithTypeArgumentList(genericsList) + .WithTypeArgumentList (genericsList) .WithTrailingTrivia (Space))) .WithArgumentList (argumentList); } diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/Emitters/BindingSyntaxFactoryRuntimeTests.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/Emitters/BindingSyntaxFactoryRuntimeTests.cs index 06896e519a3..06db8931342 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/Emitters/BindingSyntaxFactoryRuntimeTests.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/Emitters/BindingSyntaxFactoryRuntimeTests.cs @@ -145,8 +145,8 @@ void StringFromHandleTests (ImmutableArray arguments, string exp var declaration = StringFromHandle (arguments); Assert.Equal (expectedDeclaration, declaration.ToFullString ()); } - - class TestDataNSArrayFromHandleFunc: IEnumerable { + + class TestDataNSArrayFromHandleFunc : IEnumerable { public IEnumerator GetEnumerator () { yield return [ @@ -168,7 +168,7 @@ public IEnumerator GetEnumerator () IEnumerator IEnumerable.GetEnumerator () => GetEnumerator (); } - + [Theory] [ClassData (typeof (TestDataNSArrayFromHandleFunc))] void NSArrayFromHandleFuncTests (string returnType, ImmutableArray arguments, string expectedDeclaration) From 65b637e556a2dee32b3673bc44be52567c137c8d Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Saenz Date: Sun, 9 Mar 2025 19:30:19 -0400 Subject: [PATCH 3/5] Fix code to take into account those methods that return a nullable enum. --- src/bgen/Enums.cs | 17 +++++++++++++++++ src/bgen/Generator.cs | 15 +++++++-------- .../Emitters/EnumEmitter.cs | 17 ++++++++++++++++- .../Data/ExpectedAVCaptureDeviceTypeEnum.cs | 12 ++++++++++++ .../ExpectedAVCaptureSystemPressureLevel.cs | 12 ++++++++++++ .../SmartEnum/Data/ExpectedCustomLibraryEnum.cs | 12 ++++++++++++ .../Data/ExpectedCustomLibraryEnumInternal.cs | 12 ++++++++++++ .../Data/ExpectedMacOSAVMediaCharacteristics.cs | 12 ++++++++++++ .../Data/ExpectediOSAVMediaCharacteristics.cs | 12 ++++++++++++ 9 files changed, 112 insertions(+), 9 deletions(-) diff --git a/src/bgen/Enums.cs b/src/bgen/Enums.cs index 5c1624b1d01..2febbb3cad6 100644 --- a/src/bgen/Enums.cs +++ b/src/bgen/Enums.cs @@ -321,6 +321,23 @@ void GenerateEnum (Type type) print ("return GetValue (str);"); indent--; print ("}"); + + if (BindingTouch.SupportsXmlDocumentation) { + print ($"/// Retrieves the value represented by the backing field value in ."); + print ($"/// The native handle with the name of the constant to retrieve."); + } + + print ("public static {0}? GetNullableValue ({1} handle)", type.Name, NativeHandleType); + print ("{"); + indent++; + print ("using var str = Runtime.GetNSObject<{0}> (handle);", backingFieldTypeName); + print ("if (str is null)"); + indent++; + print ("return null;"); + indent--; + print ("return GetValue (str);"); + indent--; + print ("}"); } if (BindingTouch.SupportsXmlDocumentation) { diff --git a/src/bgen/Generator.cs b/src/bgen/Generator.cs index ec6fa3e547a..37a3910ae06 100644 --- a/src/bgen/Generator.cs +++ b/src/bgen/Generator.cs @@ -500,7 +500,11 @@ string GetFromBindAsWrapper (MemberInformation minfo, out string suffix) throw GetBindAsException ("unbox", retType.Name, originalReturnType.Name, "container", minfo.mi); } } else if (originalReturnType == TypeCache.NSString && IsSmartEnum (retType)) { - append = $"{TypeManager.FormatType (retType.DeclaringType, retType)}Extensions.GetValue ("; + if (isNullable) { + append = $"{TypeManager.FormatType (retType.DeclaringType, retType)}Extensions.GetNullableValue ("; + } else { + append = $"{TypeManager.FormatType (retType.DeclaringType, retType)}Extensions.GetValue ("; + } suffix = ")"; } else if (originalReturnType.IsArray && originalReturnType.GetArrayRank () == 1) { var arrType = originalReturnType.GetElementType (); @@ -2909,13 +2913,8 @@ void GetReturnsWrappers (MethodInfo mi, MemberInformation minfo, Type declaringT var wrapper = GetFromBindAsWrapper (minfo, out suffix); var formattedReturnType = TypeManager.FormatType (minfo.type, mi.ReturnType); if (mi.ReturnType == TypeCache.NSString) { - if (isNullable) { - cast_a = $"{wrapper}"; - cast_b = $"{suffix}"; - } else { - cast_a = $"{wrapper}Runtime.GetNSObject<{formattedReturnType}> ("; - cast_b = $", {owns})!{suffix}"; - } + cast_a = $"{wrapper}"; + cast_b = $"{suffix}"; } else { var enumCast = (bindAsType.IsEnum && !minfo.type.IsArray) ? $"({formattedBindAsType}) " : string.Empty; cast_a = $"{enumCast}Runtime.GetNSObject<{formattedReturnType}> ("; diff --git a/src/rgen/Microsoft.Macios.Generator/Emitters/EnumEmitter.cs b/src/rgen/Microsoft.Macios.Generator/Emitters/EnumEmitter.cs index 4970234551e..9a56d7204d9 100644 --- a/src/rgen/Microsoft.Macios.Generator/Emitters/EnumEmitter.cs +++ b/src/rgen/Microsoft.Macios.Generator/Emitters/EnumEmitter.cs @@ -112,8 +112,23 @@ void EmitExtensionMethods (TabbedWriter classBlock, string symbolN return GetValue (str); "); } - classBlock.WriteLine (); + + // get nullable value from a handle, similar to the above but used when the enum could be null (yes, apple + // does have methods that return null for enums) + classBlock.WriteDocumentation (Documentation.SmartEnum.GetValueHandle (symbolName)); + using (var getValueFromHandle = + classBlock.CreateBlock ($"public static {binding.Name}? GetNullableValue (NativeHandle handle)", + true)) { + getValueFromHandle.WriteRaw ( +@"using var str = Runtime.GetNSObject (handle); +if (str is null) + return null; +return GetValue (str); +"); + } + classBlock.WriteLine (); + // To ConstantArray classBlock.WriteDocumentation (Documentation.SmartEnum.ToConstantArray (symbolName)); classBlock.WriteRaw ( diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedAVCaptureDeviceTypeEnum.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedAVCaptureDeviceTypeEnum.cs index 053fef12920..ee57ea35c70 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedAVCaptureDeviceTypeEnum.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedAVCaptureDeviceTypeEnum.cs @@ -217,6 +217,18 @@ public static AVCaptureDeviceType GetValue (NativeHandle handle) return GetValue (str); } + /// + /// Retrieves the value represented by the backing field value in . + /// + /// The native handle with the name of the constant to retrieve. + public static AVCaptureDeviceType? GetNullableValue (NativeHandle handle) + { + using var str = Runtime.GetNSObject (handle); + if (str is null) + return null; + return GetValue (str); + } + /// /// Converts an array of enum values into an array of their corresponding constants. /// diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedAVCaptureSystemPressureLevel.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedAVCaptureSystemPressureLevel.cs index f4f394fd579..70d777dee19 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedAVCaptureSystemPressureLevel.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedAVCaptureSystemPressureLevel.cs @@ -127,6 +127,18 @@ public static AVCaptureSystemPressureLevel GetValue (NativeHandle handle) return GetValue (str); } + /// + /// Retrieves the value represented by the backing field value in . + /// + /// The native handle with the name of the constant to retrieve. + public static AVCaptureSystemPressureLevel? GetNullableValue (NativeHandle handle) + { + using var str = Runtime.GetNSObject (handle); + if (str is null) + return null; + return GetValue (str); + } + /// /// Converts an array of enum values into an array of their corresponding constants. /// diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedCustomLibraryEnum.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedCustomLibraryEnum.cs index d76d7ca76c8..935a2e6d5b1 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedCustomLibraryEnum.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedCustomLibraryEnum.cs @@ -98,6 +98,18 @@ public static CustomLibraryEnum GetValue (NativeHandle handle) return GetValue (str); } + /// + /// Retrieves the value represented by the backing field value in . + /// + /// The native handle with the name of the constant to retrieve. + public static CustomLibraryEnum? GetNullableValue (NativeHandle handle) + { + using var str = Runtime.GetNSObject (handle); + if (str is null) + return null; + return GetValue (str); + } + /// /// Converts an array of enum values into an array of their corresponding constants. /// diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedCustomLibraryEnumInternal.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedCustomLibraryEnumInternal.cs index 0208d212e14..b1d14378afa 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedCustomLibraryEnumInternal.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedCustomLibraryEnumInternal.cs @@ -98,6 +98,18 @@ public static CustomLibraryEnumInternal GetValue (NativeHandle handle) return GetValue (str); } + /// + /// Retrieves the value represented by the backing field value in . + /// + /// The native handle with the name of the constant to retrieve. + public static CustomLibraryEnumInternal? GetNullableValue (NativeHandle handle) + { + using var str = Runtime.GetNSObject (handle); + if (str is null) + return null; + return GetValue (str); + } + /// /// Converts an array of enum values into an array of their corresponding constants. /// diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedMacOSAVMediaCharacteristics.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedMacOSAVMediaCharacteristics.cs index aeb5497653d..bd92d01bc38 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedMacOSAVMediaCharacteristics.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectedMacOSAVMediaCharacteristics.cs @@ -380,6 +380,18 @@ public static AVMediaCharacteristics GetValue (NativeHandle handle) return GetValue (str); } + /// + /// Retrieves the value represented by the backing field value in . + /// + /// The native handle with the name of the constant to retrieve. + public static AVMediaCharacteristics? GetNullableValue (NativeHandle handle) + { + using var str = Runtime.GetNSObject (handle); + if (str is null) + return null; + return GetValue (str); + } + /// /// Converts an array of enum values into an array of their corresponding constants. /// diff --git a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectediOSAVMediaCharacteristics.cs b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectediOSAVMediaCharacteristics.cs index a856c0e0eb5..62388e373a1 100644 --- a/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectediOSAVMediaCharacteristics.cs +++ b/tests/rgen/Microsoft.Macios.Generator.Tests/SmartEnum/Data/ExpectediOSAVMediaCharacteristics.cs @@ -399,6 +399,18 @@ public static AVMediaCharacteristics GetValue (NativeHandle handle) return GetValue (str); } + /// + /// Retrieves the value represented by the backing field value in . + /// + /// The native handle with the name of the constant to retrieve. + public static AVMediaCharacteristics? GetNullableValue (NativeHandle handle) + { + using var str = Runtime.GetNSObject (handle); + if (str is null) + return null; + return GetValue (str); + } + /// /// Converts an array of enum values into an array of their corresponding constants. /// From ceede5db89fde29099c641e583b5b83866724018 Mon Sep 17 00:00:00 2001 From: GitHub Actions Autoformatter Date: Sun, 9 Mar 2025 23:34:02 +0000 Subject: [PATCH 4/5] Auto-format source code --- src/bgen/Enums.cs | 2 +- src/rgen/Microsoft.Macios.Generator/Emitters/EnumEmitter.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bgen/Enums.cs b/src/bgen/Enums.cs index 2febbb3cad6..fc5de2230bb 100644 --- a/src/bgen/Enums.cs +++ b/src/bgen/Enums.cs @@ -321,7 +321,7 @@ void GenerateEnum (Type type) print ("return GetValue (str);"); indent--; print ("}"); - + if (BindingTouch.SupportsXmlDocumentation) { print ($"/// Retrieves the value represented by the backing field value in ."); print ($"/// The native handle with the name of the constant to retrieve."); diff --git a/src/rgen/Microsoft.Macios.Generator/Emitters/EnumEmitter.cs b/src/rgen/Microsoft.Macios.Generator/Emitters/EnumEmitter.cs index 9a56d7204d9..d1de240035c 100644 --- a/src/rgen/Microsoft.Macios.Generator/Emitters/EnumEmitter.cs +++ b/src/rgen/Microsoft.Macios.Generator/Emitters/EnumEmitter.cs @@ -113,7 +113,7 @@ void EmitExtensionMethods (TabbedWriter classBlock, string symbolN "); } classBlock.WriteLine (); - + // get nullable value from a handle, similar to the above but used when the enum could be null (yes, apple // does have methods that return null for enums) classBlock.WriteDocumentation (Documentation.SmartEnum.GetValueHandle (symbolName)); @@ -128,7 +128,7 @@ void EmitExtensionMethods (TabbedWriter classBlock, string symbolN "); } classBlock.WriteLine (); - + // To ConstantArray classBlock.WriteDocumentation (Documentation.SmartEnum.ToConstantArray (symbolName)); classBlock.WriteRaw ( From 33f40a949aaf664876aca10d268b36a8b08e50a4 Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Saenz Date: Mon, 10 Mar 2025 11:46:10 -0400 Subject: [PATCH 5/5] Update xml doc expectations. --- tests/generator/ExpectedXmlDocs.MacCatalyst.xml | 4 ++++ tests/generator/ExpectedXmlDocs.iOS.xml | 4 ++++ tests/generator/ExpectedXmlDocs.macOS.xml | 4 ++++ tests/generator/ExpectedXmlDocs.tvOS.xml | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/tests/generator/ExpectedXmlDocs.MacCatalyst.xml b/tests/generator/ExpectedXmlDocs.MacCatalyst.xml index 0c6e3bf8d3d..9ce7b30bd14 100644 --- a/tests/generator/ExpectedXmlDocs.MacCatalyst.xml +++ b/tests/generator/ExpectedXmlDocs.MacCatalyst.xml @@ -39,6 +39,10 @@ Retrieves the value represented by the backing field value in . The native handle with the name of the constant to retrieve. + + Retrieves the value represented by the backing field value in . + The native handle with the name of the constant to retrieve. + Converts an array of enum values into an array of their corresponding constants. The array of enum values to convert. diff --git a/tests/generator/ExpectedXmlDocs.iOS.xml b/tests/generator/ExpectedXmlDocs.iOS.xml index 502a663e13b..dba5cc1b0cf 100644 --- a/tests/generator/ExpectedXmlDocs.iOS.xml +++ b/tests/generator/ExpectedXmlDocs.iOS.xml @@ -39,6 +39,10 @@ Retrieves the value represented by the backing field value in . The native handle with the name of the constant to retrieve. + + Retrieves the value represented by the backing field value in . + The native handle with the name of the constant to retrieve. + Converts an array of enum values into an array of their corresponding constants. The array of enum values to convert. diff --git a/tests/generator/ExpectedXmlDocs.macOS.xml b/tests/generator/ExpectedXmlDocs.macOS.xml index 0c6e3bf8d3d..9ce7b30bd14 100644 --- a/tests/generator/ExpectedXmlDocs.macOS.xml +++ b/tests/generator/ExpectedXmlDocs.macOS.xml @@ -39,6 +39,10 @@ Retrieves the value represented by the backing field value in . The native handle with the name of the constant to retrieve. + + Retrieves the value represented by the backing field value in . + The native handle with the name of the constant to retrieve. + Converts an array of enum values into an array of their corresponding constants. The array of enum values to convert. diff --git a/tests/generator/ExpectedXmlDocs.tvOS.xml b/tests/generator/ExpectedXmlDocs.tvOS.xml index 0c6e3bf8d3d..9ce7b30bd14 100644 --- a/tests/generator/ExpectedXmlDocs.tvOS.xml +++ b/tests/generator/ExpectedXmlDocs.tvOS.xml @@ -39,6 +39,10 @@ Retrieves the value represented by the backing field value in . The native handle with the name of the constant to retrieve. + + Retrieves the value represented by the backing field value in . + The native handle with the name of the constant to retrieve. + Converts an array of enum values into an array of their corresponding constants. The array of enum values to convert.