Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public LLVMErrorTypeId TypeId
}

return LazyMessage.IsValueCreated
? LLVMGetStringErrorTypeId()
? LLVMGetStringErrorTypeId() // string retrieved already so the "type" is known.
: LLVMErrorTypeId.FromABI(LLVMGetErrorTypeId(DangerousGetHandle()));

[DllImport( LibraryName )]
Expand Down Expand Up @@ -135,7 +135,7 @@ public static LLVMErrorRef Create( LazyEncodedString errMsg )
/// In all other cases a fully wrapped handle (<see cref="LLVMErrorRef"/>) is used via <see cref="Create(LazyEncodedString)"/>.
/// </para>
/// </remarks>
public static unsafe nint CreateForNativeOut( LazyEncodedString errMsg )
public static nint CreateForNativeOut( LazyEncodedString errMsg )
{
unsafe
{
Expand All @@ -152,6 +152,14 @@ public static unsafe nint CreateForNativeOut( LazyEncodedString errMsg )
static unsafe extern nint /*LLVMErrorRef*/ LLVMCreateStringError( byte* ErrMsg );
}

/// <summary>Create a new <see cref="LLVMErrorRef"/> as <see cref="nint"/> from <see cref="Exception.Message"/></summary>
/// <param name="ex">Exceotion to get the error message from</param>
/// <inheritdoc cref="CreateForNativeOut(LazyEncodedString)"/>
public static nint CreateForNativeOut( Exception ex)
{
return CreateForNativeOut(ex.Message);
}

public void Dispose()
{
// if a message was previously realized, dispose of it now.
Expand Down Expand Up @@ -180,19 +188,6 @@ public static LLVMErrorRef FromABI( nint abiValue )
return new(abiValue);
}

private LLVMErrorTypeId LazyGetTypeId()
{
// NOTE: Native API will fail (undocumented) if error message already retrieved.
// This causes a crash in a debugger trying to show this property as ToString()
// is already called.
return LazyMessage.IsValueCreated ? default : LLVMErrorTypeId.FromABI(LLVMGetErrorTypeId(DangerousGetHandle()));

[DllImport( LibraryName )]
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
[SuppressMessage( "Interoperability", "SYSLIB1054:Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time", Justification = "Signature is P/Invoke ready" )]
static extern /*LLVMErrorTypeId*/nint LLVMGetErrorTypeId(/*LLVMErrorRef*/ nint Err );
}

private ErrorMessageString LazyGetMessage( )
{
if(IsNull)
Expand Down
4 changes: 2 additions & 2 deletions src/Interop/Ubiquity.NET.Llvm.Interop/ABI/llvm-c/Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -421,15 +421,15 @@ public static partial class Core

[LibraryImport( LibraryName )]
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
public static unsafe partial void LLVMContextSetDiagnosticHandler( LLVMContextRefAlias C, LLVMDiagnosticHandler Handler, nint DiagnosticContext );
public static unsafe partial void LLVMContextSetDiagnosticHandler( LLVMContextRefAlias C, LLVMDiagnosticHandler Handler, void* DiagnosticContext );

[LibraryImport( LibraryName )]
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
public static unsafe partial LLVMDiagnosticHandler LLVMContextGetDiagnosticHandler( LLVMContextRefAlias C );

[LibraryImport( LibraryName )]
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
public static unsafe partial nint LLVMContextGetDiagnosticContext( LLVMContextRefAlias C );
public static unsafe partial void* LLVMContextGetDiagnosticContext( LLVMContextRefAlias C );

[LibraryImport( LibraryName )]
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ namespace Ubiquity.NET.Llvm.Interop.ABI.llvm_c
// Misplaced using directive; It isn't misplaced - tooling is too brain dead to know the difference between an alias and a using directive
#pragma warning disable IDE0065, SA1200, SA1135
using unsafe LLVMMemoryManagerAllocateCodeSectionCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, nuint /*Size*/, uint /*Alignment*/, uint /*SectionID*/, byte* /*SectionName*/, byte* /*retVal*/>;
using unsafe LLVMMemoryManagerAllocateDataSectionCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, nuint /*Size*/, uint /*Alignment*/, uint /*SectionID*/, byte* /*SectionName*/, bool /*IsReadOnly*/, byte* /*retVal*/>;
using unsafe LLVMMemoryManagerAllocateDataSectionCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, nuint /*Size*/, uint /*Alignment*/, uint /*SectionID*/, byte* /*SectionName*/, /*LLVMBool*/ Int32 /*IsReadOnly*/, byte* /*retVal*/>;
using unsafe LLVMMemoryManagerDestroyCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, void /*retVal*/ >;
using unsafe LLVMMemoryManagerFinalizeMemoryCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, byte** /*ErrMsg*/, bool /*retVal*/>;
using unsafe LLVMMemoryManagerFinalizeMemoryCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, byte** /*ErrMsg*/, /*LLVMBool*/ Int32 /*retVal*/>;
#pragma warning restore IDE0065, SA1200, SA1135

[StructLayout( LayoutKind.Sequential )]
Expand Down
4 changes: 2 additions & 2 deletions src/Interop/Ubiquity.NET.Llvm.Interop/ABI/llvm-c/Orc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ public static unsafe partial LLVMOrcSymbolStringPoolEntryRef LLVMOrcExecutionSes
LazyEncodedString Name
);

[Experimental( "LLVM001" )]
[Experimental( "LLVMEXP001" )]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void LLVMOrcExecutionSessionLookup(
LLVMOrcExecutionSessionRef ES,
Expand All @@ -223,7 +223,7 @@ public static unsafe void LLVMOrcExecutionSessionLookup(

[LibraryImport( LibraryName )]
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
[Experimental("LLVMEXP001")]
[Experimental("LLVMEXP002")]
private static unsafe partial void LLVMOrcExecutionSessionLookup(
LLVMOrcExecutionSessionRef ES,
LLVMOrcLookupKind K,
Expand Down
4 changes: 2 additions & 2 deletions src/Interop/Ubiquity.NET.Llvm.Interop/ABI/llvm-c/OrcEE.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ namespace Ubiquity.NET.Llvm.Interop.ABI.llvm_c
// Misplaced using directive; It isn't misplaced - tooling is too brain dead to know the difference between an alias and a using directive
#pragma warning disable IDE0065, SA1200, SA1135
using unsafe LLVMMemoryManagerAllocateCodeSectionCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, nuint /*Size*/, uint /*Alignment*/, uint /*SectionID*/, byte* /*SectionName*/, byte* /*retVal*/>;
using unsafe LLVMMemoryManagerAllocateDataSectionCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, nuint /*Size*/, uint /*Alignment*/, uint /*SectionID*/, byte* /*SectionName*/, bool /*IsReadOnly*/, byte* /*retVal*/>;
using unsafe LLVMMemoryManagerAllocateDataSectionCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, nuint /*Size*/, uint /*Alignment*/, uint /*SectionID*/, byte* /*SectionName*/, /*LLVMBool*/ Int32 /*IsReadOnly*/, byte* /*retVal*/>;
using unsafe LLVMMemoryManagerCreateContextCallback = delegate* unmanaged[Cdecl]< void* /*CtxCtx*/, void* /*retVal*/>;
using unsafe LLVMMemoryManagerDestroyCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, void /*retVal*/ >;
using unsafe LLVMMemoryManagerFinalizeMemoryCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, byte** /*ErrMsg*/, bool /*retVal*/>;
using unsafe LLVMMemoryManagerFinalizeMemoryCallback = delegate* unmanaged[Cdecl]< void* /*Opaque*/, byte** /*ErrMsg*/, /*LLVMBool*/ Int32 /*retVal*/>;
using unsafe LLVMMemoryManagerNotifyTerminatingCallback = delegate* unmanaged[Cdecl]< void* /*CtxCtx*/, void /*retVal*/>;
#pragma warning restore IDE0065, SA1200, SA1135

Expand Down
1 change: 0 additions & 1 deletion src/Ubiquity.NET.CommandLine.UT/RawApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the Apache-2.0 WITH LLVM-exception license. See the LICENSE.md file in the project root for full license information.

using System.CommandLine;
using System.CommandLine.Help;

using Microsoft.VisualStudio.TestTools.UnitTesting;

Expand Down
45 changes: 10 additions & 35 deletions src/Ubiquity.NET.CommandLine/ParseResultExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,23 @@
using System.CommandLine;
using System.CommandLine.Help;
using System.CommandLine.Parsing;
using System.Diagnostics.CodeAnalysis;
using System.Linq;

namespace Ubiquity.NET.CommandLine
{
// This does NOT use the new C# 14 extension syntax due to several reasons
// 1) Code lens does not work https://github.com/dotnet/roslyn/issues/79006 [Sadly marked as "not planned" - e.g., dead-end]
// 2) MANY analyzers get things wrong and need to be supressed (CA1000, CA1034, and many others [SAxxxx])
// 3) Many tools (like docfx don't support the new syntax yet)
// 4) No clear support for Caller* attributes ([CallerArgumentExpression(...)]).
//
// Bottom line it's a good idea with an incomplete implementation lacking support
// in the overall ecosystem. Don't use it unless you absolutely have to until all
// of that is sorted out.

/// <summary>Utility extension methods for command line parsing</summary>
[SuppressMessage( "Design", "CA1034:Nested types should not be visible", Justification = "BS, extension" )]
[SuppressMessage( "Performance", "CA1822:Mark members as static", Justification = "BS, Extension" )]
public static class ParseResultExtensions
{
#if DOCFX_BUILD_SUPPORTS_EXTENSION_KEYWORD
extension(ParseResult self)
{
/// <summary>Gets a value indicating whether <paramref name="self"/> has any errors</summary>
public bool HasErrors => self.Errors.Count > 0;

public HelpOption? HelpOption
{
get
{
var helpOptions = from r in self.CommandResult.RecurseWhileNotNull(r => r.Parent as CommandResult)
from o in r.Command.Options.OfType<HelpOption>()
select o;

return helpOptions.FirstOrDefault();
}
}

public VersionOption? VersionOption
{
get
{
var versionOptions = from r in self.CommandResult.RecurseWhileNotNull(r => r.Parent as CommandResult)
from o in r.Command.Options.OfType<VersionOption>()
select o;

return versionOptions.FirstOrDefault();
}
}
}
#else
/// <summary>Gets a value indicating whether <paramref name="self"/> has any errors</summary>
/// <param name="self">Result to test for errors</param>
/// <returns>value indicating whether <paramref name="self"/> has any errors</returns>
Expand Down Expand Up @@ -75,7 +51,6 @@ from o in r.Command.Options.OfType<VersionOption>()

return versionOptions.FirstOrDefault();
}
#endif

// shamelessly "borrowed" from: https://github.com/dotnet/dotnet/blob/8c7b3dcd2bd657c11b12973f1214e7c3c616b174/src/command-line-api/src/System.CommandLine/Help/HelpBuilderExtensions.cs#L42
internal static IEnumerable<T> RecurseWhileNotNull<T>( this T? source, Func<T, T?> next )
Expand Down
22 changes: 16 additions & 6 deletions src/Ubiquity.NET.Extensions/FluentValidationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,31 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.CompilerServices;

namespace Ubiquity.NET.Extensions
{
// This does NOT use the new C# 14 extension syntax due to several reasons
// 1) Code lens does not work https://github.com/dotnet/roslyn/issues/79006 [Sadly, marked as "not planned" - e.g., dead-end]
// 2) MANY analyzers get things wrong and need to be supressed (CA1000, CA1034, and many others [SAxxxx])
// 3) Many tools (like docfx) don't support the new syntax yet and it isn't clear if they will in the future.
// 4) No clear support for Caller* attributes ([CallerArgumentExpression(...)]).
//
// Bottom line it's a good idea with an incomplete implementation lacking support
// in the overall ecosystem. Don't use it unless you absolutely have to until all
// of that is sorted out.

/// <summary>Extension class to provide Fluent validation of arguments</summary>
/// <remarks>
/// These are similar to many of the built-in support checks except that
/// they use a `Fluent' style to allow validation of parameters used as inputs
/// to other functions that ultimately produce parameters for a base constructor.
/// They also serve to provide validation when using body expressions for property
/// method implementations etc...
/// method implementations etc... Though the C# 14 <c>field</c> keyword makes that
/// use mostly a moot point.
/// </remarks>
public static class FluentValidationExtensions
{
// NOTE: These DO NOT use the new `extension` keyword syntax as it is not clear
// how CallerArgumentExpression is supposed to be used for those...

/// <summary>Throws an exception if <paramref name="obj"/> is <see langword="null"/></summary>
/// <typeparam name="T">Type of reference parameter to test for</typeparam>
/// <param name="obj">Instance to test</param>
Expand Down Expand Up @@ -72,9 +79,12 @@ public static T ThrowIfNotDefined<T>( this T self, [CallerArgumentExpression( na
where T : struct, Enum
{
ArgumentNullException.ThrowIfNull(self, exp);

// TODO: Move the exception message to a resource for globalization
// This matches the overloaded constructor version but allows for reporting enums with non-int underlying type.
return Enum.IsDefined( typeof(T), self )
? self
: throw new InvalidEnumArgumentException(exp);
: throw new InvalidEnumArgumentException($"The value of argument '{exp}' ({self}) is invalid for Enum of type '{typeof(T)}'");
}
}
}
46 changes: 0 additions & 46 deletions src/Ubiquity.NET.InteropHelpers/MarshalGCHandle.cs

This file was deleted.

Loading
Loading