From 58eadbc00e351983fec532416b9700c532caa686 Mon Sep 17 00:00:00 2001 From: Davide Lettieri Date: Sun, 12 Oct 2025 09:07:31 +0200 Subject: [PATCH 1/5] feat: add support for single quote digits separator C++ single quote digits separator is now converted to underscore writing numeral literals --- .../CSharp/CSharpOutputBuilder.cs | 17 +++++++++ .../PInvokeGenerator.VisitStmt.cs | 12 +++--- .../Base/DigitsSeparatorTest.cs | 17 +++++++++ .../DigitsSeparatorTest.cs | 33 ++++++++++++++++ .../DigitsSeparatorTest.cs | 33 ++++++++++++++++ .../CSharpDefaultUnix/DigitsSeparatorTest.cs | 35 +++++++++++++++++ .../DigitsSeparatorTest.cs | 33 ++++++++++++++++ .../CSharpLatestUnix/DigitsSeparatorTest.cs | 33 ++++++++++++++++ .../DigitsSeparatorTest.cs | 33 ++++++++++++++++ .../CSharpPreviewUnix/DigitsSeparatorTest.cs | 33 ++++++++++++++++ .../DigitsSeparatorTest.cs | 33 ++++++++++++++++ .../XmlCompatibleUnix/DigitsSeparatorTest.cs | 38 +++++++++++++++++++ .../DigitsSeparatorTest.cs | 38 +++++++++++++++++++ .../XmlDefaultUnix/DigitsSeparatorTest.cs | 38 +++++++++++++++++++ .../XmlDefaultWindows/DigitsSeparatorTest.cs | 37 ++++++++++++++++++ .../XmlLatestUnix/DigitsSeparatorTest.cs | 37 ++++++++++++++++++ .../XmlLatestWindows/DigitsSeparatorTest.cs | 38 +++++++++++++++++++ .../XmlPreviewUnix/DigitsSeparatorTest.cs | 38 +++++++++++++++++++ .../XmlPreviewWindows/DigitsSeparatorTest.cs | 38 +++++++++++++++++++ 19 files changed, 608 insertions(+), 6 deletions(-) create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/Base/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewUnix/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewWindows/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewUnix/DigitsSeparatorTest.cs create mode 100644 tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewWindows/DigitsSeparatorTest.cs diff --git a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs index f6d52daa..55dacddf 100644 --- a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs +++ b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Globalization; using System.Text; +using ClangSharp.Abstractions; namespace ClangSharp.CSharp; @@ -129,6 +130,22 @@ public void WriteLabel(string name) WriteLine(':'); } + public void WriteNumberLiteral(ReadOnlySpan value) + { + for (var i = 0; i < value.Length; i++) + { + var c = value[i]; + if (c == '\'') + { + Write('_'); + } + else + { + Write(c); + } + } + } + public void WriteLine(T value) { Write(value); diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs index 5eaf6372..a8919c77 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs @@ -265,7 +265,7 @@ private void VisitCallExpr(CallExpr callExpr) outputBuilder.AddUsingDirective("System.Runtime.CompilerServices"); outputBuilder.Write("Unsafe.CopyBlockUnaligned"); } - + VisitArgs(callExpr, args); break; } @@ -1163,7 +1163,7 @@ private void VisitExplicitCastExpr(ExplicitCastExpr explicitCastExpr) { var cursorName = GetCursorName(varDecl); - if (cursorName.StartsWith("ClangSharpMacro_", StringComparison.Ordinal) && _config.WithTransparentStructs.TryGetValue(typeName, out var transparentStruct)) + if (cursorName.StartsWith("ClangSharpMacro_", StringComparison.Ordinal) && _config.WithTransparentStructs.TryGetValue(typeName, out var transparentStruct)) { if (!IsPrimitiveValue(explicitCastExpr, type) || IsConstant(typeName, varDecl.Init)) { @@ -1201,12 +1201,12 @@ private void VisitFloatingLiteral(FloatingLiteral floatingLiteral) var outputBuilder = StartCSharpCode(); if (floatingLiteral.ValueString.EndsWith(".f", StringComparison.Ordinal)) { - outputBuilder.Write(floatingLiteral.ValueString.AsSpan()[..^1]); + outputBuilder.WriteNumberLiteral(floatingLiteral.ValueString.AsSpan()[..^1]); outputBuilder.Write("0f"); } else { - outputBuilder.Write(floatingLiteral.ValueString); + outputBuilder.WriteNumberLiteral(floatingLiteral.ValueString); if (floatingLiteral.ValueString.EndsWith('.')) { @@ -2060,9 +2060,9 @@ private void VisitIntegerLiteral(IntegerLiteral integerLiteral) { valueString = valueString[..^1]; } - + var outputBuilder = StartCSharpCode(); - outputBuilder.Write(valueString); + outputBuilder.WriteNumberLiteral(valueString); outputBuilder.Write(valueSuffix); StopCSharpCode(); } diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/DigitsSeparatorTest.cs new file mode 100644 index 00000000..baffbb92 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/Base/DigitsSeparatorTest.cs @@ -0,0 +1,17 @@ +// Copyright © Tanner Gooding and Contributors. 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; + +public abstract class DigitsSeparatorTest : PInvokeGeneratorTest +{ + [TestCase("int", "1'024", "1_024")] + [TestCase("int", "1'000'001", "1_000_001")] + [TestCase("float", "1'024", "1_024")] + [TestCase("float", "1'024.0", "1_024.0")] + public Task StaticConstExprTest(string type, string nativeValue, string expectedValue) => StaticConstExprTestImpl(type, nativeValue, expectedValue); + + protected abstract Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue); +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/DigitsSeparatorTest.cs new file mode 100644 index 00000000..ea8e89a6 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/DigitsSeparatorTest.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.CSharpCompatibleUnix; + +[Platform("unix")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyClass + {{ + [NativeTypeName(""const {type}"")] + private const {type} x = {expectedValue}; + }} +}} +"; + + return ValidateGeneratedCSharpCompatibleUnixBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/DigitsSeparatorTest.cs new file mode 100644 index 00000000..ba1b7f21 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/DigitsSeparatorTest.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.CSharpCompatibleWindows; + +[Platform("win")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyClass + {{ + [NativeTypeName(""const {type}"")] + private const {type} x = {expectedValue}; + }} +}} +"; + + return ValidateGeneratedCSharpCompatibleWindowsBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/DigitsSeparatorTest.cs new file mode 100644 index 00000000..91a4ab4f --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultUnix/DigitsSeparatorTest.cs @@ -0,0 +1,35 @@ +// Copyright © Tanner Gooding and Contributors. 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.CSharpDefaultUnix; + +[Platform("unix")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyClass + {{ + [NativeTypeName(""const {type}"")] + private const {type} x = {expectedValue}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultUnixBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DigitsSeparatorTest.cs new file mode 100644 index 00000000..4713669d --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DigitsSeparatorTest.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.CSharpDefaultWindows; + +[Platform("win")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyClass + {{ + [NativeTypeName(""const {type}"")] + private const {type} x = {expectedValue}; + }} +}} +"; + + return ValidateGeneratedCSharpDefaultWindowsBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/DigitsSeparatorTest.cs new file mode 100644 index 00000000..0131f753 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/DigitsSeparatorTest.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.CSharpLatestUnix; + +[Platform("unix")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyClass + {{ + [NativeTypeName(""const {type}"")] + private const {type} x = {expectedValue}; + }} +}} +"; + + return ValidateGeneratedCSharpLatestUnixBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/DigitsSeparatorTest.cs new file mode 100644 index 00000000..c4fa75e7 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/DigitsSeparatorTest.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.CSharpLatestWindows; + +[Platform("win")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyClass + {{ + [NativeTypeName(""const {type}"")] + private const {type} x = {expectedValue}; + }} +}} +"; + + return ValidateGeneratedCSharpLatestWindowsBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewUnix/DigitsSeparatorTest.cs new file mode 100644 index 00000000..efc48808 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewUnix/DigitsSeparatorTest.cs @@ -0,0 +1,33 @@ + using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.CSharpPreviewUnix; + +[Platform("unix")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyClass + {{ + [NativeTypeName(""const {type}"")] + private const {type} x = {expectedValue}; + }} +}} +"; + + return ValidateGeneratedCSharpPreviewUnixBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewWindows/DigitsSeparatorTest.cs new file mode 100644 index 00000000..4ded8733 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewWindows/DigitsSeparatorTest.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.CSharpPreviewWindows; + +[Platform("win")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@"namespace ClangSharp.Test +{{ + public partial struct MyClass + {{ + [NativeTypeName(""const {type}"")] + private const {type} x = {expectedValue}; + }} +}} +"; + + return ValidateGeneratedCSharpPreviewWindowsBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/DigitsSeparatorTest.cs new file mode 100644 index 00000000..1b712db3 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/DigitsSeparatorTest.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.XmlCompatibleUnix; + +[Platform("unix")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {type} + + {expectedValue} + + + + + +"; + + return ValidateGeneratedXmlCompatibleUnixBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/DigitsSeparatorTest.cs new file mode 100644 index 00000000..c407a617 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/DigitsSeparatorTest.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.XmlCompatibleWindows; + +[Platform("win")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {type} + + {expectedValue} + + + + + +"; + + return ValidateGeneratedXmlCompatibleWindowsBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DigitsSeparatorTest.cs new file mode 100644 index 00000000..bac28eff --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DigitsSeparatorTest.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.XmlDefaultUnix; + +[Platform("unix")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {type} + + {expectedValue} + + + + + +"; + + return ValidateGeneratedXmlDefaultUnixBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DigitsSeparatorTest.cs new file mode 100644 index 00000000..80c17291 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DigitsSeparatorTest.cs @@ -0,0 +1,37 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.XmlDefaultWindows; + +[Platform("win")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {type} + + {expectedValue} + + + + + +"; + return ValidateGeneratedXmlDefaultWindowsBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/DigitsSeparatorTest.cs new file mode 100644 index 00000000..5f48f8e8 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/DigitsSeparatorTest.cs @@ -0,0 +1,37 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.XmlLatestUnix; + +[Platform("unix")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {type} + + {expectedValue} + + + + + +"; + return ValidateGeneratedXmlLatestUnixBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/DigitsSeparatorTest.cs new file mode 100644 index 00000000..ba3a9d94 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/DigitsSeparatorTest.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.XmlLatestWindows; + +[Platform("win")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {type} + + {expectedValue} + + + + + +"; + + return ValidateGeneratedXmlLatestWindowsBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewUnix/DigitsSeparatorTest.cs new file mode 100644 index 00000000..89235fe8 --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewUnix/DigitsSeparatorTest.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.XmlPreviewUnix; + +[Platform("unix")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {type} + + {expectedValue} + + + + + +"; + + return ValidateGeneratedXmlPreviewUnixBindingsAsync( + inputContents, + expectedOutputContents); + } +} diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewWindows/DigitsSeparatorTest.cs new file mode 100644 index 00000000..32df0cdd --- /dev/null +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewWindows/DigitsSeparatorTest.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using NUnit.Framework; + +namespace ClangSharp.UnitTests.XmlPreviewWindows; + +[Platform("win")] +public sealed class DigitsSeparatorTest : UnitTests.DigitsSeparatorTest +{ + protected override Task StaticConstExprTestImpl(string type, string nativeValue, string expectedValue) + { + var inputContents = $@"class MyClass +{{ + private: + + static constexpr {type} x = {nativeValue}; +}}; +"; + + var expectedOutputContents = $@" + + + + + {type} + + {expectedValue} + + + + + +"; + + return ValidateGeneratedXmlPreviewWindowsBindingsAsync( + inputContents, + expectedOutputContents); + } +} From 85d84aa2bddebe177f1726acdbb5aff03cc54981 Mon Sep 17 00:00:00 2001 From: Davide Lettieri Date: Sun, 12 Oct 2025 09:20:18 +0200 Subject: [PATCH 2/5] fix: add copyright header to new files --- .../CSharpCompatibleUnix/DigitsSeparatorTest.cs | 2 ++ .../CSharpCompatibleWindows/DigitsSeparatorTest.cs | 2 ++ .../CSharpDefaultWindows/DigitsSeparatorTest.cs | 2 ++ .../CSharpLatestUnix/DigitsSeparatorTest.cs | 2 ++ .../CSharpLatestWindows/DigitsSeparatorTest.cs | 2 ++ .../CSharpPreviewUnix/DigitsSeparatorTest.cs | 4 +++- .../CSharpPreviewWindows/DigitsSeparatorTest.cs | 2 ++ .../XmlCompatibleUnix/DigitsSeparatorTest.cs | 2 ++ .../XmlCompatibleWindows/DigitsSeparatorTest.cs | 2 ++ .../XmlDefaultUnix/DigitsSeparatorTest.cs | 2 ++ .../XmlDefaultWindows/DigitsSeparatorTest.cs | 2 ++ .../XmlLatestUnix/DigitsSeparatorTest.cs | 2 ++ .../XmlLatestWindows/DigitsSeparatorTest.cs | 2 ++ .../XmlPreviewUnix/DigitsSeparatorTest.cs | 2 ++ .../XmlPreviewWindows/DigitsSeparatorTest.cs | 2 ++ 15 files changed, 31 insertions(+), 1 deletion(-) diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/DigitsSeparatorTest.cs index ea8e89a6..b415d8c1 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleUnix/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/DigitsSeparatorTest.cs index ba1b7f21..0301621b 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpCompatibleWindows/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DigitsSeparatorTest.cs index 4713669d..c54271e8 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpDefaultWindows/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/DigitsSeparatorTest.cs index 0131f753..b835ab0e 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestUnix/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/DigitsSeparatorTest.cs index c4fa75e7..a1d1fd84 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpLatestWindows/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewUnix/DigitsSeparatorTest.cs index efc48808..17dd8cc7 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewUnix/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewUnix/DigitsSeparatorTest.cs @@ -1,4 +1,6 @@ - using System.Threading.Tasks; +// Copyright © Tanner Gooding and Contributors. 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.CSharpPreviewUnix; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewWindows/DigitsSeparatorTest.cs index 4ded8733..191823be 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewWindows/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/CSharpPreviewWindows/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/DigitsSeparatorTest.cs index 1b712db3..81b04cc5 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleUnix/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/DigitsSeparatorTest.cs index c407a617..ba97af4f 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlCompatibleWindows/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DigitsSeparatorTest.cs index bac28eff..156044c1 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultUnix/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DigitsSeparatorTest.cs index 80c17291..6cecde9a 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlDefaultWindows/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/DigitsSeparatorTest.cs index 5f48f8e8..a50d5265 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestUnix/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/DigitsSeparatorTest.cs index ba3a9d94..0193daf6 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlLatestWindows/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewUnix/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewUnix/DigitsSeparatorTest.cs index 89235fe8..ff12778e 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewUnix/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewUnix/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; diff --git a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewWindows/DigitsSeparatorTest.cs b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewWindows/DigitsSeparatorTest.cs index 32df0cdd..c8d82564 100644 --- a/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewWindows/DigitsSeparatorTest.cs +++ b/tests/ClangSharp.PInvokeGenerator.UnitTests/XmlPreviewWindows/DigitsSeparatorTest.cs @@ -1,3 +1,5 @@ +// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + using System.Threading.Tasks; using NUnit.Framework; From 7c0262cbeaf57c4dc723acebe1f0fa36c798ecaa Mon Sep 17 00:00:00 2001 From: Davide Lettieri Date: Wed, 15 Oct 2025 22:01:02 +0200 Subject: [PATCH 3/5] review: use string.Replace instead of for loop --- .../CSharp/CSharpOutputBuilder.cs | 16 +--------------- .../PInvokeGenerator.VisitStmt.cs | 4 ++-- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs index 55dacddf..bfe16e3f 100644 --- a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs +++ b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs @@ -130,21 +130,7 @@ public void WriteLabel(string name) WriteLine(':'); } - public void WriteNumberLiteral(ReadOnlySpan value) - { - for (var i = 0; i < value.Length; i++) - { - var c = value[i]; - if (c == '\'') - { - Write('_'); - } - else - { - Write(c); - } - } - } + public void WriteNumberLiteral(string value) => Write(value.Replace('\'', '_')); public void WriteLine(T value) { diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs index a8919c77..bb3e5d2c 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs @@ -1201,7 +1201,7 @@ private void VisitFloatingLiteral(FloatingLiteral floatingLiteral) var outputBuilder = StartCSharpCode(); if (floatingLiteral.ValueString.EndsWith(".f", StringComparison.Ordinal)) { - outputBuilder.WriteNumberLiteral(floatingLiteral.ValueString.AsSpan()[..^1]); + outputBuilder.WriteNumberLiteral(floatingLiteral.ValueString[..^1]); outputBuilder.Write("0f"); } else @@ -1994,7 +1994,7 @@ void HandleUnmanagedConstant(CSharpOutputBuilder outputBuilder, InitListExpr ini private void VisitIntegerLiteral(IntegerLiteral integerLiteral) { - var valueString = integerLiteral.ValueString.AsSpan(); + var valueString = integerLiteral.ValueString; var valueSuffix = ""; if (valueString.EndsWith("ui8", StringComparison.OrdinalIgnoreCase)) From f83e21e21af92085724ef82f5d8ac3db088f61d7 Mon Sep 17 00:00:00 2001 From: Davide Lettieri Date: Thu, 16 Oct 2025 08:00:39 +0200 Subject: [PATCH 4/5] Revert "review: use string.Replace instead of for loop" This reverts commit 7c0262cbeaf57c4dc723acebe1f0fa36c798ecaa. --- .../CSharp/CSharpOutputBuilder.cs | 16 +++++++++++++++- .../PInvokeGenerator.VisitStmt.cs | 4 ++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs index bfe16e3f..55dacddf 100644 --- a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs +++ b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs @@ -130,7 +130,21 @@ public void WriteLabel(string name) WriteLine(':'); } - public void WriteNumberLiteral(string value) => Write(value.Replace('\'', '_')); + public void WriteNumberLiteral(ReadOnlySpan value) + { + for (var i = 0; i < value.Length; i++) + { + var c = value[i]; + if (c == '\'') + { + Write('_'); + } + else + { + Write(c); + } + } + } public void WriteLine(T value) { diff --git a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs index bb3e5d2c..a8919c77 100644 --- a/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs +++ b/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitStmt.cs @@ -1201,7 +1201,7 @@ private void VisitFloatingLiteral(FloatingLiteral floatingLiteral) var outputBuilder = StartCSharpCode(); if (floatingLiteral.ValueString.EndsWith(".f", StringComparison.Ordinal)) { - outputBuilder.WriteNumberLiteral(floatingLiteral.ValueString[..^1]); + outputBuilder.WriteNumberLiteral(floatingLiteral.ValueString.AsSpan()[..^1]); outputBuilder.Write("0f"); } else @@ -1994,7 +1994,7 @@ void HandleUnmanagedConstant(CSharpOutputBuilder outputBuilder, InitListExpr ini private void VisitIntegerLiteral(IntegerLiteral integerLiteral) { - var valueString = integerLiteral.ValueString; + var valueString = integerLiteral.ValueString.AsSpan(); var valueSuffix = ""; if (valueString.EndsWith("ui8", StringComparison.OrdinalIgnoreCase)) From db2c90e4002a81d3f3c33d101c91adc3ec6db78e Mon Sep 17 00:00:00 2001 From: Davide Lettieri Date: Thu, 16 Oct 2025 08:09:55 +0200 Subject: [PATCH 5/5] review: use loop/slice --- .../CSharp/CSharpOutputBuilder.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs index 55dacddf..c8ef5432 100644 --- a/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs +++ b/sources/ClangSharp.PInvokeGenerator/CSharp/CSharpOutputBuilder.cs @@ -132,18 +132,16 @@ public void WriteLabel(string name) public void WriteNumberLiteral(ReadOnlySpan value) { - for (var i = 0; i < value.Length; i++) + var index = value.IndexOf('\''); + while (index != -1) { - var c = value[i]; - if (c == '\'') - { - Write('_'); - } - else - { - Write(c); - } + var part = value[..index]; + Write(part); + Write(['_']); + value = value[(index + 1)..]; + index = value.IndexOf('\''); } + Write(value); } public void WriteLine(T value)