mirror of
https://github.com/Sarsoo/csbindgen.git
synced 2024-12-22 22:46:26 +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.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
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
|
||||
|
||||
internal static unsafe class BindingGroupExtensions
|
||||
[GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "Px")]
|
||||
internal static unsafe partial class LibPhysxd
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
return LibQuiche.quiche_conn_set_keylog_path((quiche_conn*)Unsafe.AsPointer(ref conn), path);
|
||||
}
|
||||
namespace CsBindgen
|
||||
{
|
||||
[GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "b3")]
|
||||
internal static unsafe partial class LibBullet3
|
||||
{
|
||||
}
|
||||
|
||||
public static nuint MaxSendUdpPayloadSize(this ref quiche_conn conn)
|
||||
{
|
||||
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: "quiche_")]
|
||||
internal static unsafe partial class LibQuiche
|
||||
{
|
||||
}
|
||||
|
||||
[GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "sqlite3_")]
|
||||
public static unsafe partial class LibSqlite3
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace Physx
|
||||
namespace PixivApi.ImageFile
|
||||
{
|
||||
[GroupedNativeMethodsGenerator.GroupedNativeMethods]
|
||||
internal static unsafe partial class LibPhysxd
|
||||
[GroupedNativeMethodsGenerator.GroupedNativeMethods(removePrefix: "png_")]
|
||||
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.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
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.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
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.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
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.
|
||||
// DON'T CHANGE THIS DIRECTLY.
|
||||
// </auto-generated>
|
||||
#pragma warning disable CS8500
|
||||
#pragma warning disable CS8981
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
Loading…
Reference in New Issue
Block a user