diff --git a/generator.json b/generator.json index 6c68161c18..f5cc22acac 100644 --- a/generator.json +++ b/generator.json @@ -43,7 +43,9 @@ "ClangScraper", "MarkNativeNames", "ExtractHandles", - "ExtractNestedTyping", + "ExtractNestedTypes", + "ExtractEnumConstants", + "ExtractFunctionPointers", "TransformHandles", "TransformFunctions", "TransformProperties", @@ -254,7 +256,9 @@ "AddApiProfiles", "MixKhronosData", "ExtractHandles", - "ExtractNestedTyping", + "ExtractNestedTypes", + "ExtractEnumConstants", + "ExtractFunctionPointers", "TransformHandles", "InterceptNativeFunctions", "TransformFunctions", @@ -397,7 +401,9 @@ "ClangScraper", "MarkNativeNames", "ExtractHandles", - "ExtractNestedTyping", + "ExtractNestedTypes", + "ExtractEnumConstants", + "ExtractFunctionPointers", "TransformHandles", "MixKhronosData", "AddApiProfiles", diff --git a/sources/OpenAL/OpenAL/Handles/ContextHandle.gen.cs b/sources/OpenAL/OpenAL/Handles/ContextHandle.gen.cs index 5c15c4fb93..9dbc1cb8c4 100644 --- a/sources/OpenAL/OpenAL/Handles/ContextHandle.gen.cs +++ b/sources/OpenAL/OpenAL/Handles/ContextHandle.gen.cs @@ -11,7 +11,7 @@ namespace Silk.NET.OpenAL; [NativeName("ALCcontext")] -public readonly unsafe partial struct ContextHandle +public readonly unsafe partial struct ContextHandle : IEquatable { public readonly void* Handle; diff --git a/sources/OpenAL/OpenAL/Handles/DeviceHandle.gen.cs b/sources/OpenAL/OpenAL/Handles/DeviceHandle.gen.cs index 3142e2084a..240556c635 100644 --- a/sources/OpenAL/OpenAL/Handles/DeviceHandle.gen.cs +++ b/sources/OpenAL/OpenAL/Handles/DeviceHandle.gen.cs @@ -11,7 +11,7 @@ namespace Silk.NET.OpenAL; [NativeName("ALCdevice")] -public readonly unsafe partial struct DeviceHandle +public readonly unsafe partial struct DeviceHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/AudioStreamHandle.gen.cs b/sources/SDL/SDL/Handles/AudioStreamHandle.gen.cs index 7a7b89eb90..13bdad885b 100644 --- a/sources/SDL/SDL/Handles/AudioStreamHandle.gen.cs +++ b/sources/SDL/SDL/Handles/AudioStreamHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_AudioStream")] -public readonly unsafe partial struct AudioStreamHandle +public readonly unsafe partial struct AudioStreamHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/CameraHandle.gen.cs b/sources/SDL/SDL/Handles/CameraHandle.gen.cs index 3bca5b66b6..c0d29f9813 100644 --- a/sources/SDL/SDL/Handles/CameraHandle.gen.cs +++ b/sources/SDL/SDL/Handles/CameraHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Camera")] -public readonly unsafe partial struct CameraHandle +public readonly unsafe partial struct CameraHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/ConditionHandle.gen.cs b/sources/SDL/SDL/Handles/ConditionHandle.gen.cs index 47f3c3ab8a..ba35465896 100644 --- a/sources/SDL/SDL/Handles/ConditionHandle.gen.cs +++ b/sources/SDL/SDL/Handles/ConditionHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Condition")] -public readonly unsafe partial struct ConditionHandle +public readonly unsafe partial struct ConditionHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/CursorHandle.gen.cs b/sources/SDL/SDL/Handles/CursorHandle.gen.cs index 1ccd8ca8af..eec52dad40 100644 --- a/sources/SDL/SDL/Handles/CursorHandle.gen.cs +++ b/sources/SDL/SDL/Handles/CursorHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Cursor")] -public readonly unsafe partial struct CursorHandle +public readonly unsafe partial struct CursorHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/DisplayModeDataHandle.gen.cs b/sources/SDL/SDL/Handles/DisplayModeDataHandle.gen.cs index 7abf2c85d1..9fbeb3149d 100644 --- a/sources/SDL/SDL/Handles/DisplayModeDataHandle.gen.cs +++ b/sources/SDL/SDL/Handles/DisplayModeDataHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_DisplayModeData")] -public readonly unsafe partial struct DisplayModeDataHandle +public readonly unsafe partial struct DisplayModeDataHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/EnvironmentHandle.gen.cs b/sources/SDL/SDL/Handles/EnvironmentHandle.gen.cs index 8e8591a674..c27314fb8a 100644 --- a/sources/SDL/SDL/Handles/EnvironmentHandle.gen.cs +++ b/sources/SDL/SDL/Handles/EnvironmentHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Environment")] -public readonly unsafe partial struct EnvironmentHandle +public readonly unsafe partial struct EnvironmentHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GLContextStateHandle.gen.cs b/sources/SDL/SDL/Handles/GLContextStateHandle.gen.cs index f1e92e496b..fff5b39c08 100644 --- a/sources/SDL/SDL/Handles/GLContextStateHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GLContextStateHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GLContextState")] -public readonly unsafe partial struct GLContextStateHandle +public readonly unsafe partial struct GLContextStateHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GamepadHandle.gen.cs b/sources/SDL/SDL/Handles/GamepadHandle.gen.cs index 211fb22364..dae6f276d7 100644 --- a/sources/SDL/SDL/Handles/GamepadHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GamepadHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Gamepad")] -public readonly unsafe partial struct GamepadHandle +public readonly unsafe partial struct GamepadHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuBufferHandle.gen.cs b/sources/SDL/SDL/Handles/GpuBufferHandle.gen.cs index 441a6b5c1c..fcc5c2ff78 100644 --- a/sources/SDL/SDL/Handles/GpuBufferHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuBufferHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUBuffer")] -public readonly unsafe partial struct GpuBufferHandle +public readonly unsafe partial struct GpuBufferHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuCommandBufferHandle.gen.cs b/sources/SDL/SDL/Handles/GpuCommandBufferHandle.gen.cs index 127bfc2288..362afda340 100644 --- a/sources/SDL/SDL/Handles/GpuCommandBufferHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuCommandBufferHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUCommandBuffer")] -public readonly unsafe partial struct GpuCommandBufferHandle +public readonly unsafe partial struct GpuCommandBufferHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuComputePassHandle.gen.cs b/sources/SDL/SDL/Handles/GpuComputePassHandle.gen.cs index b8d8dcdc03..c7df4c054d 100644 --- a/sources/SDL/SDL/Handles/GpuComputePassHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuComputePassHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUComputePass")] -public readonly unsafe partial struct GpuComputePassHandle +public readonly unsafe partial struct GpuComputePassHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuComputePipelineHandle.gen.cs b/sources/SDL/SDL/Handles/GpuComputePipelineHandle.gen.cs index 15d5e9fcc3..4034d392e8 100644 --- a/sources/SDL/SDL/Handles/GpuComputePipelineHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuComputePipelineHandle.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUComputePipeline")] public readonly unsafe partial struct GpuComputePipelineHandle + : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuCopyPassHandle.gen.cs b/sources/SDL/SDL/Handles/GpuCopyPassHandle.gen.cs index a4395e1e96..f7eaffb9c2 100644 --- a/sources/SDL/SDL/Handles/GpuCopyPassHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuCopyPassHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUCopyPass")] -public readonly unsafe partial struct GpuCopyPassHandle +public readonly unsafe partial struct GpuCopyPassHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuDeviceHandle.gen.cs b/sources/SDL/SDL/Handles/GpuDeviceHandle.gen.cs index 2934694a99..40918cdd2c 100644 --- a/sources/SDL/SDL/Handles/GpuDeviceHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuDeviceHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUDevice")] -public readonly unsafe partial struct GpuDeviceHandle +public readonly unsafe partial struct GpuDeviceHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuFenceHandle.gen.cs b/sources/SDL/SDL/Handles/GpuFenceHandle.gen.cs index c273ebc876..f93d869a8c 100644 --- a/sources/SDL/SDL/Handles/GpuFenceHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuFenceHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUFence")] -public readonly unsafe partial struct GpuFenceHandle +public readonly unsafe partial struct GpuFenceHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuGraphicsPipelineHandle.gen.cs b/sources/SDL/SDL/Handles/GpuGraphicsPipelineHandle.gen.cs index 1f9636a547..b2930c73e2 100644 --- a/sources/SDL/SDL/Handles/GpuGraphicsPipelineHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuGraphicsPipelineHandle.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUGraphicsPipeline")] public readonly unsafe partial struct GpuGraphicsPipelineHandle + : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuRenderPassHandle.gen.cs b/sources/SDL/SDL/Handles/GpuRenderPassHandle.gen.cs index bd817ca4c5..50e069d7aa 100644 --- a/sources/SDL/SDL/Handles/GpuRenderPassHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuRenderPassHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPURenderPass")] -public readonly unsafe partial struct GpuRenderPassHandle +public readonly unsafe partial struct GpuRenderPassHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuRenderStateHandle.gen.cs b/sources/SDL/SDL/Handles/GpuRenderStateHandle.gen.cs index bf90afce7c..14812e7050 100644 --- a/sources/SDL/SDL/Handles/GpuRenderStateHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuRenderStateHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPURenderState")] -public readonly unsafe partial struct GpuRenderStateHandle +public readonly unsafe partial struct GpuRenderStateHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuSamplerHandle.gen.cs b/sources/SDL/SDL/Handles/GpuSamplerHandle.gen.cs index 4964892f5d..9c50c7fee2 100644 --- a/sources/SDL/SDL/Handles/GpuSamplerHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuSamplerHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUSampler")] -public readonly unsafe partial struct GpuSamplerHandle +public readonly unsafe partial struct GpuSamplerHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuShaderHandle.gen.cs b/sources/SDL/SDL/Handles/GpuShaderHandle.gen.cs index c5c1af3178..d091896d89 100644 --- a/sources/SDL/SDL/Handles/GpuShaderHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuShaderHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUShader")] -public readonly unsafe partial struct GpuShaderHandle +public readonly unsafe partial struct GpuShaderHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuTextureHandle.gen.cs b/sources/SDL/SDL/Handles/GpuTextureHandle.gen.cs index 1f4e485615..307afa9d89 100644 --- a/sources/SDL/SDL/Handles/GpuTextureHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuTextureHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUTexture")] -public readonly unsafe partial struct GpuTextureHandle +public readonly unsafe partial struct GpuTextureHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/GpuTransferBufferHandle.gen.cs b/sources/SDL/SDL/Handles/GpuTransferBufferHandle.gen.cs index 23d2a08016..3b66ad704e 100644 --- a/sources/SDL/SDL/Handles/GpuTransferBufferHandle.gen.cs +++ b/sources/SDL/SDL/Handles/GpuTransferBufferHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_GPUTransferBuffer")] -public readonly unsafe partial struct GpuTransferBufferHandle +public readonly unsafe partial struct GpuTransferBufferHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/HapticHandle.gen.cs b/sources/SDL/SDL/Handles/HapticHandle.gen.cs index 2482783395..75285352bb 100644 --- a/sources/SDL/SDL/Handles/HapticHandle.gen.cs +++ b/sources/SDL/SDL/Handles/HapticHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Haptic")] -public readonly unsafe partial struct HapticHandle +public readonly unsafe partial struct HapticHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/HidDeviceHandle.gen.cs b/sources/SDL/SDL/Handles/HidDeviceHandle.gen.cs index ad9360bd75..a14f7a2c49 100644 --- a/sources/SDL/SDL/Handles/HidDeviceHandle.gen.cs +++ b/sources/SDL/SDL/Handles/HidDeviceHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_hid_device")] -public readonly unsafe partial struct HidDeviceHandle +public readonly unsafe partial struct HidDeviceHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/IOStreamHandle.gen.cs b/sources/SDL/SDL/Handles/IOStreamHandle.gen.cs index b12053e4c2..a941ade657 100644 --- a/sources/SDL/SDL/Handles/IOStreamHandle.gen.cs +++ b/sources/SDL/SDL/Handles/IOStreamHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_IOStream")] -public readonly unsafe partial struct IOStreamHandle +public readonly unsafe partial struct IOStreamHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/IconvDataTHandle.gen.cs b/sources/SDL/SDL/Handles/IconvDataTHandle.gen.cs index 7ac28b98a0..b8b7898a59 100644 --- a/sources/SDL/SDL/Handles/IconvDataTHandle.gen.cs +++ b/sources/SDL/SDL/Handles/IconvDataTHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_iconv_data_t")] -public readonly unsafe partial struct IconvDataTHandle +public readonly unsafe partial struct IconvDataTHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/JoystickHandle.gen.cs b/sources/SDL/SDL/Handles/JoystickHandle.gen.cs index 4e7276dd3e..44e0e96622 100644 --- a/sources/SDL/SDL/Handles/JoystickHandle.gen.cs +++ b/sources/SDL/SDL/Handles/JoystickHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Joystick")] -public readonly unsafe partial struct JoystickHandle +public readonly unsafe partial struct JoystickHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/MutexHandle.gen.cs b/sources/SDL/SDL/Handles/MutexHandle.gen.cs index c51b3cb34a..1db5ac5920 100644 --- a/sources/SDL/SDL/Handles/MutexHandle.gen.cs +++ b/sources/SDL/SDL/Handles/MutexHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Mutex")] -public readonly unsafe partial struct MutexHandle +public readonly unsafe partial struct MutexHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/ProcessHandle.gen.cs b/sources/SDL/SDL/Handles/ProcessHandle.gen.cs index 95ec428a48..b8ffa75dbf 100644 --- a/sources/SDL/SDL/Handles/ProcessHandle.gen.cs +++ b/sources/SDL/SDL/Handles/ProcessHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Process")] -public readonly unsafe partial struct ProcessHandle +public readonly unsafe partial struct ProcessHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/RWLockHandle.gen.cs b/sources/SDL/SDL/Handles/RWLockHandle.gen.cs index dd9700c19f..955896e679 100644 --- a/sources/SDL/SDL/Handles/RWLockHandle.gen.cs +++ b/sources/SDL/SDL/Handles/RWLockHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_RWLock")] -public readonly unsafe partial struct RWLockHandle +public readonly unsafe partial struct RWLockHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/RendererHandle.gen.cs b/sources/SDL/SDL/Handles/RendererHandle.gen.cs index 053e82e57e..d8c35d0a6e 100644 --- a/sources/SDL/SDL/Handles/RendererHandle.gen.cs +++ b/sources/SDL/SDL/Handles/RendererHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Renderer")] -public readonly unsafe partial struct RendererHandle +public readonly unsafe partial struct RendererHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/SemaphoreHandle.gen.cs b/sources/SDL/SDL/Handles/SemaphoreHandle.gen.cs index c99c29686e..11a5d9129a 100644 --- a/sources/SDL/SDL/Handles/SemaphoreHandle.gen.cs +++ b/sources/SDL/SDL/Handles/SemaphoreHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Semaphore")] -public readonly unsafe partial struct SemaphoreHandle +public readonly unsafe partial struct SemaphoreHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/SensorHandle.gen.cs b/sources/SDL/SDL/Handles/SensorHandle.gen.cs index 4820b8d143..65ac93fd60 100644 --- a/sources/SDL/SDL/Handles/SensorHandle.gen.cs +++ b/sources/SDL/SDL/Handles/SensorHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Sensor")] -public readonly unsafe partial struct SensorHandle +public readonly unsafe partial struct SensorHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/SharedObjectHandle.gen.cs b/sources/SDL/SDL/Handles/SharedObjectHandle.gen.cs index c594be4b4c..f9c0dab805 100644 --- a/sources/SDL/SDL/Handles/SharedObjectHandle.gen.cs +++ b/sources/SDL/SDL/Handles/SharedObjectHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_SharedObject")] -public readonly unsafe partial struct SharedObjectHandle +public readonly unsafe partial struct SharedObjectHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/StorageHandle.gen.cs b/sources/SDL/SDL/Handles/StorageHandle.gen.cs index 1f7209c7ad..1b043d2585 100644 --- a/sources/SDL/SDL/Handles/StorageHandle.gen.cs +++ b/sources/SDL/SDL/Handles/StorageHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Storage")] -public readonly unsafe partial struct StorageHandle +public readonly unsafe partial struct StorageHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/ThreadHandle.gen.cs b/sources/SDL/SDL/Handles/ThreadHandle.gen.cs index e87920c916..d2d1935800 100644 --- a/sources/SDL/SDL/Handles/ThreadHandle.gen.cs +++ b/sources/SDL/SDL/Handles/ThreadHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Thread")] -public readonly unsafe partial struct ThreadHandle +public readonly unsafe partial struct ThreadHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/Handles/WindowHandle.gen.cs b/sources/SDL/SDL/Handles/WindowHandle.gen.cs index 597ca13bd8..96434fcd75 100644 --- a/sources/SDL/SDL/Handles/WindowHandle.gen.cs +++ b/sources/SDL/SDL/Handles/WindowHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.SDL; [NativeName("SDL_Window")] -public readonly unsafe partial struct WindowHandle +public readonly unsafe partial struct WindowHandle : IEquatable { public readonly void* Handle; diff --git a/sources/SDL/SDL/SDL3/BlendMode.gen.cs b/sources/SDL/SDL/SDL3/BlendMode.gen.cs index 89924340d7..76f3f168ba 100644 --- a/sources/SDL/SDL/SDL3/BlendMode.gen.cs +++ b/sources/SDL/SDL/SDL3/BlendMode.gen.cs @@ -8,6 +8,7 @@ namespace Silk.NET.SDL; +[NativeName("SDL_BlendMode")] public enum BlendMode : uint { None = 0, diff --git a/sources/SDL/SDL/SDL3/ISdl.gen.cs b/sources/SDL/SDL/SDL3/ISdl.gen.cs index d5c8c95c5f..608dfe1d1d 100644 --- a/sources/SDL/SDL/SDL3/ISdl.gen.cs +++ b/sources/SDL/SDL/SDL3/ISdl.gen.cs @@ -914,7 +914,7 @@ uint newval [NativeName("SDL_ComposeCustomBlendMode")] [NativeFunction("SDL3", EntryPoint = "SDL_ComposeCustomBlendMode")] - static abstract uint ComposeCustomBlendMode( + static abstract BlendMode ComposeCustomBlendMode( BlendFactor srcColorFactor, BlendFactor dstColorFactor, BlendOperation colorOperation, @@ -11555,7 +11555,7 @@ uint depth_or_layer_count [NativeName("SDL_ComposeCustomBlendMode")] [NativeFunction("SDL3", EntryPoint = "SDL_ComposeCustomBlendMode")] - uint ComposeCustomBlendMode( + BlendMode ComposeCustomBlendMode( BlendFactor srcColorFactor, BlendFactor dstColorFactor, BlendOperation colorOperation, diff --git a/sources/SDL/SDL/SDL3/Sdl.gen.cs b/sources/SDL/SDL/SDL3/Sdl.gen.cs index c4f2200c54..ca5c5513e2 100644 --- a/sources/SDL/SDL/SDL3/Sdl.gen.cs +++ b/sources/SDL/SDL/SDL3/Sdl.gen.cs @@ -1496,7 +1496,7 @@ uint newval [NativeName("SDL_ComposeCustomBlendMode")] [DllImport("SDL3", ExactSpelling = true, EntryPoint = "SDL_ComposeCustomBlendMode")] - public static extern uint ComposeCustomBlendMode( + public static extern BlendMode ComposeCustomBlendMode( BlendFactor srcColorFactor, BlendFactor dstColorFactor, BlendOperation colorOperation, @@ -18691,7 +18691,7 @@ uint newval [MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )] - public uint ComposeCustomBlendMode( + public BlendMode ComposeCustomBlendMode( BlendFactor srcColorFactor, BlendFactor dstColorFactor, BlendOperation colorOperation, @@ -36633,7 +36633,7 @@ uint newval [MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )] - public static uint ComposeCustomBlendMode( + public static BlendMode ComposeCustomBlendMode( BlendFactor srcColorFactor, BlendFactor dstColorFactor, BlendOperation colorOperation, @@ -63880,7 +63880,7 @@ uint newval [NativeName("SDL_ComposeCustomBlendMode")] [NativeFunction("SDL3", EntryPoint = "SDL_ComposeCustomBlendMode")] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - uint ISdl.ComposeCustomBlendMode( + BlendMode ISdl.ComposeCustomBlendMode( BlendFactor srcColorFactor, BlendFactor dstColorFactor, BlendOperation colorOperation, @@ -63896,7 +63896,7 @@ BlendOperation alphaOperation BlendFactor, BlendFactor, BlendOperation, - uint>)( + BlendMode>)( _slots[84] is not null and var loadedFnPtr ? loadedFnPtr : _slots[84] = nativeContext.LoadFunction("SDL_ComposeCustomBlendMode", "SDL3") @@ -63913,7 +63913,7 @@ _slots[84] is not null and var loadedFnPtr [NativeName("SDL_ComposeCustomBlendMode")] [NativeFunction("SDL3", EntryPoint = "SDL_ComposeCustomBlendMode")] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static uint ComposeCustomBlendMode( + public static BlendMode ComposeCustomBlendMode( BlendFactor srcColorFactor, BlendFactor dstColorFactor, BlendOperation colorOperation, diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescCleanup.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescCleanup.gen.cs index b492776668..5249ca465f 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescCleanup.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescCleanup.gen.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_Cleanup")] public readonly unsafe struct VirtualJoystickDescCleanup : IDisposable { diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescCleanupDelegate.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescCleanupDelegate.gen.cs index 6a99135605..c0bc9260bd 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescCleanupDelegate.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescCleanupDelegate.gen.cs @@ -6,5 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_Cleanup")] public unsafe delegate void VirtualJoystickDescCleanupDelegate(void* arg0); diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescRumble.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescRumble.gen.cs index 5e8c087e46..a614f6c48e 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescRumble.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescRumble.gen.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_Rumble")] public readonly unsafe struct VirtualJoystickDescRumble : IDisposable { diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleDelegate.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleDelegate.gen.cs index 3ed4f4bdc8..37b1626b64 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleDelegate.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleDelegate.gen.cs @@ -6,5 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_Rumble")] public unsafe delegate byte VirtualJoystickDescRumbleDelegate(void* arg0, ushort arg1, ushort arg2); diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleTriggers.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleTriggers.gen.cs index bf5f71aa6b..072173e604 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleTriggers.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleTriggers.gen.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_RumbleTriggers")] public readonly unsafe struct VirtualJoystickDescRumbleTriggers : IDisposable { diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleTriggersDelegate.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleTriggersDelegate.gen.cs index fc133d07b8..3578e6b51b 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleTriggersDelegate.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescRumbleTriggersDelegate.gen.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_RumbleTriggers")] public unsafe delegate byte VirtualJoystickDescRumbleTriggersDelegate( void* arg0, diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescSendEffect.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescSendEffect.gen.cs index 5966a79a12..8ed1212912 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescSendEffect.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescSendEffect.gen.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_SendEffect")] public readonly unsafe struct VirtualJoystickDescSendEffect : IDisposable { diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescSendEffectDelegate.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescSendEffectDelegate.gen.cs index ee675138b3..6150e24b48 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescSendEffectDelegate.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescSendEffectDelegate.gen.cs @@ -6,5 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_SendEffect")] public unsafe delegate byte VirtualJoystickDescSendEffectDelegate(void* arg0, void* arg1, int arg2); diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetLed.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetLed.gen.cs index 850d070382..690c9f121b 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetLed.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetLed.gen.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_SetLED")] public readonly unsafe struct VirtualJoystickDescSetLed : IDisposable { diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetLedDelegate.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetLedDelegate.gen.cs index e1e865335e..af1146aa34 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetLedDelegate.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetLedDelegate.gen.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_SetLED")] public unsafe delegate byte VirtualJoystickDescSetLedDelegate( void* arg0, diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetPlayerIndex.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetPlayerIndex.gen.cs index 12a83b4781..462e1d1b26 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetPlayerIndex.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetPlayerIndex.gen.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_SetPlayerIndex")] public readonly unsafe struct VirtualJoystickDescSetPlayerIndex : IDisposable { diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetPlayerIndexDelegate.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetPlayerIndexDelegate.gen.cs index ddd3eadd90..5eb9da79b2 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetPlayerIndexDelegate.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetPlayerIndexDelegate.gen.cs @@ -6,5 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_SetPlayerIndex")] public unsafe delegate void VirtualJoystickDescSetPlayerIndexDelegate(void* arg0, int arg1); diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetSensorsEnabled.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetSensorsEnabled.gen.cs index 8174ae5f5c..f88157f11d 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetSensorsEnabled.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetSensorsEnabled.gen.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_SetSensorsEnabled")] public readonly unsafe struct VirtualJoystickDescSetSensorsEnabled : IDisposable { diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetSensorsEnabledDelegate.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetSensorsEnabledDelegate.gen.cs index 706cecf759..f53ea42f08 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescSetSensorsEnabledDelegate.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescSetSensorsEnabledDelegate.gen.cs @@ -6,5 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_SetSensorsEnabled")] public unsafe delegate byte VirtualJoystickDescSetSensorsEnabledDelegate(void* arg0, byte arg1); diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescUpdate.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescUpdate.gen.cs index cdc8c7c4e6..7824302a89 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescUpdate.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescUpdate.gen.cs @@ -6,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_Update")] public readonly unsafe struct VirtualJoystickDescUpdate : IDisposable { diff --git a/sources/SDL/SDL/SDL3/VirtualJoystickDescUpdateDelegate.gen.cs b/sources/SDL/SDL/SDL3/VirtualJoystickDescUpdateDelegate.gen.cs index f44e1e27f1..62830392e5 100644 --- a/sources/SDL/SDL/SDL3/VirtualJoystickDescUpdateDelegate.gen.cs +++ b/sources/SDL/SDL/SDL3/VirtualJoystickDescUpdateDelegate.gen.cs @@ -6,5 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +namespace Silk.NET.SDL; + [NativeName("SDL_VirtualJoystickDesc_Update")] public unsafe delegate void VirtualJoystickDescUpdateDelegate(void* arg0); diff --git a/sources/SilkTouch/SilkTouch/Mods/AddApiProfiles.cs b/sources/SilkTouch/SilkTouch/Mods/AddApiProfiles.cs index 0df1ec07ea..5c2b818c55 100644 --- a/sources/SilkTouch/SilkTouch/Mods/AddApiProfiles.cs +++ b/sources/SilkTouch/SilkTouch/Mods/AddApiProfiles.cs @@ -28,7 +28,7 @@ public class AddApiProfiles( IEnumerable< IJobDependency>> > versionProviders -) : Mod +) : IMod { /// /// The mod configuration. @@ -209,9 +209,8 @@ out var parentSymbolBefore } /// - public override async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) + public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) { - await base.ExecuteAsync(ctx, ct); if (ctx.SourceProject is null) { return; diff --git a/sources/SilkTouch/SilkTouch/Mods/Common/AttributeUtils.cs b/sources/SilkTouch/SilkTouch/Mods/Common/AttributeUtils.cs index c00cdfc2b1..fa83d1547f 100644 --- a/sources/SilkTouch/SilkTouch/Mods/Common/AttributeUtils.cs +++ b/sources/SilkTouch/SilkTouch/Mods/Common/AttributeUtils.cs @@ -314,16 +314,19 @@ .. attributes.Where(attribute => /// Retrieves the native type name within the given attribute list. /// /// The attributes. - /// The required attribute target/context. + /// + /// The required attribute target specifier. + /// Eg: for [return: Attribute]. + /// /// The native type name. public static string? GetNativeTypeName( this IEnumerable attrs, - SyntaxKind? requireContext = null + SyntaxKind? requiredTargetSpecifier = null ) => attrs .SelectMany(x => - (x.Target is null && requireContext is null) - || (requireContext is { } rc && (x.Target?.Identifier.IsKind(rc) ?? false)) + (x.Target is null && requiredTargetSpecifier is null) + || (requiredTargetSpecifier is { } rc && (x.Target?.Identifier.IsKind(rc) ?? false)) ? x.Attributes : [] ) @@ -341,16 +344,21 @@ .. attributes.Where(attribute => /// /// The attributes. /// The parsed native type info. Invalid if this method returns false. + /// + /// The required attribute target specifier. + /// Eg: for [return: Attribute]. + /// /// Whether the type name was successfully parsed. /// /// This does not handle all of the possible cases. /// public static bool TryParseNativeTypeName( this IEnumerable attrs, - out NativeTypeNameInfo info + out NativeTypeNameInfo info, + SyntaxKind? requiredTargetSpecifier = null ) { - var nativeTypeNameString = attrs.GetNativeTypeName(); + var nativeTypeNameString = attrs.GetNativeTypeName(requiredTargetSpecifier); var nativeTypeName = nativeTypeNameString.AsSpan(); if (nativeTypeName.Length == 0) { diff --git a/sources/SilkTouch/SilkTouch/Mods/Common/Mod.cs b/sources/SilkTouch/SilkTouch/Mods/Common/Mod.cs index 2c72d986cb..a50a625c4f 100644 --- a/sources/SilkTouch/SilkTouch/Mods/Common/Mod.cs +++ b/sources/SilkTouch/SilkTouch/Mods/Common/Mod.cs @@ -40,7 +40,8 @@ public string PathForFullyQualified(string fullyQualified, string extension = ". } /// - public virtual void InitializeAsync(IModContext ctx, CancellationToken ct = default) { } + public virtual Task InitializeAsync(IModContext ctx, CancellationToken ct = default) => + Task.CompletedTask; /// public virtual async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) diff --git a/sources/SilkTouch/SilkTouch/Mods/Common/ModLoader.cs b/sources/SilkTouch/SilkTouch/Mods/Common/ModLoader.cs index 5ad3bb237d..ded27503ea 100644 --- a/sources/SilkTouch/SilkTouch/Mods/Common/ModLoader.cs +++ b/sources/SilkTouch/SilkTouch/Mods/Common/ModLoader.cs @@ -24,8 +24,10 @@ public class ModLoader nameof(ChangeNamespace) => typeof(ChangeNamespace), nameof(ChangeNativeClass) => typeof(ChangeNativeClass), nameof(ClangScraper) => typeof(ClangScraper), + nameof(ExtractEnumConstants) => typeof(ExtractEnumConstants), + nameof(ExtractFunctionPointers) => typeof(ExtractFunctionPointers), nameof(ExtractHandles) => typeof(ExtractHandles), - nameof(ExtractNestedTyping) => typeof(ExtractNestedTyping), + nameof(ExtractNestedTypes) => typeof(ExtractNestedTypes), nameof(IdentifySharedPrefixes) => typeof(IdentifySharedPrefixes), nameof(InterceptNativeFunctions) => typeof(InterceptNativeFunctions), nameof(MarkNativeNames) => typeof(MarkNativeNames), diff --git a/sources/SilkTouch/SilkTouch/Mods/ExtractEnumConstants.cs b/sources/SilkTouch/SilkTouch/Mods/ExtractEnumConstants.cs new file mode 100644 index 0000000000..82c8034d52 --- /dev/null +++ b/sources/SilkTouch/SilkTouch/Mods/ExtractEnumConstants.cs @@ -0,0 +1,444 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Silk.NET.SilkTouch.Naming; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Silk.NET.SilkTouch.Mods; + +/// +/// Moves enum constants into their respective enums. +/// These constants are identified by checking for an enum with +/// a matching prefix, as identified by the enum's . +/// This accounts for the below pattern seen frequently pre-C99: +/// +/// typedef unsigned int MyEnum; +/// #define MY_ENUM_HELLO 0 +/// extern MyEnum GetMyEnum(); +/// +/// +public class ExtractEnumConstants : IMod +{ + /// + public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) + { + var project = ctx.SourceProject; + if (project == null) + { + return; + } + + // First pass to gather data, such as the types to extract and generate + var walker = new Walker(); + foreach (var doc in project.Documents) + { + var file = doc.RelativePath(); + if (file is null) + { + continue; + } + + var node = await doc.GetSyntaxRootAsync(ct); + walker.File = file; + walker.Visit(node); + } + + var (enums, constants) = walker.GetExtractedEnums(); + var rewriter = new Rewriter(constants, enums.Keys); + foreach (var docId in project.DocumentIds) + { + var doc = + project.GetDocument(docId) + ?? throw new InvalidOperationException("Document missing"); + + var file = doc.RelativePath(); + if (file is null) + { + continue; + } + + project = doc.WithSyntaxRoot( + rewriter.Visit(await doc.GetSyntaxRootAsync(ct)) + ?? throw new InvalidOperationException("Visit returned null.") + ).Project; + } + + var newEnums = enums.Select(x => new ExtractedType( + x.Value.Node, + x.Value.Node.Identifier.ToString(), + x.Value.ReferencingFileDirs, + x.Value.ReferencingNamespaces + )); + + foreach (var (typeDecl, identifier, fileDirs, namespaces) in newEnums) + { + var ns = NameUtils.FindCommonPrefix(namespaces, true, false, true); + var dir = NameUtils.FindCommonPrefix(fileDirs, true, false, true).TrimEnd('/'); + project = project + ?.AddDocument( + $"{identifier}.gen.cs", + CompilationUnit() + .WithMembers( + ns is { Length: > 0 } + ? SingletonList( + FileScopedNamespaceDeclaration( + ModUtils.NamespaceIntoIdentifierName(ns.TrimEnd('.')) + ) + .WithMembers(SingletonList(typeDecl)) + ) + : SingletonList(typeDecl) + ), + // Place extracted enum types in the directory common to where the types are referenced from + filePath: project.FullPath($"{dir}/{identifier}.gen.cs") + ) + .Project; + } + + ctx.SourceProject = project; + } + + /// + /// Returns the native type name for a predefined type syntax node found in the syntax tree. + /// The native type name will be retrieved from the corresponding [NativeTypeName] attribute. + /// + /// + /// This is designed to be used to find references to enum types. + /// As such, this method returns "" for native type names that are identifiable as being potential enum members. + /// + private static ReadOnlySpan GetNativeTypeNameForPredefinedType(PredefinedTypeSyntax node) + { + // Walk up to the parameter or method. We only allow primitive integer types right now. + var current = node.Parent; + var indirectionLevels = 0; + while (current is PointerTypeSyntax) + { + indirectionLevels++; + current = current.Parent; + } + + SyntaxList attributes; + SyntaxKind? requiredTargetSpecifier = null; + switch (current) + { + // Method return type + case MethodDeclarationSyntax method: + { + attributes = method.AttributeLists; + requiredTargetSpecifier = SyntaxKind.ReturnKeyword; + + break; + } + // Method parameter + case ParameterSyntax param: + { + attributes = param.AttributeLists; + break; + } + // Maybe a field + case VariableDeclarationSyntax variable: + { + attributes = default; + if ( + variable.Parent is FieldDeclarationSyntax field + && !field.Modifiers.Any(m => m.IsKind(SyntaxKind.ConstKeyword)) + ) + { + attributes = field.AttributeLists; + } + + break; + } + default: + { + attributes = default; + break; + } + } + + if (attributes.Count == 0) + { + return default; + } + + if (!attributes.TryParseNativeTypeName(out var info, requiredTargetSpecifier)) + { + return default; + } + + // Ignore defines. + // These are likely enum members. + if (info.IsDefine) + { + return default; + } + + // Ensure that the indirection levels indicated by the type name is the same as we've encountered when walking + // up the type. If this isn't, this indicates that the native type name is a typedef to a pointer and shouldn't + // be something that is mapped into an enum. + if (info.IndirectionLevels != indirectionLevels) + { + return default; + } + + return info.Name; + } + + private record struct ExtractedType( + MemberDeclarationSyntax Node, + string Identifier, + HashSet ReferencingFileDirs, + HashSet ReferencingNamespaces + ); + + private record struct ExtractedEnumType( + EnumDeclarationSyntax Node, + HashSet ReferencingFileDirs, + HashSet ReferencingNamespaces + ); + + private class Walker : CSharpSyntaxRewriter + { + private record struct BackingType( + SyntaxKind Type, + HashSet ReferencingFileDirs, + HashSet ReferencingNamespaces + ); + + /// + /// Tracks the backing type to use for identified enum types. + /// Null is used when there are more than one potential backing type + /// or if the identified backing type cannot be used as a valid C# enum backing type. + /// + private readonly Dictionary _numericTypeNames = new(); + + /// + /// Tracks the name and value of constants discovered. + /// + private readonly Dictionary _constants = []; + + public string? File { get; set; } + + public override SyntaxNode? VisitPredefinedType(PredefinedTypeSyntax node) + { + var nativeTypeName = GetNativeTypeNameForPredefinedType(node).ToString(); + if (nativeTypeName.Length > 0) + { + // Detect type discrepancies. + var thisType = node.Keyword.Kind(); + if (!_numericTypeNames.TryGetValue(nativeTypeName, out var numericTypeName)) + { + _numericTypeNames[nativeTypeName] = numericTypeName = new BackingType( + thisType, + [], + [] + ); + } + + if ( + thisType + is not ( + SyntaxKind.ByteKeyword + or SyntaxKind.SByteKeyword + or SyntaxKind.ShortKeyword + or SyntaxKind.UShortKeyword + or SyntaxKind.IntKeyword + or SyntaxKind.UIntKeyword + or SyntaxKind.LongKeyword + or SyntaxKind.ULongKeyword + ) + || thisType != numericTypeName?.Type + ) + { + _numericTypeNames[nativeTypeName] = numericTypeName = null; + } + + if (numericTypeName is { } theTypeDetails) + { + theTypeDetails.ReferencingNamespaces.Add(node.NamespaceFromSyntaxNode()); + if (File?[..File.LastIndexOf('/')] is { } dir) + { + theTypeDetails.ReferencingFileDirs.Add(dir); + } + } + } + + return base.VisitPredefinedType(node); + } + + // This code can probably be better. + public ( + Dictionary ExtractedEnums, + HashSet ExtractedConstants + ) GetExtractedEnums() + { + var ineligibleConstants = new HashSet(); + var extractedConstants = new HashSet(); + var extractedEnums = new Dictionary(_numericTypeNames.Count); + + // Try and find constants for each of the enums we've found. + // We do this in descending length order to ensure that we find the longest match for constant names to enum + // names. + foreach ( + var (enumName, enumType) in _numericTypeNames.OrderByDescending(x => x.Key.Length) + ) + { + var enumTrimmingName = NameSplitter.Underscore(enumName); + ExtractedEnumType? extractedEnum = enumType is { } theType + ? new ExtractedEnumType( + EnumDeclaration(enumName) + .AddBaseListTypes(SimpleBaseType(PredefinedType(Token(theType.Type)))) + .AddModifiers(Token(SyntaxKind.PublicKeyword)), + theType.ReferencingFileDirs, + theType.ReferencingNamespaces + ) + : null; + + // Look through all of the constants and see whether they start with our enum name. + foreach (var (constant, value) in _constants) + { + // We want to account for PascalCase vs SCREAMING_SNAKE_CASE differences (for example) so we do + // four passes (for each combination of the original name vs trimming name, the latter of which + // taking casing into account). It is possible that this could be expanded, but this should be done + // carefully to ensure we don't light up prematurely. + var nextConst = false; + var trimmingName = NameSplitter.Underscore(constant); + foreach ( + var enumCandidate in (ReadOnlySpan)[enumName, enumTrimmingName] + ) + { + foreach ( + var constCandidate in (ReadOnlySpan)[constant, trimmingName] + ) + { + // Make sure the constant name starts with the enum name, and that there is clearly a word + // gap after the enum name in the constant name e.g. API_BlendOp doesn't pull in + // API_BLEND_OPAQUE but it does pull in API_BLEND_OP_ADD (or API_BLENDOP_ADD). + // I wouldn't feel safe relaxing this right now, despite there being obvious use cases. + // Perhaps as a future improvement we can try to walk back the enum's trimming name, check + // that there are no other enums that conflict with that shorter trimming name, and then try + // to widen the scope. So for example, if we have found nothing for API_BlendOp then we'd + // just try API_Blend (provided there's no API_BlendFactor, API_Blend, or any other + // conflicts) which would then sweep up API_BLEND_OPAQUE. We'd then keep the original enum + // names to stay in-keeping with the native API. TODO investigate this + if ( + !constCandidate.StartsWith( + enumCandidate, + StringComparison.OrdinalIgnoreCase + ) + || ( + constCandidate[enumCandidate.Length] != '_' + && char.IsUpper(constCandidate[enumCandidate.Length - 1]) + == char.IsUpper(constCandidate[enumCandidate.Length]) + ) + ) + { + continue; + } + + // We don't generate enums that have had inconsistent usage (e.g. int vs short vs long) but + // if we are able to map constants into those enums, we still want to ensure we don't go and + // map it to a less relevant enum as a result. So we add the constant to a separate HashSet, + // with which we remove the constant from the _constants dictionary but don't return it to + // the Rewriter, ensuring it is not removed (at is has not been mapped to an eligible enum). + (enumType is null ? ineligibleConstants : extractedConstants).Add( + constant + ); + nextConst = true; + if (extractedEnum is not { } theExtractedEnum) + { + break; + } + + theExtractedEnum.Node = theExtractedEnum + .Node.AddMembers( + EnumMemberDeclaration(constant) + .WithEqualsValue(EqualsValueClause(value)) + ) + .WithAttributeLists( + theExtractedEnum.Node.AttributeLists.WithNativeName(enumName) + ); + + extractedEnum = theExtractedEnum; + break; + } + + if (nextConst) + { + break; + } + } + } + + // Remove the constants that we've mapped into enums + foreach ( + var constant in (IEnumerable) + [.. ineligibleConstants, .. extractedConstants] + ) + { + _constants.Remove(constant); + } + + ineligibleConstants.Clear(); + if (extractedEnum is { Node.Members.Count: > 0 }) + { + extractedEnums[enumName] = extractedEnum.Value; + } + } + + return (extractedEnums, extractedConstants); + } + + public override SyntaxNode? VisitFieldDeclaration(FieldDeclarationSyntax node) + { + if (node.Modifiers.Any(SyntaxKind.ConstKeyword)) + { + foreach (var vardec in node.Declaration.Variables) + { + if (vardec.Initializer is null) + { + continue; + } + + _constants.Add(vardec.Identifier.ToString(), vardec.Initializer.Value); + } + } + return base.VisitFieldDeclaration(node); + } + } + + private class Rewriter( + IReadOnlyCollection constantsToRemove, + IReadOnlyCollection extractedEnums + ) : CSharpSyntaxRewriter + { + public override SyntaxNode? VisitPredefinedType(PredefinedTypeSyntax node) + { + var nativeTypeName = GetNativeTypeNameForPredefinedType(node).ToString(); + if (extractedEnums.Contains(nativeTypeName)) + { + return IdentifierName(nativeTypeName).WithTriviaFrom(node); + } + + return base.VisitPredefinedType(node); + } + + public override SyntaxNode? VisitFieldDeclaration(FieldDeclarationSyntax node) + { + var ret = base.VisitFieldDeclaration(node) as FieldDeclarationSyntax; + return ret?.Declaration.Variables.Count == 0 ? null : ret; + } + + public override SyntaxNode? VisitVariableDeclarator(VariableDeclaratorSyntax node) + { + if (constantsToRemove.Contains(node.Identifier.ToString())) + { + return null; + } + + return base.VisitVariableDeclarator(node); + } + } +} diff --git a/sources/SilkTouch/SilkTouch/Mods/ExtractFunctionPointers.cs b/sources/SilkTouch/SilkTouch/Mods/ExtractFunctionPointers.cs new file mode 100644 index 0000000000..209962030e --- /dev/null +++ b/sources/SilkTouch/SilkTouch/Mods/ExtractFunctionPointers.cs @@ -0,0 +1,553 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.Extensions.Logging; +using Silk.NET.SilkTouch.Naming; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Silk.NET.SilkTouch.Mods; + +/// +/// Replaces function pointers identified by their s +/// with delegates and function pointer structs. +/// +public partial class ExtractFunctionPointers(ILogger logger) : IMod +{ + /// + public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) + { + var project = ctx.SourceProject; + if (project == null) + { + return; + } + + // Scan and extract function pointers + var rewriter = new Rewriter(logger); + foreach (var docId in project.DocumentIds) + { + var doc = + project.GetDocument(docId) + ?? throw new InvalidOperationException("Document missing"); + + var file = doc.RelativePath(); + if (file is null) + { + continue; + } + + rewriter.File = file; + project = doc.WithSyntaxRoot( + rewriter.Visit(await doc.GetSyntaxRootAsync(ct)) + ?? throw new InvalidOperationException("Visit returned null.") + ).Project; + } + + // Add documents for each extracted function pointer + // This is moved out of the foreach statement for better debuggability + var extractedFunctionPointers = rewriter + .FunctionPointerTypes.Values.SelectMany(x => + (IEnumerable) + [ + new ExtractedType( + x.Delegate, + x.Delegate.Identifier.ToString(), + x.ReferencingFileDirs, + x.ReferencingNamespaces + ), + new ExtractedType( + x.Pfn, + x.Pfn.Identifier.ToString(), + x.ReferencingFileDirs, + x.ReferencingNamespaces + ), + ] + ) + .ToList(); + + foreach (var (typeDecl, identifier, fileDirs, namespaces) in extractedFunctionPointers) + { + var ns = NameUtils.FindCommonPrefix(namespaces, true, false, true); + var dir = NameUtils.FindCommonPrefix(fileDirs, true, false, true).TrimEnd('/'); + project = project + ?.AddDocument( + $"{identifier}.gen.cs", + CompilationUnit() + .WithMembers( + ns is { Length: > 0 } + ? SingletonList( + FileScopedNamespaceDeclaration( + ModUtils.NamespaceIntoIdentifierName(ns.TrimEnd('.')) + ) + .WithMembers(SingletonList(typeDecl)) + ) + : SingletonList(typeDecl) + ), + // Place extracted function pointer types in the directory common to where the types are referenced from + filePath: project.FullPath($"{dir}/{identifier}.gen.cs") + ) + .Project; + } + + ctx.SourceProject = project; + } + + private record struct ExtractedType( + MemberDeclarationSyntax Node, + string Identifier, + HashSet ReferencingFileDirs, + HashSet ReferencingNamespaces + ); + + private record struct ExtractedFunctionPointerType( + StructDeclarationSyntax Pfn, + DelegateDeclarationSyntax Delegate, + HashSet ReferencingFileDirs, + HashSet ReferencingNamespaces + ); + + private partial class Rewriter(ILogger logger) : CSharpSyntaxRewriter + { + private string? _typeNameFromOuterFunctionPointer; + private string? _fallbackFromOuterFunctionPointer; + + public Dictionary FunctionPointerTypes { get; } = []; + + public string? File { get; set; } + + public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node) + { + if (!FunctionPointerTypes.TryGetValue(node.Identifier.ToString(), out var pfnInfo)) + { + return node; + } + + return node.WithIdentifier(Identifier(pfnInfo.Pfn.Identifier.ToString())); + } + + public override SyntaxNode VisitFunctionPointerType(FunctionPointerTypeSyntax node) + { + // Walk up the type. We expect only pointers above us, but we could encounter a function pointer type in + // which case we just ignore all this as we should already have a _currentNativeTypeName. Anything else and + // we don't have enough context for a fallback. + var current = node.Parent; + var indirectionLevels = 0; + while (current is PointerTypeSyntax) + { + indirectionLevels++; + current = current.Parent; + } + + // As above, get the native type name if we can and also get a fallback name based on context. + var (currentNativeTypeName, fallback) = current switch + { + MethodDeclarationSyntax meth => ( + meth.AttributeLists.GetNativeTypeName(SyntaxKind.ReturnKeyword), + $"{meth.Identifier}_r" + ), + ParameterSyntax { Parent.Parent: MethodDeclarationSyntax meth } param => ( + param.AttributeLists.GetNativeTypeName(), + $"{meth.Identifier}_{param.Identifier}" + ), + VariableDeclarationSyntax + { + Parent: FieldDeclarationSyntax { Parent: BaseTypeDeclarationSyntax type } fld + } vardec => ( + fld.AttributeLists.GetNativeTypeName(), + $"{type.Identifier}_{vardec.Variables[0].Identifier}" + ), + _ => (null, null), + }; + + // If the native type name is actually the function pointer signature (i.e. not through a typedef) then we + // should pass the native type name down when recursing. + fallback = _fallbackFromOuterFunctionPointer ?? fallback; + currentNativeTypeName = + (_typeNameFromOuterFunctionPointer ?? currentNativeTypeName)?.Trim() ?? fallback; + string[]? recursiveTypeNames = null; + if (currentNativeTypeName.AsSpan().ContainsAnyExcept(NameUtils.IdentifierChars)) + { + var match = FunctionPointerNativeTypeNameRegex().Match(currentNativeTypeName!); + if (match.Success) + { + currentNativeTypeName = fallback; + + // NOTE: We expect the groups to be as follows: + // 0 = everything + // 1 = return type + // 2 = indirection levels + 1 + // 3 = comma separated parameter types + recursiveTypeNames = new string[ + 1 + + (match.Groups[3].Value.Length > 0 ? 1 : 0) + + match.Groups[3].Value.AsSpan().Count(',') + ]; + if (match.Groups[2].Value.AsSpan().Count('*') != indirectionLevels + 1) + { + logger.LogWarning( + "Unable to deal with function pointer usage at {} - mismatch of indirection " + + "levels: {} for {}", + node.GetLocation().GetLineSpan(), + node, + currentNativeTypeName + ); + return node; + } + + recursiveTypeNames[^1] = match.Groups[1].Value; + var @params = match + .Groups[3] + .Value.Split( + ',', + StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries + ); + for (var i = 0; i < @params.Length; i++) + { + recursiveTypeNames[i] = @params[i]; + } + } + else + { + // Maybe it's a pointer type? + var idSpan = currentNativeTypeName.AsSpan(); + if (idSpan.StartsWith("const ")) + { + idSpan = idSpan["const ".Length..]; + } + + // If the indirection levels match (and the only other non-identifier characters are whitespace) + // then we can use the identifier as the native name. + idSpan = idSpan.Trim(); + var badStart = idSpan.IndexOfAnyExcept(NameUtils.IdentifierChars); + var bad = idSpan[badStart..]; + currentNativeTypeName = + badStart == -1 + || ( + bad.Count('*') == indirectionLevels + && bad.Count(' ') == bad.Length - indirectionLevels + ) + ? idSpan[..badStart].ToString() + : fallback; + } + } + + if (currentNativeTypeName is null) + { + logger.LogWarning( + "Unable to deal with function pointer usage at {} - terminated at {}: {}", + node.GetLocation().GetLineSpan(), + current?.GetType().Name ?? "null", + current + ); + return node; + } + + // Assert that our state is valid given the tests we've done above before recursing. + Debug.Assert( + _fallbackFromOuterFunctionPointer is not null + == node.Ancestors().OfType().Any() + ); + + // Ensure that we've recursively generated and fixed up any function pointers contained within this function + // pointer. + var ns = node.NamespaceFromSyntaxNode(); + node = node.WithParameterList( + node.ParameterList.WithParameters( + SeparatedList( + node.ParameterList.Parameters.Select( + (x, i) => + { + var typeNameBefore = _typeNameFromOuterFunctionPointer; + var fallbackBefore = _fallbackFromOuterFunctionPointer; + _typeNameFromOuterFunctionPointer = recursiveTypeNames?[i]; + _fallbackFromOuterFunctionPointer = + $"{currentNativeTypeName}_p{i}"; + var ret = base.Visit(x); + _typeNameFromOuterFunctionPointer = typeNameBefore; + _fallbackFromOuterFunctionPointer = fallbackBefore; + return ret; + } + ) + .OfType() + ) + ) + ); + + // Generate the types if we haven't already. + if (!FunctionPointerTypes.TryGetValue(currentNativeTypeName, out var pfnInfo)) + { + var (pfn, @delegate) = CreateFunctionPointerTypes( + currentNativeTypeName, + $"{currentNativeTypeName}Delegate", + ( + currentNativeTypeName == fallback + ? SingletonList( + AttributeList( + SingletonSeparatedList(Attribute(IdentifierName("Transformed"))) + ) + ) + : default + ).WithNativeName(currentNativeTypeName), + ( + currentNativeTypeName == fallback + ? SingletonList( + AttributeList( + SingletonSeparatedList(Attribute(IdentifierName("Transformed"))) + ) + ) + : default + ) + .WithNativeName(currentNativeTypeName) + .AddReferencedNameAffix( + NameAffixType.Prefix, + "FunctionPointerParent", + currentNativeTypeName + ) + .AddNameAffix( + NameAffixType.Suffix, + "FunctionPointerDelegateType", + "Delegate" + ), + node + ); + + FunctionPointerTypes[currentNativeTypeName] = pfnInfo = + new ExtractedFunctionPointerType(pfn, @delegate, [], []); + } + + // Ensure this visitation is used to determine the namespace/location. + pfnInfo.ReferencingNamespaces.Add(ns); + if (File?[..File.LastIndexOf('/')] is { } dir) + { + pfnInfo.ReferencingFileDirs.Add(dir); + } + + return IdentifierName(currentNativeTypeName); + } + + private static ( + StructDeclarationSyntax Pfn, + DelegateDeclarationSyntax Delegate + ) CreateFunctionPointerTypes( + string pfnName, + string delegateName, + SyntaxList pfnAttrLists, + SyntaxList delegateAttrLists, + FunctionPointerTypeSyntax rawPfn + ) + { + // Ported from https://github.com/dotnet/Silk.NET/blob/d30cc43b/src/Core/Silk.NET.BuildTools/Bind/StructWriter.cs#L744-L774 + var pfn = StructDeclaration(pfnName) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.UnsafeKeyword), + Token(SyntaxKind.ReadOnlyKeyword) + ) + ) + .WithBaseList( + BaseList( + SingletonSeparatedList( + SimpleBaseType(IdentifierName("IDisposable")) + ) + ) + ) + .WithAttributeLists(pfnAttrLists) + .WithMembers( + List( + [ + FieldDeclaration( + VariableDeclaration( + PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))), + SingletonSeparatedList(VariableDeclarator("_pointer")) + ) + ) + .WithModifiers( + TokenList( + Token(SyntaxKind.PrivateKeyword), + Token(SyntaxKind.ReadOnlyKeyword) + ) + ), + PropertyDeclaration(rawPfn, "Handle") + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) + .WithExpressionBody( + ArrowExpressionClause( + CastExpression(rawPfn, IdentifierName("_pointer")) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + ConstructorDeclaration(pfnName) + .WithParameterList( + ParameterList( + SingletonSeparatedList( + Parameter(Identifier("ptr")).WithType(rawPfn) + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName("_pointer"), + IdentifierName("ptr") + ) + ) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + ConstructorDeclaration(pfnName) + .WithParameterList( + ParameterList( + SingletonSeparatedList( + Parameter(Identifier("proc")) + .WithType(IdentifierName(delegateName)) + ) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName("_pointer"), + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("SilkMarshal"), + IdentifierName("DelegateToPtr") + ), + ArgumentList( + SingletonSeparatedList( + Argument(IdentifierName("proc")) + ) + ) + ) + ) + ) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + MethodDeclaration( + PredefinedType(Token(SyntaxKind.VoidKeyword)), + "Dispose" + ) + .WithExpressionBody( + ArrowExpressionClause( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("SilkMarshal"), + IdentifierName("Free") + ), + ArgumentList( + SingletonSeparatedList( + Argument(IdentifierName("_pointer")) + ) + ) + ) + ) + ) + .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + ConversionOperatorDeclaration( + Token(SyntaxKind.ImplicitKeyword), + IdentifierName(pfnName) + ) + .WithParameterList( + ParameterList( + SingletonSeparatedList( + Parameter(Identifier("pfn")).WithType(rawPfn) + ) + ) + ) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.StaticKeyword) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + ImplicitObjectCreationExpression( + ArgumentList( + SingletonSeparatedList( + Argument(IdentifierName("pfn")) + ) + ), + null + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + ConversionOperatorDeclaration(Token(SyntaxKind.ImplicitKeyword), rawPfn) + .WithParameterList( + ParameterList( + SingletonSeparatedList( + Parameter(Identifier("pfn")) + .WithType(IdentifierName(pfnName)) + ) + ) + ) + .WithModifiers( + TokenList( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.StaticKeyword) + ) + ) + .WithExpressionBody( + ArrowExpressionClause( + CastExpression( + rawPfn, + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("pfn"), + IdentifierName("_pointer") + ) + ) + ) + ) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), + // TODO invoke method? + ] + ) + ); + + var @delegate = DelegateDeclaration( + rawPfn.ParameterList.Parameters.Last().Type, + Identifier(delegateName) + ) + .WithModifiers( + TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.UnsafeKeyword)) + ) + .WithAttributeLists(delegateAttrLists) + .WithParameterList( + ParameterList( + SeparatedList( + rawPfn + .ParameterList.Parameters.SkipLast(1) + .Select( + (y, i) => + Parameter( + y.AttributeLists, + y.Modifiers, + y.Type, + Identifier($"arg{i}"), + null + ) + ) + ) + ) + ); + return (pfn, @delegate); + } + + [GeneratedRegex( + @"^((?:[A-Za-z0-9\s\*_]|\[[0-9]*\])+)\((\*)+\)\(((?:(?:[A-Za-z0-9\s\*_]|\[[0-9]*\])+,?)*)\)" + )] + private partial Regex FunctionPointerNativeTypeNameRegex(); + } +} diff --git a/sources/SilkTouch/SilkTouch/Mods/ExtractNestedTypes.cs b/sources/SilkTouch/SilkTouch/Mods/ExtractNestedTypes.cs new file mode 100644 index 0000000000..d7f28816b0 --- /dev/null +++ b/sources/SilkTouch/SilkTouch/Mods/ExtractNestedTypes.cs @@ -0,0 +1,167 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Silk.NET.SilkTouch.Clang; +using Silk.NET.SilkTouch.Naming; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Silk.NET.SilkTouch.Mods; + +/// +/// Extracts fixed buffers and anonymous structs output by +/// into their own files as non-nested structs. +/// +/// +/// Apparently this mod only handles the special nested structs output by +/// right now. We might change this in the future if there is the need. +/// +public partial class ExtractNestedTypes : IMod +{ + /// + public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) + { + var project = ctx.SourceProject; + if (project == null) + { + return; + } + + // Scan and extract nested structs + var rewriter = new Rewriter(); + foreach (var docId in project.DocumentIds) + { + var doc = + project.GetDocument(docId) + ?? throw new InvalidOperationException("Document missing"); + + var file = doc.RelativePath(); + if (file is null) + { + continue; + } + + project = doc.WithSyntaxRoot( + rewriter.Visit(await doc.GetSyntaxRootAsync(ct)) + ?? throw new InvalidOperationException("Visit returned null.") + ).Project; + + foreach (var newStruct in rewriter.ExtractedNestedStructs) + { + // Add new documents for each nested struct + project = project + .AddDocument( + $"{newStruct.Identifier}.gen.cs", + CompilationUnit() + .WithMembers( + rewriter.Namespace is not null + ? SingletonList( + FileScopedNamespaceDeclaration( + ModUtils.NamespaceIntoIdentifierName( + rewriter.Namespace + ) + ) + .WithMembers( + SingletonList(newStruct) + ) + ) + : SingletonList(newStruct) + ), + // Place extracted struct next to the original file it came from + filePath: project.FullPath( + $"{file.AsSpan()[..file.LastIndexOf('/')]}/{newStruct.Identifier}.gen.cs" + ) + ) + .Project; + } + + rewriter.Namespace = null; + rewriter.ExtractedNestedStructs.Clear(); + } + + ctx.SourceProject = project; + } + + private partial class Rewriter : CSharpSyntaxRewriter + { + private Dictionary _typeRenames = []; + + public List ExtractedNestedStructs { get; } = []; + + public string? Namespace { get; set; } + + public override SyntaxNode? VisitIdentifierName(IdentifierNameSyntax node) => + base.VisitIdentifierName( + _typeRenames.TryGetValue(node.Identifier.ToString(), out var newType) + || (newType = null) is not null + ? node.WithIdentifier(Identifier(newType)) + : node + ); + + public override SyntaxNode? VisitStructDeclaration(StructDeclarationSyntax node) + { + // Extract nested structs + // This will do two things: + // 1. Remove the nested struct(s) from the original struct + // 2. Add them to the ExtractedNestedStructs list to be processed later + var nextExtractedNestedIdx = ExtractedNestedStructs.Count; + var members = node.Members; + for (var i = 0; i < members.Count; i++) + { + var member = members[i]; + if ( + member is not StructDeclarationSyntax structNode + || GeneratedNestedTypeRegex().Match(structNode.Identifier.ToString()) + is not { Success: true, Groups.Count: 3 } match + ) + { + continue; + } + + var extractedIdentifier = $"{node.Identifier}{match.Groups[1].Value}"; + _typeRenames[structNode.Identifier.ToString()] = extractedIdentifier; + structNode = + VisitStructDeclaration( + structNode + .WithIdentifier(Identifier(extractedIdentifier)) + .WithAttributeLists( + structNode.AttributeLists.AddReferencedNameAffix( + NameAffixType.Prefix, + "NestedStructParent", + node.Identifier.ToString() + ) + ) + ) as StructDeclarationSyntax + ?? structNode; + ExtractedNestedStructs.Add(structNode); + members = members.RemoveAt(i--); + } + + var ret = base.VisitStructDeclaration(node.WithMembers(members)); + for (var i = nextExtractedNestedIdx; i < ExtractedNestedStructs.Count; i++) + { + if ( + _typeRenames + .FirstOrDefault(x => + x.Value == ExtractedNestedStructs[i].Identifier.ToString() + ) + .Key + is not { } key + ) + { + continue; + } + _typeRenames.Remove(key); + } + + Namespace = node.NamespaceFromSyntaxNode(); + return ret; + } + + [GeneratedRegex("^_([a-zA-Z0-9_]*)_e__(Union|Struct|FixedBuffer)$")] + private partial Regex GeneratedNestedTypeRegex(); + } +} diff --git a/sources/SilkTouch/SilkTouch/Mods/ExtractNestedTyping.cs b/sources/SilkTouch/SilkTouch/Mods/ExtractNestedTyping.cs deleted file mode 100644 index 273eee7491..0000000000 --- a/sources/SilkTouch/SilkTouch/Mods/ExtractNestedTyping.cs +++ /dev/null @@ -1,991 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Text.RegularExpressions; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.Extensions.Logging; -using Silk.NET.SilkTouch.Naming; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace Silk.NET.SilkTouch.Mods; - -/// -/// A mod that extracts type system information nested within other types. This currently includes: -/// -/// -/// Replacing function pointers identified by their s with delegates and -/// function pointer structs. -/// -/// -/// Moving constants into their respective enums. These constants are identified by checking for an enum with -/// a matching prefix, as identified by the enum's . -/// This accounts for the below pattern seen frequently pre-C99: -/// -/// typedef unsigned int MyEnum; -/// #define MY_ENUM_HELLO 0 -/// extern MyEnum GetMyEnum(); -/// -/// -/// -/// Extracting fixed buffers and anonymous structures contained within structures into separate types. -/// -/// -/// -public partial class ExtractNestedTyping(ILogger logger) : Mod -{ - /// - public override async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) - { - await base.ExecuteAsync(ctx, ct); - - var project = ctx.SourceProject; - if (project == null) - { - return; - } - - // First pass to gather data, such as the types to extract and generate - var walker = new Walker(); - foreach (var doc in project.Documents) - { - var (fname, node) = (doc.RelativePath(), await doc.GetSyntaxRootAsync(ct)); - if (fname is null) - { - continue; - } - - walker.File = fname; - walker.Visit(node); - } - - // Second pass to modify existing files as per our discovery. - var rewriter = new Rewriter(logger); - // rewriter.FunctionPointerTypes = walker.GetFunctionPointerTypes(); - var (enums, constants) = walker.GetExtractedEnums(); - rewriter.ConstantsToRemove = constants; - rewriter.ExtractedEnums = enums.Keys; - foreach (var docId in project.DocumentIds) - { - var doc = - project.GetDocument(docId) - ?? throw new InvalidOperationException("Document missing"); - var (fname, node) = (doc.RelativePath(), await doc.GetSyntaxRootAsync(ct)); - if (fname is null) - { - continue; - } - - // Rewrite node - // What this does depends on the node's type - // - // For example: - // This will handle removing nested structs. - // This is also where extracted enums are processed. - rewriter.File = fname; - project = doc.WithSyntaxRoot( - rewriter.Visit(node) - ?? throw new InvalidOperationException("Rewriter returned null") - ).Project; - - foreach (var newStruct in rewriter.ExtractedNestedStructs) - { - // Add new documents for each nested struct - project = project - .AddDocument( - $"{newStruct.Identifier}.gen.cs", - CompilationUnit() - .WithMembers( - rewriter.Namespace is not null - ? SingletonList( - FileScopedNamespaceDeclaration( - ModUtils.NamespaceIntoIdentifierName( - rewriter.Namespace - ) - ) - .WithMembers( - SingletonList(newStruct) - ) - ) - : SingletonList(newStruct) - ), - filePath: project.FullPath( - $"{fname.AsSpan()[..fname.LastIndexOf('/')]}/{newStruct.Identifier}.gen.cs" - ) - ) - .Project; - } - - rewriter.File = null; - rewriter.Namespace = null; - rewriter.ExtractedNestedStructs.Clear(); - } - - // Add documents for each extracted function pointer - // This is moved out of the foreach statement for better debuggability - var extractedFunctionPointers = rewriter - .FunctionPointerTypes.Values //.Where(x => x.IsUnique) - .SelectMany(x => - (IEnumerable<(MemberDeclarationSyntax, string, HashSet, HashSet)>) - [ - ( - x.Delegate, - x.Delegate.Identifier.ToString(), - x.ReferencingFileDirs, - x.ReferencingNamespaces - ), - ( - x.Pfn, - x.Pfn.Identifier.ToString(), - x.ReferencingFileDirs, - x.ReferencingNamespaces - ), - ] - ) - .Concat( - enums.Select(x => - ( - (MemberDeclarationSyntax)x.Value.Item1, - x.Value.Item1.Identifier.ToString(), - x.Value.Item2, - x.Value.Item3 - ) - ) - ) - .ToList(); - - foreach (var (typeDecl, identifier, fileDirs, namespaces) in extractedFunctionPointers) - { - var ns = NameUtils.FindCommonPrefix(namespaces, true, false, true); - var dir = NameUtils.FindCommonPrefix(fileDirs, true, false, true).TrimEnd('/'); - project = project - ?.AddDocument( - $"{identifier}.gen.cs", - CompilationUnit() - .WithMembers( - ns is { Length: > 0 } - ? SingletonList( - FileScopedNamespaceDeclaration( - ModUtils.NamespaceIntoIdentifierName(ns.TrimEnd('.')) - ) - .WithMembers(SingletonList(typeDecl)) - ) - : SingletonList(typeDecl) - ), - filePath: project.FullPath($"{dir}/{identifier}.gen.cs") - ) - .Project; - } - - ctx.SourceProject = project; - } - - private static ReadOnlySpan GetNativeTypeNameForPredefinedType( - PredefinedTypeSyntax node, - Dictionary, HashSet)?>? numericTypeNames = null - ) - { - // Walk up to the parameter or method. We only allow primitive integer types right now. - var current = node.Parent; - var indirectionLevels = 0; - while (current is PointerTypeSyntax) - { - indirectionLevels++; - current = current.Parent; - } - - var attrs = current switch - { - MethodDeclarationSyntax meth => meth.AttributeLists, - ParameterSyntax param => param.AttributeLists, - _ => default, - }; - - if (attrs.Count == 0) - { - return default; - } - - if (!attrs.TryParseNativeTypeName(out var info)) - { - return null; - } - - // Ensure that the indirection levels indicated by the type name is the same as we've encountered when walking - // up the type. If this isn't, this indicates that the native type name is a typedef to a pointer and shouldn't - // be something that is mapped into an enum. - if (info.IndirectionLevels == indirectionLevels) - { - return info.Name; - } - - InvalidateIfSeen(numericTypeNames, info.Name); - return null; - } - - private static void InvalidateIfSeen( - Dictionary, HashSet)?>? numericTypeNames, - string nativeTypeName - ) - { - if (numericTypeNames?.ContainsKey(nativeTypeName) ?? false) - { - numericTypeNames[nativeTypeName] = null; - } - } - - partial class Rewriter(ILogger logger) : CSharpSyntaxRewriter - { - private Dictionary _typeRenames = []; - - public List ExtractedNestedStructs { get; } = []; - - public Dictionary< - string, - ( - StructDeclarationSyntax Pfn, - DelegateDeclarationSyntax Delegate, - HashSet ReferencingFileDirs, - HashSet ReferencingNamespaces - ) - > FunctionPointerTypes { get; set; } = []; - - public IReadOnlyCollection? ConstantsToRemove { get; set; } - - public IReadOnlyCollection? ExtractedEnums { get; set; } - - public string? Namespace { get; set; } - public string? File { get; set; } - - public override SyntaxNode? VisitIdentifierName(IdentifierNameSyntax node) => - base.VisitIdentifierName( - _typeRenames.TryGetValue(node.Identifier.ToString(), out var v) - || ( - v = - FunctionPointerTypes?.TryGetValue(node.Identifier.ToString(), out var pfni) - ?? false - ? pfni.Pfn.Identifier.ToString() - : null - ) - is not null - ? node.WithIdentifier(Identifier(v)) - : node - ); - - public override SyntaxNode? VisitPredefinedType(PredefinedTypeSyntax node) - { - var nativeTypeName = GetNativeTypeNameForPredefinedType(node).ToString(); - if (ExtractedEnums?.Contains(nativeTypeName) ?? false) - { - return IdentifierName(nativeTypeName).WithTriviaFrom(node); - } - - return base.VisitPredefinedType(node); - } - - public override SyntaxNode? VisitFieldDeclaration(FieldDeclarationSyntax node) - { - var ret = base.VisitFieldDeclaration(node) as FieldDeclarationSyntax; - return ret?.Declaration.Variables.Count == 0 ? null : ret; - } - - public override SyntaxNode? VisitVariableDeclarator(VariableDeclaratorSyntax node) - { - if (ConstantsToRemove?.Contains(node.Identifier.ToString()) ?? false) - { - return null; - } - return base.VisitVariableDeclarator(node); - } - - public override SyntaxNode? VisitStructDeclaration(StructDeclarationSyntax node) - { - // Extract nested structs - // This will do two things: - // 1. Remove the nested struct(s) from the original struct - // 2. Add them to the ExtractedNestedStructs list to be processed later - var nextExtractedNestedIdx = ExtractedNestedStructs.Count; - var members = node.Members; - for (var i = 0; i < members.Count; i++) - { - var mem = members[i]; - if ( - mem is not StructDeclarationSyntax struc - || GeneratedNestedTypeRegex().Match(struc.Identifier.ToString()) - is not { Success: true, Groups.Count: 3 } match - ) - { - continue; - } - - var iden = $"{node.Identifier}{match.Groups[1].Value}"; - _typeRenames[struc.Identifier.ToString()] = iden; - struc = - VisitStructDeclaration( - struc - .WithIdentifier(Identifier(iden)) - .WithAttributeLists( - struc.AttributeLists.AddReferencedNameAffix( - NameAffixType.Prefix, - "NestedStructParent", - node.Identifier.ToString() - ) - ) - ) as StructDeclarationSyntax - ?? struc; - ExtractedNestedStructs.Add(struc); - members = members.RemoveAt(i--); - } - - var ret = base.VisitStructDeclaration(node.WithMembers(members)); - for (var i = nextExtractedNestedIdx; i < ExtractedNestedStructs.Count; i++) - { - if ( - _typeRenames - .FirstOrDefault(x => - x.Value == ExtractedNestedStructs[i].Identifier.ToString() - ) - .Key - is not { } key - ) - { - continue; - } - _typeRenames.Remove(key); - } - - Namespace = node.NamespaceFromSyntaxNode(); - return ret; - } - - private string? _typeNameFromOuterFunctionPointer; - private string? _fallbackFromOuterFunctionPointer; - - public override SyntaxNode? VisitFunctionPointerType(FunctionPointerTypeSyntax node) - { - // Walk up the type. We expect only pointers above us, but we could encounter a function pointer type in - // which case we just ignore all this as we should already have a _currentNativeTypeName. Anything else and - // we don't have enough context for a fallback. - var current = node.Parent; - var indirectionLevels = 0; - while (current is PointerTypeSyntax) - { - indirectionLevels++; - current = current.Parent; - } - - // As above, get the native type name if we can and also get a fallback name based on context. - var (currentNativeTypeName, fallback) = current switch - { - MethodDeclarationSyntax meth => ( - meth.AttributeLists.GetNativeTypeName(SyntaxKind.ReturnKeyword), - $"{meth.Identifier}_r" - ), - ParameterSyntax { Parent.Parent: MethodDeclarationSyntax meth } param => ( - param.AttributeLists.GetNativeTypeName(), - $"{meth.Identifier}_{param.Identifier}" - ), - VariableDeclarationSyntax - { - Parent: FieldDeclarationSyntax { Parent: BaseTypeDeclarationSyntax type } fld - } vardec => ( - fld.AttributeLists.GetNativeTypeName(), - $"{type.Identifier}_{vardec.Variables[0].Identifier}" - ), - _ => (null, null), - }; - - // If the native type name is actually the function pointer signature (i.e. not through a typedef) then we - // should pass the native type name down when recursing. - fallback = _fallbackFromOuterFunctionPointer ?? fallback; - currentNativeTypeName = - (_typeNameFromOuterFunctionPointer ?? currentNativeTypeName)?.Trim() ?? fallback; - string[]? recursiveTypeNames = null; - if (currentNativeTypeName.AsSpan().ContainsAnyExcept(NameUtils.IdentifierChars)) - { - var match = FunctionPointerNativeTypeNameRegex().Match(currentNativeTypeName!); - if (match.Success) - { - currentNativeTypeName = fallback; - - // NOTE: We expect the groups to be as follows: - // 0 = everything - // 1 = return type - // 2 = indirection levels + 1 - // 3 = comma separated parameter types - recursiveTypeNames = new string[ - 1 - + (match.Groups[3].Value.Length > 0 ? 1 : 0) - + match.Groups[3].Value.AsSpan().Count(',') - ]; - if (match.Groups[2].Value.AsSpan().Count('*') != indirectionLevels + 1) - { - logger.LogWarning( - "Unable to deal with function pointer usage at {} - mismatch of indirection " - + "levels: {} for {}", - node.GetLocation().GetLineSpan(), - node, - currentNativeTypeName - ); - return node; - } - - recursiveTypeNames[^1] = match.Groups[1].Value; - var @params = match - .Groups[3] - .Value.Split( - ',', - StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries - ); - for (var i = 0; i < @params.Length; i++) - { - recursiveTypeNames[i] = @params[i]; - } - } - else - { - // Maybe it's a pointer type? - var idSpan = currentNativeTypeName.AsSpan(); - if (idSpan.StartsWith("const ")) - { - idSpan = idSpan["const ".Length..]; - } - - // If the indirection levels match (and the only other non-identifier characters are whitespace) - // then we can use the identifier as the native name. - idSpan = idSpan.Trim(); - var badStart = idSpan.IndexOfAnyExcept(NameUtils.IdentifierChars); - var bad = idSpan[badStart..]; - currentNativeTypeName = - badStart == -1 - || ( - bad.Count('*') == indirectionLevels - && bad.Count(' ') == bad.Length - indirectionLevels - ) - ? idSpan[..badStart].ToString() - : fallback; - } - } - - if (currentNativeTypeName is null) - { - logger.LogWarning( - "Unable to deal with function pointer usage at {} - terminated at {}: {}", - node.GetLocation().GetLineSpan(), - current?.GetType().Name ?? "null", - current - ); - return node; - } - - // Assert that our state is valid given the tests we've done above before recursing. - Debug.Assert( - _fallbackFromOuterFunctionPointer is not null - == node.Ancestors().OfType().Any() - ); - - // Ensure that we've recursively generated and fixed up any function pointers contained within this function - // pointer. - var ns = node.NamespaceFromSyntaxNode(); - node = node.WithParameterList( - node.ParameterList.WithParameters( - SeparatedList( - node.ParameterList.Parameters.Select( - (x, i) => - { - var typeNameBefore = _typeNameFromOuterFunctionPointer; - var fallbackBefore = _fallbackFromOuterFunctionPointer; - _typeNameFromOuterFunctionPointer = recursiveTypeNames?[i]; - _fallbackFromOuterFunctionPointer = - $"{currentNativeTypeName}_p{i}"; - var ret = base.Visit(x); - _typeNameFromOuterFunctionPointer = typeNameBefore; - _fallbackFromOuterFunctionPointer = fallbackBefore; - return ret; - } - ) - .OfType() - ) - ) - ); - - // Generate the types if we haven't already. - if (!FunctionPointerTypes.TryGetValue(currentNativeTypeName, out var pfnInfo)) - { - var (pfn, @delegate) = CreateFunctionPointerTypes( - currentNativeTypeName, - $"{currentNativeTypeName}Delegate", - ( - currentNativeTypeName == fallback - ? SingletonList( - AttributeList( - SingletonSeparatedList(Attribute(IdentifierName("Transformed"))) - ) - ) - : default - ).WithNativeName(currentNativeTypeName), - ( - currentNativeTypeName == fallback - ? SingletonList( - AttributeList( - SingletonSeparatedList(Attribute(IdentifierName("Transformed"))) - ) - ) - : default - ) - .WithNativeName(currentNativeTypeName) - .AddReferencedNameAffix( - NameAffixType.Prefix, - "FunctionPointerParent", - currentNativeTypeName - ) - .AddNameAffix( - NameAffixType.Suffix, - "FunctionPointerDelegateType", - "Delegate" - ), - node - ); - FunctionPointerTypes[currentNativeTypeName] = pfnInfo = (pfn, @delegate, [], []); - } - - // Ensure this visitation is used to determine the namespace/location. - pfnInfo.ReferencingNamespaces.Add(ns); - if (File?[..File.LastIndexOf('/')] is { } dir) - { - pfnInfo.ReferencingFileDirs.Add(dir); - } - - return IdentifierName(currentNativeTypeName); - } - - [GeneratedRegex("^_([a-zA-Z0-9_]*)_e__(Union|Struct|FixedBuffer)$")] - private partial Regex GeneratedNestedTypeRegex(); - - [GeneratedRegex( - @"^((?:[A-Za-z0-9\s\*_]|\[[0-9]*\])+)\((\*)+\)\(((?:(?:[A-Za-z0-9\s\*_]|\[[0-9]*\])+,?)*)\)" - )] - private partial Regex FunctionPointerNativeTypeNameRegex(); - } - - class Walker : CSharpSyntaxRewriter - { - private readonly Dictionary< - string, - ( - SyntaxKind Type, - HashSet ReferencingFileDirs, - HashSet ReferencingNamespaces - )? - > _numericTypeNames = new(); - - /// - /// Tracks the name and value of constants discovered. - /// - private readonly Dictionary _constants = []; - - public string? File { get; set; } - - public override SyntaxNode? VisitPredefinedType(PredefinedTypeSyntax node) - { - var nativeTypeName = GetNativeTypeNameForPredefinedType(node).ToString(); - if (nativeTypeName.Length > 0) - { - // Detect type discrepancies. - var thisType = node.Keyword.Kind(); - if (!_numericTypeNames.TryGetValue(nativeTypeName, out var numericTypeName)) - { - _numericTypeNames[nativeTypeName] = numericTypeName = (thisType, [], []); - } - - if ( - thisType - is not ( - SyntaxKind.ByteKeyword - or SyntaxKind.SByteKeyword - or SyntaxKind.ShortKeyword - or SyntaxKind.UShortKeyword - or SyntaxKind.IntKeyword - or SyntaxKind.UIntKeyword - or SyntaxKind.LongKeyword - or SyntaxKind.ULongKeyword - ) - || thisType != numericTypeName?.Type - ) - { - _numericTypeNames[nativeTypeName] = numericTypeName = null; - } - - if (numericTypeName is { } theTypeDetails) - { - theTypeDetails.ReferencingNamespaces.Add(node.NamespaceFromSyntaxNode()); - if (File?[..File.LastIndexOf('/')] is { } dir) - { - theTypeDetails.ReferencingFileDirs.Add(dir); - } - } - } - return base.VisitPredefinedType(node); - } - - // This code can probably be better. - public ( - Dictionary< - string, - (EnumDeclarationSyntax, HashSet, HashSet) - > ExtractedEnums, - HashSet ExtractedConstants - ) GetExtractedEnums() - { - var ineligibleConstants = new HashSet(); - var extractedConstants = new HashSet(); - var extractedEnums = new Dictionary< - string, - (EnumDeclarationSyntax, HashSet, HashSet) - >(_numericTypeNames.Count); - - // Try and find constants for each of the enums we've found. - // We do this in descending length order to ensure that we find the longest match for constant names to enum - // names. - foreach ( - var (enumName, enumType) in _numericTypeNames.OrderByDescending(x => x.Key.Length) - ) - { - var enumTrimmingName = NameSplitter.Underscore(enumName); - (EnumDeclarationSyntax, HashSet, HashSet)? extractedEnum = enumType - is { } theType - ? ( - EnumDeclaration(enumName) - .AddBaseListTypes(SimpleBaseType(PredefinedType(Token(theType.Type)))) - .AddModifiers(Token(SyntaxKind.PublicKeyword)), - theType.ReferencingFileDirs, - theType.ReferencingNamespaces - ) - : null; - - // Look through all of the constants and see whether they start with our enum name. - foreach (var (constant, value) in _constants) - { - // We want to account for PascalCase vs SCREAMING_SNAKE_CASE differences (for example) so we do - // four passes (for each combination of the original name vs trimming name, the latter of which - // taking casing into account). It is possible that this could be expanded, but this should be done - // carefully to ensure we don't light up prematurely. - var nextConst = false; - var trimmingName = NameSplitter.Underscore(constant); - foreach ( - var enumCandidate in (ReadOnlySpan)[enumName, enumTrimmingName] - ) - { - foreach ( - var constCandidate in (ReadOnlySpan)[constant, trimmingName] - ) - { - // Make sure the constant name starts with the enum name, and that there is clearly a word - // gap after the enum name in the constant name e.g. API_BlendOp doesn't pull in - // API_BLEND_OPAQUE but it does pull in API_BLEND_OP_ADD (or API_BLENDOP_ADD). - // I wouldn't feel safe relaxing this right now, despite there being obvious use cases. - // Perhaps as a future improvement we can try to walk back the enum's trimming name, check - // that there are no other enums that conflict with that shorter trimming name, and then try - // to widen the scope. So for example, if we have found nothing for API_BlendOp then we'd - // just try API_Blend (provided there's no API_BlendFactor, API_Blend, or any other - // conflicts) which would then sweep up API_BLEND_OPAQUE. We'd then keep the original enum - // names to stay in-keeping with the native API. TODO investigate this - if ( - !constCandidate.StartsWith( - enumCandidate, - StringComparison.OrdinalIgnoreCase - ) - || ( - constCandidate[enumCandidate.Length] != '_' - && char.IsUpper(constCandidate[enumCandidate.Length - 1]) - == char.IsUpper(constCandidate[enumCandidate.Length]) - ) - ) - { - continue; - } - - // We don't generate enums that have had inconsistent usage (e.g. int vs short vs long) but - // if we are able to map constants into those enums, we still want to ensure we don't go and - // map it to a less relevant enum as a result. So we add the constant to a separate HashSet, - // with which we remove the constant from the _constants dictionary but don't return it to - // the Rewriter, ensuring it is not removed (at is has not been mapped to an eligible enum). - (enumType is null ? ineligibleConstants : extractedConstants).Add( - constant - ); - nextConst = true; - if (extractedEnum is not { } theExtractedEnum) - { - break; - } - - theExtractedEnum.Item1 = theExtractedEnum.Item1.AddMembers( - EnumMemberDeclaration(constant) - .WithEqualsValue(EqualsValueClause(value)) - ); - extractedEnum = theExtractedEnum; - break; - } - - if (nextConst) - { - break; - } - } - } - - // Remove the constants that we've mapped into enums - foreach ( - var constant in (IEnumerable) - [.. ineligibleConstants, .. extractedConstants] - ) - { - _constants.Remove(constant); - } - - ineligibleConstants.Clear(); - if (extractedEnum is { Item1.Members.Count: > 0 }) - { - extractedEnums[enumName] = extractedEnum.Value; - } - } - - return (extractedEnums, extractedConstants); - } - - public override SyntaxNode? VisitFieldDeclaration(FieldDeclarationSyntax node) - { - if (node.Modifiers.Any(SyntaxKind.ConstKeyword)) - { - foreach (var vardec in node.Declaration.Variables) - { - if (vardec.Initializer is null) - { - continue; - } - - _constants.Add(vardec.Identifier.ToString(), vardec.Initializer.Value); - } - } - return base.VisitFieldDeclaration(node); - } - - public override SyntaxNode? VisitEnumDeclaration(EnumDeclarationSyntax node) - { - InvalidateIfSeen(_numericTypeNames, node.Identifier.ToString()); - return base.VisitEnumDeclaration(node); - } - } - - private static ( - StructDeclarationSyntax Pfn, - DelegateDeclarationSyntax Delegate - ) CreateFunctionPointerTypes( - string pfnName, - string delegateName, - SyntaxList pfnAttrLists, - SyntaxList delegateAttrLists, - FunctionPointerTypeSyntax rawPfn - ) - { - // Ported from https://github.com/dotnet/Silk.NET/blob/d30cc43b/src/Core/Silk.NET.BuildTools/Bind/StructWriter.cs#L744-L774 - var pfn = StructDeclaration(pfnName) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.UnsafeKeyword), - Token(SyntaxKind.ReadOnlyKeyword) - ) - ) - .WithBaseList( - BaseList( - SingletonSeparatedList( - SimpleBaseType(IdentifierName("IDisposable")) - ) - ) - ) - .WithAttributeLists(pfnAttrLists) - .WithMembers( - List( - [ - FieldDeclaration( - VariableDeclaration( - PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))), - SingletonSeparatedList(VariableDeclarator("_pointer")) - ) - ) - .WithModifiers( - TokenList( - Token(SyntaxKind.PrivateKeyword), - Token(SyntaxKind.ReadOnlyKeyword) - ) - ), - PropertyDeclaration(rawPfn, "Handle") - .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) - .WithExpressionBody( - ArrowExpressionClause( - CastExpression(rawPfn, IdentifierName("_pointer")) - ) - ) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), - ConstructorDeclaration(pfnName) - .WithParameterList( - ParameterList( - SingletonSeparatedList( - Parameter(Identifier("ptr")).WithType(rawPfn) - ) - ) - ) - .WithExpressionBody( - ArrowExpressionClause( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - IdentifierName("_pointer"), - IdentifierName("ptr") - ) - ) - ) - .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), - ConstructorDeclaration(pfnName) - .WithParameterList( - ParameterList( - SingletonSeparatedList( - Parameter(Identifier("proc")) - .WithType(IdentifierName(delegateName)) - ) - ) - ) - .WithExpressionBody( - ArrowExpressionClause( - AssignmentExpression( - SyntaxKind.SimpleAssignmentExpression, - IdentifierName("_pointer"), - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("SilkMarshal"), - IdentifierName("DelegateToPtr") - ), - ArgumentList( - SingletonSeparatedList( - Argument(IdentifierName("proc")) - ) - ) - ) - ) - ) - ) - .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), - MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), "Dispose") - .WithExpressionBody( - ArrowExpressionClause( - InvocationExpression( - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("SilkMarshal"), - IdentifierName("Free") - ), - ArgumentList( - SingletonSeparatedList( - Argument(IdentifierName("_pointer")) - ) - ) - ) - ) - ) - .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), - ConversionOperatorDeclaration( - Token(SyntaxKind.ImplicitKeyword), - IdentifierName(pfnName) - ) - .WithParameterList( - ParameterList( - SingletonSeparatedList( - Parameter(Identifier("pfn")).WithType(rawPfn) - ) - ) - ) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) - ) - ) - .WithExpressionBody( - ArrowExpressionClause( - ImplicitObjectCreationExpression( - ArgumentList( - SingletonSeparatedList(Argument(IdentifierName("pfn"))) - ), - null - ) - ) - ) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), - ConversionOperatorDeclaration(Token(SyntaxKind.ImplicitKeyword), rawPfn) - .WithParameterList( - ParameterList( - SingletonSeparatedList( - Parameter(Identifier("pfn")) - .WithType(IdentifierName(pfnName)) - ) - ) - ) - .WithModifiers( - TokenList( - Token(SyntaxKind.PublicKeyword), - Token(SyntaxKind.StaticKeyword) - ) - ) - .WithExpressionBody( - ArrowExpressionClause( - CastExpression( - rawPfn, - MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName("pfn"), - IdentifierName("_pointer") - ) - ) - ) - ) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)), - // TODO invoke method? - ] - ) - ); - - var @delegate = DelegateDeclaration( - rawPfn.ParameterList.Parameters.Last().Type, - Identifier(delegateName) - ) - .WithModifiers( - TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.UnsafeKeyword)) - ) - .WithAttributeLists(delegateAttrLists) - .WithParameterList( - ParameterList( - SeparatedList( - rawPfn - .ParameterList.Parameters.SkipLast(1) - .Select( - (y, i) => - Parameter( - y.AttributeLists, - y.Modifiers, - y.Type, - Identifier($"arg{i}"), - null - ) - ) - ) - ) - ); - return (pfn, @delegate); - } -} diff --git a/sources/SilkTouch/SilkTouch/Mods/IdentifySharedPrefixes.cs b/sources/SilkTouch/SilkTouch/Mods/IdentifySharedPrefixes.cs index 34ba8ae567..fa36866f91 100644 --- a/sources/SilkTouch/SilkTouch/Mods/IdentifySharedPrefixes.cs +++ b/sources/SilkTouch/SilkTouch/Mods/IdentifySharedPrefixes.cs @@ -19,7 +19,7 @@ namespace Silk.NET.SilkTouch.Mods; /// [ModConfiguration] public class IdentifySharedPrefixes(IOptionsSnapshot config) - : Mod + : IMod { /// /// This was from the original NameTrimmer code @@ -55,7 +55,7 @@ public record Configuration } /// - public override async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) + public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) { var configuration = config.Get(ctx.JobKey); var project = ctx.SourceProject; diff --git a/sources/SilkTouch/SilkTouch/Mods/PrettifyNames.cs b/sources/SilkTouch/SilkTouch/Mods/PrettifyNames.cs index afccdb95ab..131311c7bb 100644 --- a/sources/SilkTouch/SilkTouch/Mods/PrettifyNames.cs +++ b/sources/SilkTouch/SilkTouch/Mods/PrettifyNames.cs @@ -15,7 +15,7 @@ namespace Silk.NET.SilkTouch.Mods; /// A mod that will convert other naming conventions to the PascalCase nomenclature typically used in C#. /// /// -/// Does not support nested types. Please use before this mod. +/// Does not support nested types. Please use before this mod. /// Note that despite this, some initial work has been done to add nested type support so that it can be added when necessary. /// [ModConfiguration] diff --git a/sources/SilkTouch/SilkTouch/Mods/TransformHandles.cs b/sources/SilkTouch/SilkTouch/Mods/TransformHandles.cs index b74ffba117..e722c105a4 100644 --- a/sources/SilkTouch/SilkTouch/Mods/TransformHandles.cs +++ b/sources/SilkTouch/SilkTouch/Mods/TransformHandles.cs @@ -32,7 +32,7 @@ namespace Silk.NET.SilkTouch.Mods; public class TransformHandles( IOptionsSnapshot config, ILogger logger -) : Mod +) : IMod { /// /// The configuration for the mod. @@ -46,10 +46,8 @@ public class Config } /// - public override async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) + public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) { - await base.ExecuteAsync(ctx, ct); - var cfg = config.Get(ctx.JobKey); var project = ctx.SourceProject; if (project == null) @@ -252,6 +250,22 @@ public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node) Token(SyntaxKind.UnsafeKeyword), Token(SyntaxKind.PartialKeyword) ) + ) + .WithBaseList( + BaseList( + SingletonSeparatedList( + SimpleBaseType( + GenericName(Identifier("IEquatable")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + IdentifierName(structName) + ) + ) + ) + ) + ) + ) ); } diff --git a/sources/Vulkan/Vulkan/Handles/AccelerationStructureHandleKHR.gen.cs b/sources/Vulkan/Vulkan/Handles/AccelerationStructureHandleKHR.gen.cs index 5ce625e52e..76fe391cbb 100644 --- a/sources/Vulkan/Vulkan/Handles/AccelerationStructureHandleKHR.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/AccelerationStructureHandleKHR.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkAccelerationStructureKHR")] public readonly unsafe partial struct AccelerationStructureHandleKHR + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/AccelerationStructureHandleNV.gen.cs b/sources/Vulkan/Vulkan/Handles/AccelerationStructureHandleNV.gen.cs index e0b5cfd31a..9a06651042 100644 --- a/sources/Vulkan/Vulkan/Handles/AccelerationStructureHandleNV.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/AccelerationStructureHandleNV.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkAccelerationStructureNV")] public readonly unsafe partial struct AccelerationStructureHandleNV + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/BufferHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/BufferHandle.gen.cs index ee402effc7..279ce57be4 100644 --- a/sources/Vulkan/Vulkan/Handles/BufferHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/BufferHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkBuffer")] -public readonly unsafe partial struct BufferHandle +public readonly unsafe partial struct BufferHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/BufferViewHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/BufferViewHandle.gen.cs index fbd8cf601d..300221eaef 100644 --- a/sources/Vulkan/Vulkan/Handles/BufferViewHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/BufferViewHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkBufferView")] -public readonly unsafe partial struct BufferViewHandle +public readonly unsafe partial struct BufferViewHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/CommandBufferHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/CommandBufferHandle.gen.cs index 78040914cc..19140194de 100644 --- a/sources/Vulkan/Vulkan/Handles/CommandBufferHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/CommandBufferHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkCommandBuffer")] -public readonly unsafe partial struct CommandBufferHandle +public readonly unsafe partial struct CommandBufferHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/CommandPoolHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/CommandPoolHandle.gen.cs index 8901079ffa..41754f71c5 100644 --- a/sources/Vulkan/Vulkan/Handles/CommandPoolHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/CommandPoolHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkCommandPool")] -public readonly unsafe partial struct CommandPoolHandle +public readonly unsafe partial struct CommandPoolHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/CuFunctionHandleNVX.gen.cs b/sources/Vulkan/Vulkan/Handles/CuFunctionHandleNVX.gen.cs index 2092efbac6..88e3245aa6 100644 --- a/sources/Vulkan/Vulkan/Handles/CuFunctionHandleNVX.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/CuFunctionHandleNVX.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkCuFunctionNVX")] -public readonly unsafe partial struct CuFunctionHandleNVX +public readonly unsafe partial struct CuFunctionHandleNVX : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/CuModuleHandleNVX.gen.cs b/sources/Vulkan/Vulkan/Handles/CuModuleHandleNVX.gen.cs index 38b157fb12..0c458ddb9a 100644 --- a/sources/Vulkan/Vulkan/Handles/CuModuleHandleNVX.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/CuModuleHandleNVX.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkCuModuleNVX")] -public readonly unsafe partial struct CuModuleHandleNVX +public readonly unsafe partial struct CuModuleHandleNVX : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DataGraphPipelineSessionHandleARM.gen.cs b/sources/Vulkan/Vulkan/Handles/DataGraphPipelineSessionHandleARM.gen.cs index 9fc3cce025..c168c7c13f 100644 --- a/sources/Vulkan/Vulkan/Handles/DataGraphPipelineSessionHandleARM.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DataGraphPipelineSessionHandleARM.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDataGraphPipelineSessionARM")] public readonly unsafe partial struct DataGraphPipelineSessionHandleARM + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DebugReportCallbackHandleEXT.gen.cs b/sources/Vulkan/Vulkan/Handles/DebugReportCallbackHandleEXT.gen.cs index 9b5e6d4ba1..48fe437077 100644 --- a/sources/Vulkan/Vulkan/Handles/DebugReportCallbackHandleEXT.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DebugReportCallbackHandleEXT.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDebugReportCallbackEXT")] public readonly unsafe partial struct DebugReportCallbackHandleEXT + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DebugUtilsMessengerHandleEXT.gen.cs b/sources/Vulkan/Vulkan/Handles/DebugUtilsMessengerHandleEXT.gen.cs index ba82694671..fb076e55f9 100644 --- a/sources/Vulkan/Vulkan/Handles/DebugUtilsMessengerHandleEXT.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DebugUtilsMessengerHandleEXT.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDebugUtilsMessengerEXT")] public readonly unsafe partial struct DebugUtilsMessengerHandleEXT + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DeferredOperationHandleKHR.gen.cs b/sources/Vulkan/Vulkan/Handles/DeferredOperationHandleKHR.gen.cs index f434144c21..0b6acfe23e 100644 --- a/sources/Vulkan/Vulkan/Handles/DeferredOperationHandleKHR.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DeferredOperationHandleKHR.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDeferredOperationKHR")] public readonly unsafe partial struct DeferredOperationHandleKHR + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DescriptorPoolHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/DescriptorPoolHandle.gen.cs index e26a03f71d..81aa517e0c 100644 --- a/sources/Vulkan/Vulkan/Handles/DescriptorPoolHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DescriptorPoolHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDescriptorPool")] -public readonly unsafe partial struct DescriptorPoolHandle +public readonly unsafe partial struct DescriptorPoolHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DescriptorSetHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/DescriptorSetHandle.gen.cs index 6dbf7d78be..874c5c8e29 100644 --- a/sources/Vulkan/Vulkan/Handles/DescriptorSetHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DescriptorSetHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDescriptorSet")] -public readonly unsafe partial struct DescriptorSetHandle +public readonly unsafe partial struct DescriptorSetHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DescriptorSetLayoutHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/DescriptorSetLayoutHandle.gen.cs index 1da304d04e..d143152f82 100644 --- a/sources/Vulkan/Vulkan/Handles/DescriptorSetLayoutHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DescriptorSetLayoutHandle.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDescriptorSetLayout")] public readonly unsafe partial struct DescriptorSetLayoutHandle + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DescriptorUpdateTemplateHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/DescriptorUpdateTemplateHandle.gen.cs index 0406977bf4..363a66fd97 100644 --- a/sources/Vulkan/Vulkan/Handles/DescriptorUpdateTemplateHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DescriptorUpdateTemplateHandle.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDescriptorUpdateTemplate")] public readonly unsafe partial struct DescriptorUpdateTemplateHandle + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DeviceHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/DeviceHandle.gen.cs index 9ed0681e99..1152d2fb72 100644 --- a/sources/Vulkan/Vulkan/Handles/DeviceHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DeviceHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDevice")] -public readonly unsafe partial struct DeviceHandle +public readonly unsafe partial struct DeviceHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DeviceMemoryHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/DeviceMemoryHandle.gen.cs index 7ba8e70aac..4a83741a28 100644 --- a/sources/Vulkan/Vulkan/Handles/DeviceMemoryHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DeviceMemoryHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDeviceMemory")] -public readonly unsafe partial struct DeviceMemoryHandle +public readonly unsafe partial struct DeviceMemoryHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DisplayHandleKHR.gen.cs b/sources/Vulkan/Vulkan/Handles/DisplayHandleKHR.gen.cs index b24b1bba43..c3059547ff 100644 --- a/sources/Vulkan/Vulkan/Handles/DisplayHandleKHR.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DisplayHandleKHR.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDisplayKHR")] -public readonly unsafe partial struct DisplayHandleKHR +public readonly unsafe partial struct DisplayHandleKHR : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/DisplayModeHandleKHR.gen.cs b/sources/Vulkan/Vulkan/Handles/DisplayModeHandleKHR.gen.cs index 14fda9f162..a799fca91e 100644 --- a/sources/Vulkan/Vulkan/Handles/DisplayModeHandleKHR.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/DisplayModeHandleKHR.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkDisplayModeKHR")] -public readonly unsafe partial struct DisplayModeHandleKHR +public readonly unsafe partial struct DisplayModeHandleKHR : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/EventHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/EventHandle.gen.cs index f7ffb1943a..bc87c05bab 100644 --- a/sources/Vulkan/Vulkan/Handles/EventHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/EventHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkEvent")] -public readonly unsafe partial struct EventHandle +public readonly unsafe partial struct EventHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/ExternalComputeQueueHandleNV.gen.cs b/sources/Vulkan/Vulkan/Handles/ExternalComputeQueueHandleNV.gen.cs index e7458c5252..f88983bfdb 100644 --- a/sources/Vulkan/Vulkan/Handles/ExternalComputeQueueHandleNV.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/ExternalComputeQueueHandleNV.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkExternalComputeQueueNV")] public readonly unsafe partial struct ExternalComputeQueueHandleNV + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/FenceHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/FenceHandle.gen.cs index 5c58f15b3a..2c70b404d8 100644 --- a/sources/Vulkan/Vulkan/Handles/FenceHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/FenceHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkFence")] -public readonly unsafe partial struct FenceHandle +public readonly unsafe partial struct FenceHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/FramebufferHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/FramebufferHandle.gen.cs index 7b74cde225..c4cfd8bce5 100644 --- a/sources/Vulkan/Vulkan/Handles/FramebufferHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/FramebufferHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkFramebuffer")] -public readonly unsafe partial struct FramebufferHandle +public readonly unsafe partial struct FramebufferHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/ImageHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/ImageHandle.gen.cs index 155bd385c9..a94961a9b1 100644 --- a/sources/Vulkan/Vulkan/Handles/ImageHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/ImageHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkImage")] -public readonly unsafe partial struct ImageHandle +public readonly unsafe partial struct ImageHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/ImageViewHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/ImageViewHandle.gen.cs index 0af6321e26..5e8c796732 100644 --- a/sources/Vulkan/Vulkan/Handles/ImageViewHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/ImageViewHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkImageView")] -public readonly unsafe partial struct ImageViewHandle +public readonly unsafe partial struct ImageViewHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/IndirectCommandsLayoutHandleEXT.gen.cs b/sources/Vulkan/Vulkan/Handles/IndirectCommandsLayoutHandleEXT.gen.cs index e7bd1380fa..48457ba646 100644 --- a/sources/Vulkan/Vulkan/Handles/IndirectCommandsLayoutHandleEXT.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/IndirectCommandsLayoutHandleEXT.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkIndirectCommandsLayoutEXT")] public readonly unsafe partial struct IndirectCommandsLayoutHandleEXT + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/IndirectCommandsLayoutHandleNV.gen.cs b/sources/Vulkan/Vulkan/Handles/IndirectCommandsLayoutHandleNV.gen.cs index 19ac887c9b..dd6c43bd8d 100644 --- a/sources/Vulkan/Vulkan/Handles/IndirectCommandsLayoutHandleNV.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/IndirectCommandsLayoutHandleNV.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkIndirectCommandsLayoutNV")] public readonly unsafe partial struct IndirectCommandsLayoutHandleNV + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/IndirectExecutionSetHandleEXT.gen.cs b/sources/Vulkan/Vulkan/Handles/IndirectExecutionSetHandleEXT.gen.cs index e961f08da0..b8fe5999fd 100644 --- a/sources/Vulkan/Vulkan/Handles/IndirectExecutionSetHandleEXT.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/IndirectExecutionSetHandleEXT.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkIndirectExecutionSetEXT")] public readonly unsafe partial struct IndirectExecutionSetHandleEXT + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/InstanceHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/InstanceHandle.gen.cs index 0e9b81b12b..54213c139f 100644 --- a/sources/Vulkan/Vulkan/Handles/InstanceHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/InstanceHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkInstance")] -public readonly unsafe partial struct InstanceHandle +public readonly unsafe partial struct InstanceHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/MicromapHandleEXT.gen.cs b/sources/Vulkan/Vulkan/Handles/MicromapHandleEXT.gen.cs index a97f82b265..ede3548e8b 100644 --- a/sources/Vulkan/Vulkan/Handles/MicromapHandleEXT.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/MicromapHandleEXT.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkMicromapEXT")] -public readonly unsafe partial struct MicromapHandleEXT +public readonly unsafe partial struct MicromapHandleEXT : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/OpticalFlowSessionHandleNV.gen.cs b/sources/Vulkan/Vulkan/Handles/OpticalFlowSessionHandleNV.gen.cs index bca03c2e28..b4a0db4630 100644 --- a/sources/Vulkan/Vulkan/Handles/OpticalFlowSessionHandleNV.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/OpticalFlowSessionHandleNV.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkOpticalFlowSessionNV")] public readonly unsafe partial struct OpticalFlowSessionHandleNV + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/PerformanceConfigurationHandleINTEL.gen.cs b/sources/Vulkan/Vulkan/Handles/PerformanceConfigurationHandleINTEL.gen.cs index 6a9b08f502..152a66483b 100644 --- a/sources/Vulkan/Vulkan/Handles/PerformanceConfigurationHandleINTEL.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/PerformanceConfigurationHandleINTEL.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkPerformanceConfigurationINTEL")] public readonly unsafe partial struct PerformanceConfigurationHandleINTEL + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/PhysicalDeviceHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/PhysicalDeviceHandle.gen.cs index c90993f1ad..eca4c5bb5e 100644 --- a/sources/Vulkan/Vulkan/Handles/PhysicalDeviceHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/PhysicalDeviceHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkPhysicalDevice")] -public readonly unsafe partial struct PhysicalDeviceHandle +public readonly unsafe partial struct PhysicalDeviceHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/PipelineBinaryHandleKHR.gen.cs b/sources/Vulkan/Vulkan/Handles/PipelineBinaryHandleKHR.gen.cs index f265c168b3..9591593f76 100644 --- a/sources/Vulkan/Vulkan/Handles/PipelineBinaryHandleKHR.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/PipelineBinaryHandleKHR.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkPipelineBinaryKHR")] -public readonly unsafe partial struct PipelineBinaryHandleKHR +public readonly unsafe partial struct PipelineBinaryHandleKHR : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/PipelineCacheHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/PipelineCacheHandle.gen.cs index 4f36c1b0d0..9711010cb4 100644 --- a/sources/Vulkan/Vulkan/Handles/PipelineCacheHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/PipelineCacheHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkPipelineCache")] -public readonly unsafe partial struct PipelineCacheHandle +public readonly unsafe partial struct PipelineCacheHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/PipelineHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/PipelineHandle.gen.cs index 958f87e6e6..e16111cdb2 100644 --- a/sources/Vulkan/Vulkan/Handles/PipelineHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/PipelineHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkPipeline")] -public readonly unsafe partial struct PipelineHandle +public readonly unsafe partial struct PipelineHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/PipelineLayoutHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/PipelineLayoutHandle.gen.cs index 318bf3bbf3..cb281c1bfe 100644 --- a/sources/Vulkan/Vulkan/Handles/PipelineLayoutHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/PipelineLayoutHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkPipelineLayout")] -public readonly unsafe partial struct PipelineLayoutHandle +public readonly unsafe partial struct PipelineLayoutHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/PrivateDataSlotHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/PrivateDataSlotHandle.gen.cs index 05caee5e6f..443605f22b 100644 --- a/sources/Vulkan/Vulkan/Handles/PrivateDataSlotHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/PrivateDataSlotHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkPrivateDataSlot")] -public readonly unsafe partial struct PrivateDataSlotHandle +public readonly unsafe partial struct PrivateDataSlotHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/QueryPoolHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/QueryPoolHandle.gen.cs index dc596517a8..4dd7c80b63 100644 --- a/sources/Vulkan/Vulkan/Handles/QueryPoolHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/QueryPoolHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkQueryPool")] -public readonly unsafe partial struct QueryPoolHandle +public readonly unsafe partial struct QueryPoolHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/QueueHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/QueueHandle.gen.cs index e384979c17..6bd5619726 100644 --- a/sources/Vulkan/Vulkan/Handles/QueueHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/QueueHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkQueue")] -public readonly unsafe partial struct QueueHandle +public readonly unsafe partial struct QueueHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/RenderPassHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/RenderPassHandle.gen.cs index d511ff3ee9..c2de29a3c3 100644 --- a/sources/Vulkan/Vulkan/Handles/RenderPassHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/RenderPassHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkRenderPass")] -public readonly unsafe partial struct RenderPassHandle +public readonly unsafe partial struct RenderPassHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/SamplerHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/SamplerHandle.gen.cs index 82bc961d77..7ca94c5470 100644 --- a/sources/Vulkan/Vulkan/Handles/SamplerHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/SamplerHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkSampler")] -public readonly unsafe partial struct SamplerHandle +public readonly unsafe partial struct SamplerHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/SamplerYcbcrConversionHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/SamplerYcbcrConversionHandle.gen.cs index 07fef2a2b0..30dec14482 100644 --- a/sources/Vulkan/Vulkan/Handles/SamplerYcbcrConversionHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/SamplerYcbcrConversionHandle.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkSamplerYcbcrConversion")] public readonly unsafe partial struct SamplerYcbcrConversionHandle + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/SemaphoreHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/SemaphoreHandle.gen.cs index 5df2a58297..c12311a17b 100644 --- a/sources/Vulkan/Vulkan/Handles/SemaphoreHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/SemaphoreHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkSemaphore")] -public readonly unsafe partial struct SemaphoreHandle +public readonly unsafe partial struct SemaphoreHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/ShaderHandleEXT.gen.cs b/sources/Vulkan/Vulkan/Handles/ShaderHandleEXT.gen.cs index 2dcc8dedc6..6fa17c6360 100644 --- a/sources/Vulkan/Vulkan/Handles/ShaderHandleEXT.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/ShaderHandleEXT.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkShaderEXT")] -public readonly unsafe partial struct ShaderHandleEXT +public readonly unsafe partial struct ShaderHandleEXT : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/ShaderModuleHandle.gen.cs b/sources/Vulkan/Vulkan/Handles/ShaderModuleHandle.gen.cs index 9d26c0f67f..012d3f16cb 100644 --- a/sources/Vulkan/Vulkan/Handles/ShaderModuleHandle.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/ShaderModuleHandle.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkShaderModule")] -public readonly unsafe partial struct ShaderModuleHandle +public readonly unsafe partial struct ShaderModuleHandle : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/SurfaceHandleKHR.gen.cs b/sources/Vulkan/Vulkan/Handles/SurfaceHandleKHR.gen.cs index dfe65c6351..c9bebce0dd 100644 --- a/sources/Vulkan/Vulkan/Handles/SurfaceHandleKHR.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/SurfaceHandleKHR.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkSurfaceKHR")] -public readonly unsafe partial struct SurfaceHandleKHR +public readonly unsafe partial struct SurfaceHandleKHR : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/SwapchainHandleKHR.gen.cs b/sources/Vulkan/Vulkan/Handles/SwapchainHandleKHR.gen.cs index 23fbfb7afb..5ad23268fa 100644 --- a/sources/Vulkan/Vulkan/Handles/SwapchainHandleKHR.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/SwapchainHandleKHR.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkSwapchainKHR")] -public readonly unsafe partial struct SwapchainHandleKHR +public readonly unsafe partial struct SwapchainHandleKHR : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/TensorHandleARM.gen.cs b/sources/Vulkan/Vulkan/Handles/TensorHandleARM.gen.cs index 2ea1b5a006..5bba8062cb 100644 --- a/sources/Vulkan/Vulkan/Handles/TensorHandleARM.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/TensorHandleARM.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkTensorARM")] -public readonly unsafe partial struct TensorHandleARM +public readonly unsafe partial struct TensorHandleARM : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/TensorViewHandleARM.gen.cs b/sources/Vulkan/Vulkan/Handles/TensorViewHandleARM.gen.cs index 49c93f1b65..893871df46 100644 --- a/sources/Vulkan/Vulkan/Handles/TensorViewHandleARM.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/TensorViewHandleARM.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkTensorViewARM")] -public readonly unsafe partial struct TensorViewHandleARM +public readonly unsafe partial struct TensorViewHandleARM : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/ValidationCacheHandleEXT.gen.cs b/sources/Vulkan/Vulkan/Handles/ValidationCacheHandleEXT.gen.cs index 3c44743b29..2bcdc08683 100644 --- a/sources/Vulkan/Vulkan/Handles/ValidationCacheHandleEXT.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/ValidationCacheHandleEXT.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkValidationCacheEXT")] public readonly unsafe partial struct ValidationCacheHandleEXT + : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/VideoSessionHandleKHR.gen.cs b/sources/Vulkan/Vulkan/Handles/VideoSessionHandleKHR.gen.cs index 95217381bd..084dc88d43 100644 --- a/sources/Vulkan/Vulkan/Handles/VideoSessionHandleKHR.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/VideoSessionHandleKHR.gen.cs @@ -9,7 +9,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkVideoSessionKHR")] -public readonly unsafe partial struct VideoSessionHandleKHR +public readonly unsafe partial struct VideoSessionHandleKHR : IEquatable { public readonly void* Handle; diff --git a/sources/Vulkan/Vulkan/Handles/VideoSessionParametersHandleKHR.gen.cs b/sources/Vulkan/Vulkan/Handles/VideoSessionParametersHandleKHR.gen.cs index a1b97f68bf..6b07c0fe85 100644 --- a/sources/Vulkan/Vulkan/Handles/VideoSessionParametersHandleKHR.gen.cs +++ b/sources/Vulkan/Vulkan/Handles/VideoSessionParametersHandleKHR.gen.cs @@ -10,6 +10,7 @@ namespace Silk.NET.Vulkan; [NativeName("VkVideoSessionParametersKHR")] public readonly unsafe partial struct VideoSessionParametersHandleKHR + : IEquatable { public readonly void* Handle; diff --git a/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_Field.verified.txt b/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_Field.verified.txt new file mode 100644 index 0000000000..bc67d17fc4 --- /dev/null +++ b/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_Field.verified.txt @@ -0,0 +1,24 @@ +// SDL_BlendMode.gen.cs +[NativeName("SDL_BlendMode")] +public enum SDL_BlendMode : uint +{ + SDL_BLENDMODE_NONE = 0x00000000U, + SDL_BLENDMODE_BLEND = 0x00000001U, + SDL_BLENDMODE_BLEND_PREMULTIPLIED = 0x00000010U, + SDL_BLENDMODE_ADD = 0x00000002U, + SDL_BLENDMODE_ADD_PREMULTIPLIED = 0x00000020U, + SDL_BLENDMODE_MOD = 0x00000004U, + SDL_BLENDMODE_MUL = 0x00000008U, + SDL_BLENDMODE_INVALID = 0x7FFFFFFFU +} + +// Sdl.gen.cs +public unsafe partial struct Sdl +{ +} + +public class Test +{ + [NativeTypeName("SDL_BlendMode")] + public SDL_BlendMode Blend; +} diff --git a/tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.SuccessfullyExtractsCStyleEnumConstants_MethodParameter.verified.txt b/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_MethodParameter.verified.txt similarity index 95% rename from tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.SuccessfullyExtractsCStyleEnumConstants_MethodParameter.verified.txt rename to tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_MethodParameter.verified.txt index 6381c82a87..b3ec17bbdb 100644 --- a/tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.SuccessfullyExtractsCStyleEnumConstants_MethodParameter.verified.txt +++ b/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_MethodParameter.verified.txt @@ -1,4 +1,5 @@ // SDL_BlendMode.gen.cs +[NativeName("SDL_BlendMode")] public enum SDL_BlendMode : uint { SDL_BLENDMODE_NONE = 0x00000000U, diff --git a/tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.SuccessfullyExtractsCStyleEnumConstants_Pointer.verified.txt b/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_Pointer.verified.txt similarity index 95% rename from tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.SuccessfullyExtractsCStyleEnumConstants_Pointer.verified.txt rename to tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_Pointer.verified.txt index 3ff556a066..c28e8ef78d 100644 --- a/tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.SuccessfullyExtractsCStyleEnumConstants_Pointer.verified.txt +++ b/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_Pointer.verified.txt @@ -1,4 +1,5 @@ // SDL_BlendMode.gen.cs +[NativeName("SDL_BlendMode")] public enum SDL_BlendMode : uint { SDL_BLENDMODE_NONE = 0x00000000U, diff --git a/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_ReturnType.verified.txt b/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_ReturnType.verified.txt new file mode 100644 index 0000000000..95eb0696e8 --- /dev/null +++ b/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.SuccessfullyExtractsCStyleEnumConstants_ReturnType.verified.txt @@ -0,0 +1,21 @@ +// SDL_BlendMode.gen.cs +[NativeName("SDL_BlendMode")] +public enum SDL_BlendMode : uint +{ + SDL_BLENDMODE_NONE = 0x00000000U, + SDL_BLENDMODE_BLEND = 0x00000001U, + SDL_BLENDMODE_BLEND_PREMULTIPLIED = 0x00000010U, + SDL_BLENDMODE_ADD = 0x00000002U, + SDL_BLENDMODE_ADD_PREMULTIPLIED = 0x00000020U, + SDL_BLENDMODE_MOD = 0x00000004U, + SDL_BLENDMODE_MUL = 0x00000008U, + SDL_BLENDMODE_INVALID = 0x7FFFFFFFU +} + +// Sdl.gen.cs +public unsafe partial struct Sdl +{ + [DllImport("SDL3", ExactSpelling = true)] + [return: NativeTypeName("SDL_BlendMode")] + public static extern SDL_BlendMode SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor, SDL_BlendFactor dstColorFactor, SDL_BlendOperation colorOperation, SDL_BlendFactor srcAlphaFactor, SDL_BlendFactor dstAlphaFactor, SDL_BlendOperation alphaOperation); +} diff --git a/tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.cs b/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.cs similarity index 74% rename from tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.cs rename to tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.cs index d6e4d373d6..102fe5d45b 100644 --- a/tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.cs +++ b/tests/SilkTouch/SilkTouch/ExtractEnumConstantsTests.cs @@ -1,14 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Extensions.Logging.Abstractions; using Silk.NET.SilkTouch.Mods; namespace Silk.NET.SilkTouch.UnitTests; -public class ExtractNestedTypingTests +public class ExtractEnumConstantsTests { - static ExtractNestedTypingTests() + static ExtractEnumConstantsTests() { if (!VerifyDiffPlex.Initialized) { @@ -16,83 +15,6 @@ static ExtractNestedTypingTests() } } - [Test] - public async Task SuccessfullyExtractsNestedInlineArray() - { - var inputDocName = "VkPerformanceCounterDescriptionARM.gen.cs"; - var project = TestUtils - .CreateTestProject() - .AddDocument( - inputDocName, - """ - namespace Silk.NET.Vulkan; - - public struct VkPerformanceCounterDescriptionARM - { - [NativeTypeName("char[256]")] - public _name_e__FixedBuffer name; - - [InlineArray(256)] - public struct _name_e__FixedBuffer - { - public sbyte e0; - } - } - """, - // ExtractNestedTyping requires the file path to be set and that the document is under a subfolder - filePath: $"Vulkan/{inputDocName}" - ) - .Project; - - var context = new DummyModContext() { SourceProject = project }; - - var extractNestedTyping = new ExtractNestedTyping(NullLogger.Instance); - - await extractNestedTyping.ExecuteAsync(context); - - // The nested struct should be extracted and named as VkPerformanceCounterDescriptionARMname - await TestUtils.VerifyDocumentsAsync(context.SourceProject.Documents); - } - - [Test] - public async Task SuccessfullyExtractsFunctionPointer() - { - var inputDocName = "VkDebugReportCallbackCreateInfoEXT.gen.cs"; - var project = TestUtils - .CreateTestProject() - .AddDocument( - inputDocName, - """ - public unsafe partial struct VkDebugReportCallbackCreateInfoEXT - { - [NativeTypeName("PFN_vkDebugReportCallbackEXT")] - public delegate* unmanaged< - uint, - VkDebugReportObjectTypeEXT, - ulong, - nuint, - int, - sbyte*, - sbyte*, - void*, - uint> pfnCallback; - } - """, - // ExtractNestedTyping requires the file path to be set and that the document is under a subfolder - filePath: $"Vulkan/{inputDocName}" - ) - .Project; - - var context = new DummyModContext() { SourceProject = project }; - - var extractNestedTyping = new ExtractNestedTyping(NullLogger.Instance); - - await extractNestedTyping.ExecuteAsync(context); - - // The function pointer should be extracted as both a struct and a delegate - await TestUtils.VerifyDocumentsAsync(context.SourceProject.Documents); - } - [Test] public async Task SuccessfullyExtractsCStyleEnumConstants_Field() { @@ -135,16 +57,16 @@ public class Test public uint Blend; } """, - // ExtractNestedTyping requires the file path to be set and that the document is under a subfolder + // ExtractEnumConstants requires the file path to be set and that the document is under a subfolder filePath: $"SDL3/{inputDocName}" ) .Project; var context = new DummyModContext() { SourceProject = project }; - var extractNestedTyping = new ExtractNestedTyping(NullLogger.Instance); + var extractEnumConstants = new ExtractEnumConstants(); - await extractNestedTyping.ExecuteAsync(context); + await extractEnumConstants.ExecuteAsync(context); // The constants should have been moved from the Sdl clas to the SDL_BlendMode enum await TestUtils.VerifyDocumentsAsync(context.SourceProject.Documents); @@ -200,7 +122,7 @@ public static extern byte SDL_SetSurfaceBlendMode( var context = new DummyModContext() { SourceProject = project }; - var extractNestedTyping = new ExtractNestedTyping(NullLogger.Instance); + var extractNestedTyping = new ExtractEnumConstants(); await extractNestedTyping.ExecuteAsync(context); @@ -258,7 +180,7 @@ public static extern byte SDL_GetSurfaceBlendMode( var context = new DummyModContext() { SourceProject = project }; - var extractNestedTyping = new ExtractNestedTyping(NullLogger.Instance); + var extractNestedTyping = new ExtractEnumConstants(); await extractNestedTyping.ExecuteAsync(context); @@ -320,7 +242,7 @@ SDL_BlendOperation alphaOperation var context = new DummyModContext() { SourceProject = project }; - var extractNestedTyping = new ExtractNestedTyping(NullLogger.Instance); + var extractNestedTyping = new ExtractEnumConstants(); await extractNestedTyping.ExecuteAsync(context); diff --git a/tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.SuccessfullyExtractsFunctionPointer.verified.txt b/tests/SilkTouch/SilkTouch/ExtractFunctionPointersTests.SuccessfullyExtractsFunctionPointer.verified.txt similarity index 100% rename from tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.SuccessfullyExtractsFunctionPointer.verified.txt rename to tests/SilkTouch/SilkTouch/ExtractFunctionPointersTests.SuccessfullyExtractsFunctionPointer.verified.txt diff --git a/tests/SilkTouch/SilkTouch/ExtractFunctionPointersTests.cs b/tests/SilkTouch/SilkTouch/ExtractFunctionPointersTests.cs new file mode 100644 index 0000000000..0f53b33375 --- /dev/null +++ b/tests/SilkTouch/SilkTouch/ExtractFunctionPointersTests.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Logging.Abstractions; +using Silk.NET.SilkTouch.Mods; + +namespace Silk.NET.SilkTouch.UnitTests; + +public class ExtractFunctionPointersTests +{ + static ExtractFunctionPointersTests() + { + if (!VerifyDiffPlex.Initialized) + { + VerifyDiffPlex.Initialize(); + } + } + + [Test] + public async Task SuccessfullyExtractsFunctionPointer() + { + var inputDocName = "VkDebugReportCallbackCreateInfoEXT.gen.cs"; + var project = TestUtils + .CreateTestProject() + .AddDocument( + inputDocName, + """ + public unsafe partial struct VkDebugReportCallbackCreateInfoEXT + { + [NativeTypeName("PFN_vkDebugReportCallbackEXT")] + public delegate* unmanaged< + uint, + VkDebugReportObjectTypeEXT, + ulong, + nuint, + int, + sbyte*, + sbyte*, + void*, + uint> pfnCallback; + } + """, + // ExtractFunctionPointers requires the file path to be set and that the document is under a subfolder + filePath: $"Vulkan/{inputDocName}" + ) + .Project; + + var context = new DummyModContext() { SourceProject = project }; + + var extractFunctionPointers = new ExtractFunctionPointers( + NullLogger.Instance + ); + + await extractFunctionPointers.ExecuteAsync(context); + + // The function pointer should be extracted as both a struct and a delegate + await TestUtils.VerifyDocumentsAsync(context.SourceProject.Documents); + } +} diff --git a/tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.SuccessfullyExtractsNestedInlineArray.verified.txt b/tests/SilkTouch/SilkTouch/ExtractNestedTypesTests.SuccessfullyExtractsNestedInlineArray.verified.txt similarity index 100% rename from tests/SilkTouch/SilkTouch/ExtractNestedTypingTests.SuccessfullyExtractsNestedInlineArray.verified.txt rename to tests/SilkTouch/SilkTouch/ExtractNestedTypesTests.SuccessfullyExtractsNestedInlineArray.verified.txt diff --git a/tests/SilkTouch/SilkTouch/ExtractNestedTypesTests.cs b/tests/SilkTouch/SilkTouch/ExtractNestedTypesTests.cs new file mode 100644 index 0000000000..f8c0f8cab0 --- /dev/null +++ b/tests/SilkTouch/SilkTouch/ExtractNestedTypesTests.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Silk.NET.SilkTouch.Mods; + +namespace Silk.NET.SilkTouch.UnitTests; + +public class ExtractNestedTypesTests +{ + static ExtractNestedTypesTests() + { + if (!VerifyDiffPlex.Initialized) + { + VerifyDiffPlex.Initialize(); + } + } + + [Test] + public async Task SuccessfullyExtractsNestedInlineArray() + { + var inputDocName = "VkPerformanceCounterDescriptionARM.gen.cs"; + var project = TestUtils + .CreateTestProject() + .AddDocument( + inputDocName, + """ + namespace Silk.NET.Vulkan; + + public struct VkPerformanceCounterDescriptionARM + { + [NativeTypeName("char[256]")] + public _name_e__FixedBuffer name; + + [InlineArray(256)] + public struct _name_e__FixedBuffer + { + public sbyte e0; + } + } + """, + // ExtractNestedTyping requires the file path to be set and that the document is under a subfolder + filePath: $"Vulkan/{inputDocName}" + ) + .Project; + + var context = new DummyModContext() { SourceProject = project }; + + var extractNestedTyping = new ExtractNestedTypes(); + + await extractNestedTyping.ExecuteAsync(context); + + // The nested struct should be extracted and named as VkPerformanceCounterDescriptionARMname + await TestUtils.VerifyDocumentsAsync(context.SourceProject.Documents); + } +} diff --git a/tests/SilkTouch/SilkTouch/TransformHandlesTests.DoesNotTransform_WhenNotAllReferencesAreThroughPointers.verified.txt b/tests/SilkTouch/SilkTouch/TransformHandlesTests.DoesNotTransform_WhenNotAllReferencesAreThroughPointers.verified.txt new file mode 100644 index 0000000000..9d3bd3862f --- /dev/null +++ b/tests/SilkTouch/SilkTouch/TransformHandlesTests.DoesNotTransform_WhenNotAllReferencesAreThroughPointers.verified.txt @@ -0,0 +1,9 @@ +// Vk.gen.cs +public struct VkInstance_T +{ +} + +public class Vk +{ + public static extern VkResult vkCreateInstance(VkInstance_T pInstance, VkInstance_T* pInstance, VkInstance_T** pInstance); +} diff --git a/tests/SilkTouch/SilkTouch/TransformHandlesTests.SuccessfullyTransformsHandleType_NoDsl.verified.txt b/tests/SilkTouch/SilkTouch/TransformHandlesTests.SuccessfullyTransformsHandleType_NoDsl.verified.txt new file mode 100644 index 0000000000..d8c9e87daf --- /dev/null +++ b/tests/SilkTouch/SilkTouch/TransformHandlesTests.SuccessfullyTransformsHandleType_NoDsl.verified.txt @@ -0,0 +1,22 @@ +// Vk.gen.cs +[NativeName("VkInstance_T")] +[NameAffix("Suffix", "HandleType", "Handle")] +public readonly unsafe partial struct VkInstance_T : IEquatable +{ + public readonly void* Handle; + public VkInstance_T(void* handle) + { + Handle = handle; + } + + public bool Equals(VkInstance_T other) => Handle == other.Handle; + public override bool Equals(object? obj) => obj is VkInstance_T other && Equals(other); + public override int GetHashCode() => HashCode.Combine((nuint)Handle); + public static bool operator ==(VkInstance_T left, VkInstance_T right) => left.Equals(right); + public static bool operator !=(VkInstance_T left, VkInstance_T right) => !left.Equals(right); +} + +public class Vk +{ + public static extern VkResult vkCreateInstance(VkInstance_T pInstance, VkInstance_T* pInstance); +} diff --git a/tests/SilkTouch/SilkTouch/TransformHandlesTests.SuccessfullyTransformsHandleType_WithDsl.verified.txt b/tests/SilkTouch/SilkTouch/TransformHandlesTests.SuccessfullyTransformsHandleType_WithDsl.verified.txt new file mode 100644 index 0000000000..a9b4efe4ef --- /dev/null +++ b/tests/SilkTouch/SilkTouch/TransformHandlesTests.SuccessfullyTransformsHandleType_WithDsl.verified.txt @@ -0,0 +1,26 @@ +// Vk.gen.cs +[NativeName("VkInstance_T")] +[NameAffix("Suffix", "HandleType", "Handle")] +public readonly unsafe partial struct VkInstance_T : IEquatable +{ + public readonly void* Handle; + public VkInstance_T(void* handle) + { + Handle = handle; + } + + public bool Equals(VkInstance_T other) => Handle == other.Handle; + public override bool Equals(object? obj) => obj is VkInstance_T other && Equals(other); + public override int GetHashCode() => HashCode.Combine((nuint)Handle); + public static bool operator ==(VkInstance_T left, VkInstance_T right) => left.Equals(right); + public static bool operator !=(VkInstance_T left, VkInstance_T right) => !left.Equals(right); + public bool Equals(NullPtr _) => Handle is null; + public static bool operator ==(VkInstance_T left, NullPtr right) => left.Equals(right); + public static bool operator !=(VkInstance_T left, NullPtr right) => !left.Equals(right); + public static implicit operator VkInstance_T(NullPtr _) => default; +} + +public class Vk +{ + public static extern VkResult vkCreateInstance(VkInstance_T pInstance, VkInstance_T* pInstance); +} diff --git a/tests/SilkTouch/SilkTouch/TransformHandlesTests.cs b/tests/SilkTouch/SilkTouch/TransformHandlesTests.cs new file mode 100644 index 0000000000..6e8ffb6154 --- /dev/null +++ b/tests/SilkTouch/SilkTouch/TransformHandlesTests.cs @@ -0,0 +1,127 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Logging.Abstractions; +using Silk.NET.SilkTouch.Mods; + +namespace Silk.NET.SilkTouch.UnitTests; + +public class TransformHandlesTests +{ + static TransformHandlesTests() + { + if (!VerifyDiffPlex.Initialized) + { + VerifyDiffPlex.Initialize(); + } + } + + [Test] + public async Task SuccessfullyTransformsHandleType_NoDsl() + { + var inputDocName = "Vk.gen.cs"; + var project = TestUtils + .CreateTestProject() + .AddDocument( + inputDocName, + """ + public struct VkInstance_T { } + + public class Vk + { + public static extern VkResult vkCreateInstance( + VkInstance_T* pInstance, + VkInstance_T** pInstance + ); + } + """ + ) + .Project; + + var context = new DummyModContext() { SourceProject = project }; + + var transformHandles = new TransformHandles( + new DummyOptions( + new TransformHandles.Config() { UseDsl = false } + ), + NullLogger.Instance + ); + + await transformHandles.ExecuteAsync(context); + + await TestUtils.VerifyDocumentsAsync(context.SourceProject.Documents); + } + + [Test] + public async Task SuccessfullyTransformsHandleType_WithDsl() + { + var inputDocName = "Vk.gen.cs"; + var project = TestUtils + .CreateTestProject() + .AddDocument( + inputDocName, + """ + public struct VkInstance_T { } + + public class Vk + { + public static extern VkResult vkCreateInstance( + VkInstance_T* pInstance, + VkInstance_T** pInstance + ); + } + """ + ) + .Project; + + var context = new DummyModContext() { SourceProject = project }; + + var transformHandles = new TransformHandles( + new DummyOptions( + new TransformHandles.Config() { UseDsl = true } + ), + NullLogger.Instance + ); + + await transformHandles.ExecuteAsync(context); + + await TestUtils.VerifyDocumentsAsync(context.SourceProject.Documents); + } + + [Test] + public async Task DoesNotTransform_WhenNotAllReferencesAreThroughPointers() + { + var inputDocName = "Vk.gen.cs"; + var project = TestUtils + .CreateTestProject() + .AddDocument( + inputDocName, + """ + public struct VkInstance_T { } + + public class Vk + { + public static extern VkResult vkCreateInstance( + VkInstance_T pInstance, + VkInstance_T* pInstance, + VkInstance_T** pInstance + ); + } + """ + ) + .Project; + + var context = new DummyModContext() { SourceProject = project }; + + var transformHandles = new TransformHandles( + new DummyOptions( + new TransformHandles.Config() { UseDsl = true } + ), + NullLogger.Instance + ); + + await transformHandles.ExecuteAsync(context); + + await TestUtils.VerifyDocumentsAsync(context.SourceProject.Documents); + } +}