diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs index 1a874965..99c25007 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs @@ -2722,7 +2722,7 @@ void VisitBitfieldDecl(FieldDecl fieldDecl, BitfieldDesc[] bitfieldDescs, Record var recordDeclName = GetCursorName(recordDecl); var isSmallType = currentSize < 4; - var isRemappedToSelf = _config.RemappedNames.TryGetValue(typeName, out var remappedTypeName) && typeName.Equals(remappedTypeName, StringComparison.Ordinal); + var isRemappedToSelf = (_config.RemappedNames.TryGetValue(typeName, out var remappedTypeName) || TryRemapRegex(typeName,out remappedTypeName)) && typeName.Equals(remappedTypeName, StringComparison.Ordinal); var isTypeMismatch = type != builtinTypeBacking; var isUnsignedToSigned = !isTypeBackingSigned && isTypeSigned; diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs index ed878237..4dad19ba 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs @@ -62,7 +62,7 @@ public sealed partial class PInvokeGenerator : IDisposable private readonly Dictionary> _topLevelClassUsings; private readonly Dictionary> _topLevelClassAttributes; private readonly HashSet _topLevelClassNames; - private readonly HashSet _usedRemappings; + private readonly SortedDictionary _usedRemappings; private readonly string _placeholderMacroType; private string _filePath; @@ -1747,7 +1747,7 @@ public void GenerateBindings(TranslationUnit translationUnit, string filePath, s } } - if (!_config.RemappedNames.TryGetValue(name, out _)) + if (!(_config.RemappedNames.TryGetValue(name, out _) || TryRemapRegex(name,out _))) { var addDiag = false; @@ -1769,9 +1769,9 @@ public void GenerateBindings(TranslationUnit translationUnit, string filePath, s addDiag = true; } - if (!addDiag && !_config.RemappedNames.TryGetValue(altName, out _)) + if (!addDiag && !(_config.RemappedNames.TryGetValue(altName, out _) || TryRemapRegex(altName,out _))) { - if (!_config.RemappedNames.TryGetValue(smlName, out _)) + if (!(_config.RemappedNames.TryGetValue(smlName, out _) || TryRemapRegex(smlName,out _))) { addDiag = true; } @@ -1789,7 +1789,7 @@ public void GenerateBindings(TranslationUnit translationUnit, string filePath, s var name = kvp.Key; var remappings = kvp.Value; - if (_config.RemappedNames.TryGetValue(name, out var remappedName) && !remappings.Contains(remappedName) && (name != remappedName) && !_config.ForceRemappedNames.Contains(name)) + if ((_config.RemappedNames.TryGetValue(name, out var remappedName) || TryRemapRegex(name, out remappedName)) && !remappings.Contains(remappedName) && (name != remappedName) && !(_config.ForceRemappedNames.Contains(name) || _config.ForceRemappedRegexes.Any(c => c.IsMatch(name)))) { var addDiag = false; @@ -1811,9 +1811,9 @@ public void GenerateBindings(TranslationUnit translationUnit, string filePath, s addDiag = true; } - if (!addDiag && _config.RemappedNames.TryGetValue(altName, out remappedName) && !remappings.Contains(remappedName) && (altName != remappedName) && !_config.ForceRemappedNames.Contains(altName)) + if (!addDiag && (_config.RemappedNames.TryGetValue(altName, out remappedName) || TryRemapRegex(altName,out remappedName)) && !remappings.Contains(remappedName) && (altName != remappedName) && !(_config.ForceRemappedNames.Contains(altName) || _config.ForceRemappedRegexes.Any(c => c.IsMatch(altName)))) { - if (_config.RemappedNames.TryGetValue(smlName, out remappedName) && !remappings.Contains(remappedName) && (smlName != remappedName) && !_config.ForceRemappedNames.Contains(smlName)) + if ((_config.RemappedNames.TryGetValue(smlName, out remappedName) || TryRemapRegex(smlName,out remappedName)) && !remappings.Contains(remappedName) && (smlName != remappedName) && !(_config.ForceRemappedNames.Contains(smlName) || _config.ForceRemappedRegexes.Any(c => c.IsMatch(smlName)))) { addDiag = true; } @@ -1826,11 +1826,9 @@ public void GenerateBindings(TranslationUnit translationUnit, string filePath, s } } - foreach (var name in _usedRemappings) + foreach (var (name,remappedName) in _usedRemappings) { - var remappedName = _config.RemappedNames[name]; - - if (!_allValidNameRemappings.ContainsKey(name) && (name != remappedName) && !_config.ForceRemappedNames.Contains(name)) + if (!_allValidNameRemappings.ContainsKey(name) && (name != remappedName) && !(_config.ForceRemappedNames.Contains(name) || _config.ForceRemappedRegexes.Any(c => c.IsMatch(name)))) { var addDiag = false; @@ -1852,9 +1850,9 @@ public void GenerateBindings(TranslationUnit translationUnit, string filePath, s addDiag = true; } - if (!addDiag && !_allValidNameRemappings.ContainsKey(altName) && (altName != remappedName) && !_config.ForceRemappedNames.Contains(altName)) + if (!addDiag && !_allValidNameRemappings.ContainsKey(altName) && (altName != remappedName) && !(_config.ForceRemappedNames.Contains(altName) || _config.ForceRemappedRegexes.Any(c => c.IsMatch(altName)))) { - if (!_allValidNameRemappings.ContainsKey(smlName) && (smlName != remappedName) && !_config.ForceRemappedNames.Contains(smlName)) + if (!_allValidNameRemappings.ContainsKey(smlName) && (smlName != remappedName) && !(_config.ForceRemappedNames.Contains(smlName) || _config.ForceRemappedRegexes.Any(c => c.IsMatch(smlName)))) { addDiag = true; } @@ -3288,12 +3286,30 @@ private string GetRemappedNameForAnonymousRecord(RecordDecl recordDecl) private string GetRemappedName(string name, Cursor? cursor, bool tryRemapOperatorName, out bool wasRemapped, bool skipUsing = false) => GetRemappedName(name, cursor, tryRemapOperatorName, out wasRemapped, skipUsing, skipUsingIfNotRemapped: skipUsing); + private bool TryRemapRegex(string name,[MaybeNullWhen(false)] out string remappedName) + { + foreach (var remapRegex in _config.RemappedRegexes.Keys) + { + var match = remapRegex.Match(name); + if(!match.Success) + { + continue; + } + + var groups = match.Groups.Values.Skip(1).Select(object (group) => group.Value).ToArray(); + remappedName = string.Format(CultureInfo.InvariantCulture,_config.RemappedRegexes[remapRegex],groups); + return true; + } + + remappedName = null; + return false; + } private string GetRemappedName(string name, Cursor? cursor, bool tryRemapOperatorName, out bool wasRemapped, bool skipUsing, bool skipUsingIfNotRemapped) { - if (_config.RemappedNames.TryGetValue(name, out var remappedName)) + if (_config.RemappedNames.TryGetValue(name, out var remappedName) || TryRemapRegex(name, out remappedName)) { wasRemapped = true; - _ = _usedRemappings.Add(name); + _ = _usedRemappings.TryAdd(name,remappedName); return AddUsingDirectiveIfNeeded(_outputBuilder, remappedName, skipUsing); } @@ -3301,11 +3317,11 @@ private string GetRemappedName(string name, Cursor? cursor, bool tryRemapOperato { var tmpName = name[6..]; - if (_config.RemappedNames.TryGetValue(tmpName, out remappedName)) + if (_config.RemappedNames.TryGetValue(tmpName, out remappedName) || TryRemapRegex(tmpName, out remappedName)) { wasRemapped = true; - _ = _usedRemappings.Add(tmpName); + _ = _usedRemappings.TryAdd(tmpName,remappedName); return AddUsingDirectiveIfNeeded(_outputBuilder, remappedName, skipUsing); } } @@ -6807,11 +6823,23 @@ private void WithAttributes(NamedDecl namedDecl, bool onlySupportedOSPlatform = var outputBuilder = isTestOutput ? _testOutputBuilder : _outputBuilder; Debug.Assert(outputBuilder is not null); - if (TryGetRemappedValue(namedDecl, _config.WithAttributes, out var attributes, matchStar: true)) { - foreach (var attribute in attributes.Where((a) => !onlySupportedOSPlatform || a.StartsWith("SupportedOSPlatform(", StringComparison.Ordinal))) + if (TryGetRemappedValue(namedDecl, _config.WithAttributes, out var attributes, matchStar: true)) { - outputBuilder.WriteCustomAttribute(attribute); + foreach (var attribute in attributes.Where((a) => !onlySupportedOSPlatform || a.StartsWith("SupportedOSPlatform(", StringComparison.Ordinal))) + { + outputBuilder.WriteCustomAttribute(attribute); + } + } + } + + { + if (TryGetRemappedValueRegex(namedDecl, _config.WithAttributesRegex, out var attributes)) + { + foreach (var attribute in attributes.Where((a) => !onlySupportedOSPlatform || a.StartsWith("SupportedOSPlatform(", StringComparison.Ordinal))) + { + outputBuilder.WriteCustomAttribute(attribute); + } } } @@ -7090,6 +7118,92 @@ private bool TryGetRemappedValue(NamedDecl namedDecl, IReadOnlyDictionary(NamedDecl namedDecl, IReadOnlyDictionary remappings, [MaybeNullWhen(false)] out T value) + { + var name = GetCursorQualifiedName(namedDecl); + + if (name.StartsWith("ClangSharpMacro_", StringComparison.Ordinal)) + { + name = name["ClangSharpMacro_".Length..]; + } + + foreach (var regex in remappings.Keys) + { + if (!regex.IsMatch(name)) + { + continue; + } + + value = remappings[regex]; + return true; + } + + name = name.Replace("::", ".", StringComparison.Ordinal); + + foreach (var regex in remappings.Keys) + { + if (!regex.IsMatch(name)) + { + continue; + } + + value = remappings[regex]; + return true; + } + + name = GetCursorQualifiedName(namedDecl, truncateParameters: true); + + if (name.StartsWith("ClangSharpMacro_", StringComparison.Ordinal)) + { + name = name["ClangSharpMacro_".Length..]; + } + + foreach (var regex in remappings.Keys) + { + if (!regex.IsMatch(name)) + { + continue; + } + + value = remappings[regex]; + return true; + } + + name = name.Replace("::", ".", StringComparison.Ordinal); + + foreach (var regex in remappings.Keys) + { + if (!regex.IsMatch(name)) + { + continue; + } + + value = remappings[regex]; + return true; + } + + name = GetRemappedCursorName(namedDecl); + + if (name.StartsWith("ClangSharpMacro_", StringComparison.Ordinal)) + { + name = name["ClangSharpMacro_".Length..]; + } + + foreach (var regex in remappings.Keys) + { + if (!regex.IsMatch(name)) + { + continue; + } + + value = remappings[regex]; + return true; + } + + value = default; + return false; + } + private void WithTestAttribute() { if (_config.GenerateTestsNUnit) diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs index 53eacc0b..ea80a955 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Text.RegularExpressions; namespace ClangSharp; @@ -29,6 +30,7 @@ public sealed class PInvokeGeneratorConfiguration private readonly SortedSet _excludedNames; private readonly SortedSet _forceRemappedNames; + private readonly SortedSet _forceRemappedRegexes; private readonly SortedSet _includedNames; private readonly SortedSet _nativeTypeNamesToStrip; private readonly SortedSet _withManualImports; @@ -37,8 +39,10 @@ public sealed class PInvokeGeneratorConfiguration private readonly SortedSet _withSuppressGCTransitions; private readonly SortedDictionary _remappedNames; + private readonly SortedDictionary _remappedRegexes; private readonly SortedDictionary _withAccessSpecifiers; private readonly SortedDictionary> _withAttributes; + private readonly SortedDictionary> _withAttributesRegex; private readonly SortedDictionary _withCallConvs; private readonly SortedDictionary _withClasses; private readonly SortedDictionary _withGuids; @@ -83,6 +87,7 @@ public PInvokeGeneratorConfiguration(string language, string languageStandard, s _excludedNames = []; _forceRemappedNames = []; + _forceRemappedRegexes = new SortedSet(new RegexComparer()); _includedNames = []; _nativeTypeNamesToStrip = []; _withManualImports = []; @@ -91,8 +96,10 @@ public PInvokeGeneratorConfiguration(string language, string languageStandard, s _withSuppressGCTransitions = []; _remappedNames = []; + _remappedRegexes = new SortedDictionary(new RegexComparer()); _withAccessSpecifiers = []; _withAttributes = []; + _withAttributesRegex = new SortedDictionary>(new RegexComparer()); _withCallConvs = []; _withClasses = []; _withGuids = []; @@ -359,7 +366,23 @@ public IReadOnlyDictionary RemappedNames } } + [AllowNull] + public IReadOnlyDictionary RemappedRegexes + { + get + { + return _remappedRegexes; + } + + init + { + AddRange(_forceRemappedRegexes, value,ValueStartsWithAt); + AddRange(_remappedRegexes, value,RemoveAtPrefix); + } + } + public IReadOnlyCollection ForceRemappedNames => _forceRemappedNames; + public IReadOnlyCollection ForceRemappedRegexes => _forceRemappedRegexes; [AllowNull] public string TestOutputLocation @@ -418,6 +441,20 @@ public IReadOnlyDictionary> WithAttributes } } + [AllowNull] + public IReadOnlyDictionary> WithAttributesRegex + { + get + { + return _withAttributesRegex; + } + + init + { + AddRange(_withAttributesRegex, value); + } + } + [AllowNull] public IReadOnlyDictionary WithCallConvs { @@ -612,7 +649,7 @@ public static AccessSpecifier ConvertStringToAccessSpecifier(string input) : input.Equals("public", StringComparison.OrdinalIgnoreCase) ? AccessSpecifier.Public : AccessSpecifier.None; } - private static void AddRange(SortedDictionary dictionary, IEnumerable>? keyValuePairs) + private static void AddRange(SortedDictionary dictionary, IEnumerable>? keyValuePairs) where TKey : notnull { if (keyValuePairs != null) { @@ -638,6 +675,19 @@ private static void AddRange(SortedDictionary di } } + private static void AddRange(SortedDictionary dictionary, IEnumerable>? keyValuePairs, Func convert) + { + if (keyValuePairs != null) + { + foreach (var keyValuePair in keyValuePairs) + { + // Use the indexer, rather than Add, so that any + // default mappings can be overwritten if desired. + dictionary[keyValuePair.Key] = convert(keyValuePair.Value); + } + } + } + private static void AddRange(SortedSet hashSet, IEnumerable? keys) { if (keys != null) @@ -674,6 +724,20 @@ private static void AddRange(SortedSet hashSet, IEnumerable(SortedSet hashSet, IEnumerable>? keyValuePairs, Func shouldAdd) + { + if (keyValuePairs != null) + { + foreach (var keyValuePair in keyValuePairs) + { + if (shouldAdd(keyValuePair.Value)) + { + _ = hashSet.Add(keyValuePair.Key); + } + } + } + } + private static string RemoveAtPrefix(string value) => ValueStartsWithAt(value) ? value[1..] : value; private static (string, PInvokeGeneratorTransparentStructKind) RemoveAtPrefix((string Name, PInvokeGeneratorTransparentStructKind Kind) value) => (ValueStartsWithAt(value.Name) ? value.Name[1..] : value.Name, value.Kind); diff --git a/sources/ClangSharp.PInvokeGenerator/RegexComparer.cs b/sources/ClangSharp.PInvokeGenerator/RegexComparer.cs new file mode 100644 index 00000000..2a734638 --- /dev/null +++ b/sources/ClangSharp.PInvokeGenerator/RegexComparer.cs @@ -0,0 +1,11 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace ClangSharp; + +internal class RegexComparer : IComparer +{ + public int Compare(Regex? x, Regex? y) => string.CompareOrdinal(x?.ToString(), y?.ToString()); +} diff --git a/sources/ClangSharpPInvokeGenerator/Program.cs b/sources/ClangSharpPInvokeGenerator/Program.cs index 0545723b..4e94ed42 100644 --- a/sources/ClangSharpPInvokeGenerator/Program.cs +++ b/sources/ClangSharpPInvokeGenerator/Program.cs @@ -12,6 +12,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; +using System.Text.RegularExpressions; using System.Threading.Tasks; using ClangSharp.Interop; using static ClangSharp.Interop.CXDiagnosticSeverity; @@ -40,12 +41,14 @@ public static class Program private static readonly string[] s_outputOptionAliases = ["--output", "-o"]; private static readonly string[] s_prefixStripOptionAliases = ["--prefixStrip", "-p"]; private static readonly string[] s_remapOptionAliases = ["--remap", "-r"]; + private static readonly string[] s_remapRegexOptionAliases = ["--remap-regex", "-rr"]; private static readonly string[] s_stdOptionAliases = ["--std", "-std"]; private static readonly string[] s_testOutputOptionAliases = ["--test-output", "-to"]; private static readonly string[] s_traverseOptionAliases = ["--traverse", "-t"]; private static readonly string[] s_versionOptionAliases = ["--version", "-v"]; private static readonly string[] s_withAccessSpecifierOptionAliases = ["--with-access-specifier", "-was"]; private static readonly string[] s_withAttributeOptionAliases = ["--with-attribute", "-wa"]; + private static readonly string[] s_withAttributeRegexOptionAliases = ["--with-attribute-regex", "-war"]; private static readonly string[] s_withCallConvOptionAliases = ["--with-callconv", "-wcc"]; private static readonly string[] s_withClassOptionAliases = ["--with-class", "-wc"]; private static readonly string[] s_withGuidOptionAliases = ["--with-guid", "-wg"]; @@ -78,12 +81,14 @@ public static class Program private static readonly Option s_outputLocation = GetOutputOption(); private static readonly Option s_outputMode = GetOutputModeOption(); private static readonly Option s_remappedNameValuePairs = GetRemapOption(); + private static readonly Option s_remappedRegexValuePairs = GetRemapRegexOption(); private static readonly Option s_std = GetStdOption(); private static readonly Option s_testOutputLocation = GetTestOutputOption(); private static readonly Option s_traversalNames = GetTraverseOption(); private static readonly Option s_versionOption = GetVersionOption(); private static readonly Option s_withAccessSpecifierNameValuePairs = GetWithAccessSpecifierOption(); private static readonly Option s_withAttributeNameValuePairs = GetWithAttributeOption(); + private static readonly Option s_withAttributeRegexNameValuePairs = GetWithAttributeRegexOption(); private static readonly Option s_withCallConvNameValuePairs = GetWithCallConvOption(); private static readonly Option s_withClassNameValuePairs = GetWithClassOption(); private static readonly Option s_withGuidNameValuePairs = GetWithGuidOption(); @@ -243,11 +248,13 @@ public static void Run(InvocationContext context) var outputLocation = context.ParseResult.GetValueForOption(s_outputLocation) ?? ""; var outputMode = context.ParseResult.GetValueForOption(s_outputMode); var remappedNameValuePairs = context.ParseResult.GetValueForOption(s_remappedNameValuePairs) ?? []; + var remappedRegexValuePairs = context.ParseResult.GetValueForOption(s_remappedRegexValuePairs) ?? []; var std = context.ParseResult.GetValueForOption(s_std) ?? ""; var testOutputLocation = context.ParseResult.GetValueForOption(s_testOutputLocation) ?? ""; var traversalNames = context.ParseResult.GetValueForOption(s_traversalNames) ?? []; var withAccessSpecifierNameValuePairs = context.ParseResult.GetValueForOption(s_withAccessSpecifierNameValuePairs) ?? []; var withAttributeNameValuePairs = context.ParseResult.GetValueForOption(s_withAttributeNameValuePairs) ?? []; + var withAttributeRegexNameValuePairs = context.ParseResult.GetValueForOption(s_withAttributeRegexNameValuePairs) ?? []; var withCallConvNameValuePairs = context.ParseResult.GetValueForOption(s_withCallConvNameValuePairs) ?? []; var withClassNameValuePairs = context.ParseResult.GetValueForOption(s_withClassNameValuePairs) ?? []; var withGuidNameValuePairs = context.ParseResult.GetValueForOption(s_withGuidNameValuePairs) ?? []; @@ -291,8 +298,10 @@ public static void Run(InvocationContext context) } ParseKeyValuePairs(remappedNameValuePairs, errorList, out Dictionary remappedNames); + ParseRegexValuePairs(remappedRegexValuePairs, errorList, out Dictionary remappedRegexes); ParseKeyValuePairs(withAccessSpecifierNameValuePairs, errorList, out Dictionary withAccessSpecifiers); ParseKeyValuePairs(withAttributeNameValuePairs, errorList, out Dictionary> withAttributes); + ParseKeyValuePairs(withAttributeRegexNameValuePairs, errorList, out Dictionary> withAttributesRegex); ParseKeyValuePairs(withCallConvNameValuePairs, errorList, out Dictionary withCallConvs); ParseKeyValuePairs(withClassNameValuePairs, errorList, out Dictionary withClasses); ParseKeyValuePairs(withGuidNameValuePairs, errorList, out Dictionary withGuids); @@ -718,10 +727,12 @@ public static void Run(InvocationContext context) MethodPrefixToStrip = methodPrefixToStrip, NativeTypeNamesToStrip = nativeTypeNamesToStrip, RemappedNames = remappedNames, + RemappedRegexes = remappedRegexes, TraversalNames = traversalNames, TestOutputLocation = testOutputLocation, WithAccessSpecifiers = withAccessSpecifiers, WithAttributes = withAttributes, + WithAttributesRegex = withAttributesRegex, WithCallConvs = withCallConvs, WithClasses = withClasses, WithGuids = withGuids, @@ -861,6 +872,32 @@ private static void ParseKeyValuePairs(IEnumerable keyValuePairs, List keyValuePairs, List errorList, out Dictionary result) + { + result = []; + + foreach (var keyValuePair in keyValuePairs) + { + var parts = keyValuePair.Split('=', 2); + + if (parts.Length < 2) + { + errorList.Add($"Error: Invalid regex/value pair argument: {keyValuePair}. Expected 'name=value'"); + continue; + } + + var key = new Regex(string.Join('=',parts[..^1]).TrimEnd(),RegexOptions.Compiled); + + if (result.TryGetValue(key, out var value)) + { + errorList.Add($"Error: A regex with the given name already exists: {key}. Existing: {value}"); + continue; + } + + result.Add(key, parts[^1].TrimStart()); + } + } + private static void ParseKeyValuePairs(IEnumerable keyValuePairs, List errorList, out Dictionary result) { result = []; @@ -959,6 +996,33 @@ private static void ParseKeyValuePairs(IEnumerable keyValuePairs, List keyValuePairs, List errorList, out Dictionary> result) + { + result = []; + + foreach (var keyValuePair in keyValuePairs) + { + var parts = keyValuePair.Split('='); + + if (parts.Length != 2) + { + errorList.Add($"Error: Invalid key/value pair argument: {keyValuePair}. Expected 'name=value'"); + continue; + } + + var key = new Regex(string.Join('=',parts[..^1]).TrimEnd(),RegexOptions.Compiled); + + if (!result.TryGetValue(key, out var value)) + { + value = new List(); + result.Add(key, value); + } + + var list = (List)value; + list.Add(parts[^1].TrimStart()); + } + } + private static void ParseKeyValuePairs(IEnumerable keyValuePairs, List errorList, out Dictionary> result) { result = []; @@ -1166,6 +1230,17 @@ private static Option GetRemapOption() }; } + private static Option GetRemapRegexOption() + { + return new Option( + aliases: s_remapRegexOptionAliases, + description: "A declaration name to be remapped to another name using regex during binding generation.", + getDefaultValue: Array.Empty + ) { + AllowMultipleArgumentsPerToken = true + }; + } + private static RootCommand GetRootCommand() { var rootCommand = new RootCommand("ClangSharp P/Invoke Binding Generator") @@ -1188,12 +1263,14 @@ private static RootCommand GetRootCommand() s_methodPrefixToStrip, s_nativeTypeNamesToStrip, s_remappedNameValuePairs, + s_remappedRegexValuePairs, s_std, s_testOutputLocation, s_traversalNames, s_versionOption, s_withAccessSpecifierNameValuePairs, s_withAttributeNameValuePairs, + s_withAttributeRegexNameValuePairs, s_withCallConvNameValuePairs, s_withClassNameValuePairs, s_withGuidNameValuePairs, @@ -1273,6 +1350,17 @@ private static Option GetWithAttributeOption() }; } + private static Option GetWithAttributeRegexOption() + { + return new Option( + aliases: s_withAttributeRegexOptionAliases, + description: "An attribute to be added to the given remapped declaration name during binding generation. Supports regex.", + getDefaultValue: Array.Empty + ) { + AllowMultipleArgumentsPerToken = true + }; + } + private static Option GetWithCallConvOption() { return new Option(