Skip to content

Commit

Permalink
Merge pull request #527 from fredrikhr/strip-enum-member-type-name
Browse files Browse the repository at this point in the history
Config option: strip-enum-member-type-name
  • Loading branch information
tannergooding authored May 24, 2024
2 parents 305eff5 + c246b41 commit 7e48890
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 31 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ Options:
generate-unmanaged-constants Unmanaged constants should be generated using static ref readonly properties. This is currently experimental.
generate-vtbl-index-attribute [VtblIndex(#)] attribute should be generated to document the underlying VTBL index for a helper method.
# Stripping Options
strip-enum-member-type-name Strips the enum type name from the beginning of its member names.
# Logging Options
log-exclusions A list of excluded declaration types should be generated. This will also log if the exclusion was due to an exact or partial match.
Expand Down
20 changes: 13 additions & 7 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using ClangSharp.Abstractions;
using ClangSharp.CSharp;
using static ClangSharp.Interop.CX_CastKind;
Expand Down Expand Up @@ -294,6 +295,11 @@ private void VisitEnumConstantDecl(EnumConstantDecl enumConstantDecl)
parentName = _outputBuilder.Name;
}

if (Config.StripEnumMemberTypeName)
{
escapedName = PrefixAndStrip(escapedName, parentName, trimChar: '_');
}

var kind = isAnonymousEnum ? ValueKind.Primitive : ValueKind.Enumerator;
var flags = ValueFlags.Constant;

Expand Down Expand Up @@ -535,12 +541,12 @@ private void VisitFunctionDecl(FunctionDecl functionDecl)
if ((cxxMethodDecl is not null) && cxxMethodDecl.IsVirtual)
{
isVirtual = true;
escapedName = PrefixAndStripName(name, GetOverloadIndex(cxxMethodDecl));
escapedName = PrefixAndStripMethodName(name, GetOverloadIndex(cxxMethodDecl));
}
else
{
isVirtual = false;
escapedName = EscapeAndStripName(name);
escapedName = EscapeAndStripMethodName(name);
}

var returnType = functionDecl.ReturnType;
Expand Down Expand Up @@ -2024,7 +2030,7 @@ void OutputMarkerInterface(CXXRecordDecl cxxRecordDecl, CXXMethodDecl cxxMethodD

var desc = new FunctionOrDelegateDesc {
AccessSpecifier = AccessSpecifier.Public,
EscapedName = EscapeAndStripName(name),
EscapedName = EscapeAndStripMethodName(name),
IsMemberFunction = true,
NativeTypeName = nativeTypeName,
HasFnPtrCodeGen = !_config.ExcludeFnptrCodegen,
Expand Down Expand Up @@ -2112,7 +2118,7 @@ void OutputVtblEntry(CXXRecordDecl cxxRecordDecl, CXXMethodDecl cxxMethodDecl)
}

var remappedName = FixupNameForMultipleHits(cxxMethodDecl);
var escapedName = EscapeAndStripName(remappedName);
var escapedName = EscapeAndStripMethodName(remappedName);

var desc = new FieldDesc
{
Expand Down Expand Up @@ -2181,7 +2187,7 @@ void OutputVtblHelperMethod(CXXRecordDecl cxxRecordDecl, CXXMethodDecl cxxMethod
var desc = new FunctionOrDelegateDesc {
AccessSpecifier = AccessSpecifier.Public,
IsAggressivelyInlined = _config.GenerateAggressiveInlining,
EscapedName = EscapeAndStripName(name),
EscapedName = EscapeAndStripMethodName(name),
ParentName = parentName,
IsMemberFunction = true,
IsInherited = isInherited,
Expand Down Expand Up @@ -2261,7 +2267,7 @@ void OutputVtblHelperMethod(CXXRecordDecl cxxRecordDecl, CXXMethodDecl cxxMethod
{
body.Write("Marshal.GetDelegateForFunctionPointer<");
body.BeginMarker("delegate");
body.Write(PrefixAndStripName(name, GetOverloadIndex(cxxMethodDecl)));
body.Write(PrefixAndStripMethodName(name, GetOverloadIndex(cxxMethodDecl)));
body.EndMarker("delegate");
body.Write(">(");
}
Expand All @@ -2270,7 +2276,7 @@ void OutputVtblHelperMethod(CXXRecordDecl cxxRecordDecl, CXXMethodDecl cxxMethod
{
body.Write("lpVtbl->");
body.BeginMarker("vtbl", new KeyValuePair<string, object>("explicit", true));
body.Write(EscapeAndStripName(remappedName));
body.Write(EscapeAndStripMethodName(remappedName));
body.EndMarker("vtbl");
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ private void VisitDeclRefExpr(DeclRefExpr declRefExpr)

if (declRefExpr.Decl is FunctionDecl)
{
escapedName = EscapeAndStripName(name);
escapedName = EscapeAndStripMethodName(name);
}
}

Expand Down
61 changes: 38 additions & 23 deletions sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1454,18 +1454,18 @@ static void GenerateTransparentStructs(PInvokeGenerator generator, Stream? strea
return type.Contains('*', StringComparison.Ordinal)
? (8, 4, +1)
: type switch {
"sbyte" => (1, 1, -1),
"byte" => (1, 1, +1),
"short" => (2, 2, -1),
"ushort" => (2, 2, +1),
"int" => (4, 4, -1),
"uint" => (4, 4, +1),
"nint" => (8, 4, -1),
"nuint" => (8, 4, +1),
"long" => (8, 8, -1),
"ulong" => (8, 8, +1),
_ => (0, 0, 0),
};
"sbyte" => (1, 1, -1),
"byte" => (1, 1, +1),
"short" => (2, 2, -1),
"ushort" => (2, 2, +1),
"int" => (4, 4, -1),
"uint" => (4, 4, +1),
"nint" => (8, 4, -1),
"nuint" => (8, 4, +1),
"long" => (8, 8, -1),
"ulong" => (8, 8, +1),
_ => (0, 0, 0),
};
}

static void OutputConversions(StreamWriter sw, string indentString, string name, string type, PInvokeGeneratorTransparentStructKind kind, string target)
Expand Down Expand Up @@ -2326,13 +2326,9 @@ private static string EscapeName(string name)
}
}

private string EscapeAndStripName(string name)
private string EscapeAndStripMethodName(string name)
{
if (name.StartsWith(_config.MethodPrefixToStrip, StringComparison.Ordinal))
{
name = name[_config.MethodPrefixToStrip.Length..];
}

name = PrefixAndStrip(name, _config.MethodPrefixToStrip);
return EscapeName(name);
}

Expand Down Expand Up @@ -5407,7 +5403,7 @@ private static bool IsTransparentStructBoolean(PInvokeGeneratorTransparentStruct
=> kind is PInvokeGeneratorTransparentStructKind.Boolean;

private static bool IsTransparentStructHandle(PInvokeGeneratorTransparentStructKind kind)
=> kind is PInvokeGeneratorTransparentStructKind.Handle
=> kind is PInvokeGeneratorTransparentStructKind.Handle
or PInvokeGeneratorTransparentStructKind.HandleWin32;

private static bool IsTransparentStructHexBased(PInvokeGeneratorTransparentStructKind kind)
Expand Down Expand Up @@ -6153,7 +6149,7 @@ private bool NeedsReturnFixup(CXXMethodDecl cxxMethodDecl)

private static bool NeedsNewKeyword(string name)
{
return name.Equals("Equals",StringComparison.Ordinal)
return name.Equals("Equals", StringComparison.Ordinal)
|| name.Equals("GetHashCode", StringComparison.Ordinal)
|| name.Equals("GetType", StringComparison.Ordinal)
|| name.Equals("MemberwiseClone", StringComparison.Ordinal)
Expand Down Expand Up @@ -6198,13 +6194,32 @@ private void ParenthesizeStmt(Stmt stmt)
}
}

private string PrefixAndStripName(string name, uint overloadIndex)
/// <summary>
/// Checks whether the specified name starts with a prefix, optionally trims a separator character following the prefix and returns the remainder.
/// </summary>
/// <param name="name">The name to strip.</param>
/// <param name="prefix">The prefix to strip from <paramref name="name"/>.</param>
/// <param name="trimChar">Additional separator that may follow <paramref name="prefix"/> which should also be trimmed away.</param>
/// <returns>
/// <paramref name="name"/> if it does not start with <paramref name="prefix"/>;
/// otherwise,
/// the remainder of <paramref name="name"/> after stripping <paramref name="prefix"/> and all immediate following occurences of <paramref name="trimChar"/> from it beginning.
/// </returns>
private static string PrefixAndStrip(string name, string prefix, char trimChar = '\0')
{
if (name.StartsWith(_config.MethodPrefixToStrip, StringComparison.Ordinal))
var nameSpan = name.AsSpan();
if (nameSpan.StartsWith(prefix, StringComparison.Ordinal))
{
name = name[_config.MethodPrefixToStrip.Length..];
nameSpan = nameSpan[prefix.Length..];
nameSpan = nameSpan.TrimStart(trimChar);
return nameSpan.ToString();
}
return name;
}

private string PrefixAndStripMethodName(string name, uint overloadIndex)
{
name = PrefixAndStrip(name, _config.MethodPrefixToStrip);
return $"_{name}{((overloadIndex != 0) ? overloadIndex.ToString(CultureInfo.InvariantCulture) : "")}";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ public IReadOnlyCollection<string> ExcludedNames

public bool GenerateVtblIndexAttribute => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateVtblIndexAttribute);

public bool StripEnumMemberTypeName => _options.HasFlag(PInvokeGeneratorConfigurationOptions.StripEnumMemberTypeName);

public string HeaderText => _headerText;

[AllowNull]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,6 @@ public enum PInvokeGeneratorConfigurationOptions : long
GenerateCallConvMemberFunction = 1L << 37,

GenerateGenericPointerWrapper = 1L << 38,

StripEnumMemberTypeName = 1L << 39,
}
14 changes: 14 additions & 0 deletions sources/ClangSharpPInvokeGenerator/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,12 @@ public static class Program
new TwoColumnHelpRow("generate-unmanaged-constants", "Unmanaged constants should be generated using static ref readonly properties. This is currently experimental."),
new TwoColumnHelpRow("generate-vtbl-index-attribute", "[VtblIndex(#)] attribute should be generated to document the underlying VTBL index for a helper method."),

new TwoColumnHelpRow("", ""),
new TwoColumnHelpRow("# Stripping Options", ""),
new TwoColumnHelpRow("", ""),

new TwoColumnHelpRow("strip-enum-member-type-name", "Strips the enum type name from the beginning of its member names."),

new TwoColumnHelpRow("", ""),
new TwoColumnHelpRow("# Logging Options", ""),
new TwoColumnHelpRow("", ""),
Expand Down Expand Up @@ -617,6 +623,14 @@ public static void Run(InvocationContext context)
break;
}

// Strip Options

case "strip-enum-member-type-name":
{
configOptions |= PInvokeGeneratorConfigurationOptions.StripEnumMemberTypeName;
break;
}

// Legacy Options

case "default-remappings":
Expand Down

0 comments on commit 7e48890

Please sign in to comment.