Skip to content

Commit

Permalink
[RGen] Add docs to the SmartEnum generated methods.
Browse files Browse the repository at this point in the history
Add the documentation to the smart enum extension class and its methods.
  • Loading branch information
mandel-macaque committed Mar 3, 2025
1 parent 71c1fa8 commit c51ad86
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 4 deletions.
50 changes: 50 additions & 0 deletions src/rgen/Microsoft.Macios.Generator/Emitters/Documentation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace Microsoft.Macios.Generator.Emitters;

/// <summary>
/// Static class that holds all the documentation strings. This allows to make the code generator
/// cleaner by removing the need to have the documentation strings in the code.
/// </summary>
public static class Documentation {

/// <summary>
/// Smart enum documentation.
/// </summary>
public static class SmartEnum {

public static string ClassDocumentation (string name) =>
@$"/// <summary>
/// Extension methods for the <see cref=""{name}"" /> enumeration.
/// </summary>";

public static string GetConstant () =>
@"/// <summary>
/// Retrieves the <see cref=""global::Foundation.NSString"" /> constant that describes <paramref name=""self"" />.
/// </summary>
/// <param name=""self"">The instance on which this method operates.</param>";

public static string GetValueNSString (string name) =>
@$"/// <summary>
/// Retrieves the <see cref=""{name}"" /> value named by <paramref name=""constant"" />.
/// </summary>
/// <param name=""constant"">The name of the constant to retrieve.</param>";

public static string GetValueHandle (string name) =>
@$"/// <summary>
/// Retrieves the <see cref=""{name}"" /> value represented by the backing field value in <paramref name=""handle"" />.
/// </summary>
/// <param name=""handle"">The native handle with the name of the constant to retrieve.</param>";

public static string ToConstantArray (string name) =>
@$"/// <summary>
/// Converts an array of <see cref=""{name}"" /> enum values into an array of their corresponding constants.
/// </summary>
/// <param name=""values"">The array of enum values to convert.</param>";

public static string ToEnumArray (string _) =>
@"/// <summary>
/// Converts an array of <see cref=""NSString"" /> values into an array of their corresponding enum values.
/// </summary>
/// <param name=""values"">The array if <see cref=""NSString"" /> values to convert.</param>";

}
}
16 changes: 12 additions & 4 deletions src/rgen/Microsoft.Macios.Generator/Emitters/EnumEmitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@ bool TryEmit (TabbedWriter<StringWriter> classBlock, in Binding binding)
return true;
}

void EmitExtensionMethods (TabbedWriter<StringWriter> classBlock, in Binding binding)
void EmitExtensionMethods (TabbedWriter<StringWriter> classBlock, string symbolName, in Binding binding)
{
if (binding.EnumMembers.Length == 0)
return;

// smart enum require 4 diff methods to be able to retrieve the values

// Get constant
classBlock.WriteDocumentation (Documentation.SmartEnum.GetConstant ());
using (var getConstantBlock = classBlock.CreateBlock ($"public static NSString? GetConstant (this {binding.Name} self)", true)) {
getConstantBlock.WriteLine ("IntPtr ptr = IntPtr.Zero;");
using (var switchBlock = getConstantBlock.CreateBlock ("switch ((int) self)", true)) {
Expand All @@ -81,6 +82,7 @@ void EmitExtensionMethods (TabbedWriter<StringWriter> classBlock, in Binding bin

classBlock.WriteLine ();
// Get value
classBlock.WriteDocumentation (Documentation.SmartEnum.GetValueNSString (symbolName));
using (var getValueBlock = classBlock.CreateBlock ($"public static {binding.Name} GetValue (NSString constant)", true)) {
getValueBlock.WriteLine ("if (constant is null)");
getValueBlock.WriteLine ("\tthrow new ArgumentNullException (nameof (constant));");
Expand All @@ -98,6 +100,7 @@ void EmitExtensionMethods (TabbedWriter<StringWriter> classBlock, in Binding bin
classBlock.WriteLine ();

// get value from a handle, this is a helper method used in the BindAs bindings.
classBlock.WriteDocumentation (Documentation.SmartEnum.GetValueHandle (symbolName));
using (var getValueFromHandle =
classBlock.CreateBlock ($"public static {binding.Name} GetValue (NativeHandle handle)",
true)) {
Expand All @@ -109,6 +112,7 @@ void EmitExtensionMethods (TabbedWriter<StringWriter> classBlock, in Binding bin

classBlock.WriteLine ();
// To ConstantArray
classBlock.WriteDocumentation (Documentation.SmartEnum.ToConstantArray (symbolName));
classBlock.WriteRaw (
@$"internal static NSString?[]? ToConstantArray (this {binding.Name}[]? values)
{{
Expand All @@ -124,6 +128,7 @@ void EmitExtensionMethods (TabbedWriter<StringWriter> classBlock, in Binding bin
classBlock.WriteLine ();
classBlock.WriteLine ();
// ToEnumArray
classBlock.WriteDocumentation (Documentation.SmartEnum.ToEnumArray (symbolName));
classBlock.WriteRaw (
@$"internal static {binding.Name}[]? ToEnumArray (this NSString[]? values)
{{
Expand Down Expand Up @@ -155,10 +160,13 @@ public bool TryEmit (in BindingContext bindingContext, [NotNullWhen (false)] out
bindingContext.Builder.WriteLine ($"namespace {string.Join (".", bindingContext.Changes.Namespace)};");
bindingContext.Builder.WriteLine ();

var symbolName = GetSymbolName (bindingContext.Changes);
var extensionClassDeclaration =
bindingContext.Changes.ToSmartEnumExtensionDeclaration (symbolName);

bindingContext.Builder.WriteDocumentation (Documentation.SmartEnum.ClassDocumentation (symbolName));
bindingContext.Builder.AppendMemberAvailability (bindingContext.Changes.SymbolAvailability);
bindingContext.Builder.AppendGeneratedCodeAttribute ();
var extensionClassDeclaration =
bindingContext.Changes.ToSmartEnumExtensionDeclaration (GetSymbolName (bindingContext.Changes));
using (var classBlock = bindingContext.Builder.CreateBlock (extensionClassDeclaration.ToString (), true)) {
classBlock.WriteLine ();
classBlock.WriteLine ($"static IntPtr[] values = new IntPtr [{bindingContext.Changes.EnumMembers.Length}];");
Expand All @@ -171,7 +179,7 @@ public bool TryEmit (in BindingContext bindingContext, [NotNullWhen (false)] out
classBlock.WriteLine ();

// emit the extension methods that will be used to get the values from the enum
EmitExtensionMethods (classBlock, bindingContext.Changes);
EmitExtensionMethods (classBlock, symbolName, bindingContext.Changes);
classBlock.WriteLine ();
}

Expand Down
14 changes: 14 additions & 0 deletions src/rgen/Microsoft.Macios.Generator/IO/TabbedWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,20 @@ public TabbedWriter<T> WriteRaw (string rawString)
}
#endif

/// <summary>
/// Writes a multi-line documentation comment. Ensure that the raw string used for the docs
/// does not have a new line at the end, this method will add it for you.
/// </summary>
/// <param name="docsRawString">The documentation raw string.</param>
/// <returns>The current writer.</returns>
public TabbedWriter<T> WriteDocumentation (string docsRawString)
{
// user the raw string to write the documentation and add a new line
WriteRaw (docsRawString);
WriteLine ();
return this;
}

/// <summary>
/// Append a new raw literal by prepending the correct indentation.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

namespace AVFoundation;

/// <summary>
/// Extension methods for the <see cref="AVCaptureDeviceTypeExtensions" /> enumeration.
/// </summary>
[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
public static partial class AVCaptureDeviceTypeExtensions
{
Expand Down Expand Up @@ -125,6 +128,10 @@ internal unsafe static IntPtr AVCaptureDeviceTypeBuiltInLiDARDepthCamera
}
}

/// <summary>
/// Retrieves the <see cref="global::Foundation.NSString" /> constant that describes <paramref name="self" />.
/// </summary>
/// <param name="self">The instance on which this method operates.</param>
public static NSString? GetConstant (this AVCaptureDeviceType self)
{
IntPtr ptr = IntPtr.Zero;
Expand Down Expand Up @@ -167,6 +174,10 @@ internal unsafe static IntPtr AVCaptureDeviceTypeBuiltInLiDARDepthCamera
return (NSString?) Runtime.GetNSObject (ptr);
}

/// <summary>
/// Retrieves the <see cref="AVCaptureDeviceTypeExtensions" /> value named by <paramref name="constant" />.
/// </summary>
/// <param name="constant">The name of the constant to retrieve.</param>
public static AVCaptureDeviceType GetValue (NSString constant)
{
if (constant is null)
Expand Down Expand Up @@ -196,12 +207,20 @@ public static AVCaptureDeviceType GetValue (NSString constant)
throw new NotSupportedException ($"The constant {constant} has no associated enum value on this platform.");
}

/// <summary>
/// Retrieves the <see cref="AVCaptureDeviceTypeExtensions" /> value represented by the backing field value in <paramref name="handle" />.
/// </summary>
/// <param name="handle">The native handle with the name of the constant to retrieve.</param>
public static AVCaptureDeviceType GetValue (NativeHandle handle)
{
using var str = Runtime.GetNSObject<NSString> (handle)!;
return GetValue (str);
}

/// <summary>
/// Converts an array of <see cref="AVCaptureDeviceTypeExtensions" /> enum values into an array of their corresponding constants.
/// </summary>
/// <param name="values">The array of enum values to convert.</param>
internal static NSString?[]? ToConstantArray (this AVCaptureDeviceType[]? values)
{
if (values is null)
Expand All @@ -214,6 +233,10 @@ public static AVCaptureDeviceType GetValue (NativeHandle handle)
return rv.ToArray ();
}

/// <summary>
/// Converts an array of <see cref="NSString" /> values into an array of their corresponding enum values.
/// </summary>
/// <param name="values">The array if <see cref="NSString" /> values to convert.</param>
internal static AVCaptureDeviceType[]? ToEnumArray (this NSString[]? values)
{
if (values is null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

namespace AVFoundation;

/// <summary>
/// Extension methods for the <see cref="AVCaptureSystemPressureLevelExtensions" /> enumeration.
/// </summary>
[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
public static partial class AVCaptureSystemPressureLevelExtensions
{
Expand Down Expand Up @@ -65,6 +68,10 @@ internal unsafe static IntPtr AVCaptureSystemPressureLevelShutdown
}
}

/// <summary>
/// Retrieves the <see cref="global::Foundation.NSString" /> constant that describes <paramref name="self" />.
/// </summary>
/// <param name="self">The instance on which this method operates.</param>
public static NSString? GetConstant (this AVCaptureSystemPressureLevel self)
{
IntPtr ptr = IntPtr.Zero;
Expand All @@ -89,6 +96,10 @@ internal unsafe static IntPtr AVCaptureSystemPressureLevelShutdown
return (NSString?) Runtime.GetNSObject (ptr);
}

/// <summary>
/// Retrieves the <see cref="AVCaptureSystemPressureLevelExtensions" /> value named by <paramref name="constant" />.
/// </summary>
/// <param name="constant">The name of the constant to retrieve.</param>
public static AVCaptureSystemPressureLevel GetValue (NSString constant)
{
if (constant is null)
Expand All @@ -106,12 +117,20 @@ public static AVCaptureSystemPressureLevel GetValue (NSString constant)
throw new NotSupportedException ($"The constant {constant} has no associated enum value on this platform.");
}

/// <summary>
/// Retrieves the <see cref="AVCaptureSystemPressureLevelExtensions" /> value represented by the backing field value in <paramref name="handle" />.
/// </summary>
/// <param name="handle">The native handle with the name of the constant to retrieve.</param>
public static AVCaptureSystemPressureLevel GetValue (NativeHandle handle)
{
using var str = Runtime.GetNSObject<NSString> (handle)!;
return GetValue (str);
}

/// <summary>
/// Converts an array of <see cref="AVCaptureSystemPressureLevelExtensions" /> enum values into an array of their corresponding constants.
/// </summary>
/// <param name="values">The array of enum values to convert.</param>
internal static NSString?[]? ToConstantArray (this AVCaptureSystemPressureLevel[]? values)
{
if (values is null)
Expand All @@ -124,6 +143,10 @@ public static AVCaptureSystemPressureLevel GetValue (NativeHandle handle)
return rv.ToArray ();
}

/// <summary>
/// Converts an array of <see cref="NSString" /> values into an array of their corresponding enum values.
/// </summary>
/// <param name="values">The array if <see cref="NSString" /> values to convert.</param>
internal static AVCaptureSystemPressureLevel[]? ToEnumArray (this NSString[]? values)
{
if (values is null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

namespace CustomLibrary;

/// <summary>
/// Extension methods for the <see cref="CustomLibraryEnumExtensions" /> enumeration.
/// </summary>
[BindingImpl (BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
public static partial class CustomLibraryEnumExtensions
{
Expand Down Expand Up @@ -46,6 +49,10 @@ internal unsafe static IntPtr High
}
}

/// <summary>
/// Retrieves the <see cref="global::Foundation.NSString" /> constant that describes <paramref name="self" />.
/// </summary>
/// <param name="self">The instance on which this method operates.</param>
public static NSString? GetConstant (this CustomLibraryEnum self)
{
IntPtr ptr = IntPtr.Zero;
Expand All @@ -64,6 +71,10 @@ internal unsafe static IntPtr High
return (NSString?) Runtime.GetNSObject (ptr);
}

/// <summary>
/// Retrieves the <see cref="CustomLibraryEnumExtensions" /> value named by <paramref name="constant" />.
/// </summary>
/// <param name="constant">The name of the constant to retrieve.</param>
public static CustomLibraryEnum GetValue (NSString constant)
{
if (constant is null)
Expand All @@ -77,12 +88,20 @@ public static CustomLibraryEnum GetValue (NSString constant)
throw new NotSupportedException ($"The constant {constant} has no associated enum value on this platform.");
}

/// <summary>
/// Retrieves the <see cref="CustomLibraryEnumExtensions" /> value represented by the backing field value in <paramref name="handle" />.
/// </summary>
/// <param name="handle">The native handle with the name of the constant to retrieve.</param>
public static CustomLibraryEnum GetValue (NativeHandle handle)
{
using var str = Runtime.GetNSObject<NSString> (handle)!;
return GetValue (str);
}

/// <summary>
/// Converts an array of <see cref="CustomLibraryEnumExtensions" /> enum values into an array of their corresponding constants.
/// </summary>
/// <param name="values">The array of enum values to convert.</param>
internal static NSString?[]? ToConstantArray (this CustomLibraryEnum[]? values)
{
if (values is null)
Expand All @@ -95,6 +114,10 @@ public static CustomLibraryEnum GetValue (NativeHandle handle)
return rv.ToArray ();
}

/// <summary>
/// Converts an array of <see cref="NSString" /> values into an array of their corresponding enum values.
/// </summary>
/// <param name="values">The array if <see cref="NSString" /> values to convert.</param>
internal static CustomLibraryEnum[]? ToEnumArray (this NSString[]? values)
{
if (values is null)
Expand Down
Loading

3 comments on commit c51ad86

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💻 [CI Build #c51ad86] Windows Integration Tests passed 💻

All Windows Integration Tests passed.

Pipeline on Agent
Hash: c51ad863c8e5dc69250baaa720ad605abf98d017 [CI build]

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ API diff for current PR / commit

.NET ( No breaking changes )

❗ API diff vs stable (Breaking changes)

.NET ( ❗ Breaking changes ❗ )

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: c51ad863c8e5dc69250baaa720ad605abf98d017 [CI build]

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥 [CI Build #c51ad86] Test results 🔥

Test results

❌ Tests failed on VSTS: test results

0 tests crashed, 3 tests failed, 109 tests passed.

Failures

❌ cecil tests

1 tests failed, 0 tests passed.
  • Cecil-based tests: Failed (Execution failed with exit code 1)

Html Report (VSDrops) Download

❌ dotnettests tests (MacCatalyst)

1 tests failed, 0 tests passed.
  • DotNet tests: TimedOut (Execution timed out after 165 minutes.)

Html Report (VSDrops) Download

❌ monotouch tests (MacCatalyst)

1 tests failed, 10 tests passed.
  • monotouch-test/Mac Catalyst/Debug (managed static registrar): Failed (Test run failed.
    Tests run: 3150 Passed: 3012 Inconclusive: 13 Failed: 10 Ignored: 128)

Html Report (VSDrops) Download

Successes

✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker: All 44 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 8 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 9 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 8 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

Pipeline on Agent
Hash: c51ad863c8e5dc69250baaa720ad605abf98d017 [CI build]

Please sign in to comment.