From 1de7ad1bdd1a1e161d022e6ad6c4c5dd6deb3545 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 3 Mar 2023 13:49:11 -0800 Subject: [PATCH 1/4] Adding global.json --- ClangSharp.sln | 1 + global.json | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 global.json diff --git a/ClangSharp.sln b/ClangSharp.sln index 9775fc13..70727341 100644 --- a/ClangSharp.sln +++ b/ClangSharp.sln @@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Directory.Build.props = Directory.Build.props Directory.Build.targets = Directory.Build.targets Directory.Packages.props = Directory.Packages.props + global.json = global.json LICENSE.md = LICENSE.md NOTICE.md = NOTICE.md NuGet.config = NuGet.config diff --git a/global.json b/global.json new file mode 100644 index 00000000..f5cfe250 --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "7.0.100", + "allowPrerelease": false, + "rollForward": "latestFeature" + } +} From c87aa6ea7c323160329e06ef0c6add0637ec5acf Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 3 Mar 2023 13:55:28 -0800 Subject: [PATCH 2/4] Add a README note covering the potential native dependency resolution issue --- README.md | 4 +++- .../ClangSharp.Interop/Extensions/clang.ResolveLibrary.cs | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2b13c1c2..77f1bbab 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,13 @@ ClangSharp provides Clang bindings written in C#. It is self-hosted and auto-gen A nuget package for the project is provided here: https://www.nuget.org/packages/clangsharp. A .NET tool for the P/Invoke generator project is provided here: https://www.nuget.org/packages/ClangSharpPInvokeGenerator +**NOTE:** If you are running as a dotnet tool, you may need to manually copy the appropriate DLLs from NuGet due to limitations in the dotnet tool support. + A convenience package which provides the native libClang library for several platforms is provided here: https://www.nuget.org/packages/libclang A helper package which exposes many Clang APIs missing from libClang is provided here: https://www.nuget.org/packages/libClangSharp -NOTE: libclang and libClangSharp are meta-packages which point to the platform-specific runtime packages ([e.g.](https://www.nuget.org/packages/libClangSharp.runtime.win-x64/15.0.0); see others owned by [tannergooding](https://www.nuget.org/profiles/tannergooding)). Several manual steps may be required to use them, see discussion in [#46](https://github.com/dotnet/ClangSharp/issues/46) and [#118](https://github.com/dotnet/ClangSharp/issues/118). +**NOTE:** libclang and libClangSharp are meta-packages which point to the platform-specific runtime packages ([e.g.](https://www.nuget.org/packages/libClangSharp.runtime.win-x64/15.0.0); see others owned by [tannergooding](https://www.nuget.org/profiles/tannergooding)). Several manual steps may be required to use them, see discussion in [#46](https://github.com/dotnet/ClangSharp/issues/46) and [#118](https://github.com/dotnet/ClangSharp/issues/118). Nightly packages are available via the NuGet Feed URL: https://pkgs.clangsharp.dev/index.json diff --git a/sources/ClangSharp.Interop/Extensions/clang.ResolveLibrary.cs b/sources/ClangSharp.Interop/Extensions/clang.ResolveLibrary.cs index 98a03d72..d9198785 100644 --- a/sources/ClangSharp.Interop/Extensions/clang.ResolveLibrary.cs +++ b/sources/ClangSharp.Interop/Extensions/clang.ResolveLibrary.cs @@ -25,8 +25,12 @@ private static IntPtr OnDllImport(string libraryName, Assembly assembly, DllImpo if (result == IntPtr.Zero) { - Console.WriteLine("Failed to resolve libClang or libClangSharp."); - Console.WriteLine("If you are running as a dotnet tool, you may need to manually copy the appropriate DLLs from NuGet due to limitations in the dotnet tool support."); + Console.WriteLine(); + Console.WriteLine("*****IMPORTANT*****"); + Console.WriteLine($"Failed to resolve {libraryName}."); + Console.WriteLine("If you are running as a dotnet tool, you may need to manually copy the appropriate DLLs from NuGet due to limitations in the dotnet tool support. Please see https://github.com/dotnet/clangsharp for more details."); + Console.WriteLine("*****IMPORTANT*****"); + Console.WriteLine(); } return result; } From 4bc909eb4339c493419b9b1816209a783f05f58c Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 3 Mar 2023 14:25:21 -0800 Subject: [PATCH 3/4] Adding a differentiator between "LTS" (default) and "STS" (latest) codegen --- .../CSharp/CSharpOutputBuilder.VisitDecl.cs | 2 +- .../PInvokeGenerator.VisitDecl.cs | 8 +- .../PInvokeGenerator.VisitStmt.cs | 2 +- .../PInvokeGenerator.cs | 2 +- .../PInvokeGeneratorConfiguration.cs | 17 + .../PInvokeGeneratorConfigurationOptions.cs | 2 + sources/ClangSharpPInvokeGenerator/Program.cs | 26 +- .../CXXMethodDeclarationTest.cs | 919 ++++++++ .../DeprecatedToObsoleteTest.cs | 504 +++++ .../CSharpDefaultUnix/EnumDeclarationTest.cs | 611 +++++ .../FunctionDeclarationBodyImportTest.cs | 1777 +++++++++++++++ .../FunctionDeclarationDllImportTest.cs | 399 ++++ .../FunctionPointerDeclarationTest.cs | 74 + .../StructDeclarationTest.cs | 1777 +++++++++++++++ .../CSharpDefaultUnix/UnionDeclarationTest.cs | 1442 ++++++++++++ .../CSharpDefaultUnix/VarDeclarationTest.cs | 398 ++++ .../CXXMethodDeclarationTest.cs | 919 ++++++++ .../DeprecatedToObsoleteTest.cs | 504 +++++ .../EnumDeclarationTest.cs | 610 +++++ .../FunctionDeclarationBodyImportTest.cs | 1777 +++++++++++++++ .../FunctionDeclarationDllImportTest.cs | 416 ++++ .../FunctionPointerDeclarationTest.cs | 74 + .../StructDeclarationTest.cs | 1781 +++++++++++++++ .../UnionDeclarationTest.cs | 1448 ++++++++++++ .../VarDeclarationTest.cs | 398 ++++ .../CSharpLatestUnix/EnumDeclarationTest.cs | 2 +- .../FunctionDeclarationBodyImportTest.cs | 6 +- .../CSharpLatestUnix/StructDeclarationTest.cs | 51 +- .../CSharpLatestUnix/UnionDeclarationTest.cs | 35 +- .../CSharpLatestUnix/VarDeclarationTest.cs | 14 +- .../EnumDeclarationTest.cs | 1 + .../FunctionDeclarationBodyImportTest.cs | 6 +- .../StructDeclarationTest.cs | 51 +- .../UnionDeclarationTest.cs | 35 +- .../CSharpLatestWindows/VarDeclarationTest.cs | 14 +- .../PInvokeGeneratorTest.cs | 16 +- .../CXXMethodDeclarationTest.cs | 1063 +++++++++ .../DeprecatedToObsoleteTest.cs | 535 +++++ .../XmlDefaultUnix/EnumDeclarationTest.cs | 730 ++++++ .../FunctionDeclarationBodyImportTest.cs | 1990 +++++++++++++++++ .../FunctionDeclarationDllImportTest.cs | 452 ++++ .../FunctionPointerDeclarationTest.cs | 80 + .../XmlDefaultUnix/StructDeclarationTest.cs | 1785 +++++++++++++++ .../XmlDefaultUnix/UnionDeclarationTest.cs | 1333 +++++++++++ .../XmlDefaultUnix/VarDeclarationTest.cs | 533 +++++ .../CXXMethodDeclarationTest.cs | 1063 +++++++++ .../DeprecatedToObsoleteTest.cs | 535 +++++ .../XmlDefaultWindows/EnumDeclarationTest.cs | 730 ++++++ .../FunctionDeclarationBodyImportTest.cs | 1990 +++++++++++++++++ .../FunctionDeclarationDllImportTest.cs | 452 ++++ .../FunctionPointerDeclarationTest.cs | 80 + .../StructDeclarationTest.cs | 1791 +++++++++++++++ .../XmlDefaultWindows/UnionDeclarationTest.cs | 1339 +++++++++++ .../XmlDefaultWindows/VarDeclarationTest.cs | 533 +++++ .../FunctionDeclarationBodyImportTest.cs | 2 +- .../XmlLatestUnix/StructDeclarationTest.cs | 12 +- .../XmlLatestUnix/UnionDeclarationTest.cs | 10 +- .../XmlLatestUnix/VarDeclarationTest.cs | 22 +- .../FunctionDeclarationBodyImportTest.cs | 2 +- .../XmlLatestWindows/StructDeclarationTest.cs | 12 +- .../XmlLatestWindows/UnionDeclarationTest.cs | 10 +- .../XmlLatestWindows/VarDeclarationTest.cs | 15 +- 62 files changed, 33104 insertions(+), 113 deletions(-) create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/CXXMethodDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/DeprecatedToObsoleteTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/EnumDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionDeclarationBodyImportTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionDeclarationDllImportTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionPointerDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/StructDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/UnionDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/VarDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/CXXMethodDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DeprecatedToObsoleteTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/EnumDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionDeclarationBodyImportTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionDeclarationDllImportTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionPointerDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/StructDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/UnionDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/VarDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/CXXMethodDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DeprecatedToObsoleteTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/EnumDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionDeclarationBodyImportTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionDeclarationDllImportTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionPointerDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/StructDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/UnionDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/VarDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/CXXMethodDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DeprecatedToObsoleteTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/EnumDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionDeclarationBodyImportTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionDeclarationDllImportTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionPointerDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/StructDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/UnionDeclarationTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/VarDeclarationTest.cs diff --git a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs index 5d87fc1f..1a321b09 100644 --- a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs +++ b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.VisitDecl.cs @@ -801,7 +801,7 @@ public void BeginStruct(in StructDesc desc) Write(".Interface"); } - if ((desc.Uuid is not null) && _config.GenerateGuidMember && _config.GeneratePreviewCode) + if ((desc.Uuid is not null) && _config.GenerateGuidMember && _config.GenerateLatestCode) { Write(desc.HasVtbl ? ", " : " : "); Write("INativeGuid"); diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs index b2dacb15..43d1fc54 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitDecl.cs @@ -919,7 +919,7 @@ private void VisitIndirectFieldDecl(IndirectFieldDecl indirectFieldDecl) ParentName = GetRemappedCursorName(parent), Offset = null, NeedsNewKeyword = false, - NeedsUnscopedRef = _config.GeneratePreviewCode && !fieldDecl.IsBitField, + NeedsUnscopedRef = _config.GenerateLatestCode && !fieldDecl.IsBitField, Location = fieldDecl.Location, HasBody = true, WriteCustomAttrs = static context => { @@ -2937,7 +2937,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co } else { - _outputBuilder.BeginIndexer(AccessSpecifier.Public, isUnsafe: false, needsUnscopedRef: _config.GeneratePreviewCode); + _outputBuilder.BeginIndexer(AccessSpecifier.Public, isUnsafe: false, needsUnscopedRef: _config.GenerateLatestCode); _outputBuilder.WriteIndexer($"ref {arrayTypeName}"); _outputBuilder.BeginIndexerParameters(); var param = new ParameterDesc { @@ -2979,7 +2979,7 @@ void VisitConstantOrIncompleteArrayFieldDecl(RecordDecl recordDecl, FieldDecl co ReturnType = $"Span<{arrayTypeName}>", Location = constantOrIncompleteArray.Location, HasBody = true, - NeedsUnscopedRef = _config.GeneratePreviewCode, + NeedsUnscopedRef = _config.GenerateLatestCode, }; var isUnsafe = false; @@ -3354,7 +3354,7 @@ private void VisitVarDecl(VarDecl varDecl) case CX_CharacterKind.CX_CLK_UTF32: { - if (_config.GeneratePreviewCode && flags.HasFlag(ValueFlags.Constant)) + if (_config.GenerateLatestCode && flags.HasFlag(ValueFlags.Constant)) { typeName = "ReadOnlySpan"; } diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs index f85a9ecc..ba1faf1c 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs @@ -2472,7 +2472,7 @@ private void VisitStringLiteral(StringLiteral stringLiteral) case CX_CharacterKind.CX_CLK_Ascii: case CX_CharacterKind.CX_CLK_UTF8: { - if (Config.GeneratePreviewCode) + if (Config.GenerateLatestCode) { outputBuilder.Write('"'); outputBuilder.Write(EscapeString(stringLiteral.String)); diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs index 2d5e1010..56ca0824 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.cs @@ -326,7 +326,7 @@ public void Close() foreach (var entry in methodClassOutputBuilders) { - var hasGuidMember = _config.GenerateGuidMember && _config.GeneratePreviewCode; + var hasGuidMember = _config.GenerateGuidMember && _config.GenerateLatestCode; hasGuidMember &= _uuidsToGenerate.ContainsKey(entry.Value.Name) || _generatedUuids.Contains(entry.Value.Name); CloseOutputBuilder(stream, entry.Value, isMethodClass: true, leaveStreamOpen, emitNamespaceDeclaration); diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs index cb11991b..97c771bf 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfiguration.cs @@ -106,6 +106,21 @@ public PInvokeGeneratorConfiguration(string defaultNamespace, string outputLocat { throw new ArgumentOutOfRangeException(nameof(options)); } + else if (options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode) && options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateLatestCode)) + { + throw new ArgumentOutOfRangeException(nameof(options)); + } + else if (options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateLatestCode) && options.HasFlag(PInvokeGeneratorConfigurationOptions.GeneratePreviewCode)) + { + throw new ArgumentOutOfRangeException(nameof(options)); + } + + if (options.HasFlag(PInvokeGeneratorConfigurationOptions.GeneratePreviewCode)) + { + // While users shouldn't have passed it in like this, we can simplify + // our own downstream checks be having preview also opt into "latest". + options |= PInvokeGeneratorConfigurationOptions.GenerateLatestCode; + } _options = options; if (!_options.HasFlag(PInvokeGeneratorConfigurationOptions.NoDefaultRemappings)) @@ -205,6 +220,8 @@ public IReadOnlyCollection ExcludedNames public bool GenerateHelperTypes => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateHelperTypes); + public bool GenerateLatestCode => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateLatestCode); + public bool GenerateMacroBindings => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMacroBindings); public bool GenerateMarkerInterfaces => _options.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMarkerInterfaces); diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfigurationOptions.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfigurationOptions.cs index 839aa280..dd34e2a1 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfigurationOptions.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGeneratorConfigurationOptions.cs @@ -76,4 +76,6 @@ public enum PInvokeGeneratorConfigurationOptions : ulong GenerateDocIncludes = 1UL << 32, GenerateGuidMember = 1UL << 33, + + GenerateLatestCode = 1UL << 34, } diff --git a/sources/ClangSharpPInvokeGenerator/Program.cs b/sources/ClangSharpPInvokeGenerator/Program.cs index f6b76784..98e8a488 100644 --- a/sources/ClangSharpPInvokeGenerator/Program.cs +++ b/sources/ClangSharpPInvokeGenerator/Program.cs @@ -67,8 +67,9 @@ public class Program // Codegen Options new TwoColumnHelpRow("compatible-codegen", "Bindings should be generated with .NET Standard 2.0 compatibility. Setting this disables preview code generation."), - new TwoColumnHelpRow("latest-codegen", "Bindings should be generated for the latest stable version of .NET/C#. This is currently .NET 6/C# 10."), - new TwoColumnHelpRow("preview-codegen", "Bindings should be generated for the latest preview version of .NET/C#. This is currently .NET 7/C# 11."), + new TwoColumnHelpRow("default-codegen", "Bindings should be generated for the current LTS version of .NET/C#. This is currently .NET 6/C# 10."), + new TwoColumnHelpRow("latest-codegen", "Bindings should be generated for the current STS version of .NET/C#. This is currently .NET 7/C# 11."), + new TwoColumnHelpRow("preview-codegen", "Bindings should be generated for the preview version of .NET/C#. This is currently .NET 8/C# 12."), // File Options @@ -209,13 +210,13 @@ static Program() public static IEnumerable GetExtendedHelp(HelpContext context) { foreach (var sectionDelegate in HelpBuilder.Default.GetLayout()) + { yield return sectionDelegate; + } - yield return _ => - { - Console.WriteLine( -@"Wildcards: -You can use * as catch-all rule for remapping procedures. For example if you want make all of your generated code internal you can use --with-access-specifier *=Internal."); + yield return _ => { + Console.WriteLine("Wildcards:"); + Console.WriteLine("You can use * as catch-all rule for remapping procedures. For example if you want make all of your generated code internal you can use --with-access-specifier *=Internal."); }; } @@ -339,6 +340,15 @@ public static void Run(InvocationContext context) case "compatible-codegen": { configOptions |= PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode; + configOptions &= ~PInvokeGeneratorConfigurationOptions.GenerateLatestCode; + configOptions &= ~PInvokeGeneratorConfigurationOptions.GeneratePreviewCode; + break; + } + + case "default-codegen": + { + configOptions &= ~PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode; + configOptions &= ~PInvokeGeneratorConfigurationOptions.GenerateLatestCode; configOptions &= ~PInvokeGeneratorConfigurationOptions.GeneratePreviewCode; break; } @@ -346,6 +356,7 @@ public static void Run(InvocationContext context) case "latest-codegen": { configOptions &= ~PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode; + configOptions |= PInvokeGeneratorConfigurationOptions.GenerateLatestCode; configOptions &= ~PInvokeGeneratorConfigurationOptions.GeneratePreviewCode; break; } @@ -353,6 +364,7 @@ public static void Run(InvocationContext context) case "preview-codegen": { configOptions &= ~PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode; + configOptions &= ~PInvokeGeneratorConfigurationOptions.GenerateLatestCode; configOptions |= PInvokeGeneratorConfigurationOptions.GeneratePreviewCode; break; } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/CXXMethodDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/CXXMethodDeclarationTest.cs new file mode 100644 index 00000000..f1edb2b3 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/CXXMethodDeclarationTest.cs @@ -0,0 +1,919 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultUnix_CXXMethodDeclarationTest : CXXMethodDeclarationTest +{ + protected override Task ConstructorTestImpl() + { + var inputContents = @"struct MyStruct +{ + int _value; + + MyStruct(int value) + { + _value = value; + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int _value; + + public MyStruct(int value) + { + _value = value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConstructorWithInitializeTestImpl() + { + var inputContents = @"struct MyStruct +{ + int _x; + int _y; + int _z; + + MyStruct(int x) : _x(x) + { + } + + MyStruct(int x, int y) : _x(x), _y(y) + { + } + + MyStruct(int x, int y, int z) : _x(x), _y(y), _z() + { + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int _x; + + public int _y; + + public int _z; + + public MyStruct(int x) + { + _x = x; + } + + public MyStruct(int x, int y) + { + _x = x; + _y = y; + } + + public MyStruct(int x, int y, int z) + { + _x = x; + _y = y; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConversionTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + operator int() + { + return value; + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public int ToInt32() + { + return value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DestructorTestImpl() + { + var inputContents = @"struct MyStruct +{ + ~MyStruct() + { + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public void Dispose() + { + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InstanceTestImpl() + { + var inputContents = @"struct MyStruct +{ + void MyVoidMethod(); + + int MyInt32Method() + { + return 0; + } + + void* MyVoidStarMethod() + { + return nullptr; + } +}; +"; + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "__ZN8MyStruct12MyVoidMethodEv" : "_ZN8MyStruct12MyVoidMethodEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + if (!Environment.Is64BitProcess) + { + entryPoint = "?MyVoidMethod@MyStruct@@QAEXXZ"; + } + else + { + entryPoint = "?MyVoidMethod@MyStruct@@QEAAXXZ"; + } + } + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.ThisCall, EntryPoint = ""{entryPoint}"", ExactSpelling = true)] + public static extern void MyVoidMethod(MyStruct* pThis); + + public int MyInt32Method() + {{ + return 0; + }} + + public void* MyVoidStarMethod() + {{ + return null; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberCallTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction1() + { + return value; + } + + int MyFunction2() + { + return MyFunction1(); + } + + int MyFunction3() + { + return this->MyFunction1(); + } +}; + +int MyFunctionA(MyStruct x) +{ + return x.MyFunction1(); +} + +int MyFunctionB(MyStruct* x) +{ + return x->MyFunction2(); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public int MyFunction1() + { + return value; + } + + public int MyFunction2() + { + return MyFunction1(); + } + + public int MyFunction3() + { + return this.MyFunction1(); + } + } + + public static unsafe partial class Methods + { + public static int MyFunctionA(MyStruct x) + { + return x.MyFunction1(); + } + + public static int MyFunctionB(MyStruct* x) + { + return x->MyFunction2(); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction() + { + return value; + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public int MyFunction() + { + return value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"struct MyStruct +{ + int Equals() { return 0; } + int Equals(int obj) { return 0; } + int Dispose() { return 0; } + int Dispose(int obj) { return 0; } + int GetHashCode() { return 0; } + int GetHashCode(int obj) { return 0; } + int GetType() { return 0; } + int GetType(int obj) { return 0; } + int MemberwiseClone() { return 0; } + int MemberwiseClone(int obj) { return 0; } + int ReferenceEquals() { return 0; } + int ReferenceEquals(int obj) { return 0; } + int ToString() { return 0; } + int ToString(int obj) { return 0; } +};"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public int Equals() + {{ + return 0; + }} + + public int Equals(int obj) + {{ + return 0; + }} + + public int Dispose() + {{ + return 0; + }} + + public int Dispose(int obj) + {{ + return 0; + }} + + public new int GetHashCode() + {{ + return 0; + }} + + public int GetHashCode(int obj) + {{ + return 0; + }} + + public new int GetType() + {{ + return 0; + }} + + public int GetType(int obj) + {{ + return 0; + }} + + public new int MemberwiseClone() + {{ + return 0; + }} + + public int MemberwiseClone(int obj) + {{ + return 0; + }} + + public int ReferenceEquals() + {{ + return 0; + }} + + public int ReferenceEquals(int obj) + {{ + return 0; + }} + + public new int ToString() + {{ + return 0; + }} + + public int ToString(int obj) + {{ + return 0; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordVirtualTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + public void** lpVtbl; + + public int GetType(int objA, int objB) + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + }} + + public new int GetType() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + public int GetType(int obj) + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this), obj); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordVirtualWithExplicitVtblTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var nativeCallConv = ""; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Environment.Is64BitProcess) + { + nativeCallConv = " __attribute__((thiscall))"; + } + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + public Vtbl* lpVtbl; + + public int GetType(int objA, int objB) + {{ + return lpVtbl->GetType((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + }} + + public new int GetType() + {{ + return lpVtbl->GetType1((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + public int GetType(int obj) + {{ + return lpVtbl->GetType2((MyStruct*)Unsafe.AsPointer(ref this), obj); + }} + + public partial struct Vtbl + {{ + [NativeTypeName(""int (int, int){nativeCallConv}"")] + public new delegate* unmanaged[Thiscall] GetType; + + [NativeTypeName(""int (){nativeCallConv}"")] + public delegate* unmanaged[Thiscall] GetType1; + + [NativeTypeName(""int (int){nativeCallConv}"")] + public delegate* unmanaged[Thiscall] GetType2; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateExplicitVtbls); + } + + protected override Task NewKeywordVirtualWithExplicitVtblAndMarkerInterfaceTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var nativeCallConv = ""; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Environment.Is64BitProcess) + { + nativeCallConv = " __attribute__((thiscall))"; + } + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct : MyStruct.Interface + {{ + public Vtbl* lpVtbl; + + public int GetType(int objA, int objB) + {{ + return lpVtbl->GetType((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + }} + + public new int GetType() + {{ + return lpVtbl->GetType1((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + public int GetType(int obj) + {{ + return lpVtbl->GetType2((MyStruct*)Unsafe.AsPointer(ref this), obj); + }} + + public interface Interface + {{ + int GetType(int objA, int objB); + + int GetType(); + + int GetType(int obj); + }} + + public partial struct Vtbl + where TSelf : unmanaged, Interface + {{ + [NativeTypeName(""int (int, int){nativeCallConv}"")] + public new delegate* unmanaged[Thiscall] GetType; + + [NativeTypeName(""int (){nativeCallConv}"")] + public delegate* unmanaged[Thiscall] GetType1; + + [NativeTypeName(""int (int){nativeCallConv}"")] + public delegate* unmanaged[Thiscall] GetType2; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateExplicitVtbls | PInvokeGeneratorConfigurationOptions.GenerateMarkerInterfaces); + } + + protected override Task OperatorTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + MyStruct(int value) : value(value) + { + } + + MyStruct operator+(MyStruct rhs) + { + return MyStruct(value + rhs.value); + } +}; + +MyStruct operator-(MyStruct lhs, MyStruct rhs) +{ + return MyStruct(lhs.value - rhs.value); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public MyStruct(int value) + { + this.value = value; + } + + public MyStruct Add(MyStruct rhs) + { + return new MyStruct(value + rhs.value); + } + } + + public static partial class Methods + { + public static MyStruct Subtract(MyStruct lhs, MyStruct rhs) + { + return new MyStruct(lhs.value - rhs.value); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task OperatorCallTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + MyStruct(int value) : value(value) + { + } + + MyStruct operator+(MyStruct rhs) + { + return MyStruct(value + rhs.value); + } +}; + +MyStruct MyFunction1(MyStruct lhs, MyStruct rhs) +{ + return lhs + rhs; +} + +MyStruct operator-(MyStruct lhs, MyStruct rhs) +{ + return MyStruct(lhs.value - rhs.value); +} + +MyStruct MyFunction2(MyStruct lhs, MyStruct rhs) +{ + return lhs - rhs; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public MyStruct(int value) + { + this.value = value; + } + + public MyStruct Add(MyStruct rhs) + { + return new MyStruct(value + rhs.value); + } + } + + public static partial class Methods + { + public static MyStruct MyFunction1(MyStruct lhs, MyStruct rhs) + { + return lhs.Add(rhs); + } + + public static MyStruct Subtract(MyStruct lhs, MyStruct rhs) + { + return new MyStruct(lhs.value - rhs.value); + } + + public static MyStruct MyFunction2(MyStruct lhs, MyStruct rhs) + { + return Subtract(lhs, rhs); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StaticTestImpl() + { + var inputContents = @"struct MyStruct +{ + static void MyVoidMethod(); + + static int MyInt32Method() + { + return 0; + } + + static void* MyVoidStarMethod() + { + return nullptr; + } +}; +"; + + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "?MyVoidMethod@MyStruct@@SAXXZ" : "_ZN8MyStruct12MyVoidMethodEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + entryPoint = $"_{entryPoint}"; + } + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, EntryPoint = ""{entryPoint}"", ExactSpelling = true)] + public static extern void MyVoidMethod(); + + public static int MyInt32Method() + {{ + return 0; + }} + + public static void* MyVoidStarMethod() + {{ + return null; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ThisTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction() + { + return this->value; + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public int MyFunction() + { + return this.value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnsafeDoesNotImpactDllImportTestImpl() + { + var inputContents = @"struct MyStruct +{ + void* MyVoidStarMethod() + { + return nullptr; + } +}; + +extern ""C"" void MyFunction();"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + public void* MyVoidStarMethod() + { + return null; + } + } + + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task VirtualTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual void MyVoidMethod() = 0; + + virtual char MyInt8Method() + { + return 0; + } + + virtual int MyInt32Method(); + + virtual void* MyVoidStarMethod() = 0; +}; +"; + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + public void** lpVtbl; + + public void MyVoidMethod() + {{ + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + [return: NativeTypeName(""char"")] + public sbyte MyInt8Method() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + public int MyInt32Method() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + public void* MyVoidStarMethod() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task VirtualWithVtblIndexAttributeTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual void MyVoidMethod() = 0; + + virtual char MyInt8Method() + { + return 0; + } + + virtual int MyInt32Method(); + + virtual void* MyVoidStarMethod() = 0; +}; +"; + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + public void** lpVtbl; + + [VtblIndex(0)] + public void MyVoidMethod() + {{ + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + [VtblIndex(1)] + [return: NativeTypeName(""char"")] + public sbyte MyInt8Method() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + [VtblIndex(2)] + public int MyInt32Method() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + [VtblIndex(3)] + public void* MyVoidStarMethod() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateVtblIndexAttribute); + } + + protected override Task ValidateBindingsAsync(string inputContents, string expectedOutputContents) => ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/DeprecatedToObsoleteTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/DeprecatedToObsoleteTest.cs new file mode 100644 index 00000000..9f6f7902 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/DeprecatedToObsoleteTest.cs @@ -0,0 +1,504 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultUnix_DeprecatedToObsoleteTest : DeprecatedToObsoleteTest +{ + protected override Task SimpleStructMembersImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + + [[deprecated]] + {nativeType} g; + + [[deprecated(""This is obsolete."")]] + {nativeType} b; + + {nativeType} a; +}}; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + [Obsolete] + public {expectedManagedType} g; + + [Obsolete(""This is obsolete."")] + public {expectedManagedType} b; + + public {expectedManagedType} a; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StructDeclImpl() + { + var inputContents = $@"struct MyStruct0 +{{ + int r; +}}; + +struct [[deprecated]] MyStruct1 +{{ + int r; +}}; + +struct [[deprecated(""This is obsolete."")]] MyStruct2 +{{ + int r; +}}; + +struct MyStruct3 +{{ + int r; +}}; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct0 + {{ + public int r; + }} + + [Obsolete] + public partial struct MyStruct1 + {{ + public int r; + }} + + [Obsolete(""This is obsolete."")] + public partial struct MyStruct2 + {{ + public int r; + }} + + public partial struct MyStruct3 + {{ + public int r; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleTypedefStructMembersImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct +{{ + {nativeType} r; + + [[deprecated]] + {nativeType} g; + + [[deprecated(""This is obsolete."")]] + {nativeType} b; + + {nativeType} a; +}} MyStruct; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + [Obsolete] + public {expectedManagedType} g; + + [Obsolete(""This is obsolete."")] + public {expectedManagedType} b; + + public {expectedManagedType} a; + }} +}} +"; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefStructDeclImpl() + { + var inputContents = $@"typedef struct +{{ + int r; +}} MyStruct0; + +[[deprecated]] typedef struct +{{ + int r; +}} MyStruct1; + +[[deprecated(""This is obsolete."")]] typedef struct +{{ + int r; +}} MyStruct2; + +typedef struct +{{ + int r; +}} MyStruct3; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct0 + {{ + public int r; + }} + + [Obsolete] + public partial struct MyStruct1 + {{ + public int r; + }} + + [Obsolete(""This is obsolete."")] + public partial struct MyStruct2 + {{ + public int r; + }} + + public partial struct MyStruct3 + {{ + public int r; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleEnumMembersImpl() + { + var inputContents = $@"enum MyEnum : int +{{ + MyEnum_Value0, + MyEnum_Value1 [[deprecated]], + MyEnum_Value2 [[deprecated(""This is obsolete."")]], + MyEnum_Value3, +}}; +"; + + var expectedOutputContents = @"using System; + +namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0, + [Obsolete] + MyEnum_Value1, + [Obsolete(""This is obsolete."")] + MyEnum_Value2, + MyEnum_Value3, + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task EnumDeclImpl() + { + var inputContents = $@"enum MyEnum0 : int +{{ + MyEnum_Value0, +}}; + +enum [[deprecated]] MyEnum1 : int +{{ + MyEnum_Value1, +}}; + +enum [[deprecated(""This is obsolete."")]] MyEnum2 : int +{{ + MyEnum_Value2, +}}; + + +enum MyEnum3 : int +{{ + MyEnum_Value3, +}}; +"; + + var expectedOutputContents = @"using System; + +namespace ClangSharp.Test +{ + public enum MyEnum0 + { + MyEnum_Value0, + } + + [Obsolete] + public enum MyEnum1 + { + MyEnum_Value1, + } + + [Obsolete(""This is obsolete."")] + public enum MyEnum2 + { + MyEnum_Value2, + } + + public enum MyEnum3 + { + MyEnum_Value3, + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleVarDeclImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@" +{nativeType} MyVariable0 = 0; + +[[deprecated]] +{nativeType} MyVariable1 = 0; + +[[deprecated(""This is obsolete."")]] +{nativeType} MyVariable2 = 0; + +{nativeType} MyVariable3 = 0;"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static {expectedManagedType} MyVariable0 = 0; + + [Obsolete] + public static {expectedManagedType} MyVariable1 = 0; + + [Obsolete(""This is obsolete."")] + public static {expectedManagedType} MyVariable2 = 0; + + public static {expectedManagedType} MyVariable3 = 0; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncDeclImpl() + { + var inputContents = @" +void MyFunction0() +{ +} + +[[deprecated]] +void MyFunction1() +{ +} + +[[deprecated(""This is obsolete."")]] +void MyFunction2() +{ +} + +void MyFunction3() +{ +} +"; + + var expectedOutputContents = @"using System; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyFunction0() + { + } + + [Obsolete] + public static void MyFunction1() + { + } + + [Obsolete(""This is obsolete."")] + public static void MyFunction2() + { + } + + public static void MyFunction3() + { + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InstanceFuncImpl() + { + var inputContents = @"struct MyStruct +{ + int MyFunction0() { return 0; } + + [[deprecated]] + int MyFunction1() { return 0; } + + [[deprecated(""This is obsolete."")]] + int MyFunction2() { return 0; } + + int MyFunction3() { return 0; } +};"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public int MyFunction0() + {{ + return 0; + }} + + [Obsolete] + public int MyFunction1() + {{ + return 0; + }} + + [Obsolete(""This is obsolete."")] + public int MyFunction2() + {{ + return 0; + }} + + public int MyFunction3() + {{ + return 0; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncPtrDeclImpl() + { + var inputContents = @" +typedef void (*Callback0)(); +[[deprecated]] typedef void (*Callback1)(); +[[deprecated(""This is obsolete."")]] typedef void (*Callback2)(); +typedef void (*Callback3)(); + +struct MyStruct0 { + Callback0 _callback; +}; +struct MyStruct1 { + Callback1 _callback; +}; +struct MyStruct2 { + Callback2 _callback; +}; +struct MyStruct3 { + Callback3 _callback; +}; +"; + + var expectedOutputContents = @"using System; + +namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct0 + { + [NativeTypeName(""Callback0"")] + public delegate* unmanaged[Cdecl] _callback; + } + + public unsafe partial struct MyStruct1 + { + [NativeTypeName(""Callback1"")] + [Obsolete] + public delegate* unmanaged[Cdecl] _callback; + } + + public unsafe partial struct MyStruct2 + { + [NativeTypeName(""Callback2"")] + [Obsolete(""This is obsolete."")] + public delegate* unmanaged[Cdecl] _callback; + } + + public unsafe partial struct MyStruct3 + { + [NativeTypeName(""Callback3"")] + public delegate* unmanaged[Cdecl] _callback; + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncDllImportImpl() + { + var inputContents = @" +extern ""C"" void MyFunction0(); +extern ""C"" [[deprecated]] void MyFunction1(); +extern ""C"" [[deprecated(""This is obsolete."")]] void MyFunction2(); +extern ""C"" void MyFunction3();"; + + var expectedOutputContents = @"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction0(); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [Obsolete] + public static extern void MyFunction1(); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [Obsolete(""This is obsolete."")] + public static extern void MyFunction2(); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction3(); + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/EnumDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/EnumDeclarationTest.cs new file mode 100644 index 00000000..08b3d3a1 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/EnumDeclarationTest.cs @@ -0,0 +1,611 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultUnix_EnumDeclarationTest : EnumDeclarationTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicValueTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value1 = 1, + MyEnum_Value2, + MyEnum_Value3, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value1 = 1, + MyEnum_Value2, + MyEnum_Value3, + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyEnum" }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task ExplicitTypedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"enum MyEnum : {nativeType} +{{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public enum MyEnum : {expectedManagedType} + {{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExplicitTypedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"enum MyEnum : {nativeType} +{{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + [NativeTypeName(""{nativeType}"")] + public enum MyEnum : {expectedManagedType} + {{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = @"typedef enum _MyEnum1 : int +{ + MyEnum1_Value1, + MyEnum1_Value2, + MyEnum1_Value3, +} MyEnum1; + +namespace Namespace1 +{ + namespace Namespace2 + { + typedef enum _MyEnum2 : int + { + MyEnum2_Value1, + MyEnum2_Value2, + MyEnum2_Value3, + } MyEnum2; + + typedef enum _MyEnum3 : int + { + MyEnum3_Value1, + MyEnum3_Value2, + MyEnum3_Value3, + } MyEnum3; + + typedef enum _MyEnum4 : int + { + MyEnum4_Value1, + MyEnum4_Value2, + MyEnum4_Value3, + } MyEnum4; + } +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value1, + MyEnum1_Value2, + MyEnum1_Value3, + } + + public enum MyEnum2 + { + MyEnum2_Value1, + MyEnum2_Value2, + MyEnum2_Value3, + } + + public enum MyEnum3 + { + MyEnum3_Value1, + MyEnum3_Value2, + MyEnum3_Value3, + } + + public enum MyEnum4 + { + MyEnum4_Value1, + MyEnum4_Value2, + MyEnum4_Value3, + } +} +"; + + var remappedNames = new Dictionary { ["_MyEnum1"] = "MyEnum1", ["Namespace1.Namespace2._MyEnum2"] = "MyEnum2", ["_MyEnum3"] = "MyEnum3", ["Namespace1::Namespace2::_MyEnum4"] = "MyEnum4" }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task WithAttributeTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = 1, +}; +"; + + var expectedOutputContents = @"using System; + +namespace ClangSharp.Test +{ + [Flags] + public enum MyEnum1 + { + MyEnum1_Value1 = 1, + } + + public enum MyEnum2 + { + MyEnum2_Value1 = 1, + } +} +"; + + var withAttributes = new Dictionary> + { + ["MyEnum1"] = new List() { "Flags" } + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withAttributes: withAttributes); + } + + protected override Task WithNamespaceTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @"using static ClangSharp.Test.MyEnum1; + +namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value1 = 1, + } + + public enum MyEnum2 + { + MyEnum2_Value1 = MyEnum1_Value1, + } +} +"; + + var withNamespaces = new Dictionary> + { + ["MyEnum1"] = new List() { "static ClangSharp.Test.MyEnum1" } + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithNamespaceStarTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @"using static ClangSharp.Test.MyEnum1; + +namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value1 = 1, + } + + public enum MyEnum2 + { + MyEnum2_Value1 = MyEnum1_Value1, + } +} +"; + + var withNamespaces = new Dictionary> + { + ["*"] = new List() { "static ClangSharp.Test.MyEnum1" } + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithNamespaceStarPlusTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @"using System; +using static ClangSharp.Test.MyEnum1; + +namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value1 = 1, + } + + public enum MyEnum2 + { + MyEnum2_Value1 = MyEnum1_Value1, + } +} +"; + + var withNamespaces = new Dictionary> + { + ["*"] = new List() { "static ClangSharp.Test.MyEnum1" }, + ["MyEnum2"] = new List() { "System" } + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithCastToEnumTypeImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0 = (MyEnum) 10, + MyEnum_Value1 = (MyEnum) MyEnum_Value0, + MyEnum_Value2 = ((MyEnum) 10) + MyEnum_Value1, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0 = (int)(MyEnum)(10), + MyEnum_Value1 = (int)(MyEnum)(MyEnum_Value0), + MyEnum_Value2 = ((int)(MyEnum)(10)) + MyEnum_Value1, + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithMultipleEnumsTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 = 10, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 = MyEnum1_Value0, + MyEnum2_Value1 = MyEnum1_Value0 + (MyEnum1) 10, +}; +"; + + var expectedOutputContents = @"using static ClangSharp.Test.MyEnum1; + +namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value0 = 10, + } + + public enum MyEnum2 + { + MyEnum2_Value0 = MyEnum1_Value0, + MyEnum2_Value1 = MyEnum1_Value0 + (int)(MyEnum1)(10), + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithImplicitConversionTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = 0x80000000, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = unchecked((int)(0x80000000)), + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithTypeTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + [NativeTypeName(""int"")] + public enum MyEnum : uint + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + } +} +"; + + var withTypes = new Dictionary { + ["MyEnum"] = "uint" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeAndImplicitConversionTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = 0x80000000, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + [NativeTypeName(""int"")] + public enum MyEnum : uint + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = 0x80000000, + } +} +"; + + var withTypes = new Dictionary + { + ["MyEnum"] = "uint" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeStarTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + [NativeTypeName(""int"")] + public enum MyEnum1 : uint + { + MyEnum1_Value0, + } + + [NativeTypeName(""int"")] + public enum MyEnum2 : uint + { + MyEnum2_Value0, + } +} +"; + + var withTypes = new Dictionary + { + ["*"] = "uint" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeStarOverrideTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value0, + } + + [NativeTypeName(""int"")] + public enum MyEnum2 : uint + { + MyEnum2_Value0, + } +} +"; + + var withTypes = new Dictionary + { + ["*"] = "uint", + ["MyEnum1"] = "int", + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithAnonymousEnumTestImpl() + { + var inputContents = @"enum +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @"using static ClangSharp.Test.Methods; + +namespace ClangSharp.Test +{ + public enum MyEnum2 + { + MyEnum2_Value1 = MyEnum1_Value1, + } + + public static partial class Methods + { + public const int MyEnum1_Value1 = 1; + } +} +"; + + var diagnostics = new[] { new Diagnostic(DiagnosticLevel.Info, "Found anonymous enum: __AnonymousEnum_ClangUnsavedFile_L1_C1. Mapping values as constants in: Methods", "Line 1, Column 1 in ClangUnsavedFile.h") }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } + + protected override Task WithReferenceToAnonymousEnumEnumeratorTestImpl() + { + var inputContents = @"enum +{ + MyEnum1_Value1 = 1, +}; + +const int MyEnum2_Value1 = MyEnum1_Value1 + 1; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public const int MyEnum1_Value1 = 1; + + [NativeTypeName(""const int"")] + public const int MyEnum2_Value1 = (int)(MyEnum1_Value1) + 1; + } +} +"; + var diagnostics = new[] { new Diagnostic(DiagnosticLevel.Info, "Found anonymous enum: __AnonymousEnum_ClangUnsavedFile_L1_C1. Mapping values as constants in: Methods", "Line 1, Column 1 in ClangUnsavedFile.h") }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionDeclarationBodyImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionDeclarationBodyImportTest.cs new file mode 100644 index 00000000..7903b162 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionDeclarationBodyImportTest.cs @@ -0,0 +1,1777 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultUnix_FunctionDeclarationBodyImportTest : FunctionDeclarationBodyImportTest +{ + protected override Task ArraySubscriptTestImpl() + { + var inputContents = @"int MyFunction(int* pData, int index) +{ + return pData[index]; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static int MyFunction(int* pData, int index) + { + return pData[index]; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestImpl() + { + var inputContents = @"void MyFunction() +{ +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyFunction() + { + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorBasicTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int x, int y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static int MyFunction(int x, int y) + {{ + return x {opcode} y; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorCompareTestImpl(string opcode) + { + var inputContents = $@"bool MyFunction(int x, int y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static bool MyFunction(int x, int y) + {{ + return x {opcode} y; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorBooleanTestImpl(string opcode) + { + var inputContents = $@"bool MyFunction(bool x, bool y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static bool MyFunction(bool x, bool y) + {{ + return x {opcode} y; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BreakTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + while (true) + { + break; + } + + return 0; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + while (true) + { + break; + } + + return 0; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallFunctionTestImpl() + { + var inputContents = @"void MyCalledFunction() +{ +} + +void MyFunction() +{ + MyCalledFunction(); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyCalledFunction() + { + } + + public static void MyFunction() + { + MyCalledFunction(); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallFunctionWithArgsTestImpl() + { + var inputContents = @"void MyCalledFunction(int x, int y) +{ +} + +void MyFunction() +{ + MyCalledFunction(0, 1); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyCalledFunction(int x, int y) + { + } + + public static void MyFunction() + { + MyCalledFunction(0, 1); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CaseTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + case 0: + { + return 0; + } + + case 1: + case 2: + { + return 3; + } + } + + return -1; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + switch (value) + { + case 0: + { + return 0; + } + + case 1: + case 2: + { + return 3; + } + } + + return -1; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CaseNoCompoundTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + case 0: + return 0; + + case 2: + case 3: + return 5; + } + + return -1; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + switch (value) + { + case 0: + { + return 0; + } + + case 2: + case 3: + { + return 5; + } + } + + return -1; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CompareMultipleEnumTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; + +static inline int MyFunction(MyEnum x) +{ + return x == MyEnum_Value0 || + x == MyEnum_Value1 || + x == MyEnum_Value2; +} +"; + + var expectedOutputContents = @"using static ClangSharp.Test.MyEnum; + +namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + } + + public static partial class Methods + { + public static int MyFunction(MyEnum x) + { + return (x == MyEnum_Value0 || x == MyEnum_Value1 || x == MyEnum_Value2) ? 1 : 0; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConditionalOperatorTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + return condition ? lhs : rhs; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(bool condition, int lhs, int rhs) + { + return condition ? lhs : rhs; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ContinueTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + while (true) + { + continue; + } + + return 0; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + while (true) + { + continue; + } + + return 0; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CStyleFunctionalCastTestImpl() + { + var inputContents = @"int MyFunction(float input) +{ + return (int)input; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(float input) + { + return (int)(input); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxFunctionalCastTestImpl() + { + var inputContents = @"int MyFunction(float input) +{ + return int(input); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(float input) + { + return (int)(input); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxConstCastTestImpl() + { + var inputContents = @"void* MyFunction(const void* input) +{ + return const_cast(input); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static void* MyFunction([NativeTypeName(""const void *"")] void* input) + { + return input; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxDynamicCastTestImpl() + { + var inputContents = @"struct MyStructA +{ + virtual void MyMethod() = 0; +}; + +struct MyStructB : MyStructA { }; + +MyStructB* MyFunction(MyStructA* input) +{ + return dynamic_cast(input); +} +"; + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStructA + {{ + public void** lpVtbl; + + public void MyMethod() + {{ + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((MyStructA*)Unsafe.AsPointer(ref this)); + }} + }} + + [NativeTypeName(""struct MyStructB : MyStructA"")] + public unsafe partial struct MyStructB + {{ + public void** lpVtbl; + + public void MyMethod() + {{ + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((MyStructB*)Unsafe.AsPointer(ref this)); + }} + }} + + public static unsafe partial class Methods + {{ + public static MyStructB* MyFunction(MyStructA* input) + {{ + return (MyStructB*)(input); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxReinterpretCastTestImpl() + { + var inputContents = @"int* MyFunction(void* input) +{ + return reinterpret_cast(input); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static int* MyFunction(void* input) + { + return (int*)(input); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxStaticCastTestImpl() + { + var inputContents = @"int* MyFunction(void* input) +{ + return static_cast(input); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static int* MyFunction(void* input) + { + return (int*)(input); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DeclTestImpl() + { + var inputContents = @"\ +int MyFunction() +{ + int x = 0; + int y = 1, z = 2; + return x + y + z; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction() + { + int x = 0; + int y = 1, z = 2; + + return x + y + z; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DoTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + do + { + i++; + } + while (i < count); + + return i; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + int i = 0; + + do + { + i++; + } + while (i < count); + + return i; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DoNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + i++; + + return i; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + int i = 0; + + while (i < count) + { + i++; + } + + return i; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ForTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;;i--) + { + i += 2; + } + + for (x = 0;;x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + // x = 0; + // + // for (;; x--) + // { + // x += 2; + // } + + x = 0; + + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;; i--) + { + i += 2; + } + + for (x = 0;; x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + x = 0; + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ForNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + for (int i = 0; i < count; i--) + i += 2; + + int x; + + for (x = 0; x < count; x--) + x += 2; + + x = 0; + + for (; x < count; x--) + x += 2; + + for (int i = 0;;i--) + i += 2; + + for (x = 0;;x--) + x += 2; + + for (int i = 0; i < count;) + i++; + + for (x = 0; x < count;) + x++; + + // x = 0; + // + // for (;; x--) + // x += 2; + + x = 0; + + for (; x < count;) + x++; + + for (int i = 0;;) + i++; + + for (x = 0;;) + x++; + + for (;;) + return -1; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;; i--) + { + i += 2; + } + + for (x = 0;; x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + x = 0; + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + { + return lhs; + } + + return rhs; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(bool condition, int lhs, int rhs) + { + if (condition) + { + return lhs; + } + + return rhs; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + { + return lhs; + } + else + { + return rhs; + } +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(bool condition, int lhs, int rhs) + { + if (condition) + { + return lhs; + } + else + { + return rhs; + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseIfTestImpl() + { + var inputContents = @"int MyFunction(bool condition1, int a, int b, bool condition2, int c) +{ + if (condition1) + { + return a; + } + else if (condition2) + { + return b; + } + + return c; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(bool condition1, int a, int b, bool condition2, int c) + { + if (condition1) + { + return a; + } + else if (condition2) + { + return b; + } + + return c; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + return lhs; + else + return rhs; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(bool condition, int lhs, int rhs) + { + if (condition) + { + return lhs; + } + else + { + return rhs; + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InitListForArrayTestImpl() + { + var inputContents = @" +void MyFunction() +{ + int x[4] = { 1, 2, 3, 4 }; + int y[4] = { 1, 2, 3 }; + int z[] = { 1, 2 }; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyFunction() + { + int[] x = new int[4] + { + 1, + 2, + 3, + 4, + }; + int[] y = new int[4] + { + 1, + 2, + 3, + default, + }; + int[] z = new int[2] + { + 1, + 2, + }; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InitListForRecordDeclTestImpl() + { + var inputContents = @"struct MyStruct +{ + float x; + float y; + float z; + float w; +}; + +MyStruct MyFunction1() +{ + return { 1.0f, 2.0f, 3.0f, 4.0f }; +} + +MyStruct MyFunction2() +{ + return { 1.0f, 2.0f, 3.0f }; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public float x; + + public float y; + + public float z; + + public float w; + } + + public static partial class Methods + { + public static MyStruct MyFunction1() + { + return new MyStruct + { + x = 1.0f, + y = 2.0f, + z = 3.0f, + w = 4.0f, + }; + } + + public static MyStruct MyFunction2() + { + return new MyStruct + { + x = 1.0f, + y = 2.0f, + z = 3.0f, + }; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; +}; + +int MyFunction1(MyStruct instance) +{ + return instance.value; +} + +int MyFunction2(MyStruct* instance) +{ + return instance->value; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + } + + public static unsafe partial class Methods + { + public static int MyFunction1(MyStruct instance) + { + return instance.value; + } + + public static int MyFunction2(MyStruct* instance) + { + return instance->value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RefToPtrTestImpl() + { + var inputContents = @"struct MyStruct { + int value; +}; + +bool MyFunction(const MyStruct& lhs, const MyStruct& rhs) +{ + return lhs.value == rhs.value; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + } + + public static unsafe partial class Methods + { + public static bool MyFunction([NativeTypeName(""const MyStruct &"")] MyStruct* lhs, [NativeTypeName(""const MyStruct &"")] MyStruct* rhs) + { + return lhs->value == rhs->value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnCXXNullPtrTestImpl() + { + var inputContents = @"void* MyFunction() +{ + return nullptr; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static void* MyFunction() + { + return null; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnCXXBooleanLiteralTestImpl(string value) + { + var inputContents = $@"bool MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static bool MyFunction() + {{ + return {value}; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnFloatingLiteralDoubleTestImpl(string value) + { + var inputContents = $@"double MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static double MyFunction() + {{ + return {value}; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnFloatingLiteralSingleTestImpl(string value) + { + var inputContents = $@"float MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static float MyFunction() + {{ + return {value}; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnEmptyTestImpl() + { + var inputContents = @"void MyFunction() +{ + return; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyFunction() + { + return; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnIntegerLiteralInt32TestImpl() + { + var inputContents = @"int MyFunction() +{ + return -1; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction() + { + return -1; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task AccessUnionMemberTestImpl() + { + var inputContents = @"union MyUnion +{ + struct { int a; }; +}; + +void MyFunction() +{ + MyUnion myUnion; + myUnion.a = 10; +} +"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + { + [FieldOffset(0)] + [NativeTypeName(""MyUnion::(anonymous struct at ClangUnsavedFile.h:3:5)"")] + public _Anonymous_e__Struct Anonymous; + + public ref int a + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + } + } + + public partial struct _Anonymous_e__Struct + { + public int a; + } + } + + public static partial class Methods + { + public static void MyFunction() + { + MyUnion myUnion = new MyUnion(); + + myUnion.Anonymous.a = 10; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnStructTestImpl() + { + var inputContents = @"struct MyStruct +{ + double r; + double g; + double b; +}; + +MyStruct MyFunction() +{ + MyStruct myStruct; + return myStruct; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public double r; + + public double g; + + public double b; + } + + public static partial class Methods + { + public static MyStruct MyFunction() + { + MyStruct myStruct = new MyStruct(); + + return myStruct; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SwitchTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + default: + { + return 0; + } + } +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + switch (value) + { + default: + { + return 0; + } + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SwitchNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + default: + { + return 0; + } + + switch (value) + default: + return 0; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + switch (value) + { + default: + { + return 0; + } + } + + switch (value) + { + default: + { + return 0; + } + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorAddrOfTestImpl() + { + var inputContents = @"int* MyFunction(int value) +{ + return &value; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static int* MyFunction(int value) + { + return &value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorDerefTestImpl() + { + var inputContents = @"int MyFunction(int* value) +{ + return *value; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static int MyFunction(int* value) + { + return *value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorLogicalNotTestImpl() + { + var inputContents = @"bool MyFunction(bool value) +{ + return !value; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static bool MyFunction(bool value) + { + return !value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorPostfixTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int value) +{{ + return value{opcode}; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static int MyFunction(int value) + {{ + return value{opcode}; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorPrefixTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int value) +{{ + return {opcode}value; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static int MyFunction(int value) + {{ + return {opcode}value; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WhileTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + { + i++; + } + + return i; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + int i = 0; + + while (i < count) + { + i++; + } + + return i; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WhileNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + i++; + + return i; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + int i = 0; + + while (i < count) + { + i++; + } + + return i; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionDeclarationDllImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionDeclarationDllImportTest.cs new file mode 100644 index 00000000..ca78342c --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionDeclarationDllImportTest.cs @@ -0,0 +1,399 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultUnix_FunctionDeclarationDllImportTest : FunctionDeclarationDllImportTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ArrayParameterTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(const float color[4]);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction([NativeTypeName(""const float[4]"")] float* color); + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FunctionPointerParameterTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(void (*callback)());"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction([NativeTypeName(""void (*)()"")] delegate* unmanaged[Cdecl] callback); + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NamespaceTestImpl() + { + var inputContents = @"namespace MyNamespace +{ + void MyFunction(); +}"; + + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "__ZN11MyNamespace10MyFunctionEv" : "_ZN11MyNamespace10MyFunctionEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + entryPoint = "?MyFunction@MyNamespace@@YAXXZ"; + } + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, EntryPoint = ""{entryPoint}"", ExactSpelling = true)] + public static extern void MyFunction(); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TemplateParameterTestImpl(string nativeType, bool expectedNativeTypeAttr, string expectedManagedType, string expectedUsingStatement) + { + var inputContents = @$"template struct MyTemplate; + +extern ""C"" void MyFunction(MyTemplate<{nativeType}> myStruct);"; + + var expectedOutputContents = $@"{expectedUsingStatement}using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction({(expectedNativeTypeAttr ? $@"[NativeTypeName(""MyTemplate<{nativeType}>"")] " : "")}MyTemplate<{expectedManagedType}> myStruct); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: new[] { "MyTemplate" }); + } + + protected override Task TemplateMemberTestImpl() + { + var inputContents = @$"template struct MyTemplate +{{ +}}; + +struct MyStruct +{{ + MyTemplate a; +}}; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""MyTemplate"")] + public MyTemplate a; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: new[] { "MyTemplate" }); + } + + protected override Task NoLibraryPathTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport("""", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty); + } + + protected override Task WithLibraryPathTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + + var withLibraryPaths = new Dictionary + { + ["MyFunction"] = "ClangSharpPInvokeGenerator" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty, withLibraryPaths: withLibraryPaths); + } + + protected override Task WithLibraryPathStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + + var withLibraryPaths = new Dictionary + { + ["*"] = "ClangSharpPInvokeGenerator" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty, withLibraryPaths: withLibraryPaths); + } + + protected override Task OptionalParameterTestImpl(string nativeType, string nativeInit, bool expectedNativeTypeNameAttr, string expectedManagedType, string expectedManagedInit) + { + var inputContents = $@"extern ""C"" void MyFunction({nativeType} value = {nativeInit});"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction({(expectedNativeTypeNameAttr ? $@"[NativeTypeName(""{nativeType}"")] " : "")}{expectedManagedType} value = {expectedManagedInit}); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task OptionalParameterUnsafeTestImpl(string nativeType, string nativeInit, string expectedManagedType, string expectedManagedInit) + { + var inputContents = $@"extern ""C"" void MyFunction({nativeType} value = {nativeInit});"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public static unsafe partial class Methods + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction({expectedManagedType} value = {expectedManagedInit}); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithCallConvTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", ExactSpelling = true)] + public static extern void MyFunction1(int value); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction2(int value); + } +} +"; + + var withCallConvs = new Dictionary { + ["MyFunction1"] = "Winapi" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithCallConvStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", ExactSpelling = true)] + public static extern void MyFunction1(int value); + + [DllImport(""ClangSharpPInvokeGenerator"", ExactSpelling = true)] + public static extern void MyFunction2(int value); + } +} +"; + + var withCallConvs = new Dictionary + { + ["*"] = "Winapi" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithCallConvStarOverrideTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", ExactSpelling = true)] + public static extern void MyFunction1(int value); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)] + public static extern void MyFunction2(int value); + } +} +"; + + var withCallConvs = new Dictionary + { + ["*"] = "Winapi", + ["MyFunction2"] = "StdCall" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithSetLastErrorTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = true)] + public static extern void MyFunction1(int value); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction2(int value); + } +} +"; + + var withSetLastErrors = new string[] + { + "MyFunction1" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withSetLastErrors: withSetLastErrors); + } + + protected override Task WithSetLastErrorStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = true)] + public static extern void MyFunction1(int value); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = true)] + public static extern void MyFunction2(int value); + } +} +"; + + var withSetLastErrors = new string[] + { + "*" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withSetLastErrors: withSetLastErrors); + } + + protected override Task SourceLocationTestImpl() + { + const string InputContents = @"extern ""C"" void MyFunction(float value);"; + + const string ExpectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [SourceLocation(""ClangUnsavedFile.h"", 1, 17)] + public static extern void MyFunction([SourceLocation(""ClangUnsavedFile.h"", 1, 34)] float value); + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); + } + + protected override Task VarargsTestImpl() => Task.CompletedTask; +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionPointerDeclarationTest.cs new file mode 100644 index 00000000..dd5dbe71 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/FunctionPointerDeclarationTest.cs @@ -0,0 +1,74 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultUnix_FunctionPointerDeclarationTest : FunctionPointerDeclarationTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"typedef void (*Callback)(); + +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""Callback"")] + public delegate* unmanaged[Cdecl] _callback; + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallconvTestImpl() + { + var inputContents = @"typedef void (*Callback)() __attribute__((stdcall)); + +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""Callback"")] + public delegate* unmanaged[Stdcall] _callback; + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerlessTypedefTestImpl() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""Callback *"")] + public delegate* unmanaged[Cdecl] _callback; + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/StructDeclarationTest.cs new file mode 100644 index 00000000..d7107e8e --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/StructDeclarationTest.cs @@ -0,0 +1,1777 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using ClangSharp.Abstractions; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultUnix_StructDeclarationTest : StructDeclarationTest +{ + protected override Task IncompleteArraySizeTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} x[]; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}[]"")] + public fixed {expectedManagedType} x[1]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + public {expectedManagedType} g; + + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestInCModeImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}} MyStruct; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + public {expectedManagedType} g; + + public {expectedManagedType} b; + }} +}} +"; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, commandlineArgs: Array.Empty()); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BitfieldTestImpl() + { + var inputContents = @"struct MyStruct1 +{ + unsigned int o0_b0_24 : 24; + unsigned int o4_b0_16 : 16; + unsigned int o4_b16_3 : 3; + int o4_b19_3 : 3; + unsigned char o4_b22_1 : 1; + int o4_b23_1 : 1; + int o4_b24_1 : 1; +}; + +struct MyStruct2 +{ + unsigned int o0_b0_1 : 1; + int x; + unsigned int o8_b0_1 : 1; +}; + +struct MyStruct3 +{ + unsigned int o0_b0_1 : 1; + unsigned int o0_b1_1 : 1; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct1 + { + public uint _bitfield1; + + [NativeTypeName(""unsigned int : 24"")] + public uint o0_b0_24 + { + get + { + return _bitfield1 & 0xFFFFFFu; + } + + set + { + _bitfield1 = (_bitfield1 & ~0xFFFFFFu) | (value & 0xFFFFFFu); + } + } + + public uint _bitfield2; + + [NativeTypeName(""unsigned int : 16"")] + public uint o4_b0_16 + { + get + { + return _bitfield2 & 0xFFFFu; + } + + set + { + _bitfield2 = (_bitfield2 & ~0xFFFFu) | (value & 0xFFFFu); + } + } + + [NativeTypeName(""unsigned int : 3"")] + public uint o4_b16_3 + { + get + { + return (_bitfield2 >> 16) & 0x7u; + } + + set + { + _bitfield2 = (_bitfield2 & ~(0x7u << 16)) | ((value & 0x7u) << 16); + } + } + + [NativeTypeName(""int : 3"")] + public int o4_b19_3 + { + get + { + return (int)((_bitfield2 >> 19) & 0x7u); + } + + set + { + _bitfield2 = (_bitfield2 & ~(0x7u << 19)) | (uint)((value & 0x7) << 19); + } + } + + [NativeTypeName(""unsigned char : 1"")] + public byte o4_b22_1 + { + get + { + return (byte)((_bitfield2 >> 22) & 0x1u); + } + + set + { + _bitfield2 = (_bitfield2 & ~(0x1u << 22)) | (uint)((value & 0x1u) << 22); + } + } + + [NativeTypeName(""int : 1"")] + public int o4_b23_1 + { + get + { + return (int)((_bitfield2 >> 23) & 0x1u); + } + + set + { + _bitfield2 = (_bitfield2 & ~(0x1u << 23)) | (uint)((value & 0x1) << 23); + } + } + + [NativeTypeName(""int : 1"")] + public int o4_b24_1 + { + get + { + return (int)((_bitfield2 >> 24) & 0x1u); + } + + set + { + _bitfield2 = (_bitfield2 & ~(0x1u << 24)) | (uint)((value & 0x1) << 24); + } + } + } + + public partial struct MyStruct2 + { + public uint _bitfield1; + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b0_1 + { + get + { + return _bitfield1 & 0x1u; + } + + set + { + _bitfield1 = (_bitfield1 & ~0x1u) | (value & 0x1u); + } + } + + public int x; + + public uint _bitfield2; + + [NativeTypeName(""unsigned int : 1"")] + public uint o8_b0_1 + { + get + { + return _bitfield2 & 0x1u; + } + + set + { + _bitfield2 = (_bitfield2 & ~0x1u) | (value & 0x1u); + } + } + } + + public partial struct MyStruct3 + { + public uint _bitfield; + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b0_1 + { + get + { + return _bitfield & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + } + } + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b1_1 + { + get + { + return (_bitfield >> 1) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DeclTypeTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(); + +typedef struct +{ + decltype(&MyFunction) _callback; +} MyStruct; +"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""decltype(&MyFunction)"")] + public delegate* unmanaged[Cdecl] _callback; + } + + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = "typedef struct MyStruct MyStruct;"; + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyStruct" }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task FixedSizedBufferNonPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[3]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} value; + }} + + public partial struct MyOtherStruct + {{ + [NativeTypeName(""MyStruct[3]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyStruct e0; + public MyStruct e1; + public MyStruct e2; + + public ref MyStruct this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} value; + }} + + public partial struct MyOtherStruct + {{ + [NativeTypeName(""MyStruct[2][1][3][4]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyStruct e0_0_0_0; + public MyStruct e1_0_0_0; + + public MyStruct e0_0_1_0; + public MyStruct e1_0_1_0; + + public MyStruct e0_0_2_0; + public MyStruct e1_0_2_0; + + public MyStruct e0_0_0_1; + public MyStruct e1_0_0_1; + + public MyStruct e0_0_1_1; + public MyStruct e1_0_1_1; + + public MyStruct e0_0_2_1; + public MyStruct e1_0_2_1; + + public MyStruct e0_0_0_2; + public MyStruct e1_0_0_2; + + public MyStruct e0_0_1_2; + public MyStruct e1_0_1_2; + + public MyStruct e0_0_2_2; + public MyStruct e1_0_2_2; + + public MyStruct e0_0_0_3; + public MyStruct e1_0_0_3; + + public MyStruct e0_0_1_3; + public MyStruct e1_0_1_3; + + public MyStruct e0_0_2_3; + public MyStruct e1_0_2_3; + + public ref MyStruct this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +typedef MyStruct MyBuffer[3]; + +struct MyOtherStruct +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} value; + }} + + public partial struct MyOtherStruct + {{ + [NativeTypeName(""MyBuffer"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyStruct e0; + public MyStruct e1; + public MyStruct e2; + + public ref MyStruct this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[3]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} value; + }} + + public partial struct MyOtherStruct + {{ + [NativeTypeName(""MyStruct[3]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyStruct e0; + public MyStruct e1; + public MyStruct e2; + + public ref MyStruct this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPointerTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}[3]"")] + public _c_e__FixedBuffer c; + + public unsafe partial struct _c_e__FixedBuffer + {{ + public {expectedManagedType} e0; + public {expectedManagedType} e1; + public {expectedManagedType} e2; + + public ref {expectedManagedType} this[int index] + {{ + get + {{ + fixed ({expectedManagedType}* pThis = &e0) + {{ + return ref pThis[index]; + }} + }} + }} + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}[3]"")] + public fixed {expectedManagedType} c[3]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}[2][1][3][4]"")] + public fixed {expectedManagedType} c[2 * 1 * 3 * 4]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyBuffer[3]; + +struct MyStruct +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [NativeTypeName(""MyBuffer"")] + public fixed {expectedManagedType} c[3]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task GuidTestImpl() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Non-Windows doesn't support __declspec(uuid("")) + return Task.CompletedTask; + } + + var inputContents = $@"#define DECLSPEC_UUID(x) __declspec(uuid(x)) + +struct __declspec(uuid(""00000000-0000-0000-C000-000000000046"")) MyStruct1 +{{ + int x; +}}; + +struct DECLSPEC_UUID(""00000000-0000-0000-C000-000000000047"") MyStruct2 +{{ + int x; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [Guid(""00000000-0000-0000-C000-000000000046"")] + public partial struct MyStruct1 + {{ + public int x; + }} + + [Guid(""00000000-0000-0000-C000-000000000047"")] + public partial struct MyStruct2 + {{ + public int x; + }} + + public static partial class Methods + {{ + public static readonly Guid IID_MyStruct1 = new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + + public static readonly Guid IID_MyStruct2 = new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47); + }} +}} +"; + + var excludedNames = new string[] { "DECLSPEC_UUID" }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task InheritanceTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + int x; + int y; +}; + +struct MyStruct1B +{ + int x; + int y; +}; + +struct MyStruct2 : MyStruct1A, MyStruct1B +{ + int z; + int w; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct1A + { + public int x; + + public int y; + } + + public partial struct MyStruct1B + { + public int x; + + public int y; + } + + [NativeTypeName(""struct MyStruct2 : MyStruct1A, MyStruct1B"")] + public partial struct MyStruct2 + { + public MyStruct1A Base1; + + public MyStruct1B Base2; + + public int z; + + public int w; + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InheritanceWithNativeInheritanceAttributeTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + int x; + int y; +}; + +struct MyStruct1B +{ + int x; + int y; +}; + +struct MyStruct2 : MyStruct1A, MyStruct1B +{ + int z; + int w; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct1A + { + public int x; + + public int y; + } + + public partial struct MyStruct1B + { + public int x; + + public int y; + } + + [NativeTypeName(""struct MyStruct2 : MyStruct1A, MyStruct1B"")] + [NativeInheritance(""MyStruct1B"")] + public partial struct MyStruct2 + { + public MyStruct1A Base1; + + public MyStruct1B Base2; + + public int z; + + public int w; + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateNativeInheritanceAttribute); + } + + protected override Task NestedAnonymousTestImpl(string nativeType, string expectedManagedType, int line, int column) + { + var inputContents = $@"typedef union {{ + {nativeType} value; +}} MyUnion; + +struct MyStruct +{{ + {nativeType} x; + {nativeType} y; + + struct + {{ + {nativeType} z; + + struct + {{ + {nativeType} value; + }} w; + + struct + {{ + {nativeType} value1; + + struct + {{ + {nativeType} value; + }}; + }}; + + union + {{ + {nativeType} value2; + }}; + + MyUnion u; + {nativeType} buffer1[4]; + MyUnion buffer2[4]; + }}; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} value; + }} + + public unsafe partial struct MyStruct + {{ + public {expectedManagedType} x; + + public {expectedManagedType} y; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:{line}:{column})"")] + public _Anonymous_e__Struct Anonymous; + + public ref {expectedManagedType} z + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + }} + }} + + public ref _Anonymous_e__Struct._w_e__Struct w + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.w, 1)); + }} + }} + + public ref {expectedManagedType} value1 + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous1.value1, 1)); + }} + }} + + public ref {expectedManagedType} value + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous1.Anonymous.value, 1)); + }} + }} + + public ref {expectedManagedType} value2 + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous2.value2, 1)); + }} + }} + + public ref MyUnion u + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.u, 1)); + }} + }} + + public Span<{expectedManagedType}> buffer1 + {{ + get + {{ + return MemoryMarshal.CreateSpan(ref Anonymous.buffer1[0], 4); + }} + }} + + public Span buffer2 + {{ + get + {{ + return Anonymous.buffer2.AsSpan(); + }} + }} + + public unsafe partial struct _Anonymous_e__Struct + {{ + public {expectedManagedType} z; + + [NativeTypeName(""struct (anonymous struct at ClangUnsavedFile.h:14:9)"")] + public _w_e__Struct w; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:19:9)"")] + public _Anonymous1_e__Struct Anonymous1; + + [NativeTypeName(""MyStruct::(anonymous union at ClangUnsavedFile.h:29:9)"")] + public _Anonymous2_e__Union Anonymous2; + + public MyUnion u; + + [NativeTypeName(""{nativeType}[4]"")] + public fixed {expectedManagedType} buffer1[4]; + + [NativeTypeName(""MyUnion[4]"")] + public _buffer2_e__FixedBuffer buffer2; + + public partial struct _w_e__Struct + {{ + public {expectedManagedType} value; + }} + + public partial struct _Anonymous1_e__Struct + {{ + public {expectedManagedType} value1; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:23:13)"")] + public _Anonymous_e__Struct Anonymous; + + public partial struct _Anonymous_e__Struct + {{ + public {expectedManagedType} value; + }} + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct _Anonymous2_e__Union + {{ + [FieldOffset(0)] + public {expectedManagedType} value2; + }} + + public partial struct _buffer2_e__FixedBuffer + {{ + public MyUnion e0; + public MyUnion e1; + public MyUnion e2; + public MyUnion e3; + + public ref MyUnion this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 4); + }} + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedAnonymousWithBitfieldTestImpl() + { + var inputContents = @"struct MyStruct +{ + int x; + int y; + + struct + { + int z; + + struct + { + int w; + int o0_b0_16 : 16; + int o0_b16_4 : 4; + }; + }; +}; +"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int x; + + public int y; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:6:5)"")] + public _Anonymous_e__Struct Anonymous; + + public ref int z + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + } + } + + public ref int w + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + } + } + + public int o0_b0_16 + { + get + { + return Anonymous.Anonymous.o0_b0_16; + } + + set + { + Anonymous.Anonymous.o0_b0_16 = value; + } + } + + public int o0_b16_4 + { + get + { + return Anonymous.Anonymous.o0_b16_4; + } + + set + { + Anonymous.Anonymous.o0_b16_4 = value; + } + } + + public partial struct _Anonymous_e__Struct + { + public int z; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:10:9)"")] + public _Anonymous_e__Struct Anonymous; + + public partial struct _Anonymous_e__Struct + { + public int w; + + public int _bitfield; + + [NativeTypeName(""int : 16"")] + public int o0_b0_16 + { + get + { + return _bitfield & 0xFFFF; + } + + set + { + _bitfield = (_bitfield & ~0xFFFF) | (value & 0xFFFF); + } + } + + [NativeTypeName(""int : 4"")] + public int o0_b16_4 + { + get + { + return (_bitfield >> 16) & 0xF; + } + + set + { + _bitfield = (_bitfield & ~(0xF << 16)) | ((value & 0xF) << 16); + } + } + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + struct MyNestedStruct + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + public {expectedManagedType} g; + + public {expectedManagedType} b; + + public partial struct MyNestedStruct + {{ + public {expectedManagedType} r; + + public {expectedManagedType} g; + + public {expectedManagedType} b; + + public {expectedManagedType} a; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + struct MyNestedStruct + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + + public partial struct MyNestedStruct + {{ + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} a; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"struct MyStruct +{ + int Equals; + int Dispose; + int GetHashCode; + int GetType; + int MemberwiseClone; + int ReferenceEquals; + int ToString; +};"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public new int Equals; + + public int Dispose; + + public new int GetHashCode; + + public new int GetType; + + public new int MemberwiseClone; + + public new int ReferenceEquals; + + public new int ToString; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoDefinitionTestImpl() + { + var inputContents = "typedef struct MyStruct MyStruct;"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + }} +}} +"; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PackTestImpl() + { + const string InputContents = @"struct MyStruct1 { + unsigned Field1; + + void* Field2; + + unsigned Field3; +}; + +#pragma pack(4) + +struct MyStruct2 { + unsigned Field1; + + void* Field2; + + unsigned Field3; +}; +"; + + var usingStatement = "using System.Runtime.InteropServices;\n\n"; + var packing = " [StructLayout(LayoutKind.Sequential, Pack = 4)]\n"; + + if (!Environment.Is64BitProcess) + { + usingStatement = string.Empty; + packing = string.Empty; + } + + var expectedOutputContents = $@"{usingStatement}namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct1 + {{ + [NativeTypeName(""unsigned int"")] + public uint Field1; + + public void* Field2; + + [NativeTypeName(""unsigned int"")] + public uint Field3; + }} + +{packing} public unsafe partial struct MyStruct2 + {{ + [NativeTypeName(""unsigned int"")] + public uint Field1; + + public void* Field2; + + [NativeTypeName(""unsigned int"")] + public uint Field3; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(InputContents, expectedOutputContents); + } + + protected override Task PointerToSelfTestImpl() + { + var inputContents = @"struct example_s { + example_s* next; + void* data; +};"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct example_s + {{ + public example_s* next; + + public void* data; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfViaTypedefTestImpl() + { + var inputContents = @"typedef struct example_s example_t; + +struct example_s { + example_t* next; + void* data; +};"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct example_s + {{ + [NativeTypeName(""example_t *"")] + public example_s* next; + + public void* data; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = "typedef struct _MyStruct MyStruct;"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + }} +}} +"; + + var remappedNames = new Dictionary { ["_MyStruct"] = "MyStruct" }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task RemapNestedAnonymousTestImpl() + { + var inputContents = @"struct MyStruct +{ + double r; + double g; + double b; + + struct + { + double a; + }; +};"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public double r; + + public double g; + + public double b; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:7:5)"")] + public _Anonymous_e__Struct Anonymous; + + public ref double a + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + } + } + + public partial struct _Anonymous_e__Struct + { + public double a; + } + } +} +"; + + var remappedNames = new Dictionary { + ["__AnonymousField_ClangUnsavedFile_L7_C5"] = "Anonymous", + ["__AnonymousRecord_ClangUnsavedFile_L7_C5"] = "_Anonymous_e__Struct" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task SkipNonDefinitionTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct MyStruct MyStruct; + +struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + public {expectedManagedType} g; + + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionPointerTestImpl() + { + var inputContents = @"typedef struct MyStruct* MyStructPtr; +typedef struct MyStruct& MyStructRef; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct MyStruct MyStruct; + +struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyTypedefAlias; + +struct MyStruct +{{ + MyTypedefAlias r; + MyTypedefAlias g; + MyTypedefAlias b; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} r; + + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} g; + + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UsingDeclarationTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + void MyMethod() { } +}; + +struct MyStruct1B : MyStruct1A +{ + using MyStruct1A::MyMethod; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct1A + { + public void MyMethod() + { + } + } + + [NativeTypeName(""struct MyStruct1B : MyStruct1A"")] + public partial struct MyStruct1B + { + public void MyMethod() + { + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithAccessSpecifierTestImpl() + { + var inputContents = @"struct MyStruct1 +{ + int Field1; + int Field2; +}; + +struct MyStruct2 +{ + int Field1; + int Field2; +}; + +struct MyStruct3 +{ + int Field1; + int Field2; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + internal partial struct MyStruct1 + { + private int Field1; + + public int Field2; + } + + internal partial struct MyStruct2 + { + private int Field1; + + public int Field2; + } + + public partial struct MyStruct3 + { + private int Field1; + + internal int Field2; + } +} +"; + + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); + } + + protected override Task WithPackingTestImpl() + { + const string InputContents = @"struct MyStruct +{ + size_t FixedBuffer[1]; +}; +"; + + const string ExpectedOutputContents = @"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [StructLayout(LayoutKind.Sequential, Pack = CustomPackValue)] + public partial struct MyStruct + { + [NativeTypeName(""size_t[1]"")] + public _FixedBuffer_e__FixedBuffer FixedBuffer; + + public partial struct _FixedBuffer_e__FixedBuffer + { + public nuint e0; + + public ref nuint this[int index] + { + get + { + return ref AsSpan(int.MaxValue)[index]; + } + } + + public Span AsSpan(int length) => MemoryMarshal.CreateSpan(ref e0, length); + } + } +} +"; + + var withPackings = new Dictionary { + ["MyStruct"] = "CustomPackValue" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(InputContents, ExpectedOutputContents, withPackings: withPackings); + } + + protected override Task SourceLocationAttributeTestImpl() + { + const string InputContents = @"struct MyStruct +{ + int r; + int g; + int b; +}; +"; + + const string ExpectedOutputContents = @"namespace ClangSharp.Test +{ + [SourceLocation(""ClangUnsavedFile.h"", 1, 8)] + public partial struct MyStruct + { + [SourceLocation(""ClangUnsavedFile.h"", 3, 9)] + public int r; + + [SourceLocation(""ClangUnsavedFile.h"", 4, 9)] + public int g; + + [SourceLocation(""ClangUnsavedFile.h"", 5, 9)] + public int b; + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/UnionDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/UnionDeclarationTest.cs new file mode 100644 index 00000000..24030fd9 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/UnionDeclarationTest.cs @@ -0,0 +1,1442 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultUnix_UnionDeclarationTest : UnionDeclarationTest +{ + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestInCModeImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}} MyUnion; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + }} +}} +"; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, commandlineArgs: Array.Empty()); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BitfieldTestImpl() + { + var inputContents = @"union MyUnion1 +{ + unsigned int o0_b0_24 : 24; + unsigned int o4_b0_16 : 16; + unsigned int o4_b16_3 : 3; + int o4_b19_3 : 3; + unsigned char o4_b22_1 : 1; + int o4_b23_1 : 1; + int o4_b24_1 : 1; +}; + +union MyUnion2 +{ + unsigned int o0_b0_1 : 1; + int x; + unsigned int o8_b0_1 : 1; +}; + +union MyUnion3 +{ + unsigned int o0_b0_1 : 1; + unsigned int o0_b1_1 : 1; +}; +"; + + var expectedPack = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ", Pack = 1" : ""; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit{expectedPack})] + public partial struct MyUnion1 + {{ + [FieldOffset(0)] + public uint _bitfield1; + + [NativeTypeName(""unsigned int : 24"")] + public uint o0_b0_24 + {{ + get + {{ + return _bitfield1 & 0xFFFFFFu; + }} + + set + {{ + _bitfield1 = (_bitfield1 & ~0xFFFFFFu) | (value & 0xFFFFFFu); + }} + }} + + [FieldOffset(0)] + public uint _bitfield2; + + [NativeTypeName(""unsigned int : 16"")] + public uint o4_b0_16 + {{ + get + {{ + return _bitfield2 & 0xFFFFu; + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~0xFFFFu) | (value & 0xFFFFu); + }} + }} + + [NativeTypeName(""unsigned int : 3"")] + public uint o4_b16_3 + {{ + get + {{ + return (_bitfield2 >> 16) & 0x7u; + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~(0x7u << 16)) | ((value & 0x7u) << 16); + }} + }} + + [NativeTypeName(""int : 3"")] + public int o4_b19_3 + {{ + get + {{ + return (int)((_bitfield2 >> 19) & 0x7u); + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~(0x7u << 19)) | (uint)((value & 0x7) << 19); + }} + }} + + [NativeTypeName(""unsigned char : 1"")] + public byte o4_b22_1 + {{ + get + {{ + return (byte)((_bitfield2 >> 22) & 0x1u); + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~(0x1u << 22)) | (uint)((value & 0x1u) << 22); + }} + }} + + [NativeTypeName(""int : 1"")] + public int o4_b23_1 + {{ + get + {{ + return (int)((_bitfield2 >> 23) & 0x1u); + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~(0x1u << 23)) | (uint)((value & 0x1) << 23); + }} + }} + + [NativeTypeName(""int : 1"")] + public int o4_b24_1 + {{ + get + {{ + return (int)((_bitfield2 >> 24) & 0x1u); + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~(0x1u << 24)) | (uint)((value & 0x1) << 24); + }} + }} + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion2 + {{ + [FieldOffset(0)] + public uint _bitfield1; + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b0_1 + {{ + get + {{ + return _bitfield1 & 0x1u; + }} + + set + {{ + _bitfield1 = (_bitfield1 & ~0x1u) | (value & 0x1u); + }} + }} + + [FieldOffset(0)] + public int x; + + [FieldOffset(0)] + public uint _bitfield2; + + [NativeTypeName(""unsigned int : 1"")] + public uint o8_b0_1 + {{ + get + {{ + return _bitfield2 & 0x1u; + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~0x1u) | (value & 0x1u); + }} + }} + }} + + [StructLayout(LayoutKind.Explicit{expectedPack})] + public partial struct MyUnion3 + {{ + [FieldOffset(0)] + public uint _bitfield; + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b0_1 + {{ + get + {{ + return _bitfield & 0x1u; + }} + + set + {{ + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + }} + }} + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b1_1 + {{ + get + {{ + return (_bitfield >> 1) & 0x1u; + }} + + set + {{ + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + }} + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = "typedef union MyUnion MyUnion;"; + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyUnion" }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task FixedSizedBufferNonPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[3]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} value; + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyOtherUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyUnion[3]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyUnion e0; + public MyUnion e1; + public MyUnion e2; + + public ref MyUnion this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} value; + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyOtherUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyUnion[2][1][3][4]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyUnion e0_0_0_0; + public MyUnion e1_0_0_0; + + public MyUnion e0_0_1_0; + public MyUnion e1_0_1_0; + + public MyUnion e0_0_2_0; + public MyUnion e1_0_2_0; + + public MyUnion e0_0_0_1; + public MyUnion e1_0_0_1; + + public MyUnion e0_0_1_1; + public MyUnion e1_0_1_1; + + public MyUnion e0_0_2_1; + public MyUnion e1_0_2_1; + + public MyUnion e0_0_0_2; + public MyUnion e1_0_0_2; + + public MyUnion e0_0_1_2; + public MyUnion e1_0_1_2; + + public MyUnion e0_0_2_2; + public MyUnion e1_0_2_2; + + public MyUnion e0_0_0_3; + public MyUnion e1_0_0_3; + + public MyUnion e0_0_1_3; + public MyUnion e1_0_1_3; + + public MyUnion e0_0_2_3; + public MyUnion e1_0_2_3; + + public ref MyUnion this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +typedef MyUnion MyBuffer[3]; + +union MyOtherUnion +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} value; + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyOtherUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyBuffer"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyUnion e0; + public MyUnion e1; + public MyUnion e2; + + public ref MyUnion this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[3]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} value; + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyOtherUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyUnion[3]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyUnion e0; + public MyUnion e1; + public MyUnion e2; + + public ref MyUnion this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPointerTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}[3]"")] + public _c_e__FixedBuffer c; + + public unsafe partial struct _c_e__FixedBuffer + {{ + public {expectedManagedType} e0; + public {expectedManagedType} e1; + public {expectedManagedType} e2; + + public ref {expectedManagedType} this[int index] + {{ + get + {{ + fixed ({expectedManagedType}* pThis = &e0) + {{ + return ref pThis[index]; + }} + }} + }} + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}[3]"")] + public fixed {expectedManagedType} c[3]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}[2][1][3][4]"")] + public fixed {expectedManagedType} c[2 * 1 * 3 * 4]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyBuffer[3]; + +union MyUnion +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyBuffer"")] + public fixed {expectedManagedType} c[3]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + protected override Task GuidTestImpl() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Non-Windows doesn't support __declspec(uuid("")) + return Task.CompletedTask; + } + + var inputContents = $@"#define DECLSPEC_UUID(x) __declspec(uuid(x)) + +union __declspec(uuid(""00000000-0000-0000-C000-000000000046"")) MyUnion1 +{{ + int x; +}}; + +union DECLSPEC_UUID(""00000000-0000-0000-C000-000000000047"") MyUnion2 +{{ + int x; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + [Guid(""00000000-0000-0000-C000-000000000046"")] + public partial struct MyUnion1 + {{ + [FieldOffset(0)] + public int x; + }} + + [StructLayout(LayoutKind.Explicit)] + [Guid(""00000000-0000-0000-C000-000000000047"")] + public partial struct MyUnion2 + {{ + [FieldOffset(0)] + public int x; + }} + + public static partial class Methods + {{ + public static readonly Guid IID_MyUnion1 = new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + + public static readonly Guid IID_MyUnion2 = new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47); + }} +}} +"; + + var excludedNames = new string[] { "DECLSPEC_UUID" }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task NestedAnonymousTestImpl(string nativeType, string expectedManagedType, int line, int column) + { + var inputContents = $@"typedef struct {{ + {nativeType} value; +}} MyStruct; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union + {{ + {nativeType} a; + + MyStruct s; + + {nativeType} buffer[4]; + }}; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} value; + }} + + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + + [FieldOffset(0)] + [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:{line}:{column})"")] + public _Anonymous_e__Union Anonymous; + + public ref {expectedManagedType} a + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + }} + }} + + public ref MyStruct s + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.s, 1)); + }} + }} + + public Span<{expectedManagedType}> buffer + {{ + get + {{ + return MemoryMarshal.CreateSpan(ref Anonymous.buffer[0], 4); + }} + }} + + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct _Anonymous_e__Union + {{ + [FieldOffset(0)] + public {expectedManagedType} a; + + [FieldOffset(0)] + public MyStruct s; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}[4]"")] + public fixed {expectedManagedType} buffer[4]; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedAnonymousWithBitfieldTestImpl() + { + var inputContents = @"union MyUnion +{ + int x; + int y; + + union + { + int z; + + union + { + int w; + int o0_b0_16 : 16; + int o0_b16_4 : 4; + }; + }; +}; +"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + { + [FieldOffset(0)] + public int x; + + [FieldOffset(0)] + public int y; + + [FieldOffset(0)] + [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:6:5)"")] + public _Anonymous_e__Union Anonymous; + + public ref int z + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + } + } + + public ref int w + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + } + } + + public int o0_b0_16 + { + get + { + return Anonymous.Anonymous.o0_b0_16; + } + + set + { + Anonymous.Anonymous.o0_b0_16 = value; + } + } + + public int o0_b16_4 + { + get + { + return Anonymous.Anonymous.o0_b16_4; + } + + set + { + Anonymous.Anonymous.o0_b16_4 = value; + } + } + + [StructLayout(LayoutKind.Explicit)] + public partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + public int z; + + [FieldOffset(0)] + [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:10:9)"")] + public _Anonymous_e__Union Anonymous; + + [StructLayout(LayoutKind.Explicit)] + public partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + public int w; + + [FieldOffset(0)] + public int _bitfield; + + [NativeTypeName(""int : 16"")] + public int o0_b0_16 + { + get + { + return _bitfield & 0xFFFF; + } + + set + { + _bitfield = (_bitfield & ~0xFFFF) | (value & 0xFFFF); + } + } + + [NativeTypeName(""int : 4"")] + public int o0_b16_4 + { + get + { + return (_bitfield >> 16) & 0xF; + } + + set + { + _bitfield = (_bitfield & ~(0xF << 16)) | ((value & 0xF) << 16); + } + } + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + + protected override Task NestedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union MyNestedUnion + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyNestedUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + + [FieldOffset(0)] + public {expectedManagedType} a; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union MyNestedUnion + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyNestedUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} a; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"union MyUnion +{ + int Equals; + int Dispose; + int GetHashCode; + int GetType; + int MemberwiseClone; + int ReferenceEquals; + int ToString; +};"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public new int Equals; + + [FieldOffset(0)] + public int Dispose; + + [FieldOffset(0)] + public new int GetHashCode; + + [FieldOffset(0)] + public new int GetType; + + [FieldOffset(0)] + public new int MemberwiseClone; + + [FieldOffset(0)] + public new int ReferenceEquals; + + [FieldOffset(0)] + public new int ToString; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoDefinitionTestImpl() + { + var inputContents = "typedef union MyUnion MyUnion;"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + }} +}} +"; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfTestImpl() + { + var inputContents = @"union example_s { + example_s* next; + void* data; +};"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct example_s + {{ + [FieldOffset(0)] + public example_s* next; + + [FieldOffset(0)] + public void* data; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfViaTypedefTestImpl() + { + var inputContents = @"typedef union example_s example_t; + +union example_s { + example_t* next; + void* data; +};"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct example_s + {{ + [FieldOffset(0)] + [NativeTypeName(""example_t *"")] + public example_s* next; + + [FieldOffset(0)] + public void* data; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = "typedef union _MyUnion MyUnion;"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + }} +}} +"; + + var remappedNames = new Dictionary { ["_MyUnion"] = "MyUnion" }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task RemapNestedAnonymousTestImpl() + { + var inputContents = @"union MyUnion +{ + double r; + double g; + double b; + + union + { + double a; + }; +};"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + { + [FieldOffset(0)] + public double r; + + [FieldOffset(0)] + public double g; + + [FieldOffset(0)] + public double b; + + [FieldOffset(0)] + [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:7:5)"")] + public _Anonymous_e__Union Anonymous; + + public ref double a + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + } + } + + [StructLayout(LayoutKind.Explicit)] + public partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + public double a; + } + } +} +"; + + var remappedNames = new Dictionary { + ["__AnonymousField_ClangUnsavedFile_L7_C5"] = "Anonymous", + ["__AnonymousRecord_ClangUnsavedFile_L7_C5"] = "_Anonymous_e__Union" + }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task SkipNonDefinitionTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union MyUnion MyUnion; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionPointerTestImpl() + { + var inputContents = @"typedef union MyUnion* MyUnionPtr; +typedef union MyUnion& MyUnionRef; +"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + { + } +} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union MyUnion MyUnion; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyTypedefAlias; + +union MyUnion +{{ + MyTypedefAlias r; + MyTypedefAlias g; + MyTypedefAlias b; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} r; + + [FieldOffset(0)] + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} g; + + [FieldOffset(0)] + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/VarDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/VarDeclarationTest.cs new file mode 100644 index 00000000..caaad11c --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/VarDeclarationTest.cs @@ -0,0 +1,398 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultUnix_VarDeclarationTest : VarDeclarationTest +{ + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"{nativeType} MyVariable = 0;"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static {expectedManagedType} MyVariable = 0; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"{nativeType} MyVariable = 0;"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""{nativeType}"")] + public static {expectedManagedType} MyVariable = 0; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task GuidMacroTestImpl() + { + var inputContents = $@"struct GUID {{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +}}; + +const GUID IID_IUnknown = {{ 0x00000000, 0x0000, 0x0000, {{ 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }} }}; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const GUID"")] + public static readonly Guid IID_IUnknown = new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + }} +}} +"; + var excludedNames = new string[] { "GUID" }; + var remappedNames = new Dictionary { ["GUID"] = "Guid" }; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames, remappedNames: remappedNames); + } + + protected override Task MacroTestImpl(string nativeValue, string expectedManagedType, string expectedManagedValue) + { + var inputContents = $@"#define MyMacro1 {nativeValue} +#define MyMacro2 MyMacro1"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 {nativeValue}"")] + public const {expectedManagedType} MyMacro1 = {expectedManagedValue}; + + [NativeTypeName(""#define MyMacro2 MyMacro1"")] + public const {expectedManagedType} MyMacro2 = {expectedManagedValue}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MultilineMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 0 + \ +1"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 0 + \\\n1"")] + public const int MyMacro1 = 0 + 1; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoInitializerTestImpl(string nativeType) + { + var inputContents = $@"{nativeType} MyVariable;"; + var expectedOutputContents = ""; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task Utf8StringLiteralMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 ""Test"""; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 \""Test\"""")] + public static ReadOnlySpan MyMacro1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task Utf16StringLiteralMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 u""Test"""; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 u\""Test\"""")] + public const string MyMacro1 = ""Test""; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WideStringLiteralConstTestImpl() + { + var inputContents = $@"const wchar_t MyConst1[] = L""Test""; +const wchar_t* MyConst2 = L""Test""; +const wchar_t* const MyConst3 = L""Test"";"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const wchar_t[5]"")] + public static readonly uint[] MyConst1 = new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }}; + + [NativeTypeName(""const wchar_t *"")] + public static uint[] MyConst2 = new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }}; + + [NativeTypeName(""const wchar_t *const"")] + public static readonly uint[] MyConst3 = new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }}; + }} +}} +"; + + return ValidateGeneratedCSharpCompatibleUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StringLiteralConstTestImpl() + { + var inputContents = $@"const char MyConst1[] = ""Test""; +const char* MyConst2 = ""Test""; +const char* const MyConst3 = ""Test"";"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const char[5]"")] + public static ReadOnlySpan MyConst1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + + [NativeTypeName(""const char *"")] + public static byte[] MyConst2 = new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + + [NativeTypeName(""const char *const"")] + public static ReadOnlySpan MyConst3 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WideStringLiteralStaticConstTestImpl() + { + var inputContents = $@"static const wchar_t MyConst1[] = L""Test""; +static const wchar_t* MyConst2 = L""Test""; +static const wchar_t* const MyConst3 = L""Test"";"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const wchar_t[5]"")] + public static readonly uint[] MyConst1 = new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }}; + + [NativeTypeName(""const wchar_t *"")] + public static uint[] MyConst2 = new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }}; + + [NativeTypeName(""const wchar_t *const"")] + public static readonly uint[] MyConst3 = new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }}; + }} +}} +"; + + return ValidateGeneratedCSharpCompatibleUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StringLiteralStaticConstTestImpl() + { + var inputContents = $@"static const char MyConst1[] = ""Test""; +static const char* MyConst2 = ""Test""; +static const char* const MyConst3 = ""Test"";"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const char[5]"")] + public static ReadOnlySpan MyConst1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + + [NativeTypeName(""const char *"")] + public static byte[] MyConst2 = new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + + [NativeTypeName(""const char *const"")] + public static ReadOnlySpan MyConst3 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedConversionMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 (long)0x80000000L +#define MyMacro2 (int)0x80000000"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 (long)0x80000000L"")] + public const nint MyMacro1 = unchecked((nint)(0x80000000)); + + [NativeTypeName(""#define MyMacro2 (int)0x80000000"")] + public const int MyMacro2 = unchecked((int)(0x80000000)); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedFunctionLikeCastMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 unsigned(-1)"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 unsigned(-1)"")] + public const uint MyMacro1 = unchecked((uint)(-1)); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedConversionMacroTest2Impl() + { + var inputContents = $@"#define MyMacro1(x, y, z) ((int)(((unsigned long)(x)<<31) | ((unsigned long)(y)<<16) | ((unsigned long)(z)))) +#define MyMacro2(n) MyMacro1(1, 2, n) +#define MyMacro3 MyMacro2(3)"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro3 MyMacro2(3)"")] + public const int MyMacro3 = unchecked((int)(((nuint)(1) << 31) | ((nuint)(2) << 16) | ((nuint)(3)))); + }} +}} +"; + + var excludedNames = new string[] { "MyMacro1", "MyMacro2" }; + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task UncheckedPointerMacroTestImpl() + { + var inputContents = $@"#define Macro1 ((int*) -1)"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static unsafe partial class Methods + {{ + [NativeTypeName(""#define Macro1 ((int*) -1)"")] + public static readonly int* Macro1 = unchecked((int*)(-1)); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedReinterpretCastMacroTestImpl() + { + var inputContents = $@"#define Macro1 reinterpret_cast(-1)"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static unsafe partial class Methods + {{ + [NativeTypeName(""#define Macro1 reinterpret_cast(-1)"")] + public static readonly int* Macro1 = unchecked((int*)(-1)); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MultidimensionlArrayTestImpl() + { + var inputContents = $@"const int MyArray[2][2] = {{ {{ 0, 1 }}, {{ 2, 3 }} }};"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const int[2][2]"")] + public static readonly int[][] MyArray = new int[2][] + {{ + new int[2] + {{ + 0, + 1, + }}, + new int[2] + {{ + 2, + 3, + }}, + }}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConditionalDefineConstTestImpl() + { + var inputContents = @"typedef int TESTRESULT; +#define TESTRESULT_FROM_WIN32(x) ((TESTRESULT)(x) <= 0 ? ((TESTRESULT)(x)) : ((TESTRESULT) (((x) & 0x0000FFFF) | (7 << 16) | 0x80000000))) +#define ADDRESS_IN_USE TESTRESULT_FROM_WIN32(10048)"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define ADDRESS_IN_USE TESTRESULT_FROM_WIN32(10048)"")] + public const int ADDRESS_IN_USE = unchecked((int)(10048) <= 0 ? ((int)(10048)) : ((int)(((10048) & 0x0000FFFF) | (7 << 16) | 0x80000000))); + }} +}} +"; + var diagnostics = new Diagnostic[] { new Diagnostic(DiagnosticLevel.Warning, "Function like macro definition records are not supported: 'TESTRESULT_FROM_WIN32'. Generated bindings may be incomplete.", "Line 2, Column 9 in ClangUnsavedFile.h") }; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/CXXMethodDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/CXXMethodDeclarationTest.cs new file mode 100644 index 00000000..57dfdb08 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/CXXMethodDeclarationTest.cs @@ -0,0 +1,919 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultWindows_CXXMethodDeclarationTest : CXXMethodDeclarationTest +{ + protected override Task ConstructorTestImpl() + { + var inputContents = @"struct MyStruct +{ + int _value; + + MyStruct(int value) + { + _value = value; + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int _value; + + public MyStruct(int value) + { + _value = value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConstructorWithInitializeTestImpl() + { + var inputContents = @"struct MyStruct +{ + int _x; + int _y; + int _z; + + MyStruct(int x) : _x(x) + { + } + + MyStruct(int x, int y) : _x(x), _y(y) + { + } + + MyStruct(int x, int y, int z) : _x(x), _y(y), _z() + { + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int _x; + + public int _y; + + public int _z; + + public MyStruct(int x) + { + _x = x; + } + + public MyStruct(int x, int y) + { + _x = x; + _y = y; + } + + public MyStruct(int x, int y, int z) + { + _x = x; + _y = y; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConversionTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + operator int() + { + return value; + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public int ToInt32() + { + return value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DestructorTestImpl() + { + var inputContents = @"struct MyStruct +{ + ~MyStruct() + { + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public void Dispose() + { + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InstanceTestImpl() + { + var inputContents = @"struct MyStruct +{ + void MyVoidMethod(); + + int MyInt32Method() + { + return 0; + } + + void* MyVoidStarMethod() + { + return nullptr; + } +}; +"; + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "__ZN8MyStruct12MyVoidMethodEv" : "_ZN8MyStruct12MyVoidMethodEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + if (!Environment.Is64BitProcess) + { + entryPoint = "?MyVoidMethod@MyStruct@@QAEXXZ"; + } + else + { + entryPoint = "?MyVoidMethod@MyStruct@@QEAAXXZ"; + } + } + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.ThisCall, EntryPoint = ""{entryPoint}"", ExactSpelling = true)] + public static extern void MyVoidMethod(MyStruct* pThis); + + public int MyInt32Method() + {{ + return 0; + }} + + public void* MyVoidStarMethod() + {{ + return null; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberCallTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction1() + { + return value; + } + + int MyFunction2() + { + return MyFunction1(); + } + + int MyFunction3() + { + return this->MyFunction1(); + } +}; + +int MyFunctionA(MyStruct x) +{ + return x.MyFunction1(); +} + +int MyFunctionB(MyStruct* x) +{ + return x->MyFunction2(); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public int MyFunction1() + { + return value; + } + + public int MyFunction2() + { + return MyFunction1(); + } + + public int MyFunction3() + { + return this.MyFunction1(); + } + } + + public static unsafe partial class Methods + { + public static int MyFunctionA(MyStruct x) + { + return x.MyFunction1(); + } + + public static int MyFunctionB(MyStruct* x) + { + return x->MyFunction2(); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction() + { + return value; + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public int MyFunction() + { + return value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"struct MyStruct +{ + int Equals() { return 0; } + int Equals(int obj) { return 0; } + int Dispose() { return 0; } + int Dispose(int obj) { return 0; } + int GetHashCode() { return 0; } + int GetHashCode(int obj) { return 0; } + int GetType() { return 0; } + int GetType(int obj) { return 0; } + int MemberwiseClone() { return 0; } + int MemberwiseClone(int obj) { return 0; } + int ReferenceEquals() { return 0; } + int ReferenceEquals(int obj) { return 0; } + int ToString() { return 0; } + int ToString(int obj) { return 0; } +};"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public int Equals() + {{ + return 0; + }} + + public int Equals(int obj) + {{ + return 0; + }} + + public int Dispose() + {{ + return 0; + }} + + public int Dispose(int obj) + {{ + return 0; + }} + + public new int GetHashCode() + {{ + return 0; + }} + + public int GetHashCode(int obj) + {{ + return 0; + }} + + public new int GetType() + {{ + return 0; + }} + + public int GetType(int obj) + {{ + return 0; + }} + + public new int MemberwiseClone() + {{ + return 0; + }} + + public int MemberwiseClone(int obj) + {{ + return 0; + }} + + public int ReferenceEquals() + {{ + return 0; + }} + + public int ReferenceEquals(int obj) + {{ + return 0; + }} + + public new int ToString() + {{ + return 0; + }} + + public int ToString(int obj) + {{ + return 0; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordVirtualTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + public void** lpVtbl; + + public int GetType(int objA, int objB) + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + }} + + public new int GetType() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + public int GetType(int obj) + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this), obj); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordVirtualWithExplicitVtblTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var nativeCallConv = ""; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Environment.Is64BitProcess) + { + nativeCallConv = " __attribute__((thiscall))"; + } + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + public Vtbl* lpVtbl; + + public int GetType(int objA, int objB) + {{ + return lpVtbl->GetType((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + }} + + public new int GetType() + {{ + return lpVtbl->GetType1((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + public int GetType(int obj) + {{ + return lpVtbl->GetType2((MyStruct*)Unsafe.AsPointer(ref this), obj); + }} + + public partial struct Vtbl + {{ + [NativeTypeName(""int (int, int){nativeCallConv}"")] + public new delegate* unmanaged[Thiscall] GetType; + + [NativeTypeName(""int (){nativeCallConv}"")] + public delegate* unmanaged[Thiscall] GetType1; + + [NativeTypeName(""int (int){nativeCallConv}"")] + public delegate* unmanaged[Thiscall] GetType2; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateExplicitVtbls); + } + + protected override Task NewKeywordVirtualWithExplicitVtblAndMarkerInterfaceTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var nativeCallConv = ""; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Environment.Is64BitProcess) + { + nativeCallConv = " __attribute__((thiscall))"; + } + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct : MyStruct.Interface + {{ + public Vtbl* lpVtbl; + + public int GetType(int objA, int objB) + {{ + return lpVtbl->GetType((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + }} + + public new int GetType() + {{ + return lpVtbl->GetType1((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + public int GetType(int obj) + {{ + return lpVtbl->GetType2((MyStruct*)Unsafe.AsPointer(ref this), obj); + }} + + public interface Interface + {{ + int GetType(int objA, int objB); + + int GetType(); + + int GetType(int obj); + }} + + public partial struct Vtbl + where TSelf : unmanaged, Interface + {{ + [NativeTypeName(""int (int, int){nativeCallConv}"")] + public new delegate* unmanaged[Thiscall] GetType; + + [NativeTypeName(""int (){nativeCallConv}"")] + public delegate* unmanaged[Thiscall] GetType1; + + [NativeTypeName(""int (int){nativeCallConv}"")] + public delegate* unmanaged[Thiscall] GetType2; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateExplicitVtbls | PInvokeGeneratorConfigurationOptions.GenerateMarkerInterfaces); + } + + protected override Task OperatorTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + MyStruct(int value) : value(value) + { + } + + MyStruct operator+(MyStruct rhs) + { + return MyStruct(value + rhs.value); + } +}; + +MyStruct operator-(MyStruct lhs, MyStruct rhs) +{ + return MyStruct(lhs.value - rhs.value); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public MyStruct(int value) + { + this.value = value; + } + + public MyStruct Add(MyStruct rhs) + { + return new MyStruct(value + rhs.value); + } + } + + public static partial class Methods + { + public static MyStruct Subtract(MyStruct lhs, MyStruct rhs) + { + return new MyStruct(lhs.value - rhs.value); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task OperatorCallTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + MyStruct(int value) : value(value) + { + } + + MyStruct operator+(MyStruct rhs) + { + return MyStruct(value + rhs.value); + } +}; + +MyStruct MyFunction1(MyStruct lhs, MyStruct rhs) +{ + return lhs + rhs; +} + +MyStruct operator-(MyStruct lhs, MyStruct rhs) +{ + return MyStruct(lhs.value - rhs.value); +} + +MyStruct MyFunction2(MyStruct lhs, MyStruct rhs) +{ + return lhs - rhs; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public MyStruct(int value) + { + this.value = value; + } + + public MyStruct Add(MyStruct rhs) + { + return new MyStruct(value + rhs.value); + } + } + + public static partial class Methods + { + public static MyStruct MyFunction1(MyStruct lhs, MyStruct rhs) + { + return lhs.Add(rhs); + } + + public static MyStruct Subtract(MyStruct lhs, MyStruct rhs) + { + return new MyStruct(lhs.value - rhs.value); + } + + public static MyStruct MyFunction2(MyStruct lhs, MyStruct rhs) + { + return Subtract(lhs, rhs); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StaticTestImpl() + { + var inputContents = @"struct MyStruct +{ + static void MyVoidMethod(); + + static int MyInt32Method() + { + return 0; + } + + static void* MyVoidStarMethod() + { + return nullptr; + } +}; +"; + + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "?MyVoidMethod@MyStruct@@SAXXZ" : "_ZN8MyStruct12MyVoidMethodEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + entryPoint = $"_{entryPoint}"; + } + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, EntryPoint = ""{entryPoint}"", ExactSpelling = true)] + public static extern void MyVoidMethod(); + + public static int MyInt32Method() + {{ + return 0; + }} + + public static void* MyVoidStarMethod() + {{ + return null; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ThisTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction() + { + return this->value; + } +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + + public int MyFunction() + { + return this.value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnsafeDoesNotImpactDllImportTestImpl() + { + var inputContents = @"struct MyStruct +{ + void* MyVoidStarMethod() + { + return nullptr; + } +}; + +extern ""C"" void MyFunction();"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + public void* MyVoidStarMethod() + { + return null; + } + } + + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task VirtualTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual void MyVoidMethod() = 0; + + virtual char MyInt8Method() + { + return 0; + } + + virtual int MyInt32Method(); + + virtual void* MyVoidStarMethod() = 0; +}; +"; + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + public void** lpVtbl; + + public void MyVoidMethod() + {{ + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + [return: NativeTypeName(""char"")] + public sbyte MyInt8Method() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + public int MyInt32Method() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + public void* MyVoidStarMethod() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task VirtualWithVtblIndexAttributeTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual void MyVoidMethod() = 0; + + virtual char MyInt8Method() + { + return 0; + } + + virtual int MyInt32Method(); + + virtual void* MyVoidStarMethod() = 0; +}; +"; + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + public void** lpVtbl; + + [VtblIndex(0)] + public void MyVoidMethod() + {{ + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + [VtblIndex(1)] + [return: NativeTypeName(""char"")] + public sbyte MyInt8Method() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + [VtblIndex(2)] + public int MyInt32Method() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + + [VtblIndex(3)] + public void* MyVoidStarMethod() + {{ + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((MyStruct*)Unsafe.AsPointer(ref this)); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateVtblIndexAttribute); + } + + protected override Task ValidateBindingsAsync(string inputContents, string expectedOutputContents) => ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DeprecatedToObsoleteTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DeprecatedToObsoleteTest.cs new file mode 100644 index 00000000..01b15fe6 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DeprecatedToObsoleteTest.cs @@ -0,0 +1,504 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultWindows_DeprecatedToObsoleteTest : DeprecatedToObsoleteTest +{ + protected override Task SimpleStructMembersImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + + [[deprecated]] + {nativeType} g; + + [[deprecated(""This is obsolete."")]] + {nativeType} b; + + {nativeType} a; +}}; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + [Obsolete] + public {expectedManagedType} g; + + [Obsolete(""This is obsolete."")] + public {expectedManagedType} b; + + public {expectedManagedType} a; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StructDeclImpl() + { + var inputContents = $@"struct MyStruct0 +{{ + int r; +}}; + +struct [[deprecated]] MyStruct1 +{{ + int r; +}}; + +struct [[deprecated(""This is obsolete."")]] MyStruct2 +{{ + int r; +}}; + +struct MyStruct3 +{{ + int r; +}}; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct0 + {{ + public int r; + }} + + [Obsolete] + public partial struct MyStruct1 + {{ + public int r; + }} + + [Obsolete(""This is obsolete."")] + public partial struct MyStruct2 + {{ + public int r; + }} + + public partial struct MyStruct3 + {{ + public int r; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleTypedefStructMembersImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct +{{ + {nativeType} r; + + [[deprecated]] + {nativeType} g; + + [[deprecated(""This is obsolete."")]] + {nativeType} b; + + {nativeType} a; +}} MyStruct; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + [Obsolete] + public {expectedManagedType} g; + + [Obsolete(""This is obsolete."")] + public {expectedManagedType} b; + + public {expectedManagedType} a; + }} +}} +"; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefStructDeclImpl() + { + var inputContents = $@"typedef struct +{{ + int r; +}} MyStruct0; + +[[deprecated]] typedef struct +{{ + int r; +}} MyStruct1; + +[[deprecated(""This is obsolete."")]] typedef struct +{{ + int r; +}} MyStruct2; + +typedef struct +{{ + int r; +}} MyStruct3; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct0 + {{ + public int r; + }} + + [Obsolete] + public partial struct MyStruct1 + {{ + public int r; + }} + + [Obsolete(""This is obsolete."")] + public partial struct MyStruct2 + {{ + public int r; + }} + + public partial struct MyStruct3 + {{ + public int r; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleEnumMembersImpl() + { + var inputContents = $@"enum MyEnum : int +{{ + MyEnum_Value0, + MyEnum_Value1 [[deprecated]], + MyEnum_Value2 [[deprecated(""This is obsolete."")]], + MyEnum_Value3, +}}; +"; + + var expectedOutputContents = @"using System; + +namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0, + [Obsolete] + MyEnum_Value1, + [Obsolete(""This is obsolete."")] + MyEnum_Value2, + MyEnum_Value3, + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task EnumDeclImpl() + { + var inputContents = $@"enum MyEnum0 : int +{{ + MyEnum_Value0, +}}; + +enum [[deprecated]] MyEnum1 : int +{{ + MyEnum_Value1, +}}; + +enum [[deprecated(""This is obsolete."")]] MyEnum2 : int +{{ + MyEnum_Value2, +}}; + + +enum MyEnum3 : int +{{ + MyEnum_Value3, +}}; +"; + + var expectedOutputContents = @"using System; + +namespace ClangSharp.Test +{ + public enum MyEnum0 + { + MyEnum_Value0, + } + + [Obsolete] + public enum MyEnum1 + { + MyEnum_Value1, + } + + [Obsolete(""This is obsolete."")] + public enum MyEnum2 + { + MyEnum_Value2, + } + + public enum MyEnum3 + { + MyEnum_Value3, + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleVarDeclImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@" +{nativeType} MyVariable0 = 0; + +[[deprecated]] +{nativeType} MyVariable1 = 0; + +[[deprecated(""This is obsolete."")]] +{nativeType} MyVariable2 = 0; + +{nativeType} MyVariable3 = 0;"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static {expectedManagedType} MyVariable0 = 0; + + [Obsolete] + public static {expectedManagedType} MyVariable1 = 0; + + [Obsolete(""This is obsolete."")] + public static {expectedManagedType} MyVariable2 = 0; + + public static {expectedManagedType} MyVariable3 = 0; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncDeclImpl() + { + var inputContents = @" +void MyFunction0() +{ +} + +[[deprecated]] +void MyFunction1() +{ +} + +[[deprecated(""This is obsolete."")]] +void MyFunction2() +{ +} + +void MyFunction3() +{ +} +"; + + var expectedOutputContents = @"using System; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyFunction0() + { + } + + [Obsolete] + public static void MyFunction1() + { + } + + [Obsolete(""This is obsolete."")] + public static void MyFunction2() + { + } + + public static void MyFunction3() + { + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InstanceFuncImpl() + { + var inputContents = @"struct MyStruct +{ + int MyFunction0() { return 0; } + + [[deprecated]] + int MyFunction1() { return 0; } + + [[deprecated(""This is obsolete."")]] + int MyFunction2() { return 0; } + + int MyFunction3() { return 0; } +};"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public int MyFunction0() + {{ + return 0; + }} + + [Obsolete] + public int MyFunction1() + {{ + return 0; + }} + + [Obsolete(""This is obsolete."")] + public int MyFunction2() + {{ + return 0; + }} + + public int MyFunction3() + {{ + return 0; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncPtrDeclImpl() + { + var inputContents = @" +typedef void (*Callback0)(); +[[deprecated]] typedef void (*Callback1)(); +[[deprecated(""This is obsolete."")]] typedef void (*Callback2)(); +typedef void (*Callback3)(); + +struct MyStruct0 { + Callback0 _callback; +}; +struct MyStruct1 { + Callback1 _callback; +}; +struct MyStruct2 { + Callback2 _callback; +}; +struct MyStruct3 { + Callback3 _callback; +}; +"; + + var expectedOutputContents = @"using System; + +namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct0 + { + [NativeTypeName(""Callback0"")] + public delegate* unmanaged[Cdecl] _callback; + } + + public unsafe partial struct MyStruct1 + { + [NativeTypeName(""Callback1"")] + [Obsolete] + public delegate* unmanaged[Cdecl] _callback; + } + + public unsafe partial struct MyStruct2 + { + [NativeTypeName(""Callback2"")] + [Obsolete(""This is obsolete."")] + public delegate* unmanaged[Cdecl] _callback; + } + + public unsafe partial struct MyStruct3 + { + [NativeTypeName(""Callback3"")] + public delegate* unmanaged[Cdecl] _callback; + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncDllImportImpl() + { + var inputContents = @" +extern ""C"" void MyFunction0(); +extern ""C"" [[deprecated]] void MyFunction1(); +extern ""C"" [[deprecated(""This is obsolete."")]] void MyFunction2(); +extern ""C"" void MyFunction3();"; + + var expectedOutputContents = @"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction0(); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [Obsolete] + public static extern void MyFunction1(); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [Obsolete(""This is obsolete."")] + public static extern void MyFunction2(); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction3(); + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/EnumDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/EnumDeclarationTest.cs new file mode 100644 index 00000000..86e14c89 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/EnumDeclarationTest.cs @@ -0,0 +1,610 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultWindows_EnumDeclarationTest : EnumDeclarationTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicValueTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value1 = 1, + MyEnum_Value2, + MyEnum_Value3, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value1 = 1, + MyEnum_Value2, + MyEnum_Value3, + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyEnum" }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task ExplicitTypedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"enum MyEnum : {nativeType} +{{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public enum MyEnum : {expectedManagedType} + {{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExplicitTypedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"enum MyEnum : {nativeType} +{{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + [NativeTypeName(""{nativeType}"")] + public enum MyEnum : {expectedManagedType} + {{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = @"typedef enum _MyEnum1 : int +{ + MyEnum1_Value1, + MyEnum1_Value2, + MyEnum1_Value3, +} MyEnum1; + +namespace Namespace1 +{ + namespace Namespace2 + { + typedef enum _MyEnum2 : int + { + MyEnum2_Value1, + MyEnum2_Value2, + MyEnum2_Value3, + } MyEnum2; + + typedef enum _MyEnum3 : int + { + MyEnum3_Value1, + MyEnum3_Value2, + MyEnum3_Value3, + } MyEnum3; + + typedef enum _MyEnum4 : int + { + MyEnum4_Value1, + MyEnum4_Value2, + MyEnum4_Value3, + } MyEnum4; + } +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value1, + MyEnum1_Value2, + MyEnum1_Value3, + } + + public enum MyEnum2 + { + MyEnum2_Value1, + MyEnum2_Value2, + MyEnum2_Value3, + } + + public enum MyEnum3 + { + MyEnum3_Value1, + MyEnum3_Value2, + MyEnum3_Value3, + } + + public enum MyEnum4 + { + MyEnum4_Value1, + MyEnum4_Value2, + MyEnum4_Value3, + } +} +"; + + var remappedNames = new Dictionary { ["_MyEnum1"] = "MyEnum1", ["Namespace1.Namespace2._MyEnum2"] = "MyEnum2", ["_MyEnum3"] = "MyEnum3", ["Namespace1::Namespace2::_MyEnum4"] = "MyEnum4" }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task WithAttributeTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = 1, +}; +"; + + var expectedOutputContents = @"using System; + +namespace ClangSharp.Test +{ + [Flags] + public enum MyEnum1 + { + MyEnum1_Value1 = 1, + } + + public enum MyEnum2 + { + MyEnum2_Value1 = 1, + } +} +"; + + var withAttributes = new Dictionary> + { + ["MyEnum1"] = new List() { "Flags" } + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withAttributes: withAttributes); + } + + protected override Task WithNamespaceTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @"using static ClangSharp.Test.MyEnum1; + +namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value1 = 1, + } + + public enum MyEnum2 + { + MyEnum2_Value1 = MyEnum1_Value1, + } +} +"; + + var withNamespaces = new Dictionary> + { + ["MyEnum1"] = new List() { "static ClangSharp.Test.MyEnum1" } + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithNamespaceStarTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @"using static ClangSharp.Test.MyEnum1; + +namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value1 = 1, + } + + public enum MyEnum2 + { + MyEnum2_Value1 = MyEnum1_Value1, + } +} +"; + + var withNamespaces = new Dictionary> + { + ["*"] = new List() { "static ClangSharp.Test.MyEnum1" } + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithNamespaceStarPlusTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @"using System; +using static ClangSharp.Test.MyEnum1; + +namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value1 = 1, + } + + public enum MyEnum2 + { + MyEnum2_Value1 = MyEnum1_Value1, + } +} +"; + + var withNamespaces = new Dictionary> + { + ["*"] = new List() { "static ClangSharp.Test.MyEnum1" }, + ["MyEnum2"] = new List() { "System" } + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithCastToEnumTypeImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0 = (MyEnum) 10, + MyEnum_Value1 = (MyEnum) MyEnum_Value0, + MyEnum_Value2 = ((MyEnum) 10) + MyEnum_Value1, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0 = (int)(MyEnum)(10), + MyEnum_Value1 = (int)(MyEnum)(MyEnum_Value0), + MyEnum_Value2 = ((int)(MyEnum)(10)) + MyEnum_Value1, + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithMultipleEnumsTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 = 10, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 = MyEnum1_Value0, + MyEnum2_Value1 = MyEnum1_Value0 + (MyEnum1) 10, +}; +"; + + var expectedOutputContents = @"using static ClangSharp.Test.MyEnum1; + +namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value0 = 10, + } + + public enum MyEnum2 + { + MyEnum2_Value0 = MyEnum1_Value0, + MyEnum2_Value1 = MyEnum1_Value0 + (int)(MyEnum1)(10), + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithImplicitConversionTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = 0x80000000, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = unchecked((int)(0x80000000)), + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithTypeTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + [NativeTypeName(""int"")] + public enum MyEnum : uint + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + } +} +"; + + var withTypes = new Dictionary { + ["MyEnum"] = "uint" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeAndImplicitConversionTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = 0x80000000, +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + [NativeTypeName(""int"")] + public enum MyEnum : uint + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = 0x80000000, + } +} +"; + + var withTypes = new Dictionary + { + ["MyEnum"] = "uint" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeStarTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + [NativeTypeName(""int"")] + public enum MyEnum1 : uint + { + MyEnum1_Value0, + } + + [NativeTypeName(""int"")] + public enum MyEnum2 : uint + { + MyEnum2_Value0, + } +} +"; + + var withTypes = new Dictionary + { + ["*"] = "uint" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeStarOverrideTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public enum MyEnum1 + { + MyEnum1_Value0, + } + + [NativeTypeName(""int"")] + public enum MyEnum2 : uint + { + MyEnum2_Value0, + } +} +"; + + var withTypes = new Dictionary + { + ["*"] = "uint", + ["MyEnum1"] = "int", + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + protected override Task WithAnonymousEnumTestImpl() + { + var inputContents = @"enum +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @"using static ClangSharp.Test.Methods; + +namespace ClangSharp.Test +{ + public enum MyEnum2 + { + MyEnum2_Value1 = MyEnum1_Value1, + } + + public static partial class Methods + { + public const int MyEnum1_Value1 = 1; + } +} +"; + + var diagnostics = new[] { new Diagnostic(DiagnosticLevel.Info, "Found anonymous enum: __AnonymousEnum_ClangUnsavedFile_L1_C1. Mapping values as constants in: Methods", "Line 1, Column 1 in ClangUnsavedFile.h") }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } + + protected override Task WithReferenceToAnonymousEnumEnumeratorTestImpl() + { + var inputContents = @"enum +{ + MyEnum1_Value1 = 1, +}; + +const int MyEnum2_Value1 = MyEnum1_Value1 + 1; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public const int MyEnum1_Value1 = 1; + + [NativeTypeName(""const int"")] + public const int MyEnum2_Value1 = (int)(MyEnum1_Value1) + 1; + } +} +"; + var diagnostics = new[] { new Diagnostic(DiagnosticLevel.Info, "Found anonymous enum: __AnonymousEnum_ClangUnsavedFile_L1_C1. Mapping values as constants in: Methods", "Line 1, Column 1 in ClangUnsavedFile.h") }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionDeclarationBodyImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionDeclarationBodyImportTest.cs new file mode 100644 index 00000000..319e9b6c --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionDeclarationBodyImportTest.cs @@ -0,0 +1,1777 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultWindows_FunctionDeclarationBodyImportTest : FunctionDeclarationBodyImportTest +{ + protected override Task ArraySubscriptTestImpl() + { + var inputContents = @"int MyFunction(int* pData, int index) +{ + return pData[index]; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static int MyFunction(int* pData, int index) + { + return pData[index]; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestImpl() + { + var inputContents = @"void MyFunction() +{ +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyFunction() + { + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorBasicTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int x, int y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static int MyFunction(int x, int y) + {{ + return x {opcode} y; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorCompareTestImpl(string opcode) + { + var inputContents = $@"bool MyFunction(int x, int y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static bool MyFunction(int x, int y) + {{ + return x {opcode} y; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorBooleanTestImpl(string opcode) + { + var inputContents = $@"bool MyFunction(bool x, bool y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static bool MyFunction(bool x, bool y) + {{ + return x {opcode} y; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BreakTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + while (true) + { + break; + } + + return 0; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + while (true) + { + break; + } + + return 0; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallFunctionTestImpl() + { + var inputContents = @"void MyCalledFunction() +{ +} + +void MyFunction() +{ + MyCalledFunction(); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyCalledFunction() + { + } + + public static void MyFunction() + { + MyCalledFunction(); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallFunctionWithArgsTestImpl() + { + var inputContents = @"void MyCalledFunction(int x, int y) +{ +} + +void MyFunction() +{ + MyCalledFunction(0, 1); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyCalledFunction(int x, int y) + { + } + + public static void MyFunction() + { + MyCalledFunction(0, 1); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CaseTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + case 0: + { + return 0; + } + + case 1: + case 2: + { + return 3; + } + } + + return -1; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + switch (value) + { + case 0: + { + return 0; + } + + case 1: + case 2: + { + return 3; + } + } + + return -1; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CaseNoCompoundTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + case 0: + return 0; + + case 2: + case 3: + return 5; + } + + return -1; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + switch (value) + { + case 0: + { + return 0; + } + + case 2: + case 3: + { + return 5; + } + } + + return -1; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CompareMultipleEnumTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; + +static inline int MyFunction(MyEnum x) +{ + return x == MyEnum_Value0 || + x == MyEnum_Value1 || + x == MyEnum_Value2; +} +"; + + var expectedOutputContents = @"using static ClangSharp.Test.MyEnum; + +namespace ClangSharp.Test +{ + public enum MyEnum + { + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, + } + + public static partial class Methods + { + public static int MyFunction(MyEnum x) + { + return (x == MyEnum_Value0 || x == MyEnum_Value1 || x == MyEnum_Value2) ? 1 : 0; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConditionalOperatorTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + return condition ? lhs : rhs; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(bool condition, int lhs, int rhs) + { + return condition ? lhs : rhs; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ContinueTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + while (true) + { + continue; + } + + return 0; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + while (true) + { + continue; + } + + return 0; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CStyleFunctionalCastTestImpl() + { + var inputContents = @"int MyFunction(float input) +{ + return (int)input; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(float input) + { + return (int)(input); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxFunctionalCastTestImpl() + { + var inputContents = @"int MyFunction(float input) +{ + return int(input); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(float input) + { + return (int)(input); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxConstCastTestImpl() + { + var inputContents = @"void* MyFunction(const void* input) +{ + return const_cast(input); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static void* MyFunction([NativeTypeName(""const void *"")] void* input) + { + return input; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxDynamicCastTestImpl() + { + var inputContents = @"struct MyStructA +{ + virtual void MyMethod() = 0; +}; + +struct MyStructB : MyStructA { }; + +MyStructB* MyFunction(MyStructA* input) +{ + return dynamic_cast(input); +} +"; + + var expectedOutputContents = $@"using System.Runtime.CompilerServices; + +namespace ClangSharp.Test +{{ + public unsafe partial struct MyStructA + {{ + public void** lpVtbl; + + public void MyMethod() + {{ + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((MyStructA*)Unsafe.AsPointer(ref this)); + }} + }} + + [NativeTypeName(""struct MyStructB : MyStructA"")] + public unsafe partial struct MyStructB + {{ + public void** lpVtbl; + + public void MyMethod() + {{ + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((MyStructB*)Unsafe.AsPointer(ref this)); + }} + }} + + public static unsafe partial class Methods + {{ + public static MyStructB* MyFunction(MyStructA* input) + {{ + return (MyStructB*)(input); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxReinterpretCastTestImpl() + { + var inputContents = @"int* MyFunction(void* input) +{ + return reinterpret_cast(input); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static int* MyFunction(void* input) + { + return (int*)(input); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxStaticCastTestImpl() + { + var inputContents = @"int* MyFunction(void* input) +{ + return static_cast(input); +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static int* MyFunction(void* input) + { + return (int*)(input); + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DeclTestImpl() + { + var inputContents = @"\ +int MyFunction() +{ + int x = 0; + int y = 1, z = 2; + return x + y + z; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction() + { + int x = 0; + int y = 1, z = 2; + + return x + y + z; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DoTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + do + { + i++; + } + while (i < count); + + return i; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + int i = 0; + + do + { + i++; + } + while (i < count); + + return i; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DoNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + i++; + + return i; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + int i = 0; + + while (i < count) + { + i++; + } + + return i; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ForTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;;i--) + { + i += 2; + } + + for (x = 0;;x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + // x = 0; + // + // for (;; x--) + // { + // x += 2; + // } + + x = 0; + + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;; i--) + { + i += 2; + } + + for (x = 0;; x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + x = 0; + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ForNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + for (int i = 0; i < count; i--) + i += 2; + + int x; + + for (x = 0; x < count; x--) + x += 2; + + x = 0; + + for (; x < count; x--) + x += 2; + + for (int i = 0;;i--) + i += 2; + + for (x = 0;;x--) + x += 2; + + for (int i = 0; i < count;) + i++; + + for (x = 0; x < count;) + x++; + + // x = 0; + // + // for (;; x--) + // x += 2; + + x = 0; + + for (; x < count;) + x++; + + for (int i = 0;;) + i++; + + for (x = 0;;) + x++; + + for (;;) + return -1; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;; i--) + { + i += 2; + } + + for (x = 0;; x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + x = 0; + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + { + return lhs; + } + + return rhs; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(bool condition, int lhs, int rhs) + { + if (condition) + { + return lhs; + } + + return rhs; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + { + return lhs; + } + else + { + return rhs; + } +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(bool condition, int lhs, int rhs) + { + if (condition) + { + return lhs; + } + else + { + return rhs; + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseIfTestImpl() + { + var inputContents = @"int MyFunction(bool condition1, int a, int b, bool condition2, int c) +{ + if (condition1) + { + return a; + } + else if (condition2) + { + return b; + } + + return c; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(bool condition1, int a, int b, bool condition2, int c) + { + if (condition1) + { + return a; + } + else if (condition2) + { + return b; + } + + return c; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + return lhs; + else + return rhs; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(bool condition, int lhs, int rhs) + { + if (condition) + { + return lhs; + } + else + { + return rhs; + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InitListForArrayTestImpl() + { + var inputContents = @" +void MyFunction() +{ + int x[4] = { 1, 2, 3, 4 }; + int y[4] = { 1, 2, 3 }; + int z[] = { 1, 2 }; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyFunction() + { + int[] x = new int[4] + { + 1, + 2, + 3, + 4, + }; + int[] y = new int[4] + { + 1, + 2, + 3, + default, + }; + int[] z = new int[2] + { + 1, + 2, + }; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InitListForRecordDeclTestImpl() + { + var inputContents = @"struct MyStruct +{ + float x; + float y; + float z; + float w; +}; + +MyStruct MyFunction1() +{ + return { 1.0f, 2.0f, 3.0f, 4.0f }; +} + +MyStruct MyFunction2() +{ + return { 1.0f, 2.0f, 3.0f }; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public float x; + + public float y; + + public float z; + + public float w; + } + + public static partial class Methods + { + public static MyStruct MyFunction1() + { + return new MyStruct + { + x = 1.0f, + y = 2.0f, + z = 3.0f, + w = 4.0f, + }; + } + + public static MyStruct MyFunction2() + { + return new MyStruct + { + x = 1.0f, + y = 2.0f, + z = 3.0f, + }; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; +}; + +int MyFunction1(MyStruct instance) +{ + return instance.value; +} + +int MyFunction2(MyStruct* instance) +{ + return instance->value; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + } + + public static unsafe partial class Methods + { + public static int MyFunction1(MyStruct instance) + { + return instance.value; + } + + public static int MyFunction2(MyStruct* instance) + { + return instance->value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RefToPtrTestImpl() + { + var inputContents = @"struct MyStruct { + int value; +}; + +bool MyFunction(const MyStruct& lhs, const MyStruct& rhs) +{ + return lhs.value == rhs.value; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int value; + } + + public static unsafe partial class Methods + { + public static bool MyFunction([NativeTypeName(""const MyStruct &"")] MyStruct* lhs, [NativeTypeName(""const MyStruct &"")] MyStruct* rhs) + { + return lhs->value == rhs->value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnCXXNullPtrTestImpl() + { + var inputContents = @"void* MyFunction() +{ + return nullptr; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static void* MyFunction() + { + return null; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnCXXBooleanLiteralTestImpl(string value) + { + var inputContents = $@"bool MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static bool MyFunction() + {{ + return {value}; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnFloatingLiteralDoubleTestImpl(string value) + { + var inputContents = $@"double MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static double MyFunction() + {{ + return {value}; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnFloatingLiteralSingleTestImpl(string value) + { + var inputContents = $@"float MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static float MyFunction() + {{ + return {value}; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnEmptyTestImpl() + { + var inputContents = @"void MyFunction() +{ + return; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static void MyFunction() + { + return; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnIntegerLiteralInt32TestImpl() + { + var inputContents = @"int MyFunction() +{ + return -1; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction() + { + return -1; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task AccessUnionMemberTestImpl() + { + var inputContents = @"union MyUnion +{ + struct { int a; }; +}; + +void MyFunction() +{ + MyUnion myUnion; + myUnion.a = 10; +} +"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + { + [FieldOffset(0)] + [NativeTypeName(""MyUnion::(anonymous struct at ClangUnsavedFile.h:3:5)"")] + public _Anonymous_e__Struct Anonymous; + + public ref int a + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + } + } + + public partial struct _Anonymous_e__Struct + { + public int a; + } + } + + public static partial class Methods + { + public static void MyFunction() + { + MyUnion myUnion = new MyUnion(); + + myUnion.Anonymous.a = 10; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnStructTestImpl() + { + var inputContents = @"struct MyStruct +{ + double r; + double g; + double b; +}; + +MyStruct MyFunction() +{ + MyStruct myStruct; + return myStruct; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public double r; + + public double g; + + public double b; + } + + public static partial class Methods + { + public static MyStruct MyFunction() + { + MyStruct myStruct = new MyStruct(); + + return myStruct; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SwitchTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + default: + { + return 0; + } + } +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + switch (value) + { + default: + { + return 0; + } + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SwitchNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + default: + { + return 0; + } + + switch (value) + default: + return 0; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int value) + { + switch (value) + { + default: + { + return 0; + } + } + + switch (value) + { + default: + { + return 0; + } + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorAddrOfTestImpl() + { + var inputContents = @"int* MyFunction(int value) +{ + return &value; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static int* MyFunction(int value) + { + return &value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorDerefTestImpl() + { + var inputContents = @"int MyFunction(int* value) +{ + return *value; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + public static int MyFunction(int* value) + { + return *value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorLogicalNotTestImpl() + { + var inputContents = @"bool MyFunction(bool value) +{ + return !value; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static bool MyFunction(bool value) + { + return !value; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorPostfixTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int value) +{{ + return value{opcode}; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static int MyFunction(int value) + {{ + return value{opcode}; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorPrefixTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int value) +{{ + return {opcode}value; +}} +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static int MyFunction(int value) + {{ + return {opcode}value; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WhileTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + { + i++; + } + + return i; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + int i = 0; + + while (i < count) + { + i++; + } + + return i; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WhileNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + i++; + + return i; +} +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public static partial class Methods + { + public static int MyFunction(int count) + { + int i = 0; + + while (i < count) + { + i++; + } + + return i; + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionDeclarationDllImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionDeclarationDllImportTest.cs new file mode 100644 index 00000000..9f232de1 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionDeclarationDllImportTest.cs @@ -0,0 +1,416 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultWindows_FunctionDeclarationDllImportTest : FunctionDeclarationDllImportTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ArrayParameterTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(const float color[4]);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction([NativeTypeName(""const float[4]"")] float* color); + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FunctionPointerParameterTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(void (*callback)());"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static unsafe partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction([NativeTypeName(""void (*)()"")] delegate* unmanaged[Cdecl] callback); + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NamespaceTestImpl() + { + var inputContents = @"namespace MyNamespace +{ + void MyFunction(); +}"; + + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "__ZN11MyNamespace10MyFunctionEv" : "_ZN11MyNamespace10MyFunctionEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + entryPoint = "?MyFunction@MyNamespace@@YAXXZ"; + } + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, EntryPoint = ""{entryPoint}"", ExactSpelling = true)] + public static extern void MyFunction(); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TemplateParameterTestImpl(string nativeType, bool expectedNativeTypeAttr, string expectedManagedType, string expectedUsingStatement) + { + var inputContents = @$"template struct MyTemplate; + +extern ""C"" void MyFunction(MyTemplate<{nativeType}> myStruct);"; + + var expectedOutputContents = $@"{expectedUsingStatement}using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction({(expectedNativeTypeAttr ? $@"[NativeTypeName(""MyTemplate<{nativeType}>"")] " : "")}MyTemplate<{expectedManagedType}> myStruct); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: new[] { "MyTemplate" }); + } + + protected override Task TemplateMemberTestImpl() + { + var inputContents = @$"template struct MyTemplate +{{ +}}; + +struct MyStruct +{{ + MyTemplate a; +}}; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""MyTemplate"")] + public MyTemplate a; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: new[] { "MyTemplate" }); + } + + protected override Task NoLibraryPathTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport("""", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty); + } + + protected override Task WithLibraryPathTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + + var withLibraryPaths = new Dictionary + { + ["MyFunction"] = "ClangSharpPInvokeGenerator" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty, withLibraryPaths: withLibraryPaths); + } + + protected override Task WithLibraryPathStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + + var withLibraryPaths = new Dictionary + { + ["*"] = "ClangSharpPInvokeGenerator" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty, withLibraryPaths: withLibraryPaths); + } + + protected override Task OptionalParameterTestImpl(string nativeType, string nativeInit, bool expectedNativeTypeNameAttr, string expectedManagedType, string expectedManagedInit) + { + var inputContents = $@"extern ""C"" void MyFunction({nativeType} value = {nativeInit});"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction({(expectedNativeTypeNameAttr ? $@"[NativeTypeName(""{nativeType}"")] " : "")}{expectedManagedType} value = {expectedManagedInit}); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task OptionalParameterUnsafeTestImpl(string nativeType, string nativeInit, string expectedManagedType, string expectedManagedInit) + { + var inputContents = $@"extern ""C"" void MyFunction({nativeType} value = {nativeInit});"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public static unsafe partial class Methods + {{ + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction({expectedManagedType} value = {expectedManagedInit}); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithCallConvTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", ExactSpelling = true)] + public static extern void MyFunction1(int value); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction2(int value); + } +} +"; + + var withCallConvs = new Dictionary { + ["MyFunction1"] = "Winapi" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithCallConvStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", ExactSpelling = true)] + public static extern void MyFunction1(int value); + + [DllImport(""ClangSharpPInvokeGenerator"", ExactSpelling = true)] + public static extern void MyFunction2(int value); + } +} +"; + + var withCallConvs = new Dictionary + { + ["*"] = "Winapi" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithCallConvStarOverrideTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", ExactSpelling = true)] + public static extern void MyFunction1(int value); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.StdCall, ExactSpelling = true)] + public static extern void MyFunction2(int value); + } +} +"; + + var withCallConvs = new Dictionary + { + ["*"] = "Winapi", + ["MyFunction2"] = "StdCall" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithSetLastErrorTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = true)] + public static extern void MyFunction1(int value); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction2(int value); + } +} +"; + + var withSetLastErrors = new string[] + { + "MyFunction1" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withSetLastErrors: withSetLastErrors); + } + + protected override Task WithSetLastErrorStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = true)] + public static extern void MyFunction1(int value); + + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = true)] + public static extern void MyFunction2(int value); + } +} +"; + + var withSetLastErrors = new string[] + { + "*" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withSetLastErrors: withSetLastErrors); + } + + protected override Task SourceLocationTestImpl() + { + const string InputContents = @"extern ""C"" void MyFunction(float value);"; + + const string ExpectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [SourceLocation(""ClangUnsavedFile.h"", 1, 17)] + public static extern void MyFunction([SourceLocation(""ClangUnsavedFile.h"", 1, 34)] float value); + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); + } + + protected override Task VarargsTestImpl() + { + const string InputContents = @"extern ""C"" void MyFunction(int value, ...);"; + + const string ExpectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(int value, __arglist); + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(InputContents, ExpectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionPointerDeclarationTest.cs new file mode 100644 index 00000000..350d08cc --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/FunctionPointerDeclarationTest.cs @@ -0,0 +1,74 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultWindows_FunctionPointerDeclarationTest : FunctionPointerDeclarationTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"typedef void (*Callback)(); + +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""Callback"")] + public delegate* unmanaged[Cdecl] _callback; + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallconvTestImpl() + { + var inputContents = @"typedef void (*Callback)() __attribute__((stdcall)); + +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""Callback"")] + public delegate* unmanaged[Stdcall] _callback; + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerlessTypedefTestImpl() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""Callback *"")] + public delegate* unmanaged[Cdecl] _callback; + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/StructDeclarationTest.cs new file mode 100644 index 00000000..7f0e8cc0 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/StructDeclarationTest.cs @@ -0,0 +1,1781 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using ClangSharp.Abstractions; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultWindows_StructDeclarationTest : StructDeclarationTest +{ + protected override Task IncompleteArraySizeTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} x[]; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}[]"")] + public fixed {expectedManagedType} x[1]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + public {expectedManagedType} g; + + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestInCModeImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}} MyStruct; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + public {expectedManagedType} g; + + public {expectedManagedType} b; + }} +}} +"; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, commandlineArgs: Array.Empty()); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BitfieldTestImpl() + { + var inputContents = @"struct MyStruct1 +{ + unsigned int o0_b0_24 : 24; + unsigned int o4_b0_16 : 16; + unsigned int o4_b16_3 : 3; + int o4_b19_3 : 3; + unsigned char o8_b0_1 : 1; + int o12_b0_1 : 1; + int o12_b1_1 : 1; +}; + +struct MyStruct2 +{ + unsigned int o0_b0_1 : 1; + int x; + unsigned int o8_b0_1 : 1; +}; + +struct MyStruct3 +{ + unsigned int o0_b0_1 : 1; + unsigned int o0_b1_1 : 1; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct1 + { + public uint _bitfield1; + + [NativeTypeName(""unsigned int : 24"")] + public uint o0_b0_24 + { + get + { + return _bitfield1 & 0xFFFFFFu; + } + + set + { + _bitfield1 = (_bitfield1 & ~0xFFFFFFu) | (value & 0xFFFFFFu); + } + } + + public uint _bitfield2; + + [NativeTypeName(""unsigned int : 16"")] + public uint o4_b0_16 + { + get + { + return _bitfield2 & 0xFFFFu; + } + + set + { + _bitfield2 = (_bitfield2 & ~0xFFFFu) | (value & 0xFFFFu); + } + } + + [NativeTypeName(""unsigned int : 3"")] + public uint o4_b16_3 + { + get + { + return (_bitfield2 >> 16) & 0x7u; + } + + set + { + _bitfield2 = (_bitfield2 & ~(0x7u << 16)) | ((value & 0x7u) << 16); + } + } + + [NativeTypeName(""int : 3"")] + public int o4_b19_3 + { + get + { + return (int)((_bitfield2 >> 19) & 0x7u); + } + + set + { + _bitfield2 = (_bitfield2 & ~(0x7u << 19)) | (uint)((value & 0x7) << 19); + } + } + + public byte _bitfield3; + + [NativeTypeName(""unsigned char : 1"")] + public byte o8_b0_1 + { + get + { + return (byte)(_bitfield3 & 0x1u); + } + + set + { + _bitfield3 = (byte)((_bitfield3 & ~0x1u) | (value & 0x1u)); + } + } + + public int _bitfield4; + + [NativeTypeName(""int : 1"")] + public int o12_b0_1 + { + get + { + return _bitfield4 & 0x1; + } + + set + { + _bitfield4 = (_bitfield4 & ~0x1) | (value & 0x1); + } + } + + [NativeTypeName(""int : 1"")] + public int o12_b1_1 + { + get + { + return (_bitfield4 >> 1) & 0x1; + } + + set + { + _bitfield4 = (_bitfield4 & ~(0x1 << 1)) | ((value & 0x1) << 1); + } + } + } + + public partial struct MyStruct2 + { + public uint _bitfield1; + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b0_1 + { + get + { + return _bitfield1 & 0x1u; + } + + set + { + _bitfield1 = (_bitfield1 & ~0x1u) | (value & 0x1u); + } + } + + public int x; + + public uint _bitfield2; + + [NativeTypeName(""unsigned int : 1"")] + public uint o8_b0_1 + { + get + { + return _bitfield2 & 0x1u; + } + + set + { + _bitfield2 = (_bitfield2 & ~0x1u) | (value & 0x1u); + } + } + } + + public partial struct MyStruct3 + { + public uint _bitfield; + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b0_1 + { + get + { + return _bitfield & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + } + } + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b1_1 + { + get + { + return (_bitfield >> 1) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DeclTypeTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(); + +typedef struct +{ + decltype(&MyFunction) _callback; +} MyStruct; +"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public unsafe partial struct MyStruct + { + [NativeTypeName(""decltype(&MyFunction)"")] + public delegate* unmanaged[Cdecl] _callback; + } + + public static partial class Methods + { + [DllImport(""ClangSharpPInvokeGenerator"", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MyFunction(); + } +} +"; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = "typedef struct MyStruct MyStruct;"; + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyStruct" }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task FixedSizedBufferNonPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[3]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} value; + }} + + public partial struct MyOtherStruct + {{ + [NativeTypeName(""MyStruct[3]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyStruct e0; + public MyStruct e1; + public MyStruct e2; + + public ref MyStruct this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} value; + }} + + public partial struct MyOtherStruct + {{ + [NativeTypeName(""MyStruct[2][1][3][4]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyStruct e0_0_0_0; + public MyStruct e1_0_0_0; + + public MyStruct e0_0_1_0; + public MyStruct e1_0_1_0; + + public MyStruct e0_0_2_0; + public MyStruct e1_0_2_0; + + public MyStruct e0_0_0_1; + public MyStruct e1_0_0_1; + + public MyStruct e0_0_1_1; + public MyStruct e1_0_1_1; + + public MyStruct e0_0_2_1; + public MyStruct e1_0_2_1; + + public MyStruct e0_0_0_2; + public MyStruct e1_0_0_2; + + public MyStruct e0_0_1_2; + public MyStruct e1_0_1_2; + + public MyStruct e0_0_2_2; + public MyStruct e1_0_2_2; + + public MyStruct e0_0_0_3; + public MyStruct e1_0_0_3; + + public MyStruct e0_0_1_3; + public MyStruct e1_0_1_3; + + public MyStruct e0_0_2_3; + public MyStruct e1_0_2_3; + + public ref MyStruct this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +typedef MyStruct MyBuffer[3]; + +struct MyOtherStruct +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} value; + }} + + public partial struct MyOtherStruct + {{ + [NativeTypeName(""MyBuffer"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyStruct e0; + public MyStruct e1; + public MyStruct e2; + + public ref MyStruct this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[3]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} value; + }} + + public partial struct MyOtherStruct + {{ + [NativeTypeName(""MyStruct[3]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyStruct e0; + public MyStruct e1; + public MyStruct e2; + + public ref MyStruct this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPointerTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}[3]"")] + public _c_e__FixedBuffer c; + + public unsafe partial struct _c_e__FixedBuffer + {{ + public {expectedManagedType} e0; + public {expectedManagedType} e1; + public {expectedManagedType} e2; + + public ref {expectedManagedType} this[int index] + {{ + get + {{ + fixed ({expectedManagedType}* pThis = &e0) + {{ + return ref pThis[index]; + }} + }} + }} + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}[3]"")] + public fixed {expectedManagedType} c[3]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}[2][1][3][4]"")] + public fixed {expectedManagedType} c[2 * 1 * 3 * 4]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyBuffer[3]; + +struct MyStruct +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct + {{ + [NativeTypeName(""MyBuffer"")] + public fixed {expectedManagedType} c[3]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task GuidTestImpl() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Non-Windows doesn't support __declspec(uuid("")) + return Task.CompletedTask; + } + + var inputContents = $@"#define DECLSPEC_UUID(x) __declspec(uuid(x)) + +struct __declspec(uuid(""00000000-0000-0000-C000-000000000046"")) MyStruct1 +{{ + int x; +}}; + +struct DECLSPEC_UUID(""00000000-0000-0000-C000-000000000047"") MyStruct2 +{{ + int x; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [Guid(""00000000-0000-0000-C000-000000000046"")] + public partial struct MyStruct1 + {{ + public int x; + }} + + [Guid(""00000000-0000-0000-C000-000000000047"")] + public partial struct MyStruct2 + {{ + public int x; + }} + + public static partial class Methods + {{ + public static readonly Guid IID_MyStruct1 = new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + + public static readonly Guid IID_MyStruct2 = new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47); + }} +}} +"; + + var excludedNames = new string[] { "DECLSPEC_UUID" }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task InheritanceTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + int x; + int y; +}; + +struct MyStruct1B +{ + int x; + int y; +}; + +struct MyStruct2 : MyStruct1A, MyStruct1B +{ + int z; + int w; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct1A + { + public int x; + + public int y; + } + + public partial struct MyStruct1B + { + public int x; + + public int y; + } + + [NativeTypeName(""struct MyStruct2 : MyStruct1A, MyStruct1B"")] + public partial struct MyStruct2 + { + public MyStruct1A Base1; + + public MyStruct1B Base2; + + public int z; + + public int w; + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InheritanceWithNativeInheritanceAttributeTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + int x; + int y; +}; + +struct MyStruct1B +{ + int x; + int y; +}; + +struct MyStruct2 : MyStruct1A, MyStruct1B +{ + int z; + int w; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct1A + { + public int x; + + public int y; + } + + public partial struct MyStruct1B + { + public int x; + + public int y; + } + + [NativeTypeName(""struct MyStruct2 : MyStruct1A, MyStruct1B"")] + [NativeInheritance(""MyStruct1B"")] + public partial struct MyStruct2 + { + public MyStruct1A Base1; + + public MyStruct1B Base2; + + public int z; + + public int w; + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateNativeInheritanceAttribute); + } + + protected override Task NestedAnonymousTestImpl(string nativeType, string expectedManagedType, int line, int column) + { + var inputContents = $@"typedef union {{ + {nativeType} value; +}} MyUnion; + +struct MyStruct +{{ + {nativeType} x; + {nativeType} y; + + struct + {{ + {nativeType} z; + + struct + {{ + {nativeType} value; + }} w; + + struct + {{ + {nativeType} value1; + + struct + {{ + {nativeType} value; + }}; + }}; + + union + {{ + {nativeType} value2; + }}; + + MyUnion u; + {nativeType} buffer1[4]; + MyUnion buffer2[4]; + }}; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} value; + }} + + public unsafe partial struct MyStruct + {{ + public {expectedManagedType} x; + + public {expectedManagedType} y; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:{line}:{column})"")] + public _Anonymous_e__Struct Anonymous; + + public ref {expectedManagedType} z + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + }} + }} + + public ref _Anonymous_e__Struct._w_e__Struct w + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.w, 1)); + }} + }} + + public ref {expectedManagedType} value1 + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous1.value1, 1)); + }} + }} + + public ref {expectedManagedType} value + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous1.Anonymous.value, 1)); + }} + }} + + public ref {expectedManagedType} value2 + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous2.value2, 1)); + }} + }} + + public ref MyUnion u + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.u, 1)); + }} + }} + + public Span<{expectedManagedType}> buffer1 + {{ + get + {{ + return MemoryMarshal.CreateSpan(ref Anonymous.buffer1[0], 4); + }} + }} + + public Span buffer2 + {{ + get + {{ + return Anonymous.buffer2.AsSpan(); + }} + }} + + public unsafe partial struct _Anonymous_e__Struct + {{ + public {expectedManagedType} z; + + [NativeTypeName(""struct (anonymous struct at ClangUnsavedFile.h:14:9)"")] + public _w_e__Struct w; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:19:9)"")] + public _Anonymous1_e__Struct Anonymous1; + + [NativeTypeName(""MyStruct::(anonymous union at ClangUnsavedFile.h:29:9)"")] + public _Anonymous2_e__Union Anonymous2; + + public MyUnion u; + + [NativeTypeName(""{nativeType}[4]"")] + public fixed {expectedManagedType} buffer1[4]; + + [NativeTypeName(""MyUnion[4]"")] + public _buffer2_e__FixedBuffer buffer2; + + public partial struct _w_e__Struct + {{ + public {expectedManagedType} value; + }} + + public partial struct _Anonymous1_e__Struct + {{ + public {expectedManagedType} value1; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:23:13)"")] + public _Anonymous_e__Struct Anonymous; + + public partial struct _Anonymous_e__Struct + {{ + public {expectedManagedType} value; + }} + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct _Anonymous2_e__Union + {{ + [FieldOffset(0)] + public {expectedManagedType} value2; + }} + + public partial struct _buffer2_e__FixedBuffer + {{ + public MyUnion e0; + public MyUnion e1; + public MyUnion e2; + public MyUnion e3; + + public ref MyUnion this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 4); + }} + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedAnonymousWithBitfieldTestImpl() + { + var inputContents = @"struct MyStruct +{ + int x; + int y; + + struct + { + int z; + + struct + { + int w; + int o0_b0_16 : 16; + int o0_b16_4 : 4; + }; + }; +}; +"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public int x; + + public int y; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:6:5)"")] + public _Anonymous_e__Struct Anonymous; + + public ref int z + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + } + } + + public ref int w + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + } + } + + public int o0_b0_16 + { + get + { + return Anonymous.Anonymous.o0_b0_16; + } + + set + { + Anonymous.Anonymous.o0_b0_16 = value; + } + } + + public int o0_b16_4 + { + get + { + return Anonymous.Anonymous.o0_b16_4; + } + + set + { + Anonymous.Anonymous.o0_b16_4 = value; + } + } + + public partial struct _Anonymous_e__Struct + { + public int z; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:10:9)"")] + public _Anonymous_e__Struct Anonymous; + + public partial struct _Anonymous_e__Struct + { + public int w; + + public int _bitfield; + + [NativeTypeName(""int : 16"")] + public int o0_b0_16 + { + get + { + return _bitfield & 0xFFFF; + } + + set + { + _bitfield = (_bitfield & ~0xFFFF) | (value & 0xFFFF); + } + } + + [NativeTypeName(""int : 4"")] + public int o0_b16_4 + { + get + { + return (_bitfield >> 16) & 0xF; + } + + set + { + _bitfield = (_bitfield & ~(0xF << 16)) | ((value & 0xF) << 16); + } + } + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + struct MyNestedStruct + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + public {expectedManagedType} g; + + public {expectedManagedType} b; + + public partial struct MyNestedStruct + {{ + public {expectedManagedType} r; + + public {expectedManagedType} g; + + public {expectedManagedType} b; + + public {expectedManagedType} a; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + struct MyNestedStruct + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + + public partial struct MyNestedStruct + {{ + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} a; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"struct MyStruct +{ + int Equals; + int Dispose; + int GetHashCode; + int GetType; + int MemberwiseClone; + int ReferenceEquals; + int ToString; +};"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public new int Equals; + + public int Dispose; + + public new int GetHashCode; + + public new int GetType; + + public new int MemberwiseClone; + + public new int ReferenceEquals; + + public new int ToString; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoDefinitionTestImpl() + { + var inputContents = "typedef struct MyStruct MyStruct;"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + }} +}} +"; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PackTestImpl() + { + const string InputContents = @"struct MyStruct1 { + unsigned Field1; + + void* Field2; + + unsigned Field3; +}; + +#pragma pack(4) + +struct MyStruct2 { + unsigned Field1; + + void* Field2; + + unsigned Field3; +}; +"; + + var usingStatement = "using System.Runtime.InteropServices;\n\n"; + var packing = " [StructLayout(LayoutKind.Sequential, Pack = 4)]\n"; + + if (!Environment.Is64BitProcess) + { + usingStatement = string.Empty; + packing = string.Empty; + } + + var expectedOutputContents = $@"{usingStatement}namespace ClangSharp.Test +{{ + public unsafe partial struct MyStruct1 + {{ + [NativeTypeName(""unsigned int"")] + public uint Field1; + + public void* Field2; + + [NativeTypeName(""unsigned int"")] + public uint Field3; + }} + +{packing} public unsafe partial struct MyStruct2 + {{ + [NativeTypeName(""unsigned int"")] + public uint Field1; + + public void* Field2; + + [NativeTypeName(""unsigned int"")] + public uint Field3; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(InputContents, expectedOutputContents); + } + + protected override Task PointerToSelfTestImpl() + { + var inputContents = @"struct example_s { + example_s* next; + void* data; +};"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct example_s + {{ + public example_s* next; + + public void* data; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfViaTypedefTestImpl() + { + var inputContents = @"typedef struct example_s example_t; + +struct example_s { + example_t* next; + void* data; +};"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public unsafe partial struct example_s + {{ + [NativeTypeName(""example_t *"")] + public example_s* next; + + public void* data; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = "typedef struct _MyStruct MyStruct;"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + }} +}} +"; + + var remappedNames = new Dictionary { ["_MyStruct"] = "MyStruct" }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task RemapNestedAnonymousTestImpl() + { + var inputContents = @"struct MyStruct +{ + double r; + double g; + double b; + + struct + { + double a; + }; +};"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + public partial struct MyStruct + { + public double r; + + public double g; + + public double b; + + [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:7:5)"")] + public _Anonymous_e__Struct Anonymous; + + public ref double a + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + } + } + + public partial struct _Anonymous_e__Struct + { + public double a; + } + } +} +"; + + var remappedNames = new Dictionary { + ["__AnonymousField_ClangUnsavedFile_L7_C5"] = "Anonymous", + ["__AnonymousRecord_ClangUnsavedFile_L7_C5"] = "_Anonymous_e__Struct" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task SkipNonDefinitionTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct MyStruct MyStruct; + +struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} r; + + public {expectedManagedType} g; + + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionPointerTestImpl() + { + var inputContents = @"typedef struct MyStruct* MyStructPtr; +typedef struct MyStruct& MyStructRef; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct + { + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct MyStruct MyStruct; + +struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyTypedefAlias; + +struct MyStruct +{{ + MyTypedefAlias r; + MyTypedefAlias g; + MyTypedefAlias b; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} r; + + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} g; + + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UsingDeclarationTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + void MyMethod() { } +}; + +struct MyStruct1B : MyStruct1A +{ + using MyStruct1A::MyMethod; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + public partial struct MyStruct1A + { + public void MyMethod() + { + } + } + + [NativeTypeName(""struct MyStruct1B : MyStruct1A"")] + public partial struct MyStruct1B + { + public void MyMethod() + { + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithAccessSpecifierTestImpl() + { + var inputContents = @"struct MyStruct1 +{ + int Field1; + int Field2; +}; + +struct MyStruct2 +{ + int Field1; + int Field2; +}; + +struct MyStruct3 +{ + int Field1; + int Field2; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test +{ + internal partial struct MyStruct1 + { + private int Field1; + + public int Field2; + } + + internal partial struct MyStruct2 + { + private int Field1; + + public int Field2; + } + + public partial struct MyStruct3 + { + private int Field1; + + internal int Field2; + } +} +"; + + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); + } + + protected override Task WithPackingTestImpl() + { + const string InputContents = @"struct MyStruct +{ + size_t FixedBuffer[1]; +}; +"; + + const string ExpectedOutputContents = @"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [StructLayout(LayoutKind.Sequential, Pack = CustomPackValue)] + public partial struct MyStruct + { + [NativeTypeName(""size_t[1]"")] + public _FixedBuffer_e__FixedBuffer FixedBuffer; + + public partial struct _FixedBuffer_e__FixedBuffer + { + public nuint e0; + + public ref nuint this[int index] + { + get + { + return ref AsSpan(int.MaxValue)[index]; + } + } + + public Span AsSpan(int length) => MemoryMarshal.CreateSpan(ref e0, length); + } + } +} +"; + + var withPackings = new Dictionary { + ["MyStruct"] = "CustomPackValue" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(InputContents, ExpectedOutputContents, withPackings: withPackings); + } + + protected override Task SourceLocationAttributeTestImpl() + { + const string InputContents = @"struct MyStruct +{ + int r; + int g; + int b; +}; +"; + + const string ExpectedOutputContents = @"namespace ClangSharp.Test +{ + [SourceLocation(""ClangUnsavedFile.h"", 1, 8)] + public partial struct MyStruct + { + [SourceLocation(""ClangUnsavedFile.h"", 3, 9)] + public int r; + + [SourceLocation(""ClangUnsavedFile.h"", 4, 9)] + public int g; + + [SourceLocation(""ClangUnsavedFile.h"", 5, 9)] + public int b; + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/UnionDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/UnionDeclarationTest.cs new file mode 100644 index 00000000..dcfc0701 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/UnionDeclarationTest.cs @@ -0,0 +1,1448 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultWindows_UnionDeclarationTest : UnionDeclarationTest +{ + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestInCModeImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}} MyUnion; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + }} +}} +"; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, commandlineArgs: Array.Empty()); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BitfieldTestImpl() + { + var inputContents = @"union MyUnion1 +{ + unsigned int o0_b0_24 : 24; + unsigned int o4_b0_16 : 16; + unsigned int o4_b16_3 : 3; + int o4_b19_3 : 3; + unsigned char o8_b0_1 : 1; + int o12_b0_1 : 1; + int o12_b1_1 : 1; +}; + +union MyUnion2 +{ + unsigned int o0_b0_1 : 1; + int x; + unsigned int o8_b0_1 : 1; +}; + +union MyUnion3 +{ + unsigned int o0_b0_1 : 1; + unsigned int o0_b1_1 : 1; +}; +"; + + var expectedPack = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ", Pack = 1" : ""; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit{expectedPack})] + public partial struct MyUnion1 + {{ + [FieldOffset(0)] + public uint _bitfield1; + + [NativeTypeName(""unsigned int : 24"")] + public uint o0_b0_24 + {{ + get + {{ + return _bitfield1 & 0xFFFFFFu; + }} + + set + {{ + _bitfield1 = (_bitfield1 & ~0xFFFFFFu) | (value & 0xFFFFFFu); + }} + }} + + [FieldOffset(0)] + public uint _bitfield2; + + [NativeTypeName(""unsigned int : 16"")] + public uint o4_b0_16 + {{ + get + {{ + return _bitfield2 & 0xFFFFu; + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~0xFFFFu) | (value & 0xFFFFu); + }} + }} + + [NativeTypeName(""unsigned int : 3"")] + public uint o4_b16_3 + {{ + get + {{ + return (_bitfield2 >> 16) & 0x7u; + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~(0x7u << 16)) | ((value & 0x7u) << 16); + }} + }} + + [NativeTypeName(""int : 3"")] + public int o4_b19_3 + {{ + get + {{ + return (int)((_bitfield2 >> 19) & 0x7u); + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~(0x7u << 19)) | (uint)((value & 0x7) << 19); + }} + }} + + [FieldOffset(0)] + public byte _bitfield3; + + [NativeTypeName(""unsigned char : 1"")] + public byte o8_b0_1 + {{ + get + {{ + return (byte)(_bitfield3 & 0x1u); + }} + + set + {{ + _bitfield3 = (byte)((_bitfield3 & ~0x1u) | (value & 0x1u)); + }} + }} + + [FieldOffset(0)] + public int _bitfield4; + + [NativeTypeName(""int : 1"")] + public int o12_b0_1 + {{ + get + {{ + return _bitfield4 & 0x1; + }} + + set + {{ + _bitfield4 = (_bitfield4 & ~0x1) | (value & 0x1); + }} + }} + + [NativeTypeName(""int : 1"")] + public int o12_b1_1 + {{ + get + {{ + return (_bitfield4 >> 1) & 0x1; + }} + + set + {{ + _bitfield4 = (_bitfield4 & ~(0x1 << 1)) | ((value & 0x1) << 1); + }} + }} + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion2 + {{ + [FieldOffset(0)] + public uint _bitfield1; + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b0_1 + {{ + get + {{ + return _bitfield1 & 0x1u; + }} + + set + {{ + _bitfield1 = (_bitfield1 & ~0x1u) | (value & 0x1u); + }} + }} + + [FieldOffset(0)] + public int x; + + [FieldOffset(0)] + public uint _bitfield2; + + [NativeTypeName(""unsigned int : 1"")] + public uint o8_b0_1 + {{ + get + {{ + return _bitfield2 & 0x1u; + }} + + set + {{ + _bitfield2 = (_bitfield2 & ~0x1u) | (value & 0x1u); + }} + }} + }} + + [StructLayout(LayoutKind.Explicit{expectedPack})] + public partial struct MyUnion3 + {{ + [FieldOffset(0)] + public uint _bitfield; + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b0_1 + {{ + get + {{ + return _bitfield & 0x1u; + }} + + set + {{ + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + }} + }} + + [NativeTypeName(""unsigned int : 1"")] + public uint o0_b1_1 + {{ + get + {{ + return (_bitfield >> 1) & 0x1u; + }} + + set + {{ + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + }} + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = "typedef union MyUnion MyUnion;"; + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyUnion" }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task FixedSizedBufferNonPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[3]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} value; + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyOtherUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyUnion[3]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyUnion e0; + public MyUnion e1; + public MyUnion e2; + + public ref MyUnion this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} value; + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyOtherUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyUnion[2][1][3][4]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyUnion e0_0_0_0; + public MyUnion e1_0_0_0; + + public MyUnion e0_0_1_0; + public MyUnion e1_0_1_0; + + public MyUnion e0_0_2_0; + public MyUnion e1_0_2_0; + + public MyUnion e0_0_0_1; + public MyUnion e1_0_0_1; + + public MyUnion e0_0_1_1; + public MyUnion e1_0_1_1; + + public MyUnion e0_0_2_1; + public MyUnion e1_0_2_1; + + public MyUnion e0_0_0_2; + public MyUnion e1_0_0_2; + + public MyUnion e0_0_1_2; + public MyUnion e1_0_1_2; + + public MyUnion e0_0_2_2; + public MyUnion e1_0_2_2; + + public MyUnion e0_0_0_3; + public MyUnion e1_0_0_3; + + public MyUnion e0_0_1_3; + public MyUnion e1_0_1_3; + + public MyUnion e0_0_2_3; + public MyUnion e1_0_2_3; + + public ref MyUnion this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +typedef MyUnion MyBuffer[3]; + +union MyOtherUnion +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} value; + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyOtherUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyBuffer"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyUnion e0; + public MyUnion e1; + public MyUnion e2; + + public ref MyUnion this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[3]; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} value; + }} + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyOtherUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyUnion[3]"")] + public _c_e__FixedBuffer c; + + public partial struct _c_e__FixedBuffer + {{ + public MyUnion e0; + public MyUnion e1; + public MyUnion e2; + + public ref MyUnion this[int index] + {{ + get + {{ + return ref AsSpan()[index]; + }} + }} + + public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPointerTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}[3]"")] + public _c_e__FixedBuffer c; + + public unsafe partial struct _c_e__FixedBuffer + {{ + public {expectedManagedType} e0; + public {expectedManagedType} e1; + public {expectedManagedType} e2; + + public ref {expectedManagedType} this[int index] + {{ + get + {{ + fixed ({expectedManagedType}* pThis = &e0) + {{ + return ref pThis[index]; + }} + }} + }} + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}[3]"")] + public fixed {expectedManagedType} c[3]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}[2][1][3][4]"")] + public fixed {expectedManagedType} c[2 * 1 * 3 * 4]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyBuffer[3]; + +union MyUnion +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyBuffer"")] + public fixed {expectedManagedType} c[3]; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + protected override Task GuidTestImpl() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Non-Windows doesn't support __declspec(uuid("")) + return Task.CompletedTask; + } + + var inputContents = $@"#define DECLSPEC_UUID(x) __declspec(uuid(x)) + +union __declspec(uuid(""00000000-0000-0000-C000-000000000046"")) MyUnion1 +{{ + int x; +}}; + +union DECLSPEC_UUID(""00000000-0000-0000-C000-000000000047"") MyUnion2 +{{ + int x; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + [Guid(""00000000-0000-0000-C000-000000000046"")] + public partial struct MyUnion1 + {{ + [FieldOffset(0)] + public int x; + }} + + [StructLayout(LayoutKind.Explicit)] + [Guid(""00000000-0000-0000-C000-000000000047"")] + public partial struct MyUnion2 + {{ + [FieldOffset(0)] + public int x; + }} + + public static partial class Methods + {{ + public static readonly Guid IID_MyUnion1 = new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + + public static readonly Guid IID_MyUnion2 = new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47); + }} +}} +"; + + var excludedNames = new string[] { "DECLSPEC_UUID" }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task NestedAnonymousTestImpl(string nativeType, string expectedManagedType, int line, int column) + { + var inputContents = $@"typedef struct {{ + {nativeType} value; +}} MyStruct; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union + {{ + {nativeType} a; + + MyStruct s; + + {nativeType} buffer[4]; + }}; +}}; +"; + + var expectedOutputContents = $@"using System; +using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + public partial struct MyStruct + {{ + public {expectedManagedType} value; + }} + + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + + [FieldOffset(0)] + [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:{line}:{column})"")] + public _Anonymous_e__Union Anonymous; + + public ref {expectedManagedType} a + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + }} + }} + + public ref MyStruct s + {{ + get + {{ + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.s, 1)); + }} + }} + + public Span<{expectedManagedType}> buffer + {{ + get + {{ + return MemoryMarshal.CreateSpan(ref Anonymous.buffer[0], 4); + }} + }} + + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct _Anonymous_e__Union + {{ + [FieldOffset(0)] + public {expectedManagedType} a; + + [FieldOffset(0)] + public MyStruct s; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}[4]"")] + public fixed {expectedManagedType} buffer[4]; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedAnonymousWithBitfieldTestImpl() + { + var inputContents = @"union MyUnion +{ + int x; + int y; + + union + { + int z; + + union + { + int w; + int o0_b0_16 : 16; + int o0_b16_4 : 4; + }; + }; +}; +"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + { + [FieldOffset(0)] + public int x; + + [FieldOffset(0)] + public int y; + + [FieldOffset(0)] + [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:6:5)"")] + public _Anonymous_e__Union Anonymous; + + public ref int z + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + } + } + + public ref int w + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + } + } + + public int o0_b0_16 + { + get + { + return Anonymous.Anonymous.o0_b0_16; + } + + set + { + Anonymous.Anonymous.o0_b0_16 = value; + } + } + + public int o0_b16_4 + { + get + { + return Anonymous.Anonymous.o0_b16_4; + } + + set + { + Anonymous.Anonymous.o0_b16_4 = value; + } + } + + [StructLayout(LayoutKind.Explicit)] + public partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + public int z; + + [FieldOffset(0)] + [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:10:9)"")] + public _Anonymous_e__Union Anonymous; + + [StructLayout(LayoutKind.Explicit)] + public partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + public int w; + + [FieldOffset(0)] + public int _bitfield; + + [NativeTypeName(""int : 16"")] + public int o0_b0_16 + { + get + { + return _bitfield & 0xFFFF; + } + + set + { + _bitfield = (_bitfield & ~0xFFFF) | (value & 0xFFFF); + } + } + + [NativeTypeName(""int : 4"")] + public int o0_b16_4 + { + get + { + return (_bitfield >> 16) & 0xF; + } + + set + { + _bitfield = (_bitfield & ~(0xF << 16)) | ((value & 0xF) << 16); + } + } + } + } + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + + protected override Task NestedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union MyNestedUnion + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyNestedUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + + [FieldOffset(0)] + public {expectedManagedType} a; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union MyNestedUnion + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + + [StructLayout(LayoutKind.Explicit)] + public partial struct MyNestedUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} a; + }} + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"union MyUnion +{ + int Equals; + int Dispose; + int GetHashCode; + int GetType; + int MemberwiseClone; + int ReferenceEquals; + int ToString; +};"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public new int Equals; + + [FieldOffset(0)] + public int Dispose; + + [FieldOffset(0)] + public new int GetHashCode; + + [FieldOffset(0)] + public new int GetType; + + [FieldOffset(0)] + public new int MemberwiseClone; + + [FieldOffset(0)] + public new int ReferenceEquals; + + [FieldOffset(0)] + public new int ToString; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoDefinitionTestImpl() + { + var inputContents = "typedef union MyUnion MyUnion;"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + }} +}} +"; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfTestImpl() + { + var inputContents = @"union example_s { + example_s* next; + void* data; +};"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct example_s + {{ + [FieldOffset(0)] + public example_s* next; + + [FieldOffset(0)] + public void* data; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfViaTypedefTestImpl() + { + var inputContents = @"typedef union example_s example_t; + +union example_s { + example_t* next; + void* data; +};"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct example_s + {{ + [FieldOffset(0)] + [NativeTypeName(""example_t *"")] + public example_s* next; + + [FieldOffset(0)] + public void* data; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = "typedef union _MyUnion MyUnion;"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + }} +}} +"; + + var remappedNames = new Dictionary { ["_MyUnion"] = "MyUnion" }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task RemapNestedAnonymousTestImpl() + { + var inputContents = @"union MyUnion +{ + double r; + double g; + double b; + + union + { + double a; + }; +};"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + { + [FieldOffset(0)] + public double r; + + [FieldOffset(0)] + public double g; + + [FieldOffset(0)] + public double b; + + [FieldOffset(0)] + [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:7:5)"")] + public _Anonymous_e__Union Anonymous; + + public ref double a + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + } + } + + [StructLayout(LayoutKind.Explicit)] + public partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + public double a; + } + } +} +"; + + var remappedNames = new Dictionary { + ["__AnonymousField_ClangUnsavedFile_L7_C5"] = "Anonymous", + ["__AnonymousRecord_ClangUnsavedFile_L7_C5"] = "_Anonymous_e__Union" + }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task SkipNonDefinitionTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union MyUnion MyUnion; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + public {expectedManagedType} r; + + [FieldOffset(0)] + public {expectedManagedType} g; + + [FieldOffset(0)] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionPointerTestImpl() + { + var inputContents = @"typedef union MyUnion* MyUnionPtr; +typedef union MyUnion& MyUnionRef; +"; + + var expectedOutputContents = @"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + { + } +} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union MyUnion MyUnion; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} r; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} g; + + [FieldOffset(0)] + [NativeTypeName(""{nativeType}"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyTypedefAlias; + +union MyUnion +{{ + MyTypedefAlias r; + MyTypedefAlias g; + MyTypedefAlias b; +}}; +"; + + var expectedOutputContents = $@"using System.Runtime.InteropServices; + +namespace ClangSharp.Test +{{ + [StructLayout(LayoutKind.Explicit)] + public partial struct MyUnion + {{ + [FieldOffset(0)] + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} r; + + [FieldOffset(0)] + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} g; + + [FieldOffset(0)] + [NativeTypeName(""MyTypedefAlias"")] + public {expectedManagedType} b; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/VarDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/VarDeclarationTest.cs new file mode 100644 index 00000000..cacb1645 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/VarDeclarationTest.cs @@ -0,0 +1,398 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class CSharpDefaultWindows_VarDeclarationTest : VarDeclarationTest +{ + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"{nativeType} MyVariable = 0;"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + public static {expectedManagedType} MyVariable = 0; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"{nativeType} MyVariable = 0;"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""{nativeType}"")] + public static {expectedManagedType} MyVariable = 0; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task GuidMacroTestImpl() + { + var inputContents = $@"struct GUID {{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +}}; + +const GUID IID_IUnknown = {{ 0x00000000, 0x0000, 0x0000, {{ 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }} }}; +"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const GUID"")] + public static readonly Guid IID_IUnknown = new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + }} +}} +"; + var excludedNames = new string[] { "GUID" }; + var remappedNames = new Dictionary { ["GUID"] = "Guid" }; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames, remappedNames: remappedNames); + } + + protected override Task MacroTestImpl(string nativeValue, string expectedManagedType, string expectedManagedValue) + { + var inputContents = $@"#define MyMacro1 {nativeValue} +#define MyMacro2 MyMacro1"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 {nativeValue}"")] + public const {expectedManagedType} MyMacro1 = {expectedManagedValue}; + + [NativeTypeName(""#define MyMacro2 MyMacro1"")] + public const {expectedManagedType} MyMacro2 = {expectedManagedValue}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MultilineMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 0 + \ +1"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 0 + \\\n1"")] + public const int MyMacro1 = 0 + 1; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoInitializerTestImpl(string nativeType) + { + var inputContents = $@"{nativeType} MyVariable;"; + var expectedOutputContents = ""; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task Utf8StringLiteralMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 ""Test"""; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 \""Test\"""")] + public static ReadOnlySpan MyMacro1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task Utf16StringLiteralMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 u""Test"""; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 u\""Test\"""")] + public const string MyMacro1 = ""Test""; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WideStringLiteralConstTestImpl() + { + var inputContents = $@"const wchar_t MyConst1[] = L""Test""; +const wchar_t* MyConst2 = L""Test""; +const wchar_t* const MyConst3 = L""Test"";"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const wchar_t[5]"")] + public const string MyConst1 = ""Test""; + + [NativeTypeName(""const wchar_t *"")] + public static string MyConst2 = ""Test""; + + [NativeTypeName(""const wchar_t *const"")] + public const string MyConst3 = ""Test""; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StringLiteralConstTestImpl() + { + var inputContents = $@"const char MyConst1[] = ""Test""; +const char* MyConst2 = ""Test""; +const char* const MyConst3 = ""Test"";"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const char[5]"")] + public static ReadOnlySpan MyConst1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + + [NativeTypeName(""const char *"")] + public static byte[] MyConst2 = new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + + [NativeTypeName(""const char *const"")] + public static ReadOnlySpan MyConst3 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WideStringLiteralStaticConstTestImpl() + { + var inputContents = $@"static const wchar_t MyConst1[] = L""Test""; +static const wchar_t* MyConst2 = L""Test""; +static const wchar_t* const MyConst3 = L""Test"";"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const wchar_t[5]"")] + public const string MyConst1 = ""Test""; + + [NativeTypeName(""const wchar_t *"")] + public static string MyConst2 = ""Test""; + + [NativeTypeName(""const wchar_t *const"")] + public const string MyConst3 = ""Test""; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StringLiteralStaticConstTestImpl() + { + var inputContents = $@"static const char MyConst1[] = ""Test""; +static const char* MyConst2 = ""Test""; +static const char* const MyConst3 = ""Test"";"; + + var expectedOutputContents = $@"using System; + +namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const char[5]"")] + public static ReadOnlySpan MyConst1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + + [NativeTypeName(""const char *"")] + public static byte[] MyConst2 = new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + + [NativeTypeName(""const char *const"")] + public static ReadOnlySpan MyConst3 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedConversionMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 (long)0x80000000L +#define MyMacro2 (int)0x80000000"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 (long)0x80000000L"")] + public const int MyMacro1 = unchecked((int)(0x80000000)); + + [NativeTypeName(""#define MyMacro2 (int)0x80000000"")] + public const int MyMacro2 = unchecked((int)(0x80000000)); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedFunctionLikeCastMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 unsigned(-1)"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro1 unsigned(-1)"")] + public const uint MyMacro1 = unchecked((uint)(-1)); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedConversionMacroTest2Impl() + { + var inputContents = $@"#define MyMacro1(x, y, z) ((int)(((unsigned long)(x)<<31) | ((unsigned long)(y)<<16) | ((unsigned long)(z)))) +#define MyMacro2(n) MyMacro1(1, 2, n) +#define MyMacro3 MyMacro2(3)"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define MyMacro3 MyMacro2(3)"")] + public const int MyMacro3 = unchecked((int)(((uint)(1) << 31) | ((uint)(2) << 16) | ((uint)(3)))); + }} +}} +"; + + var excludedNames = new string[] { "MyMacro1", "MyMacro2" }; + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task UncheckedPointerMacroTestImpl() + { + var inputContents = $@"#define Macro1 ((int*) -1)"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static unsafe partial class Methods + {{ + [NativeTypeName(""#define Macro1 ((int*) -1)"")] + public static readonly int* Macro1 = unchecked((int*)(-1)); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedReinterpretCastMacroTestImpl() + { + var inputContents = $@"#define Macro1 reinterpret_cast(-1)"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static unsafe partial class Methods + {{ + [NativeTypeName(""#define Macro1 reinterpret_cast(-1)"")] + public static readonly int* Macro1 = unchecked((int*)(-1)); + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MultidimensionlArrayTestImpl() + { + var inputContents = $@"const int MyArray[2][2] = {{ {{ 0, 1 }}, {{ 2, 3 }} }};"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""const int[2][2]"")] + public static readonly int[][] MyArray = new int[2][] + {{ + new int[2] + {{ + 0, + 1, + }}, + new int[2] + {{ + 2, + 3, + }}, + }}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConditionalDefineConstTestImpl() + { + var inputContents = @"typedef int TESTRESULT; +#define TESTRESULT_FROM_WIN32(x) ((TESTRESULT)(x) <= 0 ? ((TESTRESULT)(x)) : ((TESTRESULT) (((x) & 0x0000FFFF) | (7 << 16) | 0x80000000))) +#define ADDRESS_IN_USE TESTRESULT_FROM_WIN32(10048)"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public static partial class Methods + {{ + [NativeTypeName(""#define ADDRESS_IN_USE TESTRESULT_FROM_WIN32(10048)"")] + public const int ADDRESS_IN_USE = unchecked((int)(10048) <= 0 ? ((int)(10048)) : ((int)(((10048) & 0x0000FFFF) | (7 << 16) | 0x80000000))); + }} +}} +"; + var diagnostics = new Diagnostic[] { new Diagnostic(DiagnosticLevel.Warning, "Function like macro definition records are not supported: 'TESTRESULT_FROM_WIN32'. Generated bindings may be incomplete.", "Line 2, Column 9 in ClangUnsavedFile.h") }; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/EnumDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/EnumDeclarationTest.cs index ada29394..0b218d49 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/EnumDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/EnumDeclarationTest.cs @@ -224,7 +224,7 @@ public enum MyEnum2 "; var withAttributes = new Dictionary> - { + { ["MyEnum1"] = new List() { "Flags" } }; return ValidateGeneratedCSharpLatestUnixBindingsAsync(inputContents, expectedOutputContents, withAttributes: withAttributes); diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/FunctionDeclarationBodyImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/FunctionDeclarationBodyImportTest.cs index 14959925..3cc8f50e 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/FunctionDeclarationBodyImportTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/FunctionDeclarationBodyImportTest.cs @@ -1426,7 +1426,8 @@ void MyFunction() } "; - var expectedOutputContents = @"using System.Runtime.InteropServices; + var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace ClangSharp.Test { @@ -1437,11 +1438,12 @@ public partial struct MyUnion [NativeTypeName(""MyUnion::(anonymous struct at ClangUnsavedFile.h:3:5)"")] public _Anonymous_e__Struct Anonymous; + [UnscopedRef] public ref int a { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; } } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/StructDeclarationTest.cs index fde9bf5f..d5e3b28b 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/StructDeclarationTest.cs @@ -373,6 +373,7 @@ struct MyOtherStruct "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -393,6 +394,7 @@ public partial struct _c_e__FixedBuffer public MyStruct e1; public MyStruct e2; + [UnscopedRef] public ref MyStruct this[int index] {{ get @@ -401,6 +403,7 @@ public ref MyStruct this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -424,6 +427,7 @@ struct MyOtherStruct "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -476,6 +480,7 @@ public partial struct _c_e__FixedBuffer public MyStruct e0_0_2_3; public MyStruct e1_0_2_3; + [UnscopedRef] public ref MyStruct this[int index] {{ get @@ -484,6 +489,7 @@ public ref MyStruct this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); }} }} @@ -509,6 +515,7 @@ struct MyOtherStruct "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -529,6 +536,7 @@ public partial struct _c_e__FixedBuffer public MyStruct e1; public MyStruct e2; + [UnscopedRef] public ref MyStruct this[int index] {{ get @@ -537,6 +545,7 @@ public ref MyStruct this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -560,6 +569,7 @@ struct MyOtherStruct "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -581,6 +591,7 @@ public partial struct _c_e__FixedBuffer public MyStruct e1; public MyStruct e2; + [UnscopedRef] public ref MyStruct this[int index] {{ get @@ -589,6 +600,7 @@ public ref MyStruct this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -905,6 +917,7 @@ struct MyStruct "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -925,54 +938,61 @@ public unsafe partial struct MyStruct [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:{line}:{column})"")] public _Anonymous_e__Struct Anonymous; + [UnscopedRef] public ref {expectedManagedType} z {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; }} }} + [UnscopedRef] public ref _Anonymous_e__Struct._w_e__Struct w {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.w, 1)); + return ref Anonymous.w; }} }} + [UnscopedRef] public ref {expectedManagedType} value1 {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous1.value1, 1)); + return ref Anonymous.Anonymous1.value1; }} }} + [UnscopedRef] public ref {expectedManagedType} value {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous1.Anonymous.value, 1)); + return ref Anonymous.Anonymous1.Anonymous.value; }} }} + [UnscopedRef] public ref {expectedManagedType} value2 {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous2.value2, 1)); + return ref Anonymous.Anonymous2.value2; }} }} + [UnscopedRef] public ref MyUnion u {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.u, 1)); + return ref Anonymous.u; }} }} + [UnscopedRef] public Span<{expectedManagedType}> buffer1 {{ get @@ -981,6 +1001,7 @@ public Span<{expectedManagedType}> buffer1 }} }} + [UnscopedRef] public Span buffer2 {{ get @@ -1042,6 +1063,7 @@ public partial struct _buffer2_e__FixedBuffer public MyUnion e2; public MyUnion e3; + [UnscopedRef] public ref MyUnion this[int index] {{ get @@ -1050,6 +1072,7 @@ public ref MyUnion this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 4); }} }} @@ -1081,7 +1104,7 @@ protected override Task NestedAnonymousWithBitfieldTestImpl() }; "; - var expectedOutputContents = @"using System.Runtime.InteropServices; + var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis; namespace ClangSharp.Test { @@ -1094,19 +1117,21 @@ public partial struct MyStruct [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:6:5)"")] public _Anonymous_e__Struct Anonymous; + [UnscopedRef] public ref int z { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; } } + [UnscopedRef] public ref int w { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + return ref Anonymous.Anonymous.w; } } @@ -1467,7 +1492,7 @@ protected override Task RemapNestedAnonymousTestImpl() }; };"; - var expectedOutputContents = @"using System.Runtime.InteropServices; + var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis; namespace ClangSharp.Test { @@ -1482,11 +1507,12 @@ public partial struct MyStruct [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:7:5)"")] public _Anonymous_e__Struct Anonymous; + [UnscopedRef] public ref double a { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; } } @@ -1711,6 +1737,7 @@ protected override Task WithPackingTestImpl() "; const string ExpectedOutputContents = @"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -1725,6 +1752,7 @@ public partial struct _FixedBuffer_e__FixedBuffer { public nuint e0; + [UnscopedRef] public ref nuint this[int index] { get @@ -1733,6 +1761,7 @@ public ref nuint this[int index] } } + [UnscopedRef] public Span AsSpan(int length) => MemoryMarshal.CreateSpan(ref e0, length); } } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/UnionDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/UnionDeclarationTest.cs index 1b8019ed..6e5f6497 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/UnionDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/UnionDeclarationTest.cs @@ -352,6 +352,7 @@ union MyOtherUnion "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -376,6 +377,7 @@ public partial struct _c_e__FixedBuffer public MyUnion e1; public MyUnion e2; + [UnscopedRef] public ref MyUnion this[int index] {{ get @@ -384,6 +386,7 @@ public ref MyUnion this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -407,6 +410,7 @@ union MyOtherUnion "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -463,6 +467,7 @@ public partial struct _c_e__FixedBuffer public MyUnion e0_0_2_3; public MyUnion e1_0_2_3; + [UnscopedRef] public ref MyUnion this[int index] {{ get @@ -471,6 +476,7 @@ public ref MyUnion this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); }} }} @@ -496,6 +502,7 @@ union MyOtherUnion "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -520,6 +527,7 @@ public partial struct _c_e__FixedBuffer public MyUnion e1; public MyUnion e2; + [UnscopedRef] public ref MyUnion this[int index] {{ get @@ -528,6 +536,7 @@ public ref MyUnion this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -551,6 +560,7 @@ union MyOtherUnion "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -576,6 +586,7 @@ public partial struct _c_e__FixedBuffer public MyUnion e1; public MyUnion e2; + [UnscopedRef] public ref MyUnion this[int index] {{ get @@ -584,6 +595,7 @@ public ref MyUnion this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -791,6 +803,7 @@ union MyUnion "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -816,22 +829,25 @@ public unsafe partial struct MyUnion [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:{line}:{column})"")] public _Anonymous_e__Union Anonymous; + [UnscopedRef] public ref {expectedManagedType} a {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; }} }} + [UnscopedRef] public ref MyStruct s {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.s, 1)); + return ref Anonymous.s; }} }} + [UnscopedRef] public Span<{expectedManagedType}> buffer {{ get @@ -881,7 +897,8 @@ protected override Task NestedAnonymousWithBitfieldTestImpl() }; "; - var expectedOutputContents = @"using System.Runtime.InteropServices; + var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace ClangSharp.Test { @@ -898,19 +915,21 @@ public partial struct MyUnion [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:6:5)"")] public _Anonymous_e__Union Anonymous; + [UnscopedRef] public ref int z { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; } } + [UnscopedRef] public ref int w { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + return ref Anonymous.Anonymous.w; } } @@ -1267,7 +1286,8 @@ protected override Task RemapNestedAnonymousTestImpl() }; };"; - var expectedOutputContents = @"using System.Runtime.InteropServices; + var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace ClangSharp.Test { @@ -1287,11 +1307,12 @@ public partial struct MyUnion [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:7:5)"")] public _Anonymous_e__Union Anonymous; + [UnscopedRef] public ref double a { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; } } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/VarDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/VarDeclarationTest.cs index 8e552790..b7d911dd 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/VarDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/VarDeclarationTest.cs @@ -126,7 +126,7 @@ namespace ClangSharp.Test public static partial class Methods {{ [NativeTypeName(""#define MyMacro1 \""Test\"""")] - public static ReadOnlySpan MyMacro1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static ReadOnlySpan MyMacro1 => ""Test""u8; }} }} "; @@ -189,13 +189,13 @@ namespace ClangSharp.Test public static partial class Methods {{ [NativeTypeName(""const char[5]"")] - public static ReadOnlySpan MyConst1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static ReadOnlySpan MyConst1 => ""Test""u8; [NativeTypeName(""const char *"")] - public static byte[] MyConst2 = new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static byte[] MyConst2 = ""Test""u8.ToArray(); [NativeTypeName(""const char *const"")] - public static ReadOnlySpan MyConst3 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static ReadOnlySpan MyConst3 => ""Test""u8; }} }} "; @@ -241,13 +241,13 @@ namespace ClangSharp.Test public static partial class Methods {{ [NativeTypeName(""const char[5]"")] - public static ReadOnlySpan MyConst1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static ReadOnlySpan MyConst1 => ""Test""u8; [NativeTypeName(""const char *"")] - public static byte[] MyConst2 = new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static byte[] MyConst2 = ""Test""u8.ToArray(); [NativeTypeName(""const char *const"")] - public static ReadOnlySpan MyConst3 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static ReadOnlySpan MyConst3 => ""Test""u8; }} }} "; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/EnumDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/EnumDeclarationTest.cs index abbb6b17..56ec148d 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/EnumDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/EnumDeclarationTest.cs @@ -550,6 +550,7 @@ public enum MyEnum2 : uint }; return ValidateGeneratedCSharpLatestWindowsBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); } + protected override Task WithAnonymousEnumTestImpl() { var inputContents = @"enum diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/FunctionDeclarationBodyImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/FunctionDeclarationBodyImportTest.cs index e2cb4998..98fefd33 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/FunctionDeclarationBodyImportTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/FunctionDeclarationBodyImportTest.cs @@ -1426,7 +1426,8 @@ void MyFunction() } "; - var expectedOutputContents = @"using System.Runtime.InteropServices; + var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace ClangSharp.Test { @@ -1437,11 +1438,12 @@ public partial struct MyUnion [NativeTypeName(""MyUnion::(anonymous struct at ClangUnsavedFile.h:3:5)"")] public _Anonymous_e__Struct Anonymous; + [UnscopedRef] public ref int a { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; } } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/StructDeclarationTest.cs index 1c7b1948..523e4c26 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/StructDeclarationTest.cs @@ -377,6 +377,7 @@ struct MyOtherStruct "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -397,6 +398,7 @@ public partial struct _c_e__FixedBuffer public MyStruct e1; public MyStruct e2; + [UnscopedRef] public ref MyStruct this[int index] {{ get @@ -405,6 +407,7 @@ public ref MyStruct this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -428,6 +431,7 @@ struct MyOtherStruct "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -480,6 +484,7 @@ public partial struct _c_e__FixedBuffer public MyStruct e0_0_2_3; public MyStruct e1_0_2_3; + [UnscopedRef] public ref MyStruct this[int index] {{ get @@ -488,6 +493,7 @@ public ref MyStruct this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); }} }} @@ -513,6 +519,7 @@ struct MyOtherStruct "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -533,6 +540,7 @@ public partial struct _c_e__FixedBuffer public MyStruct e1; public MyStruct e2; + [UnscopedRef] public ref MyStruct this[int index] {{ get @@ -541,6 +549,7 @@ public ref MyStruct this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -564,6 +573,7 @@ struct MyOtherStruct "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -585,6 +595,7 @@ public partial struct _c_e__FixedBuffer public MyStruct e1; public MyStruct e2; + [UnscopedRef] public ref MyStruct this[int index] {{ get @@ -593,6 +604,7 @@ public ref MyStruct this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -909,6 +921,7 @@ struct MyStruct "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -929,54 +942,61 @@ public unsafe partial struct MyStruct [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:{line}:{column})"")] public _Anonymous_e__Struct Anonymous; + [UnscopedRef] public ref {expectedManagedType} z {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; }} }} + [UnscopedRef] public ref _Anonymous_e__Struct._w_e__Struct w {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.w, 1)); + return ref Anonymous.w; }} }} + [UnscopedRef] public ref {expectedManagedType} value1 {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous1.value1, 1)); + return ref Anonymous.Anonymous1.value1; }} }} + [UnscopedRef] public ref {expectedManagedType} value {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous1.Anonymous.value, 1)); + return ref Anonymous.Anonymous1.Anonymous.value; }} }} + [UnscopedRef] public ref {expectedManagedType} value2 {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous2.value2, 1)); + return ref Anonymous.Anonymous2.value2; }} }} + [UnscopedRef] public ref MyUnion u {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.u, 1)); + return ref Anonymous.u; }} }} + [UnscopedRef] public Span<{expectedManagedType}> buffer1 {{ get @@ -985,6 +1005,7 @@ public Span<{expectedManagedType}> buffer1 }} }} + [UnscopedRef] public Span buffer2 {{ get @@ -1046,6 +1067,7 @@ public partial struct _buffer2_e__FixedBuffer public MyUnion e2; public MyUnion e3; + [UnscopedRef] public ref MyUnion this[int index] {{ get @@ -1054,6 +1076,7 @@ public ref MyUnion this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 4); }} }} @@ -1085,7 +1108,7 @@ protected override Task NestedAnonymousWithBitfieldTestImpl() }; "; - var expectedOutputContents = @"using System.Runtime.InteropServices; + var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis; namespace ClangSharp.Test { @@ -1098,19 +1121,21 @@ public partial struct MyStruct [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:6:5)"")] public _Anonymous_e__Struct Anonymous; + [UnscopedRef] public ref int z { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; } } + [UnscopedRef] public ref int w { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + return ref Anonymous.Anonymous.w; } } @@ -1471,7 +1496,7 @@ protected override Task RemapNestedAnonymousTestImpl() }; };"; - var expectedOutputContents = @"using System.Runtime.InteropServices; + var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis; namespace ClangSharp.Test { @@ -1486,11 +1511,12 @@ public partial struct MyStruct [NativeTypeName(""MyStruct::(anonymous struct at ClangUnsavedFile.h:7:5)"")] public _Anonymous_e__Struct Anonymous; + [UnscopedRef] public ref double a { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; } } @@ -1715,6 +1741,7 @@ protected override Task WithPackingTestImpl() "; const string ExpectedOutputContents = @"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -1729,6 +1756,7 @@ public partial struct _FixedBuffer_e__FixedBuffer { public nuint e0; + [UnscopedRef] public ref nuint this[int index] { get @@ -1737,6 +1765,7 @@ public ref nuint this[int index] } } + [UnscopedRef] public Span AsSpan(int length) => MemoryMarshal.CreateSpan(ref e0, length); } } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/UnionDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/UnionDeclarationTest.cs index 054c131f..25013c30 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/UnionDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/UnionDeclarationTest.cs @@ -358,6 +358,7 @@ union MyOtherUnion "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -382,6 +383,7 @@ public partial struct _c_e__FixedBuffer public MyUnion e1; public MyUnion e2; + [UnscopedRef] public ref MyUnion this[int index] {{ get @@ -390,6 +392,7 @@ public ref MyUnion this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -413,6 +416,7 @@ union MyOtherUnion "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -469,6 +473,7 @@ public partial struct _c_e__FixedBuffer public MyUnion e0_0_2_3; public MyUnion e1_0_2_3; + [UnscopedRef] public ref MyUnion this[int index] {{ get @@ -477,6 +482,7 @@ public ref MyUnion this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); }} }} @@ -502,6 +508,7 @@ union MyOtherUnion "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -526,6 +533,7 @@ public partial struct _c_e__FixedBuffer public MyUnion e1; public MyUnion e2; + [UnscopedRef] public ref MyUnion this[int index] {{ get @@ -534,6 +542,7 @@ public ref MyUnion this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -557,6 +566,7 @@ union MyOtherUnion "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -582,6 +592,7 @@ public partial struct _c_e__FixedBuffer public MyUnion e1; public MyUnion e2; + [UnscopedRef] public ref MyUnion this[int index] {{ get @@ -590,6 +601,7 @@ public ref MyUnion this[int index] }} }} + [UnscopedRef] public Span AsSpan() => MemoryMarshal.CreateSpan(ref e0, 3); }} }} @@ -797,6 +809,7 @@ union MyUnion "; var expectedOutputContents = $@"using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace ClangSharp.Test @@ -822,22 +835,25 @@ public unsafe partial struct MyUnion [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:{line}:{column})"")] public _Anonymous_e__Union Anonymous; + [UnscopedRef] public ref {expectedManagedType} a {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; }} }} + [UnscopedRef] public ref MyStruct s {{ get {{ - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.s, 1)); + return ref Anonymous.s; }} }} + [UnscopedRef] public Span<{expectedManagedType}> buffer {{ get @@ -887,7 +903,8 @@ protected override Task NestedAnonymousWithBitfieldTestImpl() }; "; - var expectedOutputContents = @"using System.Runtime.InteropServices; + var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace ClangSharp.Test { @@ -904,19 +921,21 @@ public partial struct MyUnion [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:6:5)"")] public _Anonymous_e__Union Anonymous; + [UnscopedRef] public ref int z { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; } } + [UnscopedRef] public ref int w { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + return ref Anonymous.Anonymous.w; } } @@ -1273,7 +1292,8 @@ protected override Task RemapNestedAnonymousTestImpl() }; };"; - var expectedOutputContents = @"using System.Runtime.InteropServices; + var expectedOutputContents = @"using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; namespace ClangSharp.Test { @@ -1293,11 +1313,12 @@ public partial struct MyUnion [NativeTypeName(""MyUnion::(anonymous union at ClangUnsavedFile.h:7:5)"")] public _Anonymous_e__Union Anonymous; + [UnscopedRef] public ref double a { get { - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; } } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/VarDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/VarDeclarationTest.cs index 12a5368d..e503534a 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/VarDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/VarDeclarationTest.cs @@ -126,7 +126,7 @@ namespace ClangSharp.Test public static partial class Methods {{ [NativeTypeName(""#define MyMacro1 \""Test\"""")] - public static ReadOnlySpan MyMacro1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static ReadOnlySpan MyMacro1 => ""Test""u8; }} }} "; @@ -189,13 +189,13 @@ namespace ClangSharp.Test public static partial class Methods {{ [NativeTypeName(""const char[5]"")] - public static ReadOnlySpan MyConst1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static ReadOnlySpan MyConst1 => ""Test""u8; [NativeTypeName(""const char *"")] - public static byte[] MyConst2 = new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static byte[] MyConst2 = ""Test""u8.ToArray(); [NativeTypeName(""const char *const"")] - public static ReadOnlySpan MyConst3 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static ReadOnlySpan MyConst3 => ""Test""u8; }} }} "; @@ -241,13 +241,13 @@ namespace ClangSharp.Test public static partial class Methods {{ [NativeTypeName(""const char[5]"")] - public static ReadOnlySpan MyConst1 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static ReadOnlySpan MyConst1 => ""Test""u8; [NativeTypeName(""const char *"")] - public static byte[] MyConst2 = new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static byte[] MyConst2 = ""Test""u8.ToArray(); [NativeTypeName(""const char *const"")] - public static ReadOnlySpan MyConst3 => new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }}; + public static ReadOnlySpan MyConst3 => ""Test""u8; }} }} "; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs index 9ccabb9f..07df0e0b 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/PInvokeGeneratorTest.cs @@ -45,9 +45,15 @@ protected static Task ValidateGeneratedCSharpPreviewUnixBindingsAsync(string inp => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GeneratePreviewCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, withPackings, 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, IReadOnlyDictionary? withPackings = 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, withPackings, expectedDiagnostics, libraryPath, commandlineArgs); + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateLatestCode | PInvokeGeneratorConfigurationOptions.None | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, withPackings, 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, IReadOnlyDictionary? withPackings = null, IEnumerable? expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[]? commandlineArgs = null) + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.CSharp, PInvokeGeneratorConfigurationOptions.GenerateLatestCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, withPackings, expectedDiagnostics, libraryPath, commandlineArgs); + + protected static Task ValidateGeneratedCSharpDefaultWindowsBindingsAsync(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, IReadOnlyDictionary? withPackings = 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, withPackings, expectedDiagnostics, libraryPath, commandlineArgs); + + protected static Task ValidateGeneratedCSharpDefaultUnixBindingsAsync(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, IReadOnlyDictionary? withPackings = 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, withPackings, 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, IReadOnlyDictionary? withPackings = null, IEnumerable? expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[]? commandlineArgs = null) @@ -63,9 +69,15 @@ protected static Task ValidateGeneratedXmlPreviewUnixBindingsAsync(string inputC => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GeneratePreviewCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, withPackings, 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? withClasses = null, IReadOnlyDictionary? withLibraryPaths = null, IReadOnlyDictionary? withNamespaces = null, string[]? withSetLastErrors = null, IReadOnlyDictionary? withTransparentStructs = null, IReadOnlyDictionary? withTypes = null, IReadOnlyDictionary>? withUsings = null, IReadOnlyDictionary? withPackings = 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, withPackings, expectedDiagnostics, libraryPath, commandlineArgs, filePath); + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateLatestCode | PInvokeGeneratorConfigurationOptions.None | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, withPackings, 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? withClasses = null, IReadOnlyDictionary? withLibraryPaths = null, IReadOnlyDictionary? withNamespaces = null, string[]? withSetLastErrors = null, IReadOnlyDictionary? withTransparentStructs = null, IReadOnlyDictionary? withTypes = null, IReadOnlyDictionary>? withUsings = null, IReadOnlyDictionary? withPackings = null, IEnumerable? expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[]? commandlineArgs = null) + => ValidateGeneratedBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorOutputMode.Xml, PInvokeGeneratorConfigurationOptions.GenerateLatestCode | PInvokeGeneratorConfigurationOptions.GenerateUnixTypes | additionalConfigOptions, excludedNames, remappedNames, withAccessSpecifiers, withAttributes, withCallConvs, withClasses, withLibraryPaths, withNamespaces, withSetLastErrors, withTransparentStructs, withTypes, withUsings, withPackings, expectedDiagnostics, libraryPath, commandlineArgs); + + protected static Task ValidateGeneratedXmlDefaultWindowsBindingsAsync(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, IReadOnlyDictionary? withPackings = 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, withPackings, expectedDiagnostics, libraryPath, commandlineArgs, filePath); + + protected static Task ValidateGeneratedXmlDefaultUnixBindingsAsync(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, IReadOnlyDictionary? withPackings = 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, withPackings, 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, IReadOnlyDictionary? withPackings = null, IEnumerable? expectedDiagnostics = null, string libraryPath = DefaultLibraryPath, string[]? commandlineArgs = null) diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/CXXMethodDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/CXXMethodDeclarationTest.cs new file mode 100644 index 00000000..c3819711 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/CXXMethodDeclarationTest.cs @@ -0,0 +1,1063 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultUnix_CXXMethodDeclarationTest : CXXMethodDeclarationXmlTest +{ + protected override Task ConstructorTestImpl() + { + var inputContents = @"struct MyStruct +{ + int _value; + + MyStruct(int value) + { + _value = value; + } +}; +"; + + var expectedOutputContents = @" + + + + + int + + + void + + int + + _value = value; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConstructorWithInitializeTestImpl() + { + var inputContents = @"struct MyStruct +{ + int _x; + int _y; + int _z; + + MyStruct(int x) : _x(x) + { + } + + MyStruct(int x, int y) : _x(x), _y(y) + { + } + + MyStruct(int x, int y, int z) : _x(x), _y(y), _z() + { + } +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + int + + + void + + int + + + x + + + + + void + + int + + + int + + + x + + + y + + + + + void + + int + + + int + + + int + + + x + + + y + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConversionTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + operator int() + { + return value; + } +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + return value; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DestructorTestImpl() + { + var inputContents = @"struct MyStruct +{ + ~MyStruct() + { + } +}; +"; + + var expectedOutputContents = @" + + + + + void + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InstanceTestImpl() + { + var inputContents = @"struct MyStruct +{ + void MyVoidMethod(); + + int MyInt32Method() + { + return 0; + } + + void* MyVoidStarMethod() + { + return nullptr; + } +}; +"; + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "__ZN8MyStruct12MyVoidMethodEv" : "_ZN8MyStruct12MyVoidMethodEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + if (!Environment.Is64BitProcess) + { + entryPoint = "?MyVoidMethod@MyStruct@@QAEXXZ"; + } + else + { + entryPoint = "?MyVoidMethod@MyStruct@@QEAAXXZ"; + } + } + + var expectedOutputContents = $@" + + + + + void + + MyStruct* + + + + int + return 0; + + + void* + return null; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberCallTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction1() + { + return value; + } + + int MyFunction2() + { + return MyFunction1(); + } + + int MyFunction3() + { + return this->MyFunction1(); + } +}; + +int MyFunctionA(MyStruct x) +{ + return x.MyFunction1(); +} + +int MyFunctionB(MyStruct* x) +{ + return x->MyFunction2(); +} +"; + + var expectedOutputContents = @" + + + + + int + + + int + return value; + + + int + return MyFunction1(); + + + int + return this.MyFunction1(); + + + + + int + + MyStruct + + return x.MyFunction1(); + + + int + + MyStruct* + + return x->MyFunction2(); + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction() + { + return value; + } +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + return value; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"struct MyStruct +{ + int Equals() { return 0; } + int Equals(int obj) { return 0; } + int Dispose() { return 0; } + int Dispose(int obj) { return 0; } + int GetHashCode() { return 0; } + int GetHashCode(int obj) { return 0; } + int GetType() { return 0; } + int GetType(int obj) { return 0; } + int MemberwiseClone() { return 0; } + int MemberwiseClone(int obj) { return 0; } + int ReferenceEquals() { return 0; } + int ReferenceEquals(int obj) { return 0; } + int ToString() { return 0; } + int ToString(int obj) { return 0; } +};"; + + var expectedOutputContents = $@" + + + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordVirtualTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var expectedOutputContents = $@" + + + + + void** + + + int + + int + + + int + + + return ((delegate* unmanaged[Thiscall]<MyStruct*, int, int, int>)(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + + + + int + + return ((delegate* unmanaged[Thiscall]<MyStruct*, int>)(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + int + + int + + + return ((delegate* unmanaged[Thiscall]<MyStruct*, int, int>)(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this), obj); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordVirtualWithExplicitVtblTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var nativeCallConv = ""; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Environment.Is64BitProcess) + { + nativeCallConv = " __attribute__((thiscall))"; + } + + var expectedOutputContents = $@" + + + + + Vtbl* + + + int + + int + + + int + + + return lpVtbl->GetType((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + + + + int + + return lpVtbl->GetType1((MyStruct*)Unsafe.AsPointer(ref this)); + + + + int + + int + + + return lpVtbl->GetType2((MyStruct*)Unsafe.AsPointer(ref this), obj); + + + + + delegate* unmanaged[Thiscall]<MyStruct*, int, int, int> + + + delegate* unmanaged[Thiscall]<MyStruct*, int> + + + delegate* unmanaged[Thiscall]<MyStruct*, int, int> + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateExplicitVtbls); + } + + protected override Task NewKeywordVirtualWithExplicitVtblAndMarkerInterfaceTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var nativeCallConv = ""; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Environment.Is64BitProcess) + { + nativeCallConv = " __attribute__((thiscall))"; + } + + var expectedOutputContents = $@" + + + + + Vtbl<MyStruct>* + + + int + + int + + + int + + + return lpVtbl->GetType((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + + + + int + + return lpVtbl->GetType1((MyStruct*)Unsafe.AsPointer(ref this)); + + + + int + + int + + + return lpVtbl->GetType2((MyStruct*)Unsafe.AsPointer(ref this), obj); + + + + + int + + int + + + int + + + + int + + + int + + int + + + + + + delegate* unmanaged[Thiscall]<TSelf*, int, int, int> + + + delegate* unmanaged[Thiscall]<TSelf*, int> + + + delegate* unmanaged[Thiscall]<TSelf*, int, int> + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateExplicitVtbls | PInvokeGeneratorConfigurationOptions.GenerateMarkerInterfaces); + } + + protected override Task OperatorTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + MyStruct(int value) : value(value) + { + } + + MyStruct operator+(MyStruct rhs) + { + return MyStruct(value + rhs.value); + } +}; + +MyStruct operator-(MyStruct lhs, MyStruct rhs) +{ + return MyStruct(lhs.value - rhs.value); +} +"; + + var expectedOutputContents = @" + + + + + int + + + void + + int + + + value + + + + + MyStruct + + MyStruct + + return new MyStruct(value + rhs.value); + + + + + MyStruct + + MyStruct + + + MyStruct + + return new MyStruct(lhs.value - rhs.value); + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task OperatorCallTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + MyStruct(int value) : value(value) + { + } + + MyStruct operator+(MyStruct rhs) + { + return MyStruct(value + rhs.value); + } +}; + +MyStruct MyFunction1(MyStruct lhs, MyStruct rhs) +{ + return lhs + rhs; +} + +MyStruct operator-(MyStruct lhs, MyStruct rhs) +{ + return MyStruct(lhs.value - rhs.value); +} + +MyStruct MyFunction2(MyStruct lhs, MyStruct rhs) +{ + return lhs - rhs; +} +"; + + var expectedOutputContents = @" + + + + + int + + + void + + int + + + value + + + + + MyStruct + + MyStruct + + return new MyStruct(value + rhs.value); + + + + + MyStruct + + MyStruct + + + MyStruct + + return lhs.Add(rhs); + + + MyStruct + + MyStruct + + + MyStruct + + return new MyStruct(lhs.value - rhs.value); + + + MyStruct + + MyStruct + + + MyStruct + + return Subtract(lhs, rhs); + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StaticTestImpl() + { + var inputContents = @"struct MyStruct +{ + static void MyVoidMethod(); + + static int MyInt32Method() + { + return 0; + } + + static void* MyVoidStarMethod() + { + return nullptr; + } +}; +"; + + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "?MyVoidMethod@MyStruct@@SAXXZ" : "_ZN8MyStruct12MyVoidMethodEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + entryPoint = $"_{entryPoint}"; + } + + var expectedOutputContents = $@" + + + + + void + + + int + return 0; + + + void* + return null; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ThisTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction() + { + return this->value; + } +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + return this.value; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnsafeDoesNotImpactDllImportTestImpl() + { + var inputContents = @"struct MyStruct +{ + void* MyVoidStarMethod() + { + return nullptr; + } +}; + +extern ""C"" void MyFunction();"; + + var expectedOutputContents = @" + + + + + void* + return null; + + + + + void + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task VirtualTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual void MyVoidMethod() = 0; + + virtual char MyInt8Method() + { + return 0; + } + + virtual int MyInt32Method(); + + virtual void* MyVoidStarMethod() = 0; +}; +"; + + var expectedOutputContents = $@" + + + + + void** + + + void + + ((delegate* unmanaged[Thiscall]<MyStruct*, void>)(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + sbyte + + return ((delegate* unmanaged[Thiscall]<MyStruct*, sbyte>)(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + int + + return ((delegate* unmanaged[Thiscall]<MyStruct*, int>)(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + void* + + return ((delegate* unmanaged[Thiscall]<MyStruct*, void*>)(lpVtbl[3]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task VirtualWithVtblIndexAttributeTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual void MyVoidMethod() = 0; + + virtual char MyInt8Method() + { + return 0; + } + + virtual int MyInt32Method(); + + virtual void* MyVoidStarMethod() = 0; +}; +"; + + var expectedOutputContents = $@" + + + + + void** + + + void + + ((delegate* unmanaged[Thiscall]<MyStruct*, void>)(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + sbyte + + return ((delegate* unmanaged[Thiscall]<MyStruct*, sbyte>)(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + int + + return ((delegate* unmanaged[Thiscall]<MyStruct*, int>)(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + void* + + return ((delegate* unmanaged[Thiscall]<MyStruct*, void*>)(lpVtbl[3]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateVtblIndexAttribute); + } + + protected override Task ValidateBindingsAsync(string inputContents, string expectedOutputContents) => ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DeprecatedToObsoleteTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DeprecatedToObsoleteTest.cs new file mode 100644 index 00000000..4b4e4117 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DeprecatedToObsoleteTest.cs @@ -0,0 +1,535 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultUnix_DeprecatedToObsoleteTest : DeprecatedToObsoleteTest +{ + protected override Task SimpleStructMembersImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + + [[deprecated]] + {nativeType} g; + + [[deprecated(""This is obsolete."")]] + {nativeType} b; + + {nativeType} a; +}}; +"; + + var expectedOutputContents = $@" + + + + + int + + + Obsolete + int + + + Obsolete(""This is obsolete."") + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StructDeclImpl() + { + var inputContents = $@"struct MyStruct0 +{{ + int r; +}}; + +struct [[deprecated]] MyStruct1 +{{ + int r; +}}; + +struct [[deprecated(""This is obsolete."")]] MyStruct2 +{{ + int r; +}}; + +struct MyStruct3 +{{ + int r; +}}; +"; + + var expectedOutputContents = $@" + + + + + int + + + + Obsolete + + int + + + + Obsolete(""This is obsolete."") + + int + + + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleTypedefStructMembersImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct +{{ + {nativeType} r; + + [[deprecated]] + {nativeType} g; + + [[deprecated(""This is obsolete."")]] + {nativeType} b; + + {nativeType} a; +}} MyStruct; +"; + + var expectedOutputContents = $@" + + + + + int + + + Obsolete + int + + + Obsolete(""This is obsolete."") + int + + + int + + + + +"; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefStructDeclImpl() + { + var inputContents = $@"typedef struct +{{ + int r; +}} MyStruct0; + +[[deprecated]] typedef struct +{{ + int r; +}} MyStruct1; + +[[deprecated(""This is obsolete."")]] typedef struct +{{ + int r; +}} MyStruct2; + +typedef struct +{{ + int r; +}} MyStruct3; +"; + + var expectedOutputContents = $@" + + + + + int + + + + Obsolete + + int + + + + Obsolete(""This is obsolete."") + + int + + + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleEnumMembersImpl() + { + var inputContents = $@"enum MyEnum : int +{{ + MyEnum_Value0, + MyEnum_Value1 [[deprecated]], + MyEnum_Value2 [[deprecated(""This is obsolete."")]], + MyEnum_Value3, +}}; +"; + + var expectedOutputContents = @" + + + + int + + int + + + Obsolete + int + + + Obsolete(""This is obsolete."") + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task EnumDeclImpl() + { + var inputContents = $@"enum MyEnum0 : int +{{ + MyEnum_Value0, +}}; + +enum [[deprecated]] MyEnum1 : int +{{ + MyEnum_Value1, +}}; + +enum [[deprecated(""This is obsolete."")]] MyEnum2 : int +{{ + MyEnum_Value2, +}}; + + +enum MyEnum3 : int +{{ + MyEnum_Value3, +}}; +"; + + var expectedOutputContents = @" + + + + int + + int + + + + Obsolete + int + + int + + + + Obsolete(""This is obsolete."") + int + + int + + + + int + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleVarDeclImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@" +{nativeType} MyVariable0 = 0; + +[[deprecated]] +{nativeType} MyVariable1 = 0; + +[[deprecated(""This is obsolete."")]] +{nativeType} MyVariable2 = 0; + +{nativeType} MyVariable3 = 0;"; + + var expectedOutputContents = $@" + + + + + int + + 0 + + + + Obsolete + int + + 0 + + + + Obsolete(""This is obsolete."") + int + + 0 + + + + int + + 0 + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncDeclImpl() + { + var inputContents = @" +void MyFunction0() +{ +} + +[[deprecated]] +void MyFunction1() +{ +} + +[[deprecated(""This is obsolete."")]] +void MyFunction2() +{ +} + +void MyFunction3() +{ +} +"; + + var expectedOutputContents = @" + + + + + void + + + + Obsolete + void + + + + Obsolete(""This is obsolete."") + void + + + + void + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InstanceFuncImpl() + { + var inputContents = @"struct MyStruct +{ + int MyFunction0() { return 0; } + + [[deprecated]] + int MyFunction1() { return 0; } + + [[deprecated(""This is obsolete."")]] + int MyFunction2() { return 0; } + + int MyFunction3() { return 0; } +};"; + + var expectedOutputContents = $@" + + + + + int + return 0; + + + Obsolete + int + return 0; + + + Obsolete(""This is obsolete."") + int + return 0; + + + int + return 0; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncPtrDeclImpl() + { + var inputContents = @" +typedef void (*Callback0)(); +[[deprecated]] typedef void (*Callback1)(); +[[deprecated(""This is obsolete."")]] typedef void (*Callback2)(); +typedef void (*Callback3)(); + +struct MyStruct0 { + Callback0 _callback; +}; +struct MyStruct1 { + Callback1 _callback; +}; +struct MyStruct2 { + Callback2 _callback; +}; +struct MyStruct3 { + Callback3 _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + + Obsolete + delegate* unmanaged[Cdecl]<void> + + + + + Obsolete(""This is obsolete."") + delegate* unmanaged[Cdecl]<void> + + + + + delegate* unmanaged[Cdecl]<void> + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncDllImportImpl() + { + var inputContents = @" +extern ""C"" void MyFunction0(); +extern ""C"" [[deprecated]] void MyFunction1(); +extern ""C"" [[deprecated(""This is obsolete."")]] void MyFunction2(); +extern ""C"" void MyFunction3();"; + + var expectedOutputContents = @" + + + + + void + + + Obsolete + void + + + Obsolete(""This is obsolete."") + void + + + void + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/EnumDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/EnumDeclarationTest.cs new file mode 100644 index 00000000..4ca2096f --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/EnumDeclarationTest.cs @@ -0,0 +1,730 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultUnix_EnumDeclarationTest : EnumDeclarationTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicValueTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value1 = 1, + MyEnum_Value2, + MyEnum_Value3, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + 1 + + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyEnum" }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task ExplicitTypedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"enum MyEnum : {nativeType} +{{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}}; +"; + + var expectedOutputContents = $@" + + + + {EscapeXml(expectedManagedType)} + + {EscapeXml(expectedManagedType)} + + + {EscapeXml(expectedManagedType)} + + + {EscapeXml(expectedManagedType)} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExplicitTypedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"enum MyEnum : {nativeType} +{{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}}; +"; + + var expectedOutputContents = $@" + + + + {EscapeXml(expectedManagedType)} + + {EscapeXml(expectedManagedType)} + + + {EscapeXml(expectedManagedType)} + + + {EscapeXml(expectedManagedType)} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = @"typedef enum _MyEnum : int +{ + MyEnum_Value1, + MyEnum_Value2, + MyEnum_Value3, +} MyEnum; +"; + + var expectedOutputContents = @" + + + + int + + int + + + int + + + int + + + + +"; + + var remappedNames = new Dictionary { ["_MyEnum"] = "MyEnum" }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task WithAttributeTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = 1, +}; +"; + + var expectedOutputContents = @" + + + + Flags + int + + int + + 1 + + + + + int + + int + + 1 + + + + + +"; + + var withAttributes = new Dictionary> + { + ["MyEnum1"] = new List() { "Flags" } + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withAttributes: withAttributes); + } + + protected override Task WithNamespaceTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + 1 + + + + + int + + int + + MyEnum1_Value1 + + + + + +"; + + var withNamespaces = new Dictionary> + { + ["MyEnum1"] = new List() { "static ClangSharp.Test.MyEnum1" } + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithNamespaceStarTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + 1 + + + + + int + + int + + MyEnum1_Value1 + + + + + +"; + + var withNamespaces = new Dictionary> + { + ["*"] = new List() { "static ClangSharp.Test.MyEnum1" } + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithNamespaceStarPlusTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + 1 + + + + + int + + int + + MyEnum1_Value1 + + + + + +"; + + var withNamespaces = new Dictionary> + { + ["*"] = new List() { "static ClangSharp.Test.MyEnum1" }, + ["MyEnum2"] = new List() { "System" } + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithCastToEnumTypeImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0 = (MyEnum) 10, + MyEnum_Value1 = (MyEnum) MyEnum_Value0, + MyEnum_Value2 = ((MyEnum) 10) + MyEnum_Value1, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + (int)(MyEnum)(10) + + + + int + + (int)(MyEnum)(MyEnum_Value0) + + + + int + + ((int)(MyEnum)(10)) + MyEnum_Value1 + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithMultipleEnumsTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 = 10, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 = MyEnum1_Value0, + MyEnum2_Value1 = MyEnum1_Value0 + (MyEnum1) 10, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + 10 + + + + + int + + int + + MyEnum1_Value0 + + + + int + + MyEnum1_Value0 + (int)(MyEnum1)(10) + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithImplicitConversionTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = 0x80000000, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + + int + + + int + + + + int + + 0x80000000 + + + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithTypeTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = @" + + + + uint + + uint + + + uint + + + uint + + + + +"; + + var withTypes = new Dictionary { + ["MyEnum"] = "uint" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeAndImplicitConversionTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = 0x80000000, +}; +"; + + var expectedOutputContents = @" + + + + uint + + uint + + + uint + + + uint + + 0x80000000 + + + + + +"; + + var withTypes = new Dictionary + { + ["MyEnum"] = "uint" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeStarTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 +}; +"; + + var expectedOutputContents = @" + + + + uint + + uint + + + + uint + + uint + + + + +"; + + var withTypes = new Dictionary + { + ["*"] = "uint" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeStarOverrideTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + + + uint + + uint + + + + +"; + + var withTypes = new Dictionary + { + ["*"] = "uint", + ["MyEnum1"] = "int", + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithAnonymousEnumTestImpl() + { + var inputContents = @"enum +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + MyEnum1_Value1 + + + + + + int + + 1 + + + + + +"; + + var diagnostics = new[] { new Diagnostic(DiagnosticLevel.Info, "Found anonymous enum: __AnonymousEnum_ClangUnsavedFile_L1_C1. Mapping values as constants in: Methods", "Line 1, Column 1 in ClangUnsavedFile.h") }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } + + protected override Task WithReferenceToAnonymousEnumEnumeratorTestImpl() + { + var inputContents = @"enum +{ + MyEnum1_Value1 = 1, +}; + +const int MyEnum2_Value1 = MyEnum1_Value1 + 1; +"; + + var expectedOutputContents = @" + + + + + int + + 1 + + + + int + + (int)(MyEnum1_Value1) + 1 + + + + + +"; + var diagnostics = new[] { new Diagnostic(DiagnosticLevel.Info, "Found anonymous enum: __AnonymousEnum_ClangUnsavedFile_L1_C1. Mapping values as constants in: Methods", "Line 1, Column 1 in ClangUnsavedFile.h") }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionDeclarationBodyImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionDeclarationBodyImportTest.cs new file mode 100644 index 00000000..16eb65fc --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionDeclarationBodyImportTest.cs @@ -0,0 +1,1990 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultUnix_FunctionDeclarationBodyImportTest : FunctionDeclarationBodyImportTest +{ + protected override Task ArraySubscriptTestImpl() + { + var inputContents = @"int MyFunction(int* pData, int index) +{ + return pData[index]; +} +"; + + var expectedOutputContents = @" + + + + + int + + int* + + + int + + return pData[index]; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestImpl() + { + var inputContents = @"void MyFunction() +{ +} +"; + + var expectedOutputContents = @" + + + + + void + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorBasicTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int x, int y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + + int + + return x {EscapeXml(opcode)} y; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorCompareTestImpl(string opcode) + { + var inputContents = $@"bool MyFunction(int x, int y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@" + + + + + bool + + int + + + int + + return x {EscapeXml(opcode)} y; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorBooleanTestImpl(string opcode) + { + var inputContents = $@"bool MyFunction(bool x, bool y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@" + + + + + bool + + bool + + + bool + + return x {EscapeXml(opcode)} y; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BreakTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + while (true) + { + break; + } + + return 0; +} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + while (true) + {{ + break; + }} + + return 0; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallFunctionTestImpl() + { + var inputContents = @"void MyCalledFunction() +{ +} + +void MyFunction() +{ + MyCalledFunction(); +} +"; + + var expectedOutputContents = $@" + + + + + void + + + + void + MyCalledFunction(); + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallFunctionWithArgsTestImpl() + { + var inputContents = @"void MyCalledFunction(int x, int y) +{ +} + +void MyFunction() +{ + MyCalledFunction(0, 1); +} +"; + + var expectedOutputContents = $@" + + + + + void + + int + + + int + + + + + void + MyCalledFunction(0, 1); + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CaseTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + case 0: + { + return 0; + } + + case 1: + case 2: + { + return 3; + } + } + + return -1; +} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + switch (value) + {{ + case 0: + {{ + return 0; + }} + + case 1: + case 2: + {{ + return 3; + }} + }} + + return -1; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CaseNoCompoundTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + case 0: + return 0; + + case 2: + case 3: + return 5; + } + + return -1; +} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + switch (value) + {{ + case 0: + {{ + return 0; + }} + + case 2: + case 3: + {{ + return 5; + }} + }} + + return -1; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CompareMultipleEnumTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; + +static inline int MyFunction(MyEnum x) +{ + return x == MyEnum_Value0 || + x == MyEnum_Value1 || + x == MyEnum_Value2; +} +"; + + var expectedOutputContents = $@" + + + + int + + int + + + int + + + int + + + + + int + + MyEnum + + return (x == MyEnum_Value0 || x == MyEnum_Value1 || x == MyEnum_Value2) ? 1 : 0; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConditionalOperatorTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + return condition ? lhs : rhs; +} +"; + + var expectedOutputContents = $@" + + + + + int + + bool + + + int + + + int + + return condition ? lhs : rhs; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ContinueTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + while (true) + { + continue; + } + + return 0; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + while (true) + { + continue; + } + + return 0; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CStyleFunctionalCastTestImpl() + { + var inputContents = @"int MyFunction(float input) +{ + return (int)input; +} +"; + + var expectedOutputContents = @" + + + + + int + + float + + return (int)(input); + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxFunctionalCastTestImpl() + { + var inputContents = @"int MyFunction(float input) +{ + return int(input); +} +"; + + var expectedOutputContents = @" + + + + + int + + float + + return (int)(input); + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxConstCastTestImpl() + { + var inputContents = @"void* MyFunction(const void* input) +{ + return const_cast(input); +} +"; + + var expectedOutputContents = @" + + + + + void* + + void* + + return input; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxDynamicCastTestImpl() + { + var inputContents = @"struct MyStructA +{ + virtual void MyMethod() = 0; +}; + +struct MyStructB : MyStructA { }; + +MyStructB* MyFunction(MyStructA* input) +{ + return dynamic_cast(input); +} +"; + + var expectedOutputContents = $@" + + + + + void** + + + void + + ((delegate* unmanaged[Thiscall]<MyStructA*, void>)(lpVtbl[0]))((MyStructA*)Unsafe.AsPointer(ref this)); + + + + + + void** + + + void + + ((delegate* unmanaged[Thiscall]<MyStructB*, void>)(lpVtbl[0]))((MyStructB*)Unsafe.AsPointer(ref this)); + + + + + + MyStructB* + + MyStructA* + + return (MyStructB*)(input); + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxReinterpretCastTestImpl() + { + var inputContents = @"int* MyFunction(void* input) +{ + return reinterpret_cast(input); +} +"; + + var expectedOutputContents = @" + + + + + int* + + void* + + return (int*)(input); + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxStaticCastTestImpl() + { + var inputContents = @"int* MyFunction(void* input) +{ + return static_cast(input); +} +"; + + var expectedOutputContents = @" + + + + + int* + + void* + + return (int*)(input); + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DeclTestImpl() + { + var inputContents = @"\ +int MyFunction() +{ + int x = 0; + int y = 1, z = 2; + return x + y + z; +} +"; + + var expectedOutputContents = @" + + + + + int + int x = 0; + int y = 1, z = 2; + + return x + y + z; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DoTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + do + { + i++; + } + while (i < count); + + return i; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + int i = 0; + + do + { + i++; + } + while (i < count); + + return i; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DoNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + i++; + + return i; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + int i = 0; + + while (i < count) + { + i++; + } + + return i; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ForTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;;i--) + { + i += 2; + } + + for (x = 0;;x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + // x = 0; + // + // for (;; x--) + // { + // x += 2; + // } + + x = 0; + + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;; i--) + { + i += 2; + } + + for (x = 0;; x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + x = 0; + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ForNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + for (int i = 0; i < count; i--) + i += 2; + + int x; + + for (x = 0; x < count; x--) + x += 2; + + x = 0; + + for (; x < count; x--) + x += 2; + + for (int i = 0;;i--) + i += 2; + + for (x = 0;;x--) + x += 2; + + for (int i = 0; i < count;) + i++; + + for (x = 0; x < count;) + x++; + + // x = 0; + // + // for (;; x--) + // x += 2; + + x = 0; + + for (; x < count;) + x++; + + for (int i = 0;;) + i++; + + for (x = 0;;) + x++; + + for (;;) + return -1; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;; i--) + { + i += 2; + } + + for (x = 0;; x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + x = 0; + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + { + return lhs; + } + + return rhs; +} +"; + + var expectedOutputContents = @" + + + + + int + + bool + + + int + + + int + + if (condition) + { + return lhs; + } + + return rhs; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + { + return lhs; + } + else + { + return rhs; + } +} +"; + + var expectedOutputContents = @" + + + + + int + + bool + + + int + + + int + + if (condition) + { + return lhs; + } + else + { + return rhs; + } + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseIfTestImpl() + { + var inputContents = @"int MyFunction(bool condition1, int a, int b, bool condition2, int c) +{ + if (condition1) + { + return a; + } + else if (condition2) + { + return b; + } + + return c; +} +"; + + var expectedOutputContents = @" + + + + + int + + bool + + + int + + + int + + + bool + + + int + + if (condition1) + { + return a; + } + else if (condition2) + { + return b; + } + + return c; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + return lhs; + else + return rhs; +} +"; + + var expectedOutputContents = @" + + + + + int + + bool + + + int + + + int + + if (condition) + { + return lhs; + } + else + { + return rhs; + } + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InitListForArrayTestImpl() + { + var inputContents = @" +void MyFunction() +{ + int x[4] = { 1, 2, 3, 4 }; + int y[4] = { 1, 2, 3 }; + int z[] = { 1, 2 }; +} +"; + + var expectedOutputContents = @" + + + + + void + int[] x = new int[4] + { + 1, + 2, + 3, + 4, + }; + int[] y = new int[4] + { + 1, + 2, + 3, + default, + }; + int[] z = new int[2] + { + 1, + 2, + }; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InitListForRecordDeclTestImpl() + { + var inputContents = @"struct MyStruct +{ + float x; + float y; + float z; + float w; +}; + +MyStruct MyFunction1() +{ + return { 1.0f, 2.0f, 3.0f, 4.0f }; +} + +MyStruct MyFunction2() +{ + return { 1.0f, 2.0f, 3.0f }; +} +"; + + var expectedOutputContents = @" + + + + + float + + + float + + + float + + + float + + + + + MyStruct + return new MyStruct + { + x = 1.0f, + y = 2.0f, + z = 3.0f, + w = 4.0f, + }; + + + MyStruct + return new MyStruct + { + x = 1.0f, + y = 2.0f, + z = 3.0f, + }; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; +}; + +int MyFunction1(MyStruct instance) +{ + return instance.value; +} + +int MyFunction2(MyStruct* instance) +{ + return instance->value; +} +"; + + var expectedOutputContents = @" + + + + + int + + + + + int + + MyStruct + + return instance.value; + + + int + + MyStruct* + + return instance->value; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RefToPtrTestImpl() + { + var inputContents = @"struct MyStruct { + int value; +}; + +bool MyFunction(const MyStruct& lhs, const MyStruct& rhs) +{ + return lhs.value == rhs.value; +} +"; + + var expectedOutputContents = @" + + + + + int + + + + + bool + + MyStruct* + + + MyStruct* + + return lhs->value == rhs->value; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnCXXNullPtrTestImpl() + { + var inputContents = @"void* MyFunction() +{ + return nullptr; +} +"; + + var expectedOutputContents = @" + + + + + void* + return null; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnCXXBooleanLiteralTestImpl(string value) + { + var inputContents = $@"bool MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@" + + + + + bool + return {value}; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnFloatingLiteralDoubleTestImpl(string value) + { + var inputContents = $@"double MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@" + + + + + double + return {value}; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnFloatingLiteralSingleTestImpl(string value) + { + var inputContents = $@"float MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@" + + + + + float + return {value}; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnEmptyTestImpl() + { + var inputContents = @"void MyFunction() +{ + return; +} +"; + + var expectedOutputContents = @" + + + + + void + return; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnIntegerLiteralInt32TestImpl() + { + var inputContents = @"int MyFunction() +{ + return -1; +} +"; + + var expectedOutputContents = @" + + + + + int + return -1; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task AccessUnionMemberTestImpl() + { + var inputContents = @"union MyUnion +{ + struct { int a; }; +}; + +void MyFunction() +{ + MyUnion myUnion; + myUnion.a = 10; +} +"; + + var expectedOutputContents = @" + + + + + _Anonymous_e__Struct + + + ref int + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + + + + + int + + + + + + void + MyUnion myUnion = new MyUnion(); + + myUnion.Anonymous.a = 10; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnStructTestImpl() + { + var inputContents = @"struct MyStruct +{ + double r; + double g; + double b; +}; + +MyStruct MyFunction() +{ + MyStruct myStruct; + return myStruct; +} +"; + + var expectedOutputContents = @" + + + + + double + + + double + + + double + + + + + MyStruct + MyStruct myStruct = new MyStruct(); + + return myStruct; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SwitchTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + default: + { + return 0; + } + } +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + switch (value) + { + default: + { + return 0; + } + } + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SwitchNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + default: + { + return 0; + } + + switch (value) + default: + return 0; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + switch (value) + { + default: + { + return 0; + } + } + + switch (value) + { + default: + { + return 0; + } + } + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorAddrOfTestImpl() + { + var inputContents = @"int* MyFunction(int value) +{ + return &value; +} +"; + + var expectedOutputContents = @" + + + + + int* + + int + + return &value; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorDerefTestImpl() + { + var inputContents = @"int MyFunction(int* value) +{ + return *value; +} +"; + + var expectedOutputContents = @" + + + + + int + + int* + + return *value; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorLogicalNotTestImpl() + { + var inputContents = @"bool MyFunction(bool value) +{ + return !value; +} +"; + + var expectedOutputContents = @" + + + + + bool + + bool + + return !value; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorPostfixTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int value) +{{ + return value{opcode}; +}} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + return value{opcode}; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorPrefixTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int value) +{{ + return {opcode}value; +}} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + return {opcode}value; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WhileTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + { + i++; + } + + return i; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + int i = 0; + + while (i < count) + { + i++; + } + + return i; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WhileNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + i++; + + return i; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + int i = 0; + + while (i < count) + { + i++; + } + + return i; + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionDeclarationDllImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionDeclarationDllImportTest.cs new file mode 100644 index 00000000..4adb4e9d --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionDeclarationDllImportTest.cs @@ -0,0 +1,452 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultUnix_FunctionDeclarationDllImportTest : FunctionDeclarationDllImportTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @" + + + + + void + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ArrayParameterTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(const float color[4]);"; + + var expectedOutputContents = @" + + + + + void + + float* + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FunctionPointerParameterTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(void (*callback)());"; + + var expectedOutputContents = @" + + + + + void + + delegate* unmanaged[Cdecl]<void> + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NamespaceTestImpl() + { + var inputContents = @"namespace MyNamespace +{ + void MyFunction(); +}"; + + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "__ZN11MyNamespace10MyFunctionEv" : "_ZN11MyNamespace10MyFunctionEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + entryPoint = "?MyFunction@MyNamespace@@YAXXZ"; + } + + var expectedOutputContents = $@" + + + + + void + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TemplateParameterTestImpl(string nativeType, bool expectedNativeTypeAttr, string expectedManagedType, string expectedUsingStatement) + { + var inputContents = @$"template struct MyTemplate; + +extern ""C"" void MyFunction(MyTemplate<{nativeType}> myStruct);"; + + var expectedOutputContents = $@" + + + + + void + + MyTemplate<{expectedManagedType}> + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: new[] { "MyTemplate" }); + } + + protected override Task TemplateMemberTestImpl() + { + var inputContents = @$"template struct MyTemplate +{{ +}}; + +struct MyStruct +{{ + MyTemplate a; +}}; +"; + + var expectedOutputContents = $@" + + + + + MyTemplate<IntPtr> + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: new[] { "MyTemplate" }); + } + + protected override Task NoLibraryPathTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @" + + + + + void + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty); + } + + protected override Task WithLibraryPathTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @" + + + + + void + + + + +"; + + var withLibraryPaths = new Dictionary + { + ["MyFunction"] = "ClangSharpPInvokeGenerator" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty, withLibraryPaths: withLibraryPaths); + } + + protected override Task WithLibraryPathStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @" + + + + + void + + + + +"; + + var withLibraryPaths = new Dictionary + { + ["*"] = "ClangSharpPInvokeGenerator" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty, withLibraryPaths: withLibraryPaths); + } + + protected override Task OptionalParameterTestImpl(string nativeType, string nativeInit, bool expectedNativeTypeNameAttr, string expectedManagedType, string expectedManagedInit) + { + var inputContents = $@"extern ""C"" void MyFunction({nativeType} value = {nativeInit});"; + + var expectedOutputContents = $@" + + + + + void + + {expectedManagedType} + + {expectedManagedInit} + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task OptionalParameterUnsafeTestImpl(string nativeType, string nativeInit, string expectedManagedType, string expectedManagedInit) + { + var inputContents = $@"extern ""C"" void MyFunction({nativeType} value = {nativeInit});"; + + var expectedOutputContents = $@" + + + + + void + + {expectedManagedType} + + {expectedManagedInit} + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithCallConvTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @" + + + + + void + + int + + + + void + + int + + + + + +"; + + var withCallConvs = new Dictionary { + ["MyFunction1"] = "Winapi" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithCallConvStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @" + + + + + void + + int + + + + void + + int + + + + + +"; + + var withCallConvs = new Dictionary + { + ["*"] = "Winapi" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithCallConvStarOverrideTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @" + + + + + void + + int + + + + void + + int + + + + + +"; + + var withCallConvs = new Dictionary + { + ["*"] = "Winapi", + ["MyFunction2"] = "StdCall" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithSetLastErrorTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @" + + + + + void + + int + + + + void + + int + + + + + +"; + + var withSetLastErrors = new string[] + { + "MyFunction1" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withSetLastErrors: withSetLastErrors); + } + + protected override Task WithSetLastErrorStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @" + + + + + void + + int + + + + void + + int + + + + + +"; + + var withSetLastErrors = new string[] + { + "*" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withSetLastErrors: withSetLastErrors); + } + + protected override Task SourceLocationTestImpl() + { + const string InputContents = @"extern ""C"" void MyFunction(float value);"; + + const string ExpectedOutputContents = @" + + + + + void + + float + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); + } + + protected override Task VarargsTestImpl() => Task.CompletedTask; +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionPointerDeclarationTest.cs new file mode 100644 index 00000000..f1d0c73a --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/FunctionPointerDeclarationTest.cs @@ -0,0 +1,80 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultUnix_FunctionPointerDeclarationTest : FunctionPointerDeclarationTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"typedef void (*Callback)(); + +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallconvTestImpl() + { + var inputContents = @"typedef void (*Callback)() __attribute__((stdcall)); + +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Stdcall]<void> + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerlessTypedefTestImpl() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/StructDeclarationTest.cs new file mode 100644 index 00000000..371f1db0 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/StructDeclarationTest.cs @@ -0,0 +1,1785 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using ClangSharp.Abstractions; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultUnix_StructDeclarationTest : StructDeclarationTest +{ + protected override Task IncompleteArraySizeTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} x[]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestInCModeImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}} MyStruct; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, commandlineArgs: Array.Empty()); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BitfieldTestImpl() + { + var inputContents = @"struct MyStruct1 +{ + unsigned int o0_b0_24 : 24; + unsigned int o4_b0_16 : 16; + unsigned int o4_b16_3 : 3; + int o4_b19_3 : 3; + unsigned char o8_b0_1 : 1; + int o12_b0_1 : 1; + int o12_b1_1 : 1; +}; + +struct MyStruct2 +{ + unsigned int o0_b0_1 : 1; + int x; + unsigned int o8_b0_1 : 1; +}; + +struct MyStruct3 +{ + unsigned int o0_b0_1 : 1; + unsigned int o0_b1_1 : 1; +}; +"; + + var expectedOutputContents = @" + + + + + uint + + + uint + + return _bitfield1 & 0xFFFFFFu; + + + + _bitfield1 = (_bitfield1 & ~0xFFFFFFu) | (value & 0xFFFFFFu); + + + + uint + + + uint + + return _bitfield2 & 0xFFFFu; + + + + _bitfield2 = (_bitfield2 & ~0xFFFFu) | (value & 0xFFFFu); + + + + uint + + return (_bitfield2 >> 16) & 0x7u; + + + + _bitfield2 = (_bitfield2 & ~(0x7u << 16)) | ((value & 0x7u) << 16); + + + + int + + return (int)((_bitfield2 >> 19) & 0x7u); + + + + _bitfield2 = (_bitfield2 & ~(0x7u << 19)) | (uint)((value & 0x7) << 19); + + + + byte + + return (byte)((_bitfield2 >> 22) & 0x1u); + + + + _bitfield2 = (_bitfield2 & ~(0x1u << 22)) | (uint)((value & 0x1u) << 22); + + + + int + + return (int)((_bitfield2 >> 23) & 0x1u); + + + + _bitfield2 = (_bitfield2 & ~(0x1u << 23)) | (uint)((value & 0x1) << 23); + + + + int + + return (int)((_bitfield2 >> 24) & 0x1u); + + + + _bitfield2 = (_bitfield2 & ~(0x1u << 24)) | (uint)((value & 0x1) << 24); + + + + + + uint + + + uint + + return _bitfield1 & 0x1u; + + + + _bitfield1 = (_bitfield1 & ~0x1u) | (value & 0x1u); + + + + int + + + uint + + + uint + + return _bitfield2 & 0x1u; + + + + _bitfield2 = (_bitfield2 & ~0x1u) | (value & 0x1u); + + + + + + uint + + + uint + + return _bitfield & 0x1u; + + + + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + + + + uint + + return (_bitfield >> 1) & 0x1u; + + + + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DeclTypeTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(); + +typedef struct +{ + decltype(&MyFunction) _callback; +} MyStruct; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + + void + + + + +"; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = "typedef struct MyStruct MyStruct;"; + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyStruct" }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task FixedSizedBufferNonPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyStruct + + + + MyStruct + + + MyStruct + + + MyStruct + + + ref MyStruct + + int + + + return ref AsSpan()[index]; + + + + Span<MyStruct> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyStruct + + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + ref MyStruct + + int + + + return ref AsSpan()[index]; + + + + Span<MyStruct> + MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +typedef MyStruct MyBuffer[3]; + +struct MyOtherStruct +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyStruct + + + + MyStruct + + + MyStruct + + + MyStruct + + + ref MyStruct + + int + + + return ref AsSpan()[index]; + + + + Span<MyStruct> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyStruct + + + + MyStruct + + + MyStruct + + + MyStruct + + + ref MyStruct + + int + + + return ref AsSpan()[index]; + + + + Span<MyStruct> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPointerTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + ref {expectedManagedType} + + int + + + fixed ({expectedManagedType}* pThis = &e0) + {{ + return ref pThis[index]; + }} + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyBuffer[3]; + +struct MyStruct +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task GuidTestImpl() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Non-Unix doesn't support __declspec(uuid("")) + return Task.CompletedTask; + } + + var inputContents = $@"#define DECLSPEC_UUID(x) __declspec(uuid(x)) + +struct __declspec(uuid(""00000000-0000-0000-C000-000000000046"")) MyStruct1 +{{ + int x; +}}; + +struct DECLSPEC_UUID(""00000000-0000-0000-C000-000000000047"") MyStruct2 +{{ + int x; +}}; +"; + + var expectedOutputContents = $@" + + + + + int + + + + + int + + + + + + + + +"; + + var excludedNames = new string[] { "DECLSPEC_UUID" }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task InheritanceTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + int x; + int y; +}; + +struct MyStruct1B +{ + int x; + int y; +}; + +struct MyStruct2 : MyStruct1A, MyStruct1B +{ + int z; + int w; +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + + + int + + + int + + + + + MyStruct1A + + + MyStruct1B + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InheritanceWithNativeInheritanceAttributeTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + int x; + int y; +}; + +struct MyStruct1B +{ + int x; + int y; +}; + +struct MyStruct2 : MyStruct1A, MyStruct1B +{ + int z; + int w; +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + + + int + + + int + + + + + MyStruct1A + + + MyStruct1B + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateNativeInheritanceAttribute); + } + + protected override Task NestedAnonymousTestImpl(string nativeType, string expectedManagedType, int line, int column) + { + var inputContents = $@"typedef union {{ + {nativeType} value; +}} MyUnion; + +struct MyStruct +{{ + {nativeType} x; + {nativeType} y; + + struct + {{ + {nativeType} z; + + struct + {{ + {nativeType} value; + }} w; + + MyUnion u; + {nativeType} buffer1[4]; + MyUnion buffer2[4]; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + {expectedManagedType} + + + {expectedManagedType} + + + _Anonymous_e__Struct + + + ref {expectedManagedType} + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + + + + ref _Anonymous_e__Struct._w_e__Struct + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.w, 1)); + + + + ref MyUnion + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.u, 1)); + + + + Span<{expectedManagedType}> + + return MemoryMarshal.CreateSpan(ref Anonymous.buffer1[0], 4); + + + + Span<MyUnion> + + return Anonymous.buffer2.AsSpan(); + + + + + {expectedManagedType} + + + _w_e__Struct + + + MyUnion + + + {expectedManagedType} + + + MyUnion + + + + {expectedManagedType} + + + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + ref MyUnion + + int + + + return ref AsSpan()[index]; + + + + Span<MyUnion> + MemoryMarshal.CreateSpan(ref e0, 4); + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedAnonymousWithBitfieldTestImpl() + { + var inputContents = @"struct MyStruct +{ + int x; + int y; + + struct + { + int z; + + struct + { + int w; + int o0_b0_16 : 16; + int o0_b16_4 : 4; + }; + }; +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + _Anonymous_e__Struct + + + ref int + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + + + + ref int + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + + + + int + + return Anonymous.Anonymous.o0_b0_16; + + + Anonymous.Anonymous.o0_b0_16 = value; + + + + int + + return Anonymous.Anonymous.o0_b16_4; + + + Anonymous.Anonymous.o0_b16_4 = value; + + + + + int + + + _Anonymous_e__Struct + + + + int + + + int + + + int + + return _bitfield & 0xFFFF; + + + + _bitfield = (_bitfield & ~0xFFFF) | (value & 0xFFFF); + + + + int + + return (_bitfield >> 16) & 0xF; + + + + _bitfield = (_bitfield & ~(0xF << 16)) | ((value & 0xF) << 16); + + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + struct MyNestedStruct + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + struct MyNestedStruct + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"struct MyStruct +{ + int Equals; + int Dispose; + int GetHashCode; + int GetType; + int MemberwiseClone; + int ReferenceEquals; + int ToString; +};"; + + var expectedOutputContents = $@" + + + + + int + + + int + + + int + + + int + + + int + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoDefinitionTestImpl() + { + var inputContents = "typedef struct MyStruct MyStruct;"; + + var expectedOutputContents = $@" + + + + + +"; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + protected override Task PackTestImpl() + { + const string InputContents = @"struct MyStruct1 { + unsigned Field1; + + void* Field2; + + unsigned Field3; +}; + +#pragma pack(4) + +struct MyStruct2 { + unsigned Field1; + + void* Field2; + + unsigned Field3; +}; +"; + + var packing = Environment.Is64BitProcess ? " layout=\"Sequential\" pack=\"4\"" : string.Empty; + + var expectedOutputContents = $@" + + + + + uint + + + void* + + + uint + + + + + uint + + + void* + + + uint + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(InputContents, expectedOutputContents); + } + + protected override Task PointerToSelfTestImpl() + { + var inputContents = @"struct example_s { + example_s* next; + void* data; +};"; + + var expectedOutputContents = $@" + + + + + example_s* + + + void* + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfViaTypedefTestImpl() + { + var inputContents = @"typedef struct example_s example_t; + +struct example_s { + example_t* next; + void* data; +};"; + + var expectedOutputContents = $@" + + + + + example_s* + + + void* + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = "typedef struct _MyStruct MyStruct;"; + + var expectedOutputContents = $@" + + + + + +"; + + var remappedNames = new Dictionary { ["_MyStruct"] = "MyStruct" }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task RemapNestedAnonymousTestImpl() + { + var inputContents = @"struct MyStruct +{ + double r; + double g; + double b; + + struct + { + double a; + }; +};"; + + var expectedOutputContents = @" + + + + + double + + + double + + + double + + + _Anonymous_e__Struct + + + ref double + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + + + + + double + + + + + +"; + + var remappedNames = new Dictionary { + ["__AnonymousField_ClangUnsavedFile_L7_C5"] = "Anonymous", + ["__AnonymousRecord_ClangUnsavedFile_L7_C5"] = "_Anonymous_e__Struct" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task SkipNonDefinitionTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct MyStruct MyStruct; + +struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionPointerTestImpl() + { + var inputContents = @"typedef struct MyStruct* MyStructPtr; +typedef struct MyStruct& MyStructRef; +"; + + var expectedOutputContents = @" + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct MyStruct MyStruct; + +struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyTypedefAlias; + +struct MyStruct +{{ + MyTypedefAlias r; + MyTypedefAlias g; + MyTypedefAlias b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UsingDeclarationTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + void MyMethod() { } +}; + +struct MyStruct1B : MyStruct1A +{ + using MyStruct1A::MyMethod; +}; +"; + + var expectedOutputContents = @" + + + + + void + + + + + + void + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithAccessSpecifierTestImpl() + { + var inputContents = @"struct MyStruct1 +{ + int Field1; + int Field2; +}; + +struct MyStruct2 +{ + int Field1; + int Field2; +}; + +struct MyStruct3 +{ + int Field1; + int Field2; +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + + + int + + + int + + + + + int + + + int + + + + +"; + + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); + } + + protected override Task WithPackingTestImpl() + { + const string InputContents = @"struct MyStruct +{ + size_t FixedBuffer[1]; +}; +"; + + const string ExpectedOutputContents = @" + + + + + nuint + + + + nuint + + + ref nuint + + int + + + return ref AsSpan(int.MaxValue)[index]; + + + + Span<nuint> + + int + + MemoryMarshal.CreateSpan(ref e0, length); + + + + + +"; + + var withPackings = new Dictionary { + ["MyStruct"] = "CustomPackValue" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(InputContents, ExpectedOutputContents, withPackings: withPackings); + } + + protected override Task SourceLocationAttributeTestImpl() + { + const string InputContents = @"struct MyStruct +{ + int r; + int g; + int b; +}; +"; + + const string ExpectedOutputContents = @" + + + + + int + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/UnionDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/UnionDeclarationTest.cs new file mode 100644 index 00000000..68432fb4 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/UnionDeclarationTest.cs @@ -0,0 +1,1333 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultUnix_UnionDeclarationTest : UnionDeclarationTest +{ + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestInCModeImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}} MyUnion; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, commandlineArgs: Array.Empty()); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BitfieldTestImpl() + { + var inputContents = @"union MyUnion1 +{ + unsigned int o0_b0_24 : 24; + unsigned int o4_b0_16 : 16; + unsigned int o4_b16_3 : 3; + int o4_b19_3 : 3; + unsigned char o8_b0_1 : 1; + int o12_b0_1 : 1; + int o12_b1_1 : 1; +}; + +union MyUnion2 +{ + unsigned int o0_b0_1 : 1; + int x; + unsigned int o8_b0_1 : 1; +}; + +union MyUnion3 +{ + unsigned int o0_b0_1 : 1; + unsigned int o0_b1_1 : 1; +}; +"; + + var expectedPack = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? @" pack=""1""" : ""; + + var expectedOutputContents = $@" + + + + + uint + + + uint + + return _bitfield1 & 0xFFFFFFu; + + + + _bitfield1 = (_bitfield1 & ~0xFFFFFFu) | (value & 0xFFFFFFu); + + + + uint + + + uint + + return _bitfield2 & 0xFFFFu; + + + + _bitfield2 = (_bitfield2 & ~0xFFFFu) | (value & 0xFFFFu); + + + + uint + + return (_bitfield2 >> 16) & 0x7u; + + + + _bitfield2 = (_bitfield2 & ~(0x7u << 16)) | ((value & 0x7u) << 16); + + + + int + + return (int)((_bitfield2 >> 19) & 0x7u); + + + + _bitfield2 = (_bitfield2 & ~(0x7u << 19)) | (uint)((value & 0x7) << 19); + + + + byte + + return (byte)((_bitfield2 >> 22) & 0x1u); + + + + _bitfield2 = (_bitfield2 & ~(0x1u << 22)) | (uint)((value & 0x1u) << 22); + + + + int + + return (int)((_bitfield2 >> 23) & 0x1u); + + + + _bitfield2 = (_bitfield2 & ~(0x1u << 23)) | (uint)((value & 0x1) << 23); + + + + int + + return (int)((_bitfield2 >> 24) & 0x1u); + + + + _bitfield2 = (_bitfield2 & ~(0x1u << 24)) | (uint)((value & 0x1) << 24); + + + + + + uint + + + uint + + return _bitfield1 & 0x1u; + + + + _bitfield1 = (_bitfield1 & ~0x1u) | (value & 0x1u); + + + + int + + + uint + + + uint + + return _bitfield2 & 0x1u; + + + + _bitfield2 = (_bitfield2 & ~0x1u) | (value & 0x1u); + + + + + + uint + + + uint + + return _bitfield & 0x1u; + + + + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + + + + uint + + return (_bitfield >> 1) & 0x1u; + + + + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = "typedef union MyUnion MyUnion;"; + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyUnion" }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task FixedSizedBufferNonPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyUnion + + + + MyUnion + + + MyUnion + + + MyUnion + + + ref MyUnion + + int + + + return ref AsSpan()[index]; + + + + Span<MyUnion> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyUnion + + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + ref MyUnion + + int + + + return ref AsSpan()[index]; + + + + Span<MyUnion> + MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +typedef MyUnion MyBuffer[3]; + +union MyOtherUnion +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyUnion + + + + MyUnion + + + MyUnion + + + MyUnion + + + ref MyUnion + + int + + + return ref AsSpan()[index]; + + + + Span<MyUnion> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyUnion + + + + MyUnion + + + MyUnion + + + MyUnion + + + ref MyUnion + + int + + + return ref AsSpan()[index]; + + + + Span<MyUnion> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPointerTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + ref {expectedManagedType} + + int + + + fixed ({expectedManagedType}* pThis = &e0) + {{ + return ref pThis[index]; + }} + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyBuffer[3]; + +union MyUnion +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + protected override Task GuidTestImpl() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Non-Unix doesn't support __declspec(uuid("")) + return Task.CompletedTask; + } + + var inputContents = $@"#define DECLSPEC_UUID(x) __declspec(uuid(x)) + +union __declspec(uuid(""00000000-0000-0000-C000-000000000046"")) MyUnion1 +{{ + int x; +}}; + +union DECLSPEC_UUID(""00000000-0000-0000-C000-000000000047"") MyUnion2 +{{ + int x; +}}; +"; + + var expectedOutputContents = $@" + + + + + int + + + + + int + + + + + + + + +"; + + var excludedNames = new string[] { "DECLSPEC_UUID" }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task NestedAnonymousTestImpl(string nativeType, string expectedManagedType, int line, int column) + { + var inputContents = $@"typedef struct {{ + {nativeType} value; +}} MyStruct; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union + {{ + {nativeType} a; + + MyStruct s; + + {nativeType} buffer[4]; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + _Anonymous_e__Union + + + ref {expectedManagedType} + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + + + + ref MyStruct + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.s, 1)); + + + + Span<{expectedManagedType}> + + return MemoryMarshal.CreateSpan(ref Anonymous.buffer[0], 4); + + + + + {expectedManagedType} + + + MyStruct + + + {expectedManagedType} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedAnonymousWithBitfieldTestImpl() + { + var inputContents = @"union MyUnion +{ + int x; + int y; + + union + { + int z; + + union + { + int w; + int o0_b0_16 : 16; + int o0_b16_4 : 4; + }; + }; +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + _Anonymous_e__Union + + + ref int + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + + + + ref int + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + + + + int + + return Anonymous.Anonymous.o0_b0_16; + + + Anonymous.Anonymous.o0_b0_16 = value; + + + + int + + return Anonymous.Anonymous.o0_b16_4; + + + Anonymous.Anonymous.o0_b16_4 = value; + + + + + int + + + _Anonymous_e__Union + + + + int + + + int + + + int + + return _bitfield & 0xFFFF; + + + + _bitfield = (_bitfield & ~0xFFFF) | (value & 0xFFFF); + + + + int + + return (_bitfield >> 16) & 0xF; + + + + _bitfield = (_bitfield & ~(0xF << 16)) | ((value & 0xF) << 16); + + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + + protected override Task NestedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union MyNestedUnion + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union MyNestedUnion + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"union MyUnion +{ + int Equals; + int Dispose; + int GetHashCode; + int GetType; + int MemberwiseClone; + int ReferenceEquals; + int ToString; +};"; + + var expectedOutputContents = $@" + + + + + int + + + int + + + int + + + int + + + int + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoDefinitionTestImpl() + { + var inputContents = "typedef union MyUnion MyUnion;"; + + var expectedOutputContents = $@" + + + + + +"; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfTestImpl() + { + var inputContents = @"union example_s { + example_s* next; + void* data; +};"; + + var expectedOutputContents = $@" + + + + + example_s* + + + void* + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfViaTypedefTestImpl() + { + var inputContents = @"typedef union example_s example_t; + +union example_s { + example_t* next; + void* data; +};"; + + var expectedOutputContents = $@" + + + + + example_s* + + + void* + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = "typedef union _MyUnion MyUnion;"; + + var expectedOutputContents = $@" + + + + + +"; + + var remappedNames = new Dictionary { ["_MyUnion"] = "MyUnion" }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task RemapNestedAnonymousTestImpl() + { + var inputContents = @"union MyUnion +{ + double r; + double g; + double b; + + union + { + double a; + }; +};"; + + var expectedOutputContents = @" + + + + + double + + + double + + + double + + + _Anonymous_e__Union + + + ref double + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + + + + + double + + + + + +"; + + var remappedNames = new Dictionary { + ["__AnonymousField_ClangUnsavedFile_L7_C5"] = "Anonymous", + ["__AnonymousRecord_ClangUnsavedFile_L7_C5"] = "_Anonymous_e__Union" + }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task SkipNonDefinitionTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union MyUnion MyUnion; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionPointerTestImpl() + { + var inputContents = @"typedef union MyUnion* MyUnionPtr; +typedef union MyUnion& MyUnionRef; +"; + + var expectedOutputContents = @" + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union MyUnion MyUnion; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyTypedefAlias; + +union MyUnion +{{ + MyTypedefAlias r; + MyTypedefAlias g; + MyTypedefAlias b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/VarDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/VarDeclarationTest.cs new file mode 100644 index 00000000..78c38723 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/VarDeclarationTest.cs @@ -0,0 +1,533 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultUnix_VarDeclarationTest : VarDeclarationTest +{ + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"{nativeType} MyVariable = 0;"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + 0 + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"{nativeType} MyVariable = 0;"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + 0 + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task GuidMacroTestImpl() + { + var inputContents = $@"struct GUID {{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +}}; + +const GUID IID_IUnknown = {{ 0x00000000, 0x0000, 0x0000, {{ 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }} }}; +"; + + var expectedOutputContents = $@" + + + + + Guid + + new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46) + + + + + +"; + var excludedNames = new string[] { "GUID" }; + var remappedNames = new Dictionary { ["GUID"] = "Guid" }; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames, remappedNames: remappedNames); + } + + protected override Task MacroTestImpl(string nativeValue, string expectedManagedType, string expectedManagedValue) + { + var inputContents = $@"#define MyMacro1 {nativeValue} +#define MyMacro2 MyMacro1"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + {expectedManagedValue} + + + + {expectedManagedType} + + {expectedManagedValue} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MultilineMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 0 + \ +1"; + + var expectedOutputContents = $@" + + + + + int + + 0 + 1 + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoInitializerTestImpl(string nativeType) + { + var inputContents = $@"{nativeType} MyVariable;"; + var expectedOutputContents = ""; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task Utf8StringLiteralMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 ""Test"""; + + var expectedOutputContents = $@" + + + + + ReadOnlySpan<byte> + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task Utf16StringLiteralMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 u""Test"""; + + var expectedOutputContents = $@" + + + + + string + + ""Test"" + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WideStringLiteralConstTestImpl() + { + var inputContents = $@"const wchar_t MyConst1[] = L""Test""; +const wchar_t* MyConst2 = L""Test""; +const wchar_t* const MyConst3 = L""Test"";"; + + var expectedOutputContents = $@" + + + + + uint[] + + new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }} + + + + uint[] + + new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }} + + + + uint[] + + new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StringLiteralConstTestImpl() + { + var inputContents = $@"const char MyConst1[] = ""Test""; +const char* MyConst2 = ""Test""; +const char* const MyConst3 = ""Test"";"; + + var expectedOutputContents = $@" + + + + + ReadOnlySpan<byte> + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + byte[] + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + ReadOnlySpan<byte> + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WideStringLiteralStaticConstTestImpl() + { + var inputContents = $@"static const wchar_t MyConst1[] = L""Test""; +static const wchar_t* MyConst2 = L""Test""; +static const wchar_t* const MyConst3 = L""Test"";"; + + var expectedOutputContents = $@" + + + + + uint[] + + new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }} + + + + uint[] + + new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }} + + + + uint[] + + new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StringLiteralStaticConstTestImpl() + { + var inputContents = $@"static const char MyConst1[] = ""Test""; +static const char* MyConst2 = ""Test""; +static const char* const MyConst3 = ""Test"";"; + + var expectedOutputContents = $@" + + + + + ReadOnlySpan<byte> + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + byte[] + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + ReadOnlySpan<byte> + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedConversionMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 (long)0x80000000L +#define MyMacro2 (int)0x80000000"; + + var expectedOutputContents = $@" + + + + + nint + + + + (nint)(0x80000000) + + + + + + int + + + + (int)(0x80000000) + + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedFunctionLikeCastMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 unsigned(-1)"; + + var expectedOutputContents = $@" + + + + + uint + + + + (uint)(-1) + + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedConversionMacroTest2Impl() + { + var inputContents = $@"#define MyMacro1(x, y, z) ((int)(((unsigned long)(x)<<31) | ((unsigned long)(y)<<16) | ((unsigned long)(z)))) +#define MyMacro2(n) MyMacro1(1, 2, n) +#define MyMacro3 MyMacro2(3)"; + + var expectedOutputContents = $@" + + + + + int + + + ((int)(((nuint)(1) << 31) | ((nuint)(2) << 16) | ((nuint)(3)))) + + + + + + +"; + + var excludedNames = new string[] { "MyMacro1", "MyMacro2" }; + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task UncheckedPointerMacroTestImpl() + { + var inputContents = $@"#define Macro1 ((int*) -1)"; + + var expectedOutputContents = $@" + + + + + int* + + + ((int*)(-1)) + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedReinterpretCastMacroTestImpl() + { + var inputContents = $@"#define Macro1 reinterpret_cast(-1)"; + + var expectedOutputContents = $@" + + + + + int* + + + + (int*)(-1) + + + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MultidimensionlArrayTestImpl() + { + var inputContents = $@"const int MyArray[2][2] = {{ {{ 0, 1 }}, {{ 2, 3 }} }};"; + + var expectedOutputContents = $@" + + + + + int[][] + + new int[2][] + {{ + new int[2] + {{ + 0, + 1, + }}, + new int[2] + {{ + 2, + 3, + }}, + }} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConditionalDefineConstTestImpl() + { + var inputContents = @"typedef int TESTRESULT; +#define TESTRESULT_FROM_WIN32(x) ((TESTRESULT)(x) <= 0 ? ((TESTRESULT)(x)) : ((TESTRESULT) (((x) & 0x0000FFFF) | (7 << 16) | 0x80000000))) +#define ADDRESS_IN_USE TESTRESULT_FROM_WIN32(10048)"; + + var expectedOutputContents = $@" + + + + + int + + + ((int)(10048) <= 0 ? ((int)(10048)) : ((int)(((10048) & 0x0000FFFF) | (7 << 16) | 0x80000000))) + + + + + + +"; + var diagnostics = new Diagnostic[] { new Diagnostic(DiagnosticLevel.Warning, "Function like macro definition records are not supported: 'TESTRESULT_FROM_WIN32'. Generated bindings may be incomplete.", "Line 2, Column 9 in ClangUnsavedFile.h") }; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/CXXMethodDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/CXXMethodDeclarationTest.cs new file mode 100644 index 00000000..60c9ce03 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/CXXMethodDeclarationTest.cs @@ -0,0 +1,1063 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultWindows_CXXMethodDeclarationTest : CXXMethodDeclarationXmlTest +{ + protected override Task ConstructorTestImpl() + { + var inputContents = @"struct MyStruct +{ + int _value; + + MyStruct(int value) + { + _value = value; + } +}; +"; + + var expectedOutputContents = @" + + + + + int + + + void + + int + + _value = value; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConstructorWithInitializeTestImpl() + { + var inputContents = @"struct MyStruct +{ + int _x; + int _y; + int _z; + + MyStruct(int x) : _x(x) + { + } + + MyStruct(int x, int y) : _x(x), _y(y) + { + } + + MyStruct(int x, int y, int z) : _x(x), _y(y), _z() + { + } +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + int + + + void + + int + + + x + + + + + void + + int + + + int + + + x + + + y + + + + + void + + int + + + int + + + int + + + x + + + y + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConversionTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + operator int() + { + return value; + } +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + return value; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DestructorTestImpl() + { + var inputContents = @"struct MyStruct +{ + ~MyStruct() + { + } +}; +"; + + var expectedOutputContents = @" + + + + + void + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InstanceTestImpl() + { + var inputContents = @"struct MyStruct +{ + void MyVoidMethod(); + + int MyInt32Method() + { + return 0; + } + + void* MyVoidStarMethod() + { + return nullptr; + } +}; +"; + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "__ZN8MyStruct12MyVoidMethodEv" : "_ZN8MyStruct12MyVoidMethodEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + if (!Environment.Is64BitProcess) + { + entryPoint = "?MyVoidMethod@MyStruct@@QAEXXZ"; + } + else + { + entryPoint = "?MyVoidMethod@MyStruct@@QEAAXXZ"; + } + } + + var expectedOutputContents = $@" + + + + + void + + MyStruct* + + + + int + return 0; + + + void* + return null; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberCallTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction1() + { + return value; + } + + int MyFunction2() + { + return MyFunction1(); + } + + int MyFunction3() + { + return this->MyFunction1(); + } +}; + +int MyFunctionA(MyStruct x) +{ + return x.MyFunction1(); +} + +int MyFunctionB(MyStruct* x) +{ + return x->MyFunction2(); +} +"; + + var expectedOutputContents = @" + + + + + int + + + int + return value; + + + int + return MyFunction1(); + + + int + return this.MyFunction1(); + + + + + int + + MyStruct + + return x.MyFunction1(); + + + int + + MyStruct* + + return x->MyFunction2(); + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction() + { + return value; + } +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + return value; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"struct MyStruct +{ + int Equals() { return 0; } + int Equals(int obj) { return 0; } + int Dispose() { return 0; } + int Dispose(int obj) { return 0; } + int GetHashCode() { return 0; } + int GetHashCode(int obj) { return 0; } + int GetType() { return 0; } + int GetType(int obj) { return 0; } + int MemberwiseClone() { return 0; } + int MemberwiseClone(int obj) { return 0; } + int ReferenceEquals() { return 0; } + int ReferenceEquals(int obj) { return 0; } + int ToString() { return 0; } + int ToString(int obj) { return 0; } +};"; + + var expectedOutputContents = $@" + + + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + int + return 0; + + + int + + int + + return 0; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordVirtualTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var expectedOutputContents = $@" + + + + + void** + + + int + + int + + + int + + + return ((delegate* unmanaged[Thiscall]<MyStruct*, int, int, int>)(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + + + + int + + return ((delegate* unmanaged[Thiscall]<MyStruct*, int>)(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + int + + int + + + return ((delegate* unmanaged[Thiscall]<MyStruct*, int, int>)(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this), obj); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordVirtualWithExplicitVtblTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var nativeCallConv = ""; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Environment.Is64BitProcess) + { + nativeCallConv = " __attribute__((thiscall))"; + } + + var expectedOutputContents = $@" + + + + + Vtbl* + + + int + + int + + + int + + + return lpVtbl->GetType((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + + + + int + + return lpVtbl->GetType1((MyStruct*)Unsafe.AsPointer(ref this)); + + + + int + + int + + + return lpVtbl->GetType2((MyStruct*)Unsafe.AsPointer(ref this), obj); + + + + + delegate* unmanaged[Thiscall]<MyStruct*, int, int, int> + + + delegate* unmanaged[Thiscall]<MyStruct*, int> + + + delegate* unmanaged[Thiscall]<MyStruct*, int, int> + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateExplicitVtbls); + } + + protected override Task NewKeywordVirtualWithExplicitVtblAndMarkerInterfaceTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual int GetType(int obj) = 0; + virtual int GetType() = 0; + virtual int GetType(int objA, int objB) = 0; +};"; + + var nativeCallConv = ""; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Environment.Is64BitProcess) + { + nativeCallConv = " __attribute__((thiscall))"; + } + + var expectedOutputContents = $@" + + + + + Vtbl<MyStruct>* + + + int + + int + + + int + + + return lpVtbl->GetType((MyStruct*)Unsafe.AsPointer(ref this), objA, objB); + + + + int + + return lpVtbl->GetType1((MyStruct*)Unsafe.AsPointer(ref this)); + + + + int + + int + + + return lpVtbl->GetType2((MyStruct*)Unsafe.AsPointer(ref this), obj); + + + + + int + + int + + + int + + + + int + + + int + + int + + + + + + delegate* unmanaged[Thiscall]<TSelf*, int, int, int> + + + delegate* unmanaged[Thiscall]<TSelf*, int> + + + delegate* unmanaged[Thiscall]<TSelf*, int, int> + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateExplicitVtbls | PInvokeGeneratorConfigurationOptions.GenerateMarkerInterfaces); + } + + protected override Task OperatorTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + MyStruct(int value) : value(value) + { + } + + MyStruct operator+(MyStruct rhs) + { + return MyStruct(value + rhs.value); + } +}; + +MyStruct operator-(MyStruct lhs, MyStruct rhs) +{ + return MyStruct(lhs.value - rhs.value); +} +"; + + var expectedOutputContents = @" + + + + + int + + + void + + int + + + value + + + + + MyStruct + + MyStruct + + return new MyStruct(value + rhs.value); + + + + + MyStruct + + MyStruct + + + MyStruct + + return new MyStruct(lhs.value - rhs.value); + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task OperatorCallTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + MyStruct(int value) : value(value) + { + } + + MyStruct operator+(MyStruct rhs) + { + return MyStruct(value + rhs.value); + } +}; + +MyStruct MyFunction1(MyStruct lhs, MyStruct rhs) +{ + return lhs + rhs; +} + +MyStruct operator-(MyStruct lhs, MyStruct rhs) +{ + return MyStruct(lhs.value - rhs.value); +} + +MyStruct MyFunction2(MyStruct lhs, MyStruct rhs) +{ + return lhs - rhs; +} +"; + + var expectedOutputContents = @" + + + + + int + + + void + + int + + + value + + + + + MyStruct + + MyStruct + + return new MyStruct(value + rhs.value); + + + + + MyStruct + + MyStruct + + + MyStruct + + return lhs.Add(rhs); + + + MyStruct + + MyStruct + + + MyStruct + + return new MyStruct(lhs.value - rhs.value); + + + MyStruct + + MyStruct + + + MyStruct + + return Subtract(lhs, rhs); + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StaticTestImpl() + { + var inputContents = @"struct MyStruct +{ + static void MyVoidMethod(); + + static int MyInt32Method() + { + return 0; + } + + static void* MyVoidStarMethod() + { + return nullptr; + } +}; +"; + + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "?MyVoidMethod@MyStruct@@SAXXZ" : "_ZN8MyStruct12MyVoidMethodEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + entryPoint = $"_{entryPoint}"; + } + + var expectedOutputContents = $@" + + + + + void + + + int + return 0; + + + void* + return null; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ThisTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; + + int MyFunction() + { + return this->value; + } +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + return this.value; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnsafeDoesNotImpactDllImportTestImpl() + { + var inputContents = @"struct MyStruct +{ + void* MyVoidStarMethod() + { + return nullptr; + } +}; + +extern ""C"" void MyFunction();"; + + var expectedOutputContents = @" + + + + + void* + return null; + + + + + void + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task VirtualTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual void MyVoidMethod() = 0; + + virtual char MyInt8Method() + { + return 0; + } + + virtual int MyInt32Method(); + + virtual void* MyVoidStarMethod() = 0; +}; +"; + + var expectedOutputContents = $@" + + + + + void** + + + void + + ((delegate* unmanaged[Thiscall]<MyStruct*, void>)(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + sbyte + + return ((delegate* unmanaged[Thiscall]<MyStruct*, sbyte>)(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + int + + return ((delegate* unmanaged[Thiscall]<MyStruct*, int>)(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + void* + + return ((delegate* unmanaged[Thiscall]<MyStruct*, void*>)(lpVtbl[3]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task VirtualWithVtblIndexAttributeTestImpl() + { + var inputContents = @"struct MyStruct +{ + virtual void MyVoidMethod() = 0; + + virtual char MyInt8Method() + { + return 0; + } + + virtual int MyInt32Method(); + + virtual void* MyVoidStarMethod() = 0; +}; +"; + + var expectedOutputContents = $@" + + + + + void** + + + void + + ((delegate* unmanaged[Thiscall]<MyStruct*, void>)(lpVtbl[0]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + sbyte + + return ((delegate* unmanaged[Thiscall]<MyStruct*, sbyte>)(lpVtbl[1]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + int + + return ((delegate* unmanaged[Thiscall]<MyStruct*, int>)(lpVtbl[2]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + void* + + return ((delegate* unmanaged[Thiscall]<MyStruct*, void*>)(lpVtbl[3]))((MyStruct*)Unsafe.AsPointer(ref this)); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateVtblIndexAttribute); + } + + protected override Task ValidateBindingsAsync(string inputContents, string expectedOutputContents) => ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DeprecatedToObsoleteTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DeprecatedToObsoleteTest.cs new file mode 100644 index 00000000..8a0e5423 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DeprecatedToObsoleteTest.cs @@ -0,0 +1,535 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultWindows_DeprecatedToObsoleteTest : DeprecatedToObsoleteTest +{ + protected override Task SimpleStructMembersImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + + [[deprecated]] + {nativeType} g; + + [[deprecated(""This is obsolete."")]] + {nativeType} b; + + {nativeType} a; +}}; +"; + + var expectedOutputContents = $@" + + + + + int + + + Obsolete + int + + + Obsolete(""This is obsolete."") + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StructDeclImpl() + { + var inputContents = $@"struct MyStruct0 +{{ + int r; +}}; + +struct [[deprecated]] MyStruct1 +{{ + int r; +}}; + +struct [[deprecated(""This is obsolete."")]] MyStruct2 +{{ + int r; +}}; + +struct MyStruct3 +{{ + int r; +}}; +"; + + var expectedOutputContents = $@" + + + + + int + + + + Obsolete + + int + + + + Obsolete(""This is obsolete."") + + int + + + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleTypedefStructMembersImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct +{{ + {nativeType} r; + + [[deprecated]] + {nativeType} g; + + [[deprecated(""This is obsolete."")]] + {nativeType} b; + + {nativeType} a; +}} MyStruct; +"; + + var expectedOutputContents = $@" + + + + + int + + + Obsolete + int + + + Obsolete(""This is obsolete."") + int + + + int + + + + +"; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefStructDeclImpl() + { + var inputContents = $@"typedef struct +{{ + int r; +}} MyStruct0; + +[[deprecated]] typedef struct +{{ + int r; +}} MyStruct1; + +[[deprecated(""This is obsolete."")]] typedef struct +{{ + int r; +}} MyStruct2; + +typedef struct +{{ + int r; +}} MyStruct3; +"; + + var expectedOutputContents = $@" + + + + + int + + + + Obsolete + + int + + + + Obsolete(""This is obsolete."") + + int + + + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleEnumMembersImpl() + { + var inputContents = $@"enum MyEnum : int +{{ + MyEnum_Value0, + MyEnum_Value1 [[deprecated]], + MyEnum_Value2 [[deprecated(""This is obsolete."")]], + MyEnum_Value3, +}}; +"; + + var expectedOutputContents = @" + + + + int + + int + + + Obsolete + int + + + Obsolete(""This is obsolete."") + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task EnumDeclImpl() + { + var inputContents = $@"enum MyEnum0 : int +{{ + MyEnum_Value0, +}}; + +enum [[deprecated]] MyEnum1 : int +{{ + MyEnum_Value1, +}}; + +enum [[deprecated(""This is obsolete."")]] MyEnum2 : int +{{ + MyEnum_Value2, +}}; + + +enum MyEnum3 : int +{{ + MyEnum_Value3, +}}; +"; + + var expectedOutputContents = @" + + + + int + + int + + + + Obsolete + int + + int + + + + Obsolete(""This is obsolete."") + int + + int + + + + int + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SimpleVarDeclImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@" +{nativeType} MyVariable0 = 0; + +[[deprecated]] +{nativeType} MyVariable1 = 0; + +[[deprecated(""This is obsolete."")]] +{nativeType} MyVariable2 = 0; + +{nativeType} MyVariable3 = 0;"; + + var expectedOutputContents = $@" + + + + + int + + 0 + + + + Obsolete + int + + 0 + + + + Obsolete(""This is obsolete."") + int + + 0 + + + + int + + 0 + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncDeclImpl() + { + var inputContents = @" +void MyFunction0() +{ +} + +[[deprecated]] +void MyFunction1() +{ +} + +[[deprecated(""This is obsolete."")]] +void MyFunction2() +{ +} + +void MyFunction3() +{ +} +"; + + var expectedOutputContents = @" + + + + + void + + + + Obsolete + void + + + + Obsolete(""This is obsolete."") + void + + + + void + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InstanceFuncImpl() + { + var inputContents = @"struct MyStruct +{ + int MyFunction0() { return 0; } + + [[deprecated]] + int MyFunction1() { return 0; } + + [[deprecated(""This is obsolete."")]] + int MyFunction2() { return 0; } + + int MyFunction3() { return 0; } +};"; + + var expectedOutputContents = $@" + + + + + int + return 0; + + + Obsolete + int + return 0; + + + Obsolete(""This is obsolete."") + int + return 0; + + + int + return 0; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncPtrDeclImpl() + { + var inputContents = @" +typedef void (*Callback0)(); +[[deprecated]] typedef void (*Callback1)(); +[[deprecated(""This is obsolete."")]] typedef void (*Callback2)(); +typedef void (*Callback3)(); + +struct MyStruct0 { + Callback0 _callback; +}; +struct MyStruct1 { + Callback1 _callback; +}; +struct MyStruct2 { + Callback2 _callback; +}; +struct MyStruct3 { + Callback3 _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + + Obsolete + delegate* unmanaged[Cdecl]<void> + + + + + Obsolete(""This is obsolete."") + delegate* unmanaged[Cdecl]<void> + + + + + delegate* unmanaged[Cdecl]<void> + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FuncDllImportImpl() + { + var inputContents = @" +extern ""C"" void MyFunction0(); +extern ""C"" [[deprecated]] void MyFunction1(); +extern ""C"" [[deprecated(""This is obsolete."")]] void MyFunction2(); +extern ""C"" void MyFunction3();"; + + var expectedOutputContents = @" + + + + + void + + + Obsolete + void + + + Obsolete(""This is obsolete."") + void + + + void + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/EnumDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/EnumDeclarationTest.cs new file mode 100644 index 00000000..901b3317 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/EnumDeclarationTest.cs @@ -0,0 +1,730 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultWindows_EnumDeclarationTest : EnumDeclarationTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicValueTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value1 = 1, + MyEnum_Value2, + MyEnum_Value3, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + 1 + + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyEnum" }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task ExplicitTypedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"enum MyEnum : {nativeType} +{{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}}; +"; + + var expectedOutputContents = $@" + + + + {EscapeXml(expectedManagedType)} + + {EscapeXml(expectedManagedType)} + + + {EscapeXml(expectedManagedType)} + + + {EscapeXml(expectedManagedType)} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExplicitTypedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"enum MyEnum : {nativeType} +{{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}}; +"; + + var expectedOutputContents = $@" + + + + {EscapeXml(expectedManagedType)} + + {EscapeXml(expectedManagedType)} + + + {EscapeXml(expectedManagedType)} + + + {EscapeXml(expectedManagedType)} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = @"typedef enum _MyEnum : int +{ + MyEnum_Value1, + MyEnum_Value2, + MyEnum_Value3, +} MyEnum; +"; + + var expectedOutputContents = @" + + + + int + + int + + + int + + + int + + + + +"; + + var remappedNames = new Dictionary { ["_MyEnum"] = "MyEnum" }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task WithAttributeTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = 1, +}; +"; + + var expectedOutputContents = @" + + + + Flags + int + + int + + 1 + + + + + int + + int + + 1 + + + + + +"; + + var withAttributes = new Dictionary> + { + ["MyEnum1"] = new List() { "Flags" } + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withAttributes: withAttributes); + } + + protected override Task WithNamespaceTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + 1 + + + + + int + + int + + MyEnum1_Value1 + + + + + +"; + + var withNamespaces = new Dictionary> + { + ["MyEnum1"] = new List() { "static ClangSharp.Test.MyEnum1" } + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithNamespaceStarTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + 1 + + + + + int + + int + + MyEnum1_Value1 + + + + + +"; + + var withNamespaces = new Dictionary> + { + ["*"] = new List() { "static ClangSharp.Test.MyEnum1" } + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithNamespaceStarPlusTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + 1 + + + + + int + + int + + MyEnum1_Value1 + + + + + +"; + + var withNamespaces = new Dictionary> + { + ["*"] = new List() { "static ClangSharp.Test.MyEnum1" }, + ["MyEnum2"] = new List() { "System" } + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withUsings: withNamespaces); + } + + protected override Task WithCastToEnumTypeImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0 = (MyEnum) 10, + MyEnum_Value1 = (MyEnum) MyEnum_Value0, + MyEnum_Value2 = ((MyEnum) 10) + MyEnum_Value1, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + (int)(MyEnum)(10) + + + + int + + (int)(MyEnum)(MyEnum_Value0) + + + + int + + ((int)(MyEnum)(10)) + MyEnum_Value1 + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithMultipleEnumsTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 = 10, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 = MyEnum1_Value0, + MyEnum2_Value1 = MyEnum1_Value0 + (MyEnum1) 10, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + 10 + + + + + int + + int + + MyEnum1_Value0 + + + + int + + MyEnum1_Value0 + (int)(MyEnum1)(10) + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithImplicitConversionTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = 0x80000000, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + + int + + + int + + + + int + + 0x80000000 + + + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithTypeTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; +"; + + var expectedOutputContents = @" + + + + uint + + uint + + + uint + + + uint + + + + +"; + + var withTypes = new Dictionary { + ["MyEnum"] = "uint" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeAndImplicitConversionTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2 = 0x80000000, +}; +"; + + var expectedOutputContents = @" + + + + uint + + uint + + + uint + + + uint + + 0x80000000 + + + + + +"; + + var withTypes = new Dictionary + { + ["MyEnum"] = "uint" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeStarTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 +}; +"; + + var expectedOutputContents = @" + + + + uint + + uint + + + + uint + + uint + + + + +"; + + var withTypes = new Dictionary + { + ["*"] = "uint" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithTypeStarOverrideTestImpl() + { + var inputContents = @"enum MyEnum1 : int +{ + MyEnum1_Value0 +}; + +enum MyEnum2 : int +{ + MyEnum2_Value0 +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + + + uint + + uint + + + + +"; + + var withTypes = new Dictionary + { + ["*"] = "uint", + ["MyEnum1"] = "int", + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withTypes: withTypes); + } + + protected override Task WithAnonymousEnumTestImpl() + { + var inputContents = @"enum +{ + MyEnum1_Value1 = 1, +}; + +enum MyEnum2 : int +{ + MyEnum2_Value1 = MyEnum1_Value1, +}; +"; + + var expectedOutputContents = @" + + + + int + + int + + MyEnum1_Value1 + + + + + + int + + 1 + + + + + +"; + + var diagnostics = new[] { new Diagnostic(DiagnosticLevel.Info, "Found anonymous enum: __AnonymousEnum_ClangUnsavedFile_L1_C1. Mapping values as constants in: Methods", "Line 1, Column 1 in ClangUnsavedFile.h") }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } + + protected override Task WithReferenceToAnonymousEnumEnumeratorTestImpl() + { + var inputContents = @"enum +{ + MyEnum1_Value1 = 1, +}; + +const int MyEnum2_Value1 = MyEnum1_Value1 + 1; +"; + + var expectedOutputContents = @" + + + + + int + + 1 + + + + int + + (int)(MyEnum1_Value1) + 1 + + + + + +"; + var diagnostics = new[] { new Diagnostic(DiagnosticLevel.Info, "Found anonymous enum: __AnonymousEnum_ClangUnsavedFile_L1_C1. Mapping values as constants in: Methods", "Line 1, Column 1 in ClangUnsavedFile.h") }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionDeclarationBodyImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionDeclarationBodyImportTest.cs new file mode 100644 index 00000000..4bd26387 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionDeclarationBodyImportTest.cs @@ -0,0 +1,1990 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultWindows_FunctionDeclarationBodyImportTest : FunctionDeclarationBodyImportTest +{ + protected override Task ArraySubscriptTestImpl() + { + var inputContents = @"int MyFunction(int* pData, int index) +{ + return pData[index]; +} +"; + + var expectedOutputContents = @" + + + + + int + + int* + + + int + + return pData[index]; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestImpl() + { + var inputContents = @"void MyFunction() +{ +} +"; + + var expectedOutputContents = @" + + + + + void + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorBasicTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int x, int y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + + int + + return x {EscapeXml(opcode)} y; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorCompareTestImpl(string opcode) + { + var inputContents = $@"bool MyFunction(int x, int y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@" + + + + + bool + + int + + + int + + return x {EscapeXml(opcode)} y; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BinaryOperatorBooleanTestImpl(string opcode) + { + var inputContents = $@"bool MyFunction(bool x, bool y) +{{ + return x {opcode} y; +}} +"; + + var expectedOutputContents = $@" + + + + + bool + + bool + + + bool + + return x {EscapeXml(opcode)} y; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BreakTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + while (true) + { + break; + } + + return 0; +} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + while (true) + {{ + break; + }} + + return 0; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallFunctionTestImpl() + { + var inputContents = @"void MyCalledFunction() +{ +} + +void MyFunction() +{ + MyCalledFunction(); +} +"; + + var expectedOutputContents = $@" + + + + + void + + + + void + MyCalledFunction(); + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallFunctionWithArgsTestImpl() + { + var inputContents = @"void MyCalledFunction(int x, int y) +{ +} + +void MyFunction() +{ + MyCalledFunction(0, 1); +} +"; + + var expectedOutputContents = $@" + + + + + void + + int + + + int + + + + + void + MyCalledFunction(0, 1); + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CaseTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + case 0: + { + return 0; + } + + case 1: + case 2: + { + return 3; + } + } + + return -1; +} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + switch (value) + {{ + case 0: + {{ + return 0; + }} + + case 1: + case 2: + {{ + return 3; + }} + }} + + return -1; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CaseNoCompoundTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + case 0: + return 0; + + case 2: + case 3: + return 5; + } + + return -1; +} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + switch (value) + {{ + case 0: + {{ + return 0; + }} + + case 2: + case 3: + {{ + return 5; + }} + }} + + return -1; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CompareMultipleEnumTestImpl() + { + var inputContents = @"enum MyEnum : int +{ + MyEnum_Value0, + MyEnum_Value1, + MyEnum_Value2, +}; + +static inline int MyFunction(MyEnum x) +{ + return x == MyEnum_Value0 || + x == MyEnum_Value1 || + x == MyEnum_Value2; +} +"; + + var expectedOutputContents = $@" + + + + int + + int + + + int + + + int + + + + + int + + MyEnum + + return (x == MyEnum_Value0 || x == MyEnum_Value1 || x == MyEnum_Value2) ? 1 : 0; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConditionalOperatorTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + return condition ? lhs : rhs; +} +"; + + var expectedOutputContents = $@" + + + + + int + + bool + + + int + + + int + + return condition ? lhs : rhs; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ContinueTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + while (true) + { + continue; + } + + return 0; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + while (true) + { + continue; + } + + return 0; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CStyleFunctionalCastTestImpl() + { + var inputContents = @"int MyFunction(float input) +{ + return (int)input; +} +"; + + var expectedOutputContents = @" + + + + + int + + float + + return (int)(input); + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxFunctionalCastTestImpl() + { + var inputContents = @"int MyFunction(float input) +{ + return int(input); +} +"; + + var expectedOutputContents = @" + + + + + int + + float + + return (int)(input); + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxConstCastTestImpl() + { + var inputContents = @"void* MyFunction(const void* input) +{ + return const_cast(input); +} +"; + + var expectedOutputContents = @" + + + + + void* + + void* + + return input; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxDynamicCastTestImpl() + { + var inputContents = @"struct MyStructA +{ + virtual void MyMethod() = 0; +}; + +struct MyStructB : MyStructA { }; + +MyStructB* MyFunction(MyStructA* input) +{ + return dynamic_cast(input); +} +"; + + var expectedOutputContents = $@" + + + + + void** + + + void + + ((delegate* unmanaged[Thiscall]<MyStructA*, void>)(lpVtbl[0]))((MyStructA*)Unsafe.AsPointer(ref this)); + + + + + + void** + + + void + + ((delegate* unmanaged[Thiscall]<MyStructB*, void>)(lpVtbl[0]))((MyStructB*)Unsafe.AsPointer(ref this)); + + + + + + MyStructB* + + MyStructA* + + return (MyStructB*)(input); + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxReinterpretCastTestImpl() + { + var inputContents = @"int* MyFunction(void* input) +{ + return reinterpret_cast(input); +} +"; + + var expectedOutputContents = @" + + + + + int* + + void* + + return (int*)(input); + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CxxStaticCastTestImpl() + { + var inputContents = @"int* MyFunction(void* input) +{ + return static_cast(input); +} +"; + + var expectedOutputContents = @" + + + + + int* + + void* + + return (int*)(input); + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DeclTestImpl() + { + var inputContents = @"\ +int MyFunction() +{ + int x = 0; + int y = 1, z = 2; + return x + y + z; +} +"; + + var expectedOutputContents = @" + + + + + int + int x = 0; + int y = 1, z = 2; + + return x + y + z; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DoTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + do + { + i++; + } + while (i < count); + + return i; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + int i = 0; + + do + { + i++; + } + while (i < count); + + return i; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DoNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + i++; + + return i; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + int i = 0; + + while (i < count) + { + i++; + } + + return i; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ForTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;;i--) + { + i += 2; + } + + for (x = 0;;x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + // x = 0; + // + // for (;; x--) + // { + // x += 2; + // } + + x = 0; + + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;; i--) + { + i += 2; + } + + for (x = 0;; x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + x = 0; + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ForNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + for (int i = 0; i < count; i--) + i += 2; + + int x; + + for (x = 0; x < count; x--) + x += 2; + + x = 0; + + for (; x < count; x--) + x += 2; + + for (int i = 0;;i--) + i += 2; + + for (x = 0;;x--) + x += 2; + + for (int i = 0; i < count;) + i++; + + for (x = 0; x < count;) + x++; + + // x = 0; + // + // for (;; x--) + // x += 2; + + x = 0; + + for (; x < count;) + x++; + + for (int i = 0;;) + i++; + + for (x = 0;;) + x++; + + for (;;) + return -1; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + for (int i = 0; i < count; i--) + { + i += 2; + } + + int x; + + for (x = 0; x < count; x--) + { + x += 2; + } + + x = 0; + for (; x < count; x--) + { + x += 2; + } + + for (int i = 0;; i--) + { + i += 2; + } + + for (x = 0;; x--) + { + x += 2; + } + + for (int i = 0; i < count;) + { + i++; + } + + for (x = 0; x < count;) + { + x++; + } + + x = 0; + for (; x < count;) + { + x++; + } + + for (int i = 0;;) + { + i++; + } + + for (x = 0;;) + { + x++; + } + + for (;;) + { + return -1; + } + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + { + return lhs; + } + + return rhs; +} +"; + + var expectedOutputContents = @" + + + + + int + + bool + + + int + + + int + + if (condition) + { + return lhs; + } + + return rhs; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + { + return lhs; + } + else + { + return rhs; + } +} +"; + + var expectedOutputContents = @" + + + + + int + + bool + + + int + + + int + + if (condition) + { + return lhs; + } + else + { + return rhs; + } + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseIfTestImpl() + { + var inputContents = @"int MyFunction(bool condition1, int a, int b, bool condition2, int c) +{ + if (condition1) + { + return a; + } + else if (condition2) + { + return b; + } + + return c; +} +"; + + var expectedOutputContents = @" + + + + + int + + bool + + + int + + + int + + + bool + + + int + + if (condition1) + { + return a; + } + else if (condition2) + { + return b; + } + + return c; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task IfElseNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(bool condition, int lhs, int rhs) +{ + if (condition) + return lhs; + else + return rhs; +} +"; + + var expectedOutputContents = @" + + + + + int + + bool + + + int + + + int + + if (condition) + { + return lhs; + } + else + { + return rhs; + } + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InitListForArrayTestImpl() + { + var inputContents = @" +void MyFunction() +{ + int x[4] = { 1, 2, 3, 4 }; + int y[4] = { 1, 2, 3 }; + int z[] = { 1, 2 }; +} +"; + + var expectedOutputContents = @" + + + + + void + int[] x = new int[4] + { + 1, + 2, + 3, + 4, + }; + int[] y = new int[4] + { + 1, + 2, + 3, + default, + }; + int[] z = new int[2] + { + 1, + 2, + }; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InitListForRecordDeclTestImpl() + { + var inputContents = @"struct MyStruct +{ + float x; + float y; + float z; + float w; +}; + +MyStruct MyFunction1() +{ + return { 1.0f, 2.0f, 3.0f, 4.0f }; +} + +MyStruct MyFunction2() +{ + return { 1.0f, 2.0f, 3.0f }; +} +"; + + var expectedOutputContents = @" + + + + + float + + + float + + + float + + + float + + + + + MyStruct + return new MyStruct + { + x = 1.0f, + y = 2.0f, + z = 3.0f, + w = 4.0f, + }; + + + MyStruct + return new MyStruct + { + x = 1.0f, + y = 2.0f, + z = 3.0f, + }; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MemberTestImpl() + { + var inputContents = @"struct MyStruct +{ + int value; +}; + +int MyFunction1(MyStruct instance) +{ + return instance.value; +} + +int MyFunction2(MyStruct* instance) +{ + return instance->value; +} +"; + + var expectedOutputContents = @" + + + + + int + + + + + int + + MyStruct + + return instance.value; + + + int + + MyStruct* + + return instance->value; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RefToPtrTestImpl() + { + var inputContents = @"struct MyStruct { + int value; +}; + +bool MyFunction(const MyStruct& lhs, const MyStruct& rhs) +{ + return lhs.value == rhs.value; +} +"; + + var expectedOutputContents = @" + + + + + int + + + + + bool + + MyStruct* + + + MyStruct* + + return lhs->value == rhs->value; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnCXXNullPtrTestImpl() + { + var inputContents = @"void* MyFunction() +{ + return nullptr; +} +"; + + var expectedOutputContents = @" + + + + + void* + return null; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnCXXBooleanLiteralTestImpl(string value) + { + var inputContents = $@"bool MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@" + + + + + bool + return {value}; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnFloatingLiteralDoubleTestImpl(string value) + { + var inputContents = $@"double MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@" + + + + + double + return {value}; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnFloatingLiteralSingleTestImpl(string value) + { + var inputContents = $@"float MyFunction() +{{ + return {value}; +}} +"; + + var expectedOutputContents = $@" + + + + + float + return {value}; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnEmptyTestImpl() + { + var inputContents = @"void MyFunction() +{ + return; +} +"; + + var expectedOutputContents = @" + + + + + void + return; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnIntegerLiteralInt32TestImpl() + { + var inputContents = @"int MyFunction() +{ + return -1; +} +"; + + var expectedOutputContents = @" + + + + + int + return -1; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task AccessUnionMemberTestImpl() + { + var inputContents = @"union MyUnion +{ + struct { int a; }; +}; + +void MyFunction() +{ + MyUnion myUnion; + myUnion.a = 10; +} +"; + + var expectedOutputContents = @" + + + + + _Anonymous_e__Struct + + + ref int + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + + + + + int + + + + + + void + MyUnion myUnion = new MyUnion(); + + myUnion.Anonymous.a = 10; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ReturnStructTestImpl() + { + var inputContents = @"struct MyStruct +{ + double r; + double g; + double b; +}; + +MyStruct MyFunction() +{ + MyStruct myStruct; + return myStruct; +} +"; + + var expectedOutputContents = @" + + + + + double + + + double + + + double + + + + + MyStruct + MyStruct myStruct = new MyStruct(); + + return myStruct; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SwitchTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + { + default: + { + return 0; + } + } +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + switch (value) + { + default: + { + return 0; + } + } + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SwitchNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int value) +{ + switch (value) + default: + { + return 0; + } + + switch (value) + default: + return 0; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + switch (value) + { + default: + { + return 0; + } + } + + switch (value) + { + default: + { + return 0; + } + } + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorAddrOfTestImpl() + { + var inputContents = @"int* MyFunction(int value) +{ + return &value; +} +"; + + var expectedOutputContents = @" + + + + + int* + + int + + return &value; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorDerefTestImpl() + { + var inputContents = @"int MyFunction(int* value) +{ + return *value; +} +"; + + var expectedOutputContents = @" + + + + + int + + int* + + return *value; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorLogicalNotTestImpl() + { + var inputContents = @"bool MyFunction(bool value) +{ + return !value; +} +"; + + var expectedOutputContents = @" + + + + + bool + + bool + + return !value; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorPostfixTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int value) +{{ + return value{opcode}; +}} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + return value{opcode}; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UnaryOperatorPrefixTestImpl(string opcode) + { + var inputContents = $@"int MyFunction(int value) +{{ + return {opcode}value; +}} +"; + + var expectedOutputContents = $@" + + + + + int + + int + + return {opcode}value; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WhileTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + { + i++; + } + + return i; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + int i = 0; + + while (i < count) + { + i++; + } + + return i; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WhileNonCompoundTestImpl() + { + var inputContents = @"int MyFunction(int count) +{ + int i = 0; + + while (i < count) + i++; + + return i; +} +"; + + var expectedOutputContents = @" + + + + + int + + int + + int i = 0; + + while (i < count) + { + i++; + } + + return i; + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionDeclarationDllImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionDeclarationDllImportTest.cs new file mode 100644 index 00000000..727ec4d0 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionDeclarationDllImportTest.cs @@ -0,0 +1,452 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultWindows_FunctionDeclarationDllImportTest : FunctionDeclarationDllImportTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @" + + + + + void + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ArrayParameterTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(const float color[4]);"; + + var expectedOutputContents = @" + + + + + void + + float* + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FunctionPointerParameterTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(void (*callback)());"; + + var expectedOutputContents = @" + + + + + void + + delegate* unmanaged[Cdecl]<void> + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NamespaceTestImpl() + { + var inputContents = @"namespace MyNamespace +{ + void MyFunction(); +}"; + + var entryPoint = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "__ZN11MyNamespace10MyFunctionEv" : "_ZN11MyNamespace10MyFunctionEv"; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + entryPoint = "?MyFunction@MyNamespace@@YAXXZ"; + } + + var expectedOutputContents = $@" + + + + + void + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TemplateParameterTestImpl(string nativeType, bool expectedNativeTypeAttr, string expectedManagedType, string expectedUsingStatement) + { + var inputContents = @$"template struct MyTemplate; + +extern ""C"" void MyFunction(MyTemplate<{nativeType}> myStruct);"; + + var expectedOutputContents = $@" + + + + + void + + MyTemplate<{expectedManagedType}> + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: new[] { "MyTemplate" }); + } + + protected override Task TemplateMemberTestImpl() + { + var inputContents = @$"template struct MyTemplate +{{ +}}; + +struct MyStruct +{{ + MyTemplate a; +}}; +"; + + var expectedOutputContents = $@" + + + + + MyTemplate<IntPtr> + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: new[] { "MyTemplate" }); + } + + protected override Task NoLibraryPathTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @" + + + + + void + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty); + } + + protected override Task WithLibraryPathTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @" + + + + + void + + + + +"; + + var withLibraryPaths = new Dictionary + { + ["MyFunction"] = "ClangSharpPInvokeGenerator" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty, withLibraryPaths: withLibraryPaths); + } + + protected override Task WithLibraryPathStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction();"; + + var expectedOutputContents = @" + + + + + void + + + + +"; + + var withLibraryPaths = new Dictionary + { + ["*"] = "ClangSharpPInvokeGenerator" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, libraryPath: string.Empty, withLibraryPaths: withLibraryPaths); + } + + protected override Task OptionalParameterTestImpl(string nativeType, string nativeInit, bool expectedNativeTypeNameAttr, string expectedManagedType, string expectedManagedInit) + { + var inputContents = $@"extern ""C"" void MyFunction({nativeType} value = {nativeInit});"; + + var expectedOutputContents = $@" + + + + + void + + {expectedManagedType} + + {expectedManagedInit} + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task OptionalParameterUnsafeTestImpl(string nativeType, string nativeInit, string expectedManagedType, string expectedManagedInit) + { + var inputContents = $@"extern ""C"" void MyFunction({nativeType} value = {nativeInit});"; + + var expectedOutputContents = $@" + + + + + void + + {expectedManagedType} + + {expectedManagedInit} + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithCallConvTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @" + + + + + void + + int + + + + void + + int + + + + + +"; + + var withCallConvs = new Dictionary { + ["MyFunction1"] = "Winapi" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithCallConvStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @" + + + + + void + + int + + + + void + + int + + + + + +"; + + var withCallConvs = new Dictionary + { + ["*"] = "Winapi" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithCallConvStarOverrideTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @" + + + + + void + + int + + + + void + + int + + + + + +"; + + var withCallConvs = new Dictionary + { + ["*"] = "Winapi", + ["MyFunction2"] = "StdCall" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withCallConvs: withCallConvs); + } + + protected override Task WithSetLastErrorTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @" + + + + + void + + int + + + + void + + int + + + + + +"; + + var withSetLastErrors = new string[] + { + "MyFunction1" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withSetLastErrors: withSetLastErrors); + } + + protected override Task WithSetLastErrorStarTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction1(int value); extern ""C"" void MyFunction2(int value);"; + + var expectedOutputContents = @" + + + + + void + + int + + + + void + + int + + + + + +"; + + var withSetLastErrors = new string[] + { + "*" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withSetLastErrors: withSetLastErrors); + } + + protected override Task SourceLocationTestImpl() + { + const string InputContents = @"extern ""C"" void MyFunction(float value);"; + + const string ExpectedOutputContents = @" + + + + + void + + float + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); + } + + protected override Task VarargsTestImpl() => Task.CompletedTask; +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionPointerDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionPointerDeclarationTest.cs new file mode 100644 index 00000000..e5342d0a --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/FunctionPointerDeclarationTest.cs @@ -0,0 +1,80 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultWindows_FunctionPointerDeclarationTest : FunctionPointerDeclarationTest +{ + protected override Task BasicTestImpl() + { + var inputContents = @"typedef void (*Callback)(); + +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task CallconvTestImpl() + { + var inputContents = @"typedef void (*Callback)() __attribute__((stdcall)); + +struct MyStruct { + Callback _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Stdcall]<void> + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerlessTypedefTestImpl() + { + var inputContents = @"typedef void (Callback)(); + +struct MyStruct { + Callback* _callback; +}; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/StructDeclarationTest.cs new file mode 100644 index 00000000..ff815cec --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/StructDeclarationTest.cs @@ -0,0 +1,1791 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using ClangSharp.Abstractions; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultWindows_StructDeclarationTest : StructDeclarationTest +{ + protected override Task IncompleteArraySizeTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} x[]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestInCModeImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}} MyStruct; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, commandlineArgs: Array.Empty()); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BitfieldTestImpl() + { + var inputContents = @"struct MyStruct1 +{ + unsigned int o0_b0_24 : 24; + unsigned int o4_b0_16 : 16; + unsigned int o4_b16_3 : 3; + int o4_b19_3 : 3; + unsigned char o8_b0_1 : 1; + int o12_b0_1 : 1; + int o12_b1_1 : 1; +}; + +struct MyStruct2 +{ + unsigned int o0_b0_1 : 1; + int x; + unsigned int o8_b0_1 : 1; +}; + +struct MyStruct3 +{ + unsigned int o0_b0_1 : 1; + unsigned int o0_b1_1 : 1; +}; +"; + + var expectedOutputContents = @" + + + + + uint + + + uint + + return _bitfield1 & 0xFFFFFFu; + + + + _bitfield1 = (_bitfield1 & ~0xFFFFFFu) | (value & 0xFFFFFFu); + + + + uint + + + uint + + return _bitfield2 & 0xFFFFu; + + + + _bitfield2 = (_bitfield2 & ~0xFFFFu) | (value & 0xFFFFu); + + + + uint + + return (_bitfield2 >> 16) & 0x7u; + + + + _bitfield2 = (_bitfield2 & ~(0x7u << 16)) | ((value & 0x7u) << 16); + + + + int + + return (int)((_bitfield2 >> 19) & 0x7u); + + + + _bitfield2 = (_bitfield2 & ~(0x7u << 19)) | (uint)((value & 0x7) << 19); + + + + byte + + + byte + + return (byte)(_bitfield3 & 0x1u); + + + + _bitfield3 = (byte)((_bitfield3 & ~0x1u) | (value & 0x1u)); + + + + int + + + int + + return _bitfield4 & 0x1; + + + + _bitfield4 = (_bitfield4 & ~0x1) | (value & 0x1); + + + + int + + return (_bitfield4 >> 1) & 0x1; + + + + _bitfield4 = (_bitfield4 & ~(0x1 << 1)) | ((value & 0x1) << 1); + + + + + + uint + + + uint + + return _bitfield1 & 0x1u; + + + + _bitfield1 = (_bitfield1 & ~0x1u) | (value & 0x1u); + + + + int + + + uint + + + uint + + return _bitfield2 & 0x1u; + + + + _bitfield2 = (_bitfield2 & ~0x1u) | (value & 0x1u); + + + + + + uint + + + uint + + return _bitfield & 0x1u; + + + + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + + + + uint + + return (_bitfield >> 1) & 0x1u; + + + + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task DeclTypeTestImpl() + { + var inputContents = @"extern ""C"" void MyFunction(); + +typedef struct +{ + decltype(&MyFunction) _callback; +} MyStruct; +"; + + var expectedOutputContents = @" + + + + + delegate* unmanaged[Cdecl]<void> + + + + + void + + + + +"; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = "typedef struct MyStruct MyStruct;"; + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyStruct" }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task FixedSizedBufferNonPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyStruct + + + + MyStruct + + + MyStruct + + + MyStruct + + + ref MyStruct + + int + + + return ref AsSpan()[index]; + + + + Span<MyStruct> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyStruct + + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + MyStruct + + + ref MyStruct + + int + + + return ref AsSpan()[index]; + + + + Span<MyStruct> + MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +typedef MyStruct MyBuffer[3]; + +struct MyOtherStruct +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyStruct + + + + MyStruct + + + MyStruct + + + MyStruct + + + ref MyStruct + + int + + + return ref AsSpan()[index]; + + + + Span<MyStruct> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} value; +}}; + +struct MyOtherStruct +{{ + MyStruct c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyStruct + + + + MyStruct + + + MyStruct + + + MyStruct + + + ref MyStruct + + int + + + return ref AsSpan()[index]; + + + + Span<MyStruct> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPointerTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + ref {expectedManagedType} + + int + + + fixed ({expectedManagedType}* pThis = &e0) + {{ + return ref pThis[index]; + }} + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyBuffer[3]; + +struct MyStruct +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task GuidTestImpl() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Non-Windows doesn't support __declspec(uuid("")) + return Task.CompletedTask; + } + + var inputContents = $@"#define DECLSPEC_UUID(x) __declspec(uuid(x)) + +struct __declspec(uuid(""00000000-0000-0000-C000-000000000046"")) MyStruct1 +{{ + int x; +}}; + +struct DECLSPEC_UUID(""00000000-0000-0000-C000-000000000047"") MyStruct2 +{{ + int x; +}}; +"; + + var expectedOutputContents = $@" + + + + + int + + + + + int + + + + + + + + +"; + + var excludedNames = new string[] { "DECLSPEC_UUID" }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task InheritanceTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + int x; + int y; +}; + +struct MyStruct1B +{ + int x; + int y; +}; + +struct MyStruct2 : MyStruct1A, MyStruct1B +{ + int z; + int w; +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + + + int + + + int + + + + + MyStruct1A + + + MyStruct1B + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task InheritanceWithNativeInheritanceAttributeTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + int x; + int y; +}; + +struct MyStruct1B +{ + int x; + int y; +}; + +struct MyStruct2 : MyStruct1A, MyStruct1B +{ + int z; + int w; +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + + + int + + + int + + + + + MyStruct1A + + + MyStruct1B + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateNativeInheritanceAttribute); + } + + protected override Task NestedAnonymousTestImpl(string nativeType, string expectedManagedType, int line, int column) + { + var inputContents = $@"typedef union {{ + {nativeType} value; +}} MyUnion; + +struct MyStruct +{{ + {nativeType} x; + {nativeType} y; + + struct + {{ + {nativeType} z; + + struct + {{ + {nativeType} value; + }} w; + + MyUnion u; + {nativeType} buffer1[4]; + MyUnion buffer2[4]; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + {expectedManagedType} + + + {expectedManagedType} + + + _Anonymous_e__Struct + + + ref {expectedManagedType} + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + + + + ref _Anonymous_e__Struct._w_e__Struct + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.w, 1)); + + + + ref MyUnion + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.u, 1)); + + + + Span<{expectedManagedType}> + + return MemoryMarshal.CreateSpan(ref Anonymous.buffer1[0], 4); + + + + Span<MyUnion> + + return Anonymous.buffer2.AsSpan(); + + + + + {expectedManagedType} + + + _w_e__Struct + + + MyUnion + + + {expectedManagedType} + + + MyUnion + + + + {expectedManagedType} + + + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + ref MyUnion + + int + + + return ref AsSpan()[index]; + + + + Span<MyUnion> + MemoryMarshal.CreateSpan(ref e0, 4); + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedAnonymousWithBitfieldTestImpl() + { + var inputContents = @"struct MyStruct +{ + int x; + int y; + + struct + { + int z; + + struct + { + int w; + int o0_b0_16 : 16; + int o0_b16_4 : 4; + }; + }; +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + _Anonymous_e__Struct + + + ref int + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + + + + ref int + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + + + + int + + return Anonymous.Anonymous.o0_b0_16; + + + Anonymous.Anonymous.o0_b0_16 = value; + + + + int + + return Anonymous.Anonymous.o0_b16_4; + + + Anonymous.Anonymous.o0_b16_4 = value; + + + + + int + + + _Anonymous_e__Struct + + + + int + + + int + + + int + + return _bitfield & 0xFFFF; + + + + _bitfield = (_bitfield & ~0xFFFF) | (value & 0xFFFF); + + + + int + + return (_bitfield >> 16) & 0xF; + + + + _bitfield = (_bitfield & ~(0xF << 16)) | ((value & 0xF) << 16); + + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + struct MyNestedStruct + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + struct MyNestedStruct + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"struct MyStruct +{ + int Equals; + int Dispose; + int GetHashCode; + int GetType; + int MemberwiseClone; + int ReferenceEquals; + int ToString; +};"; + + var expectedOutputContents = $@" + + + + + int + + + int + + + int + + + int + + + int + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoDefinitionTestImpl() + { + var inputContents = "typedef struct MyStruct MyStruct;"; + + var expectedOutputContents = $@" + + + + + +"; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + protected override Task PackTestImpl() + { + const string InputContents = @"struct MyStruct1 { + unsigned Field1; + + void* Field2; + + unsigned Field3; +}; + +#pragma pack(4) + +struct MyStruct2 { + unsigned Field1; + + void* Field2; + + unsigned Field3; +}; +"; + + var packing = Environment.Is64BitProcess ? " layout=\"Sequential\" pack=\"4\"" : string.Empty; + + var expectedOutputContents = $@" + + + + + uint + + + void* + + + uint + + + + + uint + + + void* + + + uint + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(InputContents, expectedOutputContents); + } + + protected override Task PointerToSelfTestImpl() + { + var inputContents = @"struct example_s { + example_s* next; + void* data; +};"; + + var expectedOutputContents = $@" + + + + + example_s* + + + void* + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfViaTypedefTestImpl() + { + var inputContents = @"typedef struct example_s example_t; + +struct example_s { + example_t* next; + void* data; +};"; + + var expectedOutputContents = $@" + + + + + example_s* + + + void* + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = "typedef struct _MyStruct MyStruct;"; + + var expectedOutputContents = $@" + + + + + +"; + + var remappedNames = new Dictionary { ["_MyStruct"] = "MyStruct" }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task RemapNestedAnonymousTestImpl() + { + var inputContents = @"struct MyStruct +{ + double r; + double g; + double b; + + struct + { + double a; + }; +};"; + + var expectedOutputContents = @" + + + + + double + + + double + + + double + + + _Anonymous_e__Struct + + + ref double + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + + + + + double + + + + + +"; + + var remappedNames = new Dictionary { + ["__AnonymousField_ClangUnsavedFile_L7_C5"] = "Anonymous", + ["__AnonymousRecord_ClangUnsavedFile_L7_C5"] = "_Anonymous_e__Struct" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task SkipNonDefinitionTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct MyStruct MyStruct; + +struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionPointerTestImpl() + { + var inputContents = @"typedef struct MyStruct* MyStructPtr; +typedef struct MyStruct& MyStructRef; +"; + + var expectedOutputContents = @" + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef struct MyStruct MyStruct; + +struct MyStruct +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyTypedefAlias; + +struct MyStruct +{{ + MyTypedefAlias r; + MyTypedefAlias g; + MyTypedefAlias b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UsingDeclarationTestImpl() + { + var inputContents = @"struct MyStruct1A +{ + void MyMethod() { } +}; + +struct MyStruct1B : MyStruct1A +{ + using MyStruct1A::MyMethod; +}; +"; + + var expectedOutputContents = @" + + + + + void + + + + + + void + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WithAccessSpecifierTestImpl() + { + var inputContents = @"struct MyStruct1 +{ + int Field1; + int Field2; +}; + +struct MyStruct2 +{ + int Field1; + int Field2; +}; + +struct MyStruct3 +{ + int Field1; + int Field2; +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + + + int + + + int + + + + + int + + + int + + + + +"; + + var withAccessSpecifiers = new Dictionary { + ["MyStruct1"] = AccessSpecifier.Private, + ["MyStruct2"] = AccessSpecifier.Internal, + ["Field1"] = AccessSpecifier.Private, + ["MyStruct3.Field2"] = AccessSpecifier.Internal, + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, withAccessSpecifiers: withAccessSpecifiers); + } + + protected override Task WithPackingTestImpl() + { + const string InputContents = @"struct MyStruct +{ + size_t FixedBuffer[1]; +}; +"; + + const string ExpectedOutputContents = @" + + + + + nuint + + + + nuint + + + ref nuint + + int + + + return ref AsSpan(int.MaxValue)[index]; + + + + Span<nuint> + + int + + MemoryMarshal.CreateSpan(ref e0, length); + + + + + +"; + + var withPackings = new Dictionary { + ["MyStruct"] = "CustomPackValue" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(InputContents, ExpectedOutputContents, withPackings: withPackings); + } + + protected override Task SourceLocationAttributeTestImpl() + { + const string InputContents = @"struct MyStruct +{ + int r; + int g; + int b; +}; +"; + + const string ExpectedOutputContents = @" + + + + + int + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(InputContents, ExpectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/UnionDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/UnionDeclarationTest.cs new file mode 100644 index 00000000..be2402ba --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/UnionDeclarationTest.cs @@ -0,0 +1,1339 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultWindows_UnionDeclarationTest : UnionDeclarationTest +{ + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicTestInCModeImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}} MyUnion; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, commandlineArgs: Array.Empty()); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BitfieldTestImpl() + { + var inputContents = @"union MyUnion1 +{ + unsigned int o0_b0_24 : 24; + unsigned int o4_b0_16 : 16; + unsigned int o4_b16_3 : 3; + int o4_b19_3 : 3; + unsigned char o8_b0_1 : 1; + int o12_b0_1 : 1; + int o12_b1_1 : 1; +}; + +union MyUnion2 +{ + unsigned int o0_b0_1 : 1; + int x; + unsigned int o8_b0_1 : 1; +}; + +union MyUnion3 +{ + unsigned int o0_b0_1 : 1; + unsigned int o0_b1_1 : 1; +}; +"; + + var expectedPack = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? @" pack=""1""" : ""; + + var expectedOutputContents = $@" + + + + + uint + + + uint + + return _bitfield1 & 0xFFFFFFu; + + + + _bitfield1 = (_bitfield1 & ~0xFFFFFFu) | (value & 0xFFFFFFu); + + + + uint + + + uint + + return _bitfield2 & 0xFFFFu; + + + + _bitfield2 = (_bitfield2 & ~0xFFFFu) | (value & 0xFFFFu); + + + + uint + + return (_bitfield2 >> 16) & 0x7u; + + + + _bitfield2 = (_bitfield2 & ~(0x7u << 16)) | ((value & 0x7u) << 16); + + + + int + + return (int)((_bitfield2 >> 19) & 0x7u); + + + + _bitfield2 = (_bitfield2 & ~(0x7u << 19)) | (uint)((value & 0x7) << 19); + + + + byte + + + byte + + return (byte)(_bitfield3 & 0x1u); + + + + _bitfield3 = (byte)((_bitfield3 & ~0x1u) | (value & 0x1u)); + + + + int + + + int + + return _bitfield4 & 0x1; + + + + _bitfield4 = (_bitfield4 & ~0x1) | (value & 0x1); + + + + int + + return (_bitfield4 >> 1) & 0x1; + + + + _bitfield4 = (_bitfield4 & ~(0x1 << 1)) | ((value & 0x1) << 1); + + + + + + uint + + + uint + + return _bitfield1 & 0x1u; + + + + _bitfield1 = (_bitfield1 & ~0x1u) | (value & 0x1u); + + + + int + + + uint + + + uint + + return _bitfield2 & 0x1u; + + + + _bitfield2 = (_bitfield2 & ~0x1u) | (value & 0x1u); + + + + + + uint + + + uint + + return _bitfield & 0x1u; + + + + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + + + + uint + + return (_bitfield >> 1) & 0x1u; + + + + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ExcludeTestImpl() + { + var inputContents = "typedef union MyUnion MyUnion;"; + var expectedOutputContents = string.Empty; + + var excludedNames = new string[] { "MyUnion" }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task FixedSizedBufferNonPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyUnion + + + + MyUnion + + + MyUnion + + + MyUnion + + + ref MyUnion + + int + + + return ref AsSpan()[index]; + + + + Span<MyUnion> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyUnion + + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + MyUnion + + + ref MyUnion + + int + + + return ref AsSpan()[index]; + + + + Span<MyUnion> + MemoryMarshal.CreateSpan(ref e0_0_0_0, 24); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +typedef MyUnion MyBuffer[3]; + +union MyOtherUnion +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyUnion + + + + MyUnion + + + MyUnion + + + MyUnion + + + ref MyUnion + + int + + + return ref AsSpan()[index]; + + + + Span<MyUnion> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferNonPrimitiveWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} value; +}}; + +union MyOtherUnion +{{ + MyUnion c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + MyUnion + + + + MyUnion + + + MyUnion + + + MyUnion + + + ref MyUnion + + int + + + return ref AsSpan()[index]; + + + + Span<MyUnion> + MemoryMarshal.CreateSpan(ref e0, 3); + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPointerTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + ref {expectedManagedType} + + int + + + fixed ({expectedManagedType}* pThis = &e0) + {{ + return ref pThis[index]; + }} + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[3]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveMultidimensionalTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} c[2][1][3][4]; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task FixedSizedBufferPrimitiveTypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyBuffer[3]; + +union MyUnion +{{ + MyBuffer c; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + protected override Task GuidTestImpl() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Non-Windows doesn't support __declspec(uuid("")) + return Task.CompletedTask; + } + + var inputContents = $@"#define DECLSPEC_UUID(x) __declspec(uuid(x)) + +union __declspec(uuid(""00000000-0000-0000-C000-000000000046"")) MyUnion1 +{{ + int x; +}}; + +union DECLSPEC_UUID(""00000000-0000-0000-C000-000000000047"") MyUnion2 +{{ + int x; +}}; +"; + + var expectedOutputContents = $@" + + + + + int + + + + + int + + + + + + + + +"; + + var excludedNames = new string[] { "DECLSPEC_UUID" }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task NestedAnonymousTestImpl(string nativeType, string expectedManagedType, int line, int column) + { + var inputContents = $@"typedef struct {{ + {nativeType} value; +}} MyStruct; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union + {{ + {nativeType} a; + + MyStruct s; + + {nativeType} buffer[4]; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + _Anonymous_e__Union + + + ref {expectedManagedType} + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + + + + ref MyStruct + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.s, 1)); + + + + Span<{expectedManagedType}> + + return MemoryMarshal.CreateSpan(ref Anonymous.buffer[0], 4); + + + + + {expectedManagedType} + + + MyStruct + + + {expectedManagedType} + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedAnonymousWithBitfieldTestImpl() + { + var inputContents = @"union MyUnion +{ + int x; + int y; + + union + { + int z; + + union + { + int w; + int o0_b0_16 : 16; + int o0_b16_4 : 4; + }; + }; +}; +"; + + var expectedOutputContents = @" + + + + + int + + + int + + + _Anonymous_e__Union + + + ref int + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + + + + ref int + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + + + + int + + return Anonymous.Anonymous.o0_b0_16; + + + Anonymous.Anonymous.o0_b0_16 = value; + + + + int + + return Anonymous.Anonymous.o0_b16_4; + + + Anonymous.Anonymous.o0_b16_4 = value; + + + + + int + + + _Anonymous_e__Union + + + + int + + + int + + + int + + return _bitfield & 0xFFFF; + + + + _bitfield = (_bitfield & ~0xFFFF) | (value & 0xFFFF); + + + + int + + return (_bitfield >> 16) & 0xF; + + + + _bitfield = (_bitfield & ~(0xF << 16)) | ((value & 0xF) << 16); + + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + + protected override Task NestedTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union MyNestedUnion + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NestedWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + + union MyNestedUnion + {{ + {nativeType} r; + {nativeType} g; + {nativeType} b; + {nativeType} a; + }}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NewKeywordTestImpl() + { + var inputContents = @"union MyUnion +{ + int Equals; + int Dispose; + int GetHashCode; + int GetType; + int MemberwiseClone; + int ReferenceEquals; + int ToString; +};"; + + var expectedOutputContents = $@" + + + + + int + + + int + + + int + + + int + + + int + + + int + + + int + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoDefinitionTestImpl() + { + var inputContents = "typedef union MyUnion MyUnion;"; + + var expectedOutputContents = $@" + + + + + +"; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfTestImpl() + { + var inputContents = @"union example_s { + example_s* next; + void* data; +};"; + + var expectedOutputContents = $@" + + + + + example_s* + + + void* + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task PointerToSelfViaTypedefTestImpl() + { + var inputContents = @"typedef union example_s example_t; + +union example_s { + example_t* next; + void* data; +};"; + + var expectedOutputContents = $@" + + + + + example_s* + + + void* + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task RemapTestImpl() + { + var inputContents = "typedef union _MyUnion MyUnion;"; + + var expectedOutputContents = $@" + + + + + +"; + + var remappedNames = new Dictionary { ["_MyUnion"] = "MyUnion" }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task RemapNestedAnonymousTestImpl() + { + var inputContents = @"union MyUnion +{ + double r; + double g; + double b; + + union + { + double a; + }; +};"; + + var expectedOutputContents = @" + + + + + double + + + double + + + double + + + _Anonymous_e__Union + + + ref double + + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + + + + + double + + + + + +"; + + var remappedNames = new Dictionary { + ["__AnonymousField_ClangUnsavedFile_L7_C5"] = "Anonymous", + ["__AnonymousRecord_ClangUnsavedFile_L7_C5"] = "_Anonymous_e__Union" + }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, remappedNames: remappedNames); + } + + protected override Task SkipNonDefinitionTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union MyUnion MyUnion; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionPointerTestImpl() + { + var inputContents = @"typedef union MyUnion* MyUnionPtr; +typedef union MyUnion& MyUnionRef; +"; + + var expectedOutputContents = @" + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task SkipNonDefinitionWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef union MyUnion MyUnion; + +union MyUnion +{{ + {nativeType} r; + {nativeType} g; + {nativeType} b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task TypedefTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"typedef {nativeType} MyTypedefAlias; + +union MyUnion +{{ + MyTypedefAlias r; + MyTypedefAlias g; + MyTypedefAlias b; +}}; +"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + + {expectedManagedType} + + + {expectedManagedType} + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/VarDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/VarDeclarationTest.cs new file mode 100644 index 00000000..6fa4d3c5 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/VarDeclarationTest.cs @@ -0,0 +1,533 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ClangSharp.UnitTests; + +public sealed class XmlDefaultWindows_VarDeclarationTest : VarDeclarationTest +{ + protected override Task BasicTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"{nativeType} MyVariable = 0;"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + 0 + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task BasicWithNativeTypeNameTestImpl(string nativeType, string expectedManagedType) + { + var inputContents = $@"{nativeType} MyVariable = 0;"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + 0 + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task GuidMacroTestImpl() + { + var inputContents = $@"struct GUID {{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +}}; + +const GUID IID_IUnknown = {{ 0x00000000, 0x0000, 0x0000, {{ 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }} }}; +"; + + var expectedOutputContents = $@" + + + + + Guid + + new Guid(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46) + + + + + +"; + var excludedNames = new string[] { "GUID" }; + var remappedNames = new Dictionary { ["GUID"] = "Guid" }; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames, remappedNames: remappedNames); + } + + protected override Task MacroTestImpl(string nativeValue, string expectedManagedType, string expectedManagedValue) + { + var inputContents = $@"#define MyMacro1 {nativeValue} +#define MyMacro2 MyMacro1"; + + var expectedOutputContents = $@" + + + + + {expectedManagedType} + + {expectedManagedValue} + + + + {expectedManagedType} + + {expectedManagedValue} + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MultilineMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 0 + \ +1"; + + var expectedOutputContents = $@" + + + + + int + + 0 + 1 + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task NoInitializerTestImpl(string nativeType) + { + var inputContents = $@"{nativeType} MyVariable;"; + var expectedOutputContents = ""; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task Utf8StringLiteralMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 ""Test"""; + + var expectedOutputContents = $@" + + + + + ReadOnlySpan<byte> + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task Utf16StringLiteralMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 u""Test"""; + + var expectedOutputContents = $@" + + + + + string + + ""Test"" + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WideStringLiteralConstTestImpl() + { + var inputContents = $@"const wchar_t MyConst1[] = L""Test""; +const wchar_t* MyConst2 = L""Test""; +const wchar_t* const MyConst3 = L""Test"";"; + + var expectedOutputContents = $@" + + + + + string + + ""Test"" + + + + string + + ""Test"" + + + + string + + ""Test"" + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StringLiteralConstTestImpl() + { + var inputContents = $@"const char MyConst1[] = ""Test""; +const char* MyConst2 = ""Test""; +const char* const MyConst3 = ""Test"";"; + + var expectedOutputContents = $@" + + + + + ReadOnlySpan<byte> + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + byte[] + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + ReadOnlySpan<byte> + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task WideStringLiteralStaticConstTestImpl() + { + var inputContents = $@"static const wchar_t MyConst1[] = L""Test""; +static const wchar_t* MyConst2 = L""Test""; +static const wchar_t* const MyConst3 = L""Test"";"; + + var expectedOutputContents = $@" + + + + + string + + ""Test"" + + + + string + + ""Test"" + + + + string + + ""Test"" + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task StringLiteralStaticConstTestImpl() + { + var inputContents = $@"static const char MyConst1[] = ""Test""; +static const char* MyConst2 = ""Test""; +static const char* const MyConst3 = ""Test"";"; + + var expectedOutputContents = $@" + + + + + ReadOnlySpan<byte> + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + byte[] + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + ReadOnlySpan<byte> + + new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedConversionMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 (long)0x80000000L +#define MyMacro2 (int)0x80000000"; + + var expectedOutputContents = $@" + + + + + int + + + + (int)(0x80000000) + + + + + + int + + + + (int)(0x80000000) + + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedFunctionLikeCastMacroTestImpl() + { + var inputContents = $@"#define MyMacro1 unsigned(-1)"; + + var expectedOutputContents = $@" + + + + + uint + + + + (uint)(-1) + + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedConversionMacroTest2Impl() + { + var inputContents = $@"#define MyMacro1(x, y, z) ((int)(((unsigned long)(x)<<31) | ((unsigned long)(y)<<16) | ((unsigned long)(z)))) +#define MyMacro2(n) MyMacro1(1, 2, n) +#define MyMacro3 MyMacro2(3)"; + + var expectedOutputContents = $@" + + + + + int + + + ((int)(((uint)(1) << 31) | ((uint)(2) << 16) | ((uint)(3)))) + + + + + + +"; + + var excludedNames = new string[] { "MyMacro1", "MyMacro2" }; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, excludedNames: excludedNames); + } + + protected override Task UncheckedPointerMacroTestImpl() + { + var inputContents = $@"#define Macro1 ((int*) -1)"; + + var expectedOutputContents = $@" + + + + + int* + + + ((int*)(-1)) + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task UncheckedReinterpretCastMacroTestImpl() + { + var inputContents = $@"#define Macro1 reinterpret_cast(-1)"; + + var expectedOutputContents = $@" + + + + + int* + + + + (int*)(-1) + + + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task MultidimensionlArrayTestImpl() + { + var inputContents = $@"const int MyArray[2][2] = {{ {{ 0, 1 }}, {{ 2, 3 }} }};"; + + var expectedOutputContents = $@" + + + + + int[][] + + new int[2][] + {{ + new int[2] + {{ + 0, + 1, + }}, + new int[2] + {{ + 2, + 3, + }}, + }} + + + + + +"; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents); + } + + protected override Task ConditionalDefineConstTestImpl() + { + var inputContents = @"typedef int TESTRESULT; +#define TESTRESULT_FROM_WIN32(x) ((TESTRESULT)(x) <= 0 ? ((TESTRESULT)(x)) : ((TESTRESULT) (((x) & 0x0000FFFF) | (7 << 16) | 0x80000000))) +#define ADDRESS_IN_USE TESTRESULT_FROM_WIN32(10048)"; + + var expectedOutputContents = $@" + + + + + int + + + ((int)(10048) <= 0 ? ((int)(10048)) : ((int)(((10048) & 0x0000FFFF) | (7 << 16) | 0x80000000))) + + + + + + +"; + var diagnostics = new Diagnostic[] { new Diagnostic(DiagnosticLevel.Warning, "Function like macro definition records are not supported: 'TESTRESULT_FROM_WIN32'. Generated bindings may be incomplete.", "Line 2, Column 9 in ClangUnsavedFile.h") }; + + return ValidateGeneratedXmlDefaultWindowsBindingsAsync(inputContents, expectedOutputContents, expectedDiagnostics: diagnostics); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/FunctionDeclarationBodyImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/FunctionDeclarationBodyImportTest.cs index fc1f578e..7a267db0 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/FunctionDeclarationBodyImportTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/FunctionDeclarationBodyImportTest.cs @@ -1616,7 +1616,7 @@ void MyFunction() ref int - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/StructDeclarationTest.cs index 6778c6a6..a01bb085 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/StructDeclarationTest.cs @@ -960,19 +960,19 @@ struct MyStruct ref {expectedManagedType} - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; ref _Anonymous_e__Struct._w_e__Struct - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.w, 1)); + return ref Anonymous.w; ref MyUnion - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.u, 1)); + return ref Anonymous.u; @@ -1081,13 +1081,13 @@ protected override Task NestedAnonymousWithBitfieldTestImpl() ref int - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; ref int - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + return ref Anonymous.Anonymous.w; @@ -1473,7 +1473,7 @@ protected override Task RemapNestedAnonymousTestImpl() ref double - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/UnionDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/UnionDeclarationTest.cs index bb6e248c..e54b9725 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/UnionDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/UnionDeclarationTest.cs @@ -785,13 +785,13 @@ union MyUnion ref {expectedManagedType} - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; ref MyStruct - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.s, 1)); + return ref Anonymous.s; @@ -856,13 +856,13 @@ protected override Task NestedAnonymousWithBitfieldTestImpl() ref int - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; ref int - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + return ref Anonymous.Anonymous.w; @@ -1195,7 +1195,7 @@ protected override Task RemapNestedAnonymousTestImpl() ref double - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/VarDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/VarDeclarationTest.cs index 5db9074c..802a1b04 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/VarDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/VarDeclarationTest.cs @@ -153,7 +153,7 @@ protected override Task Utf8StringLiteralMacroTestImpl() ReadOnlySpan<byte> - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8 @@ -197,7 +197,7 @@ protected override Task WideStringLiteralConstTestImpl() - uint[] + ReadOnlySpan<uint> new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }} @@ -209,7 +209,7 @@ protected override Task WideStringLiteralConstTestImpl() - uint[] + ReadOnlySpan<uint> new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }} @@ -235,19 +235,19 @@ protected override Task StringLiteralConstTestImpl() ReadOnlySpan<byte> - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8 byte[] - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8.ToArray() ReadOnlySpan<byte> - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8 @@ -269,7 +269,7 @@ protected override Task WideStringLiteralStaticConstTestImpl() - uint[] + ReadOnlySpan<uint> new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }} @@ -281,7 +281,7 @@ protected override Task WideStringLiteralStaticConstTestImpl() - uint[] + ReadOnlySpan<uint> new uint[] {{ 0x00000054, 0x00000065, 0x00000073, 0x00000074, 0x00000000 }} @@ -307,19 +307,19 @@ protected override Task StringLiteralStaticConstTestImpl() ReadOnlySpan<byte> - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8 byte[] - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8.ToArray() ReadOnlySpan<byte> - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8 diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/FunctionDeclarationBodyImportTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/FunctionDeclarationBodyImportTest.cs index ba49c8a5..4677b05a 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/FunctionDeclarationBodyImportTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/FunctionDeclarationBodyImportTest.cs @@ -1616,7 +1616,7 @@ void MyFunction() ref int - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/StructDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/StructDeclarationTest.cs index 205e1ed0..61c6b3c9 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/StructDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/StructDeclarationTest.cs @@ -966,19 +966,19 @@ struct MyStruct ref {expectedManagedType} - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; ref _Anonymous_e__Struct._w_e__Struct - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.w, 1)); + return ref Anonymous.w; ref MyUnion - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.u, 1)); + return ref Anonymous.u; @@ -1087,13 +1087,13 @@ protected override Task NestedAnonymousWithBitfieldTestImpl() ref int - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; ref int - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + return ref Anonymous.Anonymous.w; @@ -1479,7 +1479,7 @@ protected override Task RemapNestedAnonymousTestImpl() ref double - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/UnionDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/UnionDeclarationTest.cs index 72f7860a..6b228cd5 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/UnionDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/UnionDeclarationTest.cs @@ -791,13 +791,13 @@ union MyUnion ref {expectedManagedType} - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; ref MyStruct - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.s, 1)); + return ref Anonymous.s; @@ -862,13 +862,13 @@ protected override Task NestedAnonymousWithBitfieldTestImpl() ref int - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.z, 1)); + return ref Anonymous.z; ref int - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.Anonymous.w, 1)); + return ref Anonymous.Anonymous.w; @@ -1201,7 +1201,7 @@ protected override Task RemapNestedAnonymousTestImpl() ref double - return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.a, 1)); + return ref Anonymous.a; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/VarDeclarationTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/VarDeclarationTest.cs index 6e564c40..44835beb 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/VarDeclarationTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/VarDeclarationTest.cs @@ -1,3 +1,4 @@ + // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. using System.Collections.Generic; @@ -153,7 +154,7 @@ protected override Task Utf8StringLiteralMacroTestImpl() ReadOnlySpan<byte> - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8 @@ -235,19 +236,19 @@ protected override Task StringLiteralConstTestImpl() ReadOnlySpan<byte> - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8 byte[] - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8.ToArray() ReadOnlySpan<byte> - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8 @@ -307,19 +308,19 @@ protected override Task StringLiteralStaticConstTestImpl() ReadOnlySpan<byte> - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8 byte[] - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8.ToArray() ReadOnlySpan<byte> - new byte[] {{ 0x54, 0x65, 0x73, 0x74, 0x00 }} + ""Test""u8 From 4930f4bb6bf3732bf5f9d78d2cd8a9d12f2dda95 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Fri, 3 Mar 2023 14:28:09 -0800 Subject: [PATCH 4/4] Ensure the README is up to date with the new codegen options --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77f1bbab..9a67eb2b 100644 --- a/README.md +++ b/README.md @@ -181,8 +181,9 @@ The available configuration options (visible with `-c help`) are: 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 6/C# 10. - preview-codegen Bindings should be generated for the latest preview version of .NET/C#. This is currently .NET 7/C# 11. + default-codegen Bindings should be generated for the current LTS version of .NET/C#. This is currently .NET 6/C# 10. + latest-codegen Bindings should be generated for the current STS version of .NET/C#. This is currently .NET 7/C# 11. + preview-codegen Bindings should be generated for the preview version of .NET/C#. This is currently .NET 8/C# 12. 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.