mirror of
https://github.com/Sarsoo/csbindgen.git
synced 2024-12-23 06:56:27 +00:00
complete GroupedNativeMethodsGenerator
This commit is contained in:
parent
d6054fe092
commit
168936d9ff
@ -1,71 +0,0 @@
|
|||||||
using Microsoft.CodeAnalysis;
|
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
||||||
|
|
||||||
namespace GroupedNativeMethodsGenerator;
|
|
||||||
|
|
||||||
[Generator(LanguageNames.CSharp)]
|
|
||||||
public partial class GroupedNativeMethodsGenerator : IIncrementalGenerator
|
|
||||||
{
|
|
||||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
|
||||||
{
|
|
||||||
context.RegisterPostInitializationOutput(ctx =>
|
|
||||||
{
|
|
||||||
ctx.AddSource("GroupedNativeMethodsGenerator.Attribute.cs", """
|
|
||||||
namespace GroupedNativeMethodsGenerator
|
|
||||||
{
|
|
||||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
|
||||||
internal sealed class GroupedNativeMethodsAttribute : Attribute
|
|
||||||
{
|
|
||||||
public string RemovePrefix { get; set; } = "";
|
|
||||||
public bool RemoveUntilTypeName { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>Fix method name as C# Style, e.g.: foo_bar_baz() -> FooBarBaz()</summary>
|
|
||||||
public bool FixMethodName { get; set; } = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
""");
|
|
||||||
});
|
|
||||||
|
|
||||||
var source = context.SyntaxProvider.ForAttributeWithMetadataName("GroupedNativeMethodsGenerator.GroupedNativeMethodsAttribute",
|
|
||||||
(node, token) => node is ClassDeclarationSyntax,
|
|
||||||
(ctx, token) => ctx);
|
|
||||||
|
|
||||||
context.RegisterSourceOutput(source, Emit);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Emit(SourceProductionContext context, GeneratorAttributeSyntaxContext source)
|
|
||||||
{
|
|
||||||
var typeSymbol = (INamedTypeSymbol)source.TargetSymbol;
|
|
||||||
var typeNode = (TypeDeclarationSyntax)source.TargetNode;
|
|
||||||
|
|
||||||
var ns = typeSymbol.ContainingNamespace.IsGlobalNamespace
|
|
||||||
? ""
|
|
||||||
: $"namespace {typeSymbol.ContainingNamespace};";
|
|
||||||
|
|
||||||
var fullType = typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
|
|
||||||
.Replace("global::", "")
|
|
||||||
.Replace("<", "_")
|
|
||||||
.Replace(">", "_");
|
|
||||||
|
|
||||||
var methods = typeSymbol.GetMembers()
|
|
||||||
.OfType<IMethodSymbol>();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// context.AddSource($"{fullType}.SampleGenerator.g.cs", code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO:...
|
|
||||||
public static class DiagnosticDescriptors
|
|
||||||
{
|
|
||||||
const string Category = "SampleGenerator";
|
|
||||||
|
|
||||||
public static readonly DiagnosticDescriptor ExistsOverrideToString = new(
|
|
||||||
id: "SAMPLE001",
|
|
||||||
title: "ToString override",
|
|
||||||
messageFormat: "The GenerateToString class '{0}' has ToString override but it is not allowed.",
|
|
||||||
category: Category,
|
|
||||||
defaultSeverity: DiagnosticSeverity.Error,
|
|
||||||
isEnabledByDefault: true);
|
|
||||||
}
|
|
168
GroupedNativeMethodsGenerator/GroupedNativeMethodsGenerator.cs
Normal file
168
GroupedNativeMethodsGenerator/GroupedNativeMethodsGenerator.cs
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace GroupedNativeMethodsGenerator;
|
||||||
|
|
||||||
|
[Generator(LanguageNames.CSharp)]
|
||||||
|
public partial class GroupedNativeMethodsGenerator : IIncrementalGenerator
|
||||||
|
{
|
||||||
|
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
context.RegisterPostInitializationOutput(ctx =>
|
||||||
|
{
|
||||||
|
ctx.AddSource("GroupedNativeMethodsGenerator.Attribute.cs", """
|
||||||
|
namespace GroupedNativeMethodsGenerator
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||||
|
internal sealed class GroupedNativeMethodsAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string RemovePrefix { get; }
|
||||||
|
public string RemoveSuffix { get; }
|
||||||
|
public bool RemoveUntilTypeName { get; }
|
||||||
|
public bool FixMethodName { get; }
|
||||||
|
|
||||||
|
public GroupedNativeMethodsAttribute(string removePrefix = "", string removeSuffix = "", bool removeUntilTypeName = true, bool fixMethodName = true)
|
||||||
|
{
|
||||||
|
this.RemovePrefix = removePrefix;
|
||||||
|
this.RemoveSuffix = removeSuffix;
|
||||||
|
this.RemoveUntilTypeName = removeUntilTypeName;
|
||||||
|
this.FixMethodName = fixMethodName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
});
|
||||||
|
|
||||||
|
var source = context.SyntaxProvider.ForAttributeWithMetadataName("GroupedNativeMethodsGenerator.GroupedNativeMethodsAttribute",
|
||||||
|
(node, token) => node is ClassDeclarationSyntax,
|
||||||
|
(ctx, token) => ctx);
|
||||||
|
|
||||||
|
context.RegisterSourceOutput(source, Emit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Emit(SourceProductionContext context, GeneratorAttributeSyntaxContext source)
|
||||||
|
{
|
||||||
|
var typeSymbol = (INamedTypeSymbol)source.TargetSymbol;
|
||||||
|
var typeNode = (TypeDeclarationSyntax)source.TargetNode;
|
||||||
|
|
||||||
|
var ns = typeSymbol.ContainingNamespace.IsGlobalNamespace
|
||||||
|
? ""
|
||||||
|
: $"namespace {typeSymbol.ContainingNamespace}\n{{";
|
||||||
|
|
||||||
|
var accessibility = typeSymbol.DeclaredAccessibility == Accessibility.Public ? "public" : "internal";
|
||||||
|
|
||||||
|
var fullType = typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
|
||||||
|
.Replace("global::", "")
|
||||||
|
.Replace("<", "_")
|
||||||
|
.Replace(">", "_");
|
||||||
|
|
||||||
|
var grouped = typeSymbol.GetMembers().OfType<IMethodSymbol>()
|
||||||
|
.Where(x => x.Parameters.Length != 0)
|
||||||
|
.Where(x => x.Parameters[0].Type is IPointerTypeSymbol t && (t.PointedAtType.SpecialType is SpecialType.None) && t.PointedAtType.TypeKind != TypeKind.Pointer)
|
||||||
|
.ToLookup(x =>
|
||||||
|
{
|
||||||
|
return ((IPointerTypeSymbol)x.Parameters[0].Type).PointedAtType.ToDisplayString();
|
||||||
|
});
|
||||||
|
|
||||||
|
var libTypeName = typeSymbol.Name;
|
||||||
|
var removePrefix = (string)source.Attributes[0].ConstructorArguments[0].Value!;
|
||||||
|
var removeSuffix = (string)source.Attributes[0].ConstructorArguments[1].Value!;
|
||||||
|
var removeUntilTypeName = (bool)source.Attributes[0].ConstructorArguments[2].Value!;
|
||||||
|
var fixMethodName = (bool)source.Attributes[0].ConstructorArguments[3].Value!;
|
||||||
|
|
||||||
|
var code = new StringBuilder();
|
||||||
|
|
||||||
|
code.AppendLine($$"""
|
||||||
|
// <auto-generated/>
|
||||||
|
#nullable enable
|
||||||
|
#pragma warning disable CS8600
|
||||||
|
#pragma warning disable CS8601
|
||||||
|
#pragma warning disable CS8602
|
||||||
|
#pragma warning disable CS8603
|
||||||
|
#pragma warning disable CS8604
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
{{ns}}
|
||||||
|
|
||||||
|
{{accessibility}} static unsafe class {{typeSymbol.Name}}GroupingExtensions
|
||||||
|
{
|
||||||
|
""");
|
||||||
|
foreach (var g in grouped)
|
||||||
|
{
|
||||||
|
code.AppendLine($"#region {g.Key}({g.Count()})");
|
||||||
|
code.AppendLine();
|
||||||
|
foreach (var item in g)
|
||||||
|
{
|
||||||
|
var firstArgument = item.Parameters[0];
|
||||||
|
var ret = item.ReturnType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||||
|
var requireRet = ret == "void" ? "" : "return ";
|
||||||
|
|
||||||
|
var convertedMethodName = ConvertMethodName(((IPointerTypeSymbol)firstArgument.Type).PointedAtType.Name, item.Name, removePrefix, removeSuffix, removeUntilTypeName, fixMethodName);
|
||||||
|
var pointedType = ((IPointerTypeSymbol)firstArgument.Type).PointedAtType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||||
|
var parameterPairs = string.Join("", item.Parameters.Skip(1).Select(x => $", {x.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} @{x.Name}"));
|
||||||
|
var parameterNames = string.Join("", item.Parameters.Skip(1).Select(x => $", @{x.Name}"));
|
||||||
|
|
||||||
|
code.AppendLine($" public static {ret} {convertedMethodName}(this ref {pointedType} @{firstArgument.Name}{parameterPairs})");
|
||||||
|
code.AppendLine(" {");
|
||||||
|
code.AppendLine($" {requireRet}{libTypeName}.{item.Name}(({pointedType}*)Unsafe.AsPointer(ref @{firstArgument.Name}){parameterNames});");
|
||||||
|
code.AppendLine(" }");
|
||||||
|
code.AppendLine("");
|
||||||
|
}
|
||||||
|
code.AppendLine($"#endregion");
|
||||||
|
code.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
code.AppendLine(" }");
|
||||||
|
if (ns != "")
|
||||||
|
{
|
||||||
|
code.AppendLine("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
context.AddSource($"{fullType}.GroupedNativeMethods.g.cs", code.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
static string ConvertMethodName(string typeName, string methodName, string removePrefix, string removeSuffix, bool removeUntilTypeName, bool fixMethodName)
|
||||||
|
{
|
||||||
|
if (removeUntilTypeName)
|
||||||
|
{
|
||||||
|
var match = methodName.IndexOf(typeName);
|
||||||
|
if (match != -1)
|
||||||
|
{
|
||||||
|
methodName = methodName.Substring(match + typeName.Length);
|
||||||
|
goto FINAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(removePrefix))
|
||||||
|
{
|
||||||
|
methodName = Regex.Replace(methodName, $"^{Regex.Escape(removePrefix)}", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
FINAL:
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(removeSuffix))
|
||||||
|
{
|
||||||
|
methodName = Regex.Replace(methodName, $"{Regex.Escape(removeSuffix)}$", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
methodName = methodName.Trim('_');
|
||||||
|
|
||||||
|
if (fixMethodName)
|
||||||
|
{
|
||||||
|
var split = methodName.Split('_');
|
||||||
|
methodName = string.Concat(split.Select(x =>
|
||||||
|
{
|
||||||
|
if (x.Length == 0) return x;
|
||||||
|
if (x.Length == 1) return char.ToUpper(x[0]).ToString();
|
||||||
|
return char.ToUpper(x[0]) + x.Substring(1);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return methodName;
|
||||||
|
}
|
||||||
|
}
|
@ -292,6 +292,7 @@ pub fn emit_csharp(
|
|||||||
// This code is generated by csbindgen.
|
// This code is generated by csbindgen.
|
||||||
// DON'T CHANGE THIS DIRECTLY.
|
// DON'T CHANGE THIS DIRECTLY.
|
||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
|
#pragma warning disable CS8500
|
||||||
#pragma warning disable CS8981
|
#pragma warning disable CS8981
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
66
dotnet-sandbox/BindingGroupExtensions.cs
vendored
66
dotnet-sandbox/BindingGroupExtensions.cs
vendored
@ -1,50 +1,44 @@
|
|||||||
using CsBindgen;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace CsbindgenDotnetConsoleApp
|
namespace Physx
|
||||||
{
|
{
|
||||||
// Concept for grouping extension
|
[GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "Px")]
|
||||||
|
internal static unsafe partial class LibPhysxd
|
||||||
internal static unsafe class BindingGroupExtensions
|
|
||||||
{
|
{
|
||||||
// public static extern bool quiche_conn_set_keylog_path(quiche_conn* conn, byte* path);
|
}
|
||||||
// public static extern nuint quiche_conn_max_send_udp_payload_size(quiche_conn* conn);
|
}
|
||||||
// public static extern int quiche_conn_close(quiche_conn* conn, [MarshalAs(UnmanagedType.U1)] bool app, ulong err, byte* reason, nuint reason_len);
|
|
||||||
|
|
||||||
public static bool SetKeylogPath(this ref quiche_conn conn, byte* path)
|
namespace CsBindgen
|
||||||
{
|
{
|
||||||
return LibQuiche.quiche_conn_set_keylog_path((quiche_conn*)Unsafe.AsPointer(ref conn), path);
|
[GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "b3")]
|
||||||
}
|
internal static unsafe partial class LibBullet3
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public static nuint MaxSendUdpPayloadSize(this ref quiche_conn conn)
|
[GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "quiche_")]
|
||||||
{
|
internal static unsafe partial class LibQuiche
|
||||||
return LibQuiche.quiche_conn_max_send_udp_payload_size((quiche_conn*)Unsafe.AsPointer(ref conn));
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int MaxSendUdpPayloadSize(this ref quiche_conn conn, bool app, ulong err, byte* reason, nuint reason_len)
|
|
||||||
{
|
|
||||||
return LibQuiche.quiche_conn_close((quiche_conn*)Unsafe.AsPointer(ref conn), app, err, reason, reason_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Hoge(quiche_conn* conn, byte* path)
|
|
||||||
{
|
|
||||||
return conn->SetKeylogPath(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
[GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "sqlite3_")]
|
||||||
|
public static unsafe partial class LibSqlite3
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace Physx
|
namespace PixivApi.ImageFile
|
||||||
{
|
{
|
||||||
[GroupedNativeMethodsGenerator.GroupedNativeMethods]
|
[GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "png_")]
|
||||||
internal static unsafe partial class LibPhysxd
|
internal static unsafe partial class LibPng16
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Jolt
|
||||||
|
{
|
||||||
|
[GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "JPH_")]
|
||||||
|
internal static unsafe partial class NativeMethods
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
25
dotnet-sandbox/CsbindgenDotnetConsoleApp.sln
vendored
25
dotnet-sandbox/CsbindgenDotnetConsoleApp.sln
vendored
@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 17
|
|
||||||
VisualStudioVersion = 17.5.33414.496
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsbindgenDotnetConsoleApp", "CsbindgenDotnetConsoleApp.csproj", "{3ED7C644-A880-426C-9BF1-24675D7A6299}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{3ED7C644-A880-426C-9BF1-24675D7A6299}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{3ED7C644-A880-426C-9BF1-24675D7A6299}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{3ED7C644-A880-426C-9BF1-24675D7A6299}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{3ED7C644-A880-426C-9BF1-24675D7A6299}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {DD647440-C307-4A09-9D97-DEA74660F797}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
1
dotnet-sandbox/NativeMethods.cs
vendored
1
dotnet-sandbox/NativeMethods.cs
vendored
@ -2,6 +2,7 @@
|
|||||||
// This code is generated by csbindgen.
|
// This code is generated by csbindgen.
|
||||||
// DON'T CHANGE THIS DIRECTLY.
|
// DON'T CHANGE THIS DIRECTLY.
|
||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
|
#pragma warning disable CS8500
|
||||||
#pragma warning disable CS8981
|
#pragma warning disable CS8981
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
1
dotnet-sandbox/libphysx_csbindgen.cs
vendored
1
dotnet-sandbox/libphysx_csbindgen.cs
vendored
@ -2,6 +2,7 @@
|
|||||||
// This code is generated by csbindgen.
|
// This code is generated by csbindgen.
|
||||||
// DON'T CHANGE THIS DIRECTLY.
|
// DON'T CHANGE THIS DIRECTLY.
|
||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
|
#pragma warning disable CS8500
|
||||||
#pragma warning disable CS8981
|
#pragma warning disable CS8981
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
1
dotnet-sandbox/libpng16_csbindgen.cs
vendored
1
dotnet-sandbox/libpng16_csbindgen.cs
vendored
@ -2,6 +2,7 @@
|
|||||||
// This code is generated by csbindgen.
|
// This code is generated by csbindgen.
|
||||||
// DON'T CHANGE THIS DIRECTLY.
|
// DON'T CHANGE THIS DIRECTLY.
|
||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
|
#pragma warning disable CS8500
|
||||||
#pragma warning disable CS8981
|
#pragma warning disable CS8981
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
1
dotnet-sandbox/lz4_bindgen.cs
vendored
1
dotnet-sandbox/lz4_bindgen.cs
vendored
@ -2,6 +2,7 @@
|
|||||||
// This code is generated by csbindgen.
|
// This code is generated by csbindgen.
|
||||||
// DON'T CHANGE THIS DIRECTLY.
|
// DON'T CHANGE THIS DIRECTLY.
|
||||||
// </auto-generated>
|
// </auto-generated>
|
||||||
|
#pragma warning disable CS8500
|
||||||
#pragma warning disable CS8981
|
#pragma warning disable CS8981
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
Loading…
Reference in New Issue
Block a user