diff --git a/README.md b/README.md index 4c2ddcbf..64253eac 100644 --- a/README.md +++ b/README.md @@ -125,138 +125,86 @@ At a minimum, the command line expects one or more input files (`-f`), an output The full set of available switches: ``` -ClangSharpPInvokeGenerator: +ClangSharpPInvokeGenerator ClangSharp P/Invoke Binding Generator Usage: ClangSharpPInvokeGenerator [options] Options: - -a, --additional <> An argument to pass to Clang when parsing the input files. - [default: System.String[]] - -c, --config <> Aconfiguration option that controls how the bindings are - generated. Specify 'help' to see the available options. - [default: System.String[]] - -D, --define-macro <=> Define to (or 1 if omitted). - [default: System.String[]] - -e, --exclude <> Adeclaration name to exclude from binding generation. - [default: System.String[]] - -f, --file <> Afile to parse and generate bindings for. [default: - System.String[]] - -F, --file-directory <> The base path for files to parse. [default: ] - -h, --headerFile <> Afile which contains the header to prefix every generated - file with. [default: ] - -I, --include-directory <> Add directory to include search path. [default: - System.String[]] - -x, --language <> Treat subsequent input files as having type . - [default: c++] - -l, --libraryPath <> The string to use in the DllImport attribute used when - generating bindings. [default: ] - -m, --methodClassName <> The name of the static class that will contain the generated - method bindings. [default: Methods] - -n, --namespace <> The namespace in which to place the generated bindings. - [default: ] - -o, --output <> The output location to write the generated bindings to. - [default: ] - -p, --prefixStrip <> The prefix to strip from the generated method bindings. - [default: ] - -r, --remap <=> Adeclaration name to be remapped to another name during - binding generation. [default: System.String[]] - -std <> Language standard to compile for. [default: c++17] - -to, --test-output <> The output location to write the generated tests to. - [default: ] - -t, --traverse <> Afile name included either directly or indirectly by -f that - should be traversed during binding generation. [default: - System.String[]] - -wa, --with-attribute <=> An attribute to be added to the given remapped declaration - name during binding generation. [default: System.String[]] - -wcc, --with-callconv <=> Acalling convention to be used for the given declaration - during binding generation. [default: System.String[]] - -wlb, --with-librarypath <=> Alibrary path to be used for the given declaration during - binding generation. [default: System.String[]] - -wsle, --with-setlasterror <=> Add the SetLastError=true modifier to a given DllImport or - UnmanagedFunctionPointer. [default: System.String[]] - -wt, --with-type <=> Atype to be used for the given enum declaration during - binding generation. [default: System.String[]] - -wu, --with-using <=> Ausing directive to be included for the given remapped - declaration name during binding generation. [default: - System.String[]] - -om, --output-mode The mode describing how the information collected from the - headers are presented in the resultant bindings. [default: - CSharp] - --version Show version information - -?, -h, --help Show help and usage information + -a, --additional An argument to pass to Clang when parsing the input files. [default: ] + -c, --config A configuration option that controls how the bindings are generated. Specify 'help' to see the available options. [default: ] + -D, --define-macro Define to (or 1 if omitted). [default: ] + -e, --exclude A declaration name to exclude from binding generation. [default: ] + -f, --file A file to parse and generate bindings for. [default: ] + -F, --file-directory The base path for files to parse. [default: ] + -h, --headerFile A file which contains the header to prefix every generated file with. [default: ] + -i, --include A declaration name to include in binding generation. [default: ] + -I, --include-directory Add directory to include search path. [default: ] + -x, --language Treat subsequent input files as having type . [default: c++] + -l, --libraryPath The string to use in the DllImport attribute used when generating bindings. [default: ] + -m, --methodClassName The name of the static class that will contain the generated method bindings. [default: Methods] + -n, --namespace The namespace in which to place the generated bindings. [default: ] + -om, --output-mode The mode describing how the information collected from the headers are presented in the resultant bindings. [default: CSharp] + -o, --output The output location to write the generated bindings to. [default: ] + -p, --prefixStrip The prefix to strip from the generated method bindings. [default: ] + -r, --remap A declaration name to be remapped to another name during binding generation. [default: ] + -std Language standard to compile for. [default: ] + -to, --test-output The output location to write the generated tests to. [default: ] + -t, --traverse A file name included either directly or indirectly by -f that should be traversed during binding generation. [default: ] + -v, --version Prints the current version information for the tool and its native dependencies. + -was, --with-access-specifier An access specifier to be used with the given qualified or remapped declaration name during binding generation. [default: ] + -wa, --with-attribute An attribute to be added to the given remapped declaration name during binding generation. [default: ] + -wcc, --with-callconv A calling convention to be used for the given declaration during binding generation. [default: ] + -wc, --with-class A class to be used for the given remapped constant or function declaration name during binding generation. [default: ] + -wlb, --with-librarypath A library path to be used for the given declaration during binding generation. [default: ] + -wn, --with-namespace A namespace to be used for the given remapped declaration name during binding generation. [default: ] + -wsle, --with-setlasterror Add the SetLastError=true modifier to a given DllImport or UnmanagedFunctionPointer. [default: ] + -wts, --with-transparent-struct A remapped type name to be treated as a transparent wrapper during binding generation. [default: ] + -wt, --with-type A type to be used for the given enum declaration during binding generation. [default: ] + -wu, --with-using A using directive to be included for the given remapped declaration name during binding generation. [default: ] + -?, -h, --help Show help and usage information ``` The available configuration options (visible with `-c help`) are: ``` --c, --config <> A configuration option that controls how the bindings are generated. Specify 'help' to see the available options. +--config, -c A configuration option that controls how the bindings are generated. Specify 'help' to see the available options. Options: - ?, h, help Show help and usage information for -c, --config - - compatible-codegen Bindings should be generated with .NET Standard 2.0 compatibility. Setting - this disables preview code generation. - latest-codegen Bindings should be generated for the latest stable version of .NET/C#. This - is currently .NET 5/C# 9. - preview-codegen Bindings should be generated for the latest preview version of .NET/C#. - This is currently .NET 6/C# 10. - - single-file Bindings should be generated to a single output file. This is the default. - multi-file Bindings should be generated so there is approximately one type per file. - - unix-types Bindings should be generated assuming Unix defaults. This is the default on - Unix platforms. - windows-types Bindings should be generated assuming Windows defaults. This is the default - on Windows platforms. - - exclude-anonymous-field-helpers The helper ref properties generated for fields in nested anonymous structs - and unions should not be generated. - exclude-com-proxies Types recognized as COM proxies should not have bindings generated. Thes - are currently function declarations ending with _UserFree, _UserMarshal, - _UserSize, _UserUnmarshal, _Proxy, or _Stub. - exclude-default-remappings Default remappings for well known types should not be added. This currently - includes intptr_t, ptrdiff_t, size_t, and uintptr_t - exclude-empty-records Bindings for records that contain no members should not be generated. These - are commonly encountered for opaque handle like types such as HWND. - exclude-enum-operators Bindings for operators over enum types should not be generated. These are - largely unnecessary in C# as the operators are available by default. - exclude-fnptr-codegen Generated bindings for latest or preview codegen should not use function - pointers. - exclude-funcs-with-body Bindings for functions with bodies should not be generated. - preview-codegen-nint Generated bindings for latest or preview codegen should not use nint or - nuint. - exclude-using-statics-for-enums Enum usages should be fully qualified and should not include a - corresponding 'using static EnumName;' - - explicit-vtbls VTBLs should have an explicit type generated with named fields per entry. - implicit-vtbls VTBLs should be implicit to reduce metadata bloat. This is the current - default - - generate-tests-nunit Basic tests validating size, blittability, and associated metadata should - be generated for NUnit. - generate-tests-xunit Basic tests validating size, blittability, and associated metadata should - be generated for XUnit. - - generate-aggressive-inlining [MethodImpl(MethodImplOptions.AggressiveInlining)] should be added to - generated helper functions. - generate-cpp-attributes [CppAttributeList("")] should be generated to document the encountered C++ - attributes. - generate-macro-bindings Bindings for macro-definitions should be generated. This currently only - works with value like macros and not function-like ones. - generate-template-bindings Bindings for template-definitions should be generated. This is currently - experimental. - generate-native-inheritance-attribute [NativeInheritance("")] attribute should be generated to document the - encountered C++ base type. - generate-vtbl-index-attribute [VtblIndex(#)] attribute should be generated to document the underlying - VTBL index for a helper method. - - log-exclusions Alist of excluded declaration types should be generated. This will also log - if the exclusion was due to an exact or partial match. - log-potential-typedef-remappings Alist of potential typedef remappings should be generated. This can help - identify missing remappings. - log-visited-files Alist of the visited files should be generated. This can help identify - traversal issues. + ?, h, help Show help and usage information for -c, --config + compatible-codegen Bindings should be generated with .NET Standard 2.0 compatibility. Setting this disables preview code generation. + latest-codegen Bindings should be generated for the latest stable version of .NET/C#. This is currently .NET 5/C# 9. + preview-codegen Bindings should be generated for the latest preview version of .NET/C#. This is currently .NET 6/C# 10. + single-file Bindings should be generated to a single output file. This is the default. + multi-file Bindings should be generated so there is approximately one type per file. + unix-types Bindings should be generated assuming Unix defaults. This is the default on Unix platforms. + windows-types Bindings should be generated assuming Windows defaults. This is the default on Windows platforms. + exclude-anonymous-field-helpers The helper ref properties generated for fields in nested anonymous structs and unions should not be generated. + exclude-com-proxies Types recognized as COM proxies should not have bindings generated. Thes are currently function declarations ending with _UserFree, _UserMarshal, _UserSize, _UserUnmarshal, _Proxy, or _Stub. + exclude-default-remappings Default remappings for well known types should not be added. This currently includes intptr_t, ptrdiff_t, size_t, and uintptr_t + exclude-empty-records Bindings for records that contain no members should not be generated. These are commonly encountered for opaque handle like types such as HWND. + exclude-enum-operators Bindings for operators over enum types should not be generated. These are largely unnecessary in C# as the operators are available by default. + exclude-fnptr-codegen Generated bindings for latest or preview codegen should not use function pointers. + exclude-funcs-with-body Bindings for functions with bodies should not be generated. + preview-codegen-nint Generated bindings for latest or preview codegen should not use nint or nuint. + exclude-using-statics-for-enums Enum usages should be fully qualified and should not include a corresponding 'using static EnumName;' + explicit-vtbls VTBLs should have an explicit type generated with named fields per entry. + implicit-vtbls VTBLs should be implicit to reduce metadata bloat. This is the current default + trimmable-vtbls VTBLs should be defined but not used in helper methods to reduce metadata bloat when trimming. + generate-tests-nunit Basic tests validating size, blittability, and associated metadata should be generated for NUnit. + generate-tests-xunit Basic tests validating size, blittability, and associated metadata should be generated for XUnit. + generate-aggressive-inlining [MethodImpl(MethodImplOptions.AggressiveInlining)] should be added to generated helper functions. + generate-cpp-attributes [CppAttributeList("")] should be generated to document the encountered C++ attributes. + generate-helper-types Code files should be generated for various helper attributes and declared transparent structs. + generate-macro-bindings Bindings for macro-definitions should be generated. This currently only works with value like macros and not function-like ones. + generate-marker-interfaces Bindings for marker interfaces representing native inheritance hierarchies should be generated. + generate-native-inheritance-attribute [NativeInheritance("")] attribute should be generated to document the encountered C++ base type. + generate-template-bindings Bindings for template-definitions should be generated. This is currently experimental. + 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. + 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. + log-potential-typedef-remappings A list of potential typedef remappings should be generated. This can help identify missing remappings. + log-visited-files A list of the visited files should be generated. This can help identify traversal issues. ``` ### Using locally built versions diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs index 845a4f12..c524a5d9 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs @@ -319,7 +319,7 @@ private void VisitEnumDecl(EnumDecl enumDecl) if (name.StartsWith("__AnonymousEnum_")) { isAnonymousEnum = true; - name = _config.MethodClassName; + name = GetClass(name); } StartUsingOutputBuilder(name); @@ -418,10 +418,14 @@ private void VisitFunctionDecl(FunctionDecl functionDecl) return; } + var name = GetRemappedCursorName(functionDecl); + var className = name; + if (functionDecl.DeclContext is not CXXRecordDecl cxxRecordDecl) { cxxRecordDecl = null; - StartUsingOutputBuilder(_config.MethodClassName); + className = GetClass(name); + StartUsingOutputBuilder(className); } else if ((Cursor)functionDecl.LexicalDeclContext != cxxRecordDecl) { @@ -430,7 +434,6 @@ private void VisitFunctionDecl(FunctionDecl functionDecl) } var accessSppecifier = GetAccessSpecifier(functionDecl); - var name = GetRemappedCursorName(functionDecl); var cxxMethodDecl = functionDecl as CXXMethodDecl; var body = functionDecl.Body; @@ -494,7 +497,9 @@ private void VisitFunctionDecl(FunctionDecl functionDecl) Location = functionDecl.Location }; - _outputBuilder.BeginFunctionOrDelegate(in desc, ref _isMethodClassUnsafe); + _ = _isTopLevelClassUnsafe.TryGetValue(className, out var isUnsafe); + _outputBuilder.BeginFunctionOrDelegate(in desc, ref isUnsafe); + _isTopLevelClassUnsafe[className] = isUnsafe; _outputBuilder.BeginFunctionInnerPrototype(escapedName); @@ -1121,8 +1126,10 @@ private void VisitRecordDecl(RecordDecl recordDecl) if (_testOutputBuilder != null) { + var className = GetClass(iidName); + _testOutputBuilder.AddUsingDirective("System"); - _testOutputBuilder.AddUsingDirective($"static {GetNamespace(_config.MethodClassName)}.{_config.MethodClassName}"); + _testOutputBuilder.AddUsingDirective($"static {GetNamespace(className)}.{className}"); _testOutputBuilder.WriteIndented("/// Validates that the of the ()); @@ -2817,6 +2832,7 @@ private void VisitVarDecl(VarDecl varDecl) } var openedOutputBuilder = false; + var className = GetClass(name); if (_outputBuilder is null) { @@ -2824,7 +2840,7 @@ private void VisitVarDecl(VarDecl varDecl) if (IsUnsafe(varDecl, type) && (!varDecl.HasInit || !IsStmtAsWritten(varDecl.Init, out _, removeParens: true))) { - _isMethodClassUnsafe = true; + _isTopLevelClassUnsafe[className] = true; } } @@ -2957,7 +2973,7 @@ private void VisitVarDecl(VarDecl varDecl) if (openedOutputBuilder) { - StartUsingOutputBuilder(_config.MethodClassName); + StartUsingOutputBuilder(className); if ((kind == ValueKind.String) && (typeName == "ReadOnlySpan")) { diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs index 5a989948..2dc443da 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs @@ -596,9 +596,11 @@ private void VisitDeclRefExpr(DeclRefExpr declRefExpr) { if (enumName.StartsWith("__AnonymousEnum_")) { - if (outputBuilder.Name != _config.MethodClassName) + var className = GetClass(enumName); + + if (outputBuilder.Name != className) { - outputBuilder.AddUsingDirective($"static {GetNamespace(_config.MethodClassName)}.{_config.MethodClassName}"); + outputBuilder.AddUsingDirective($"static {GetNamespace(enumName)}.{className}"); } } else @@ -615,23 +617,17 @@ private void VisitDeclRefExpr(DeclRefExpr declRefExpr) } else { - if (TryGetNamespace(name, out var namespaceName)) + if (TryGetClass(name, out var className)) { - var namespaceNameParts = namespaceName.Split(';'); - namespaceName = namespaceNameParts[0]; - - if (namespaceNameParts.Length == 2) - { - if ($"{_currentNamespace}.{outputBuilder.Name}" != namespaceName) - { - outputBuilder.AddUsingDirective($"static {namespaceName}.{namespaceNameParts[1]}"); - } - } - else if (_currentNamespace != namespaceName) + if (TryGetNamespace(className, out var namespaceName) && ((_currentNamespace != namespaceName) || (_currentClass != className))) { - outputBuilder.AddUsingDirective(namespaceName); + outputBuilder.AddUsingDirective($"static {namespaceName}.{className}"); } } + else if (TryGetNamespace(name, out var namespaceName) && (_currentNamespace != namespaceName)) + { + outputBuilder.AddUsingDirective(namespaceName); + } if (declRefExpr.Decl is FunctionDecl) { @@ -1351,7 +1347,7 @@ void HandleUnmanagedConstant(InitListExpr initListExpr, Type type, string typeNa if (_testOutputBuilder != null) { _testOutputBuilder.AddUsingDirective("System"); - _testOutputBuilder.AddUsingDirective($"static {GetNamespace(_config.MethodClassName)}.{_config.MethodClassName}"); + _testOutputBuilder.AddUsingDirective($"static {GetNamespace(_outputBuilder.Name)}.{_outputBuilder.Name}"); _testOutputBuilder.WriteIndented("/// Validates that the value of the > _validNameRemappings; private readonly Dictionary _overloadIndices; private readonly Dictionary _isExcluded; + private readonly Dictionary _isTopLevelClassUnsafe; + private readonly HashSet _topLevelClassNames; private readonly HashSet _usedRemappings; private string _filePath; private string[] _clangCommandLineArgs; private CXTranslationUnit_Flags _translationFlags; + private string _currentClass; private string _currentNamespace; private IOutputBuilder _outputBuilder; @@ -55,7 +58,6 @@ public sealed partial class PInvokeGenerator : IDisposable private int _testStmtOutputBuilderUsers; private int _outputBuilderUsers; private bool _disposed; - private bool _isMethodClassUnsafe; public PInvokeGenerator(PInvokeGeneratorConfiguration config, Func outputStreamFactory = null) { @@ -104,6 +106,8 @@ public PInvokeGenerator(PInvokeGeneratorConfiguration config, Func(); _isExcluded = new Dictionary(); + _isTopLevelClassUnsafe = new Dictionary(); + _topLevelClassNames = new HashSet(); _usedRemappings = new HashSet(); } @@ -127,8 +131,8 @@ public PInvokeGenerator(PInvokeGeneratorConfiguration config, Func(); + var methodClassTestOutputBuilders = new Dictionary(); var emitNamespaceDeclaration = true; var leaveStreamOpen = false; @@ -141,7 +145,7 @@ public void Close() continue; } - StartUsingOutputBuilder(_config.MethodClassName); + StartUsingOutputBuilder(GetClass(iidName)); _outputBuilder.WriteIid(iidName, foundUuid.Value); StopUsingOutputBuilder(); } @@ -229,11 +233,7 @@ public void Close() foreach (var outputBuilder in _outputBuilderFactory.OutputBuilders) { var outputPath = outputBuilder.IsTestOutput ? _config.TestOutputLocation : _config.OutputLocation; - - var methodClassName = _config.MethodClassName; - var methodClassTestName = $"{methodClassName}Tests"; - - var isMethodClass = methodClassName.Equals(outputBuilder.Name) || methodClassTestName.Equals(outputBuilder.Name); + var isMethodClass = _topLevelClassNames.Contains(outputBuilder.Name); if (_config.GenerateMultipleFiles) { @@ -245,11 +245,11 @@ public void Close() { if (outputBuilder.IsTestOutput) { - methodClassTestOutputBuilder = outputBuilder; + methodClassTestOutputBuilders.Add(outputBuilder.Name, outputBuilder); } else { - methodClassOutputBuilder = outputBuilder; + methodClassOutputBuilders.Add(outputBuilder.Name, outputBuilder); } continue; } @@ -270,14 +270,14 @@ public void Close() if (leaveStreamOpen && _outputBuilderFactory.OutputBuilders.Any()) { - if (methodClassOutputBuilder is not null) + foreach (var entry in methodClassOutputBuilders) { - CloseOutputBuilder(stream, methodClassOutputBuilder, isMethodClass: true, leaveStreamOpen, emitNamespaceDeclaration); + CloseOutputBuilder(stream, entry.Value, isMethodClass: true, leaveStreamOpen, emitNamespaceDeclaration); } - if (methodClassTestOutputBuilder is not null) + foreach (var entry in methodClassTestOutputBuilders) { - CloseOutputBuilder(stream, methodClassTestOutputBuilder, isMethodClass: true, leaveStreamOpen, emitNamespaceDeclaration); + CloseOutputBuilder(stream, entry.Value, isMethodClass: true, leaveStreamOpen, emitNamespaceDeclaration); } using var sw = new StreamWriter(stream, s_defaultStreamWriterEncoding, DefaultStreamWriterBufferSize, leaveStreamOpen); @@ -1270,18 +1270,13 @@ void ForCSharp(CSharpOutputBuilder csharpOutputBuilder) sw.Write("public static "); - if (_isMethodClassUnsafe) + if (_isTopLevelClassUnsafe.TryGetValue(nonTestName, out var isUnsafe) && isUnsafe) { sw.Write("unsafe "); } sw.Write("partial class "); - sw.Write(Config.MethodClassName); - - if (outputBuilder.IsTestOutput) - { - sw.Write("Tests"); - } + sw.Write(outputBuilder.Name); sw.WriteLine(); sw.Write(indentationString); @@ -1329,7 +1324,7 @@ void ForXml(XmlOutputBuilder xmlOutputBuilder) { sw.Write(indentationString); sw.Write(""); } @@ -1339,10 +1334,10 @@ void ForXml(XmlOutputBuilder xmlOutputBuilder) { sw.Write(indentationString); sw.Write(" namespaceName.Length) && (_currentNamespace[namespaceName.Length] != '.')) - { - needsUsing = true; - } + needsUsing = true; + } + else if ((_currentNamespace.Length > namespaceName.Length) && (_currentNamespace[namespaceName.Length] != '.')) + { + needsUsing = true; } } @@ -4870,6 +4859,7 @@ private void StartUsingOutputBuilder(string name, bool includeTestOutput = false // Set the current namespace so subsequent type lookups add the right using _currentNamespace = GetNamespace(name); + _currentClass = name; if (_outputBuilder != null) { @@ -4938,14 +4928,10 @@ void CreateTestOutputBuilder(string name) { _testOutputBuilder = _outputBuilderFactory.CreateTests(name); - if (name != $"{_config.MethodClassName}Tests") + if (!_topLevelClassNames.Contains(name)) { _testOutputBuilder.AddUsingDirective("System.Runtime.InteropServices"); } - else - { - - } if (_config.GenerateTestsNUnit) { @@ -4962,6 +4948,7 @@ private void StopUsingOutputBuilder() { if (_outputBuilderUsers == 1) { + _currentClass = null; _currentNamespace = null; _outputBuilder = null; _testOutputBuilder = null; @@ -5274,11 +5261,70 @@ private string GetLibraryPath(string remappedName) : libraryPath; } + private string GetClass(string remappedName, bool disallowPrefixMatch = false) + { + if (!TryGetClass(remappedName, out var className, disallowPrefixMatch)) + { + className = _config.DefaultClass; + _ = _topLevelClassNames.Add(className); + _ = _topLevelClassNames.Add($"{className}Tests"); + } + return className; + } + + private bool TryGetClass(string remappedName, out string className, bool disallowPrefixMatch = false) + { + var index = remappedName.IndexOf('*'); + + if (index != -1) + { + remappedName = remappedName[..index]; + } + + if (_config.WithClasses.TryGetValue(remappedName, out className)) + { + _ = _topLevelClassNames.Add(className); + _ = _topLevelClassNames.Add($"{className}Tests"); + return true; + } + + if (disallowPrefixMatch) + { + return false; + } + + foreach (var withClass in _config.WithClasses) + { + if (!withClass.Key.EndsWith("*")) + { + continue; + } + + var prefix = withClass.Key[0..^1]; + + if (remappedName.StartsWith(prefix)) + { + className = withClass.Value; + _ = _topLevelClassNames.Add(className); + _ = _topLevelClassNames.Add($"{className}Tests"); + return true; + } + } + return false; + } + private string GetNamespace(string remappedName) { if (!TryGetNamespace(remappedName, out var namespaceName)) { - namespaceName = _config.DefaultNamespace; + if (s_needsSystemSupportRegex.IsMatch(remappedName)) + { + namespaceName = "System"; + } + else + { + namespaceName = _config.DefaultNamespace; + } } return namespaceName; } diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs index ad61527f..be3a1c75 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs @@ -17,6 +17,7 @@ public sealed class PInvokeGeneratorConfiguration private readonly Dictionary _withAccessSpecifiers; private readonly Dictionary> _withAttributes; private readonly Dictionary _withCallConvs; + private readonly Dictionary _withClasses; private readonly Dictionary _withLibraryPaths; private readonly Dictionary _withNamespaces; private readonly Dictionary _withTransparentStructs; @@ -25,7 +26,7 @@ public sealed class PInvokeGeneratorConfiguration private PInvokeGeneratorConfigurationOptions _options; - public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, string outputLocation, string testOutputLocation, PInvokeGeneratorOutputMode outputMode = PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions options = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, string[] includedNames = null, string headerFile = null, string methodClassName = null, string methodPrefixToStrip = null, IReadOnlyDictionary remappedNames = null, string[] traversalNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null) + public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, string outputLocation, string testOutputLocation, PInvokeGeneratorOutputMode outputMode = PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions options = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, string[] includedNames = null, string headerFile = null, string methodClassName = null, string methodPrefixToStrip = null, IReadOnlyDictionary remappedNames = null, string[] traversalNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null) { if (excludedNames is null) { @@ -98,6 +99,7 @@ public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, s _withAccessSpecifiers = new Dictionary(); _withAttributes = new Dictionary>(); _withCallConvs = new Dictionary(); + _withClasses = new Dictionary(); _withLibraryPaths = new Dictionary(); _withNamespaces = new Dictionary(); _withTransparentStructs = new Dictionary(); @@ -108,7 +110,7 @@ public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, s HeaderText = string.IsNullOrWhiteSpace(headerFile) ? string.Empty : File.ReadAllText(headerFile); IncludedNames = includedNames; LibraryPath = $@"""{libraryPath}"""; - MethodClassName = methodClassName; + DefaultClass = methodClassName; MethodPrefixToStrip = methodPrefixToStrip; DefaultNamespace = namespaceName; OutputMode = outputMode; @@ -142,6 +144,7 @@ public PInvokeGeneratorConfiguration(string libraryPath, string namespaceName, s AddRange(_withAccessSpecifiers, withAccessSpecifiers, ConvertStringToAccessSpecifier); AddRange(_withAttributes, withAttributes); AddRange(_withCallConvs, withCallConvs); + AddRange(_withClasses, withClasses); AddRange(_withLibraryPaths, withLibraryPaths); AddRange(_withNamespaces, withNamespaces); AddRange(_withTransparentStructs, withTransparentStructs, RemoveAtPrefix); @@ -231,7 +234,7 @@ public bool ExcludeFnptrCodegen public bool GenerateSourceLocationAttribute => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); - public string MethodClassName { get; } + public string DefaultClass { get; } public string MethodPrefixToStrip { get;} @@ -255,6 +258,8 @@ public bool ExcludeFnptrCodegen public IReadOnlyDictionary WithCallConvs => _withCallConvs; + public IReadOnlyDictionary WithClasses => _withClasses; + public IReadOnlyDictionary WithLibraryPaths => _withLibraryPaths; public IReadOnlyDictionary WithNamespaces => _withNamespaces; diff --git a/sources/ClangSharpPInvokeGenerator/Program.cs b/sources/ClangSharpPInvokeGenerator/Program.cs index c2a038c1..d31a85ff 100644 --- a/sources/ClangSharpPInvokeGenerator/Program.cs +++ b/sources/ClangSharpPInvokeGenerator/Program.cs @@ -114,6 +114,7 @@ public static async Task Main(params string[] args) AddWithAccessSpecifierOption(s_rootCommand); AddWithAttributeOption(s_rootCommand); AddWithCallConvOption(s_rootCommand); + AddWithClassOption(s_rootCommand); AddWithLibraryPathOption(s_rootCommand); AddWithNamespaceOption(s_rootCommand); AddWithSetLastErrorOption(s_rootCommand); @@ -150,6 +151,7 @@ public static int Run(InvocationContext context) var withAccessSpecifierNameValuePairs = context.ParseResult.ValueForOption("--with-access-specifier"); var withAttributeNameValuePairs = context.ParseResult.ValueForOption("--with-attribute"); var withCallConvNameValuePairs = context.ParseResult.ValueForOption("--with-callconv"); + var withClassNameValuePairs = context.ParseResult.ValueForOption("--with-class"); var withLibraryPathNameValuePairs = context.ParseResult.ValueForOption("--with-librarypath"); var withNamespaceNameValuePairs = context.ParseResult.ValueForOption("--with-namespace"); var withSetLastErrors = context.ParseResult.ValueForOption("--with-setlasterror"); @@ -191,6 +193,7 @@ public static int Run(InvocationContext context) ParseKeyValuePairs(withAccessSpecifierNameValuePairs, errorList, out Dictionary withAccessSpecifiers); ParseKeyValuePairs(withAttributeNameValuePairs, errorList, out Dictionary> withAttributes); ParseKeyValuePairs(withCallConvNameValuePairs, errorList, out Dictionary withCallConvs); + ParseKeyValuePairs(withClassNameValuePairs, errorList, out Dictionary withClasses); ParseKeyValuePairs(withLibraryPathNameValuePairs, errorList, out Dictionary withLibraryPath); ParseKeyValuePairs(withNamespaceNameValuePairs, errorList, out Dictionary withNamespaces); ParseKeyValuePairs(withTransparentStructNameValuePairs, errorList, out Dictionary withTransparentStructs); @@ -532,7 +535,7 @@ public static int Run(InvocationContext context) translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes; // Include attributed types in CXType translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes; // Implicit attributes should be visited - var config = new PInvokeGeneratorConfiguration(libraryPath, namespaceName, outputLocation, testOutputLocation, outputMode, configOptions, excludedNames, includedNames, headerFile, methodClassName, methodPrefixToStrip, remappedNames, traversalNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPath, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings); + var config = new PInvokeGeneratorConfiguration(libraryPath, namespaceName, outputLocation, testOutputLocation, outputMode, configOptions, excludedNames, includedNames, headerFile, methodClassName, methodPrefixToStrip, remappedNames, traversalNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPath, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings); if (config.GenerateMacroBindings) { @@ -1033,6 +1036,19 @@ private static void AddWithCallConvOption(RootCommand rootCommand) rootCommand.AddOption(option); } + private static void AddWithClassOption(RootCommand rootCommand) + { + var option = new Option( + aliases: new string[] { "--with-class", "-wc" }, + description: "A class to be used for the given remapped constant or function declaration name during binding generation.", + argumentType: typeof(string), + getDefaultValue: Array.Empty, + arity: ArgumentArity.OneOrMore + ); + + rootCommand.AddOption(option); + } + private static void AddWithLibraryPathOption(RootCommand rootCommand) { var option = new Option( diff --git a/sources/ClangSharpPInvokeGenerator/Properties/launchSettings.json b/sources/ClangSharpPInvokeGenerator/Properties/launchSettings.json index 6b3e27d3..41b61022 100644 --- a/sources/ClangSharpPInvokeGenerator/Properties/launchSettings.json +++ b/sources/ClangSharpPInvokeGenerator/Properties/launchSettings.json @@ -13,10 +13,5 @@ "commandName": "Project", "commandLineArgs": "\"@$(MSBuildProjectDirectory)/Properties/GenerateLLVM.rsp\" --file-directory \"$(LLVMIncludePath)\" --include-directory \"$(LLVMIncludePath)\" --libraryPath $(LibLLVMName)" }, - "GenerateLocal": { - "commandName": "Project", - "commandLineArgs": "@generate.rsp", - "workingDirectory": "C:\\Users\\tagoo\\Source\\repos\\terrafx.interop.windows\\generation\\um\\tpcshrd" - } } } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs index 518c572b..642f9bf6 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs @@ -36,23 +36,23 @@ public abstract class PInvokeGeneratorTest protected static string EscapeXml(string value) => new XText(value).ToString(); - protected static Task ValidateGeneratedCSharpLatestWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.None | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedCSharpLatestWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.None | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedCSharpLatestUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedCSharpLatestUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedCSharpCompatibleWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedCSharpCompatibleWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedCSharpCompatibleUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedCSharpCompatibleUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedXmlLatestWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null, [CallerFilePath] string filePath = "") => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.None | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs, filePath); + protected static Task ValidateGeneratedXmlLatestWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null, [CallerFilePath] string filePath = "") => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.None | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs, filePath); - protected static Task ValidateGeneratedXmlLatestUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedXmlLatestUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedXmlCompatibleWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedXmlCompatibleWindowsBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - protected static Task ValidateGeneratedXmlCompatibleUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); + protected static Task ValidateGeneratedXmlCompatibleUnixBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorConfigurationOptions additionalConfigOptions = PInvokeGeneratorConfigurationOptions.None, string[] excludedNames = null, IReadOnlyDictionary remappedNames = null, IReadOnlyDictionary withAccessSpecifiers = null, IReadOnlyDictionary> withAttributes = null, IReadOnlyDictionary withCallConvs = null, IReadOnlyDictionary withClasses = null, IReadOnlyDictionary withLibraryPaths = null, IReadOnlyDictionary withNamespaces = null, string[] withSetLastErrors = null, IReadOnlyDictionary withTransparentStructs = null, IReadOnlyDictionary withTypes = null, IReadOnlyDictionary> withUsings = null, IEnumerable expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[] commandlineArgs = null) => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, expectedDiagnostics, libraryPath, commandlineArgs); - private static async Task ValidateGeneratedBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorOutputMode outputMode, PInvokeGeneratorConfigurationOptions configOptions, string[] excludedNames, IReadOnlyDictionary remappedNames, IReadOnlyDictionary withAccessSpecifiers, IReadOnlyDictionary> withAttributes, IReadOnlyDictionary withCallConvs, IReadOnlyDictionary withLibraryPaths, IReadOnlyDictionary withNamespaces, string[] withSetLastErrors, IReadOnlyDictionary withTransparentStructs, IReadOnlyDictionary withTypes, IReadOnlyDictionary> withUsings, IEnumerable expectedDiagnostics, string libraryPath, string[] commandlineArgs, [CallerFilePath] string filePath = "") + private static async Task ValidateGeneratedBindingsAsync(string inputContents, string expectedOutputContents, PInvokeGeneratorOutputMode outputMode, PInvokeGeneratorConfigurationOptions configOptions, string[] excludedNames, IReadOnlyDictionary remappedNames, IReadOnlyDictionary withAccessSpecifiers, IReadOnlyDictionary> withAttributes, IReadOnlyDictionary withCallConvs, IReadOnlyDictionary withClasses, IReadOnlyDictionary withLibraryPaths, IReadOnlyDictionary withNamespaces, string[] withSetLastErrors, IReadOnlyDictionary withTransparentStructs, IReadOnlyDictionary withTypes, IReadOnlyDictionary> withUsings, IEnumerable expectedDiagnostics, string libraryPath, string[] commandlineArgs, [CallerFilePath] string filePath = "") { Assert.True(File.Exists(DefaultInputFileName)); @@ -64,7 +64,7 @@ private static async Task ValidateGeneratedBindingsAsync(string inputContents, s using var unsavedFile = CXUnsavedFile.Create(DefaultInputFileName, inputContents); var unsavedFiles = new CXUnsavedFile[] { unsavedFile }; - var config = new PInvokeGeneratorConfiguration(libraryPath, DefaultNamespaceName, Path.GetRandomFileName(), testOutputLocation: null, outputMode, configOptions, excludedNames, includedNames: null, headerFile: null, methodClassName: null, methodPrefixToStrip: null, remappedNames, traversalNames: null, withAccessSpecifiers, withAttributes, withCallConvs, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings); + var config = new PInvokeGeneratorConfiguration(libraryPath, DefaultNamespaceName, Path.GetRandomFileName(), testOutputLocation: null, outputMode, configOptions, excludedNames, includedNames: null, headerFile: null, methodClassName: null, methodPrefixToStrip: null, remappedNames, traversalNames: null, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings); using (var pinvokeGenerator = new PInvokeGenerator(config, (path) => outputStream)) {