diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Close.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Close.cs index e63c552ec..c26564af3 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Close.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.Close.cs @@ -286,7 +286,10 @@ public void Close() if (_config.OutputMode == PInvokeGeneratorOutputMode.CSharp) { - sw.WriteLine('}'); + if (!_config.GenerateFileScopedNamespaces) + { + sw.WriteLine('}'); + } } else if (_config.OutputMode == PInvokeGeneratorOutputMode.Xml) { @@ -299,7 +302,7 @@ public void Close() using var tsw = new StreamWriter(testStream, s_defaultStreamWriterEncoding, DefaultStreamWriterBufferSize, leaveStreamOpen); tsw.NewLine = "\n"; - if (_config.OutputMode == PInvokeGeneratorOutputMode.CSharp) + if ((_config.OutputMode == PInvokeGeneratorOutputMode.CSharp) && !_config.GenerateFileScopedNamespaces) { tsw.WriteLine('}'); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/FileScopedNamespaceTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/FileScopedNamespaceTest.cs new file mode 100644 index 000000000..9afe9e635 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/FileScopedNamespaceTest.cs @@ -0,0 +1,58 @@ +// 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; +using NUnit.Framework; + +namespace ClangSharp.UnitTests; + +/// +/// Regression test for https://github.com/dotnet/ClangSharp/issues/555. +/// When generate-file-scoped-namespaces is used with a single output file, no namespace +/// opening brace is emitted, so no closing brace must be emitted either. +/// +[Platform("win")] +public sealed class FileScopedNamespaceTest : PInvokeGeneratorTest +{ + [Test] + public Task MethodClassHasNoTrailingBrace() + { + 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 ValidateGeneratedCSharpLatestWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateFileScopedNamespaces); + } + + [Test] + public Task StructHasNoTrailingBrace() + { + var inputContents = @"struct Point +{ + int x; + int y; +}; +"; + + var expectedOutputContents = @"namespace ClangSharp.Test; + +public partial struct Point +{ + public int x; + + public int y; +} +"; + + return ValidateGeneratedCSharpLatestWindowsBindingsAsync(inputContents, expectedOutputContents, PInvokeGeneratorConfigurationOptions.GenerateFileScopedNamespaces); + } +}