1 //===- unittest/Format/FormatTestCSharp.cpp - Formatting tests for CSharp -===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "FormatTestUtils.h"
10 #include "clang/Format/Format.h"
11 #include "llvm/Support/Debug.h"
12 #include "gtest/gtest.h"
14 #define DEBUG_TYPE "format-test"
19 class FormatTestCSharp
: public ::testing::Test
{
21 static std::string
format(llvm::StringRef Code
, unsigned Offset
,
22 unsigned Length
, const FormatStyle
&Style
) {
23 LLVM_DEBUG(llvm::errs() << "---\n");
24 LLVM_DEBUG(llvm::errs() << Code
<< "\n\n");
25 std::vector
<tooling::Range
> Ranges(1, tooling::Range(Offset
, Length
));
26 tooling::Replacements Replaces
= reformat(Style
, Code
, Ranges
);
27 auto Result
= applyAllReplacements(Code
, Replaces
);
28 EXPECT_TRUE(static_cast<bool>(Result
));
29 LLVM_DEBUG(llvm::errs() << "\n" << *Result
<< "\n\n");
34 format(llvm::StringRef Code
,
35 const FormatStyle
&Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
)) {
36 return format(Code
, 0, Code
.size(), Style
);
39 static FormatStyle
getStyleWithColumns(unsigned ColumnLimit
) {
40 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
41 Style
.ColumnLimit
= ColumnLimit
;
45 static void verifyFormat(
47 const FormatStyle
&Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
)) {
48 EXPECT_EQ(Code
.str(), format(Code
, Style
)) << "Expected code is not stable";
49 EXPECT_EQ(Code
.str(), format(test::messUp(Code
), Style
));
53 TEST_F(FormatTestCSharp
, CSharpClass
) {
54 verifyFormat("public class SomeClass\n"
74 // Ensure that small and empty classes are handled correctly with condensed
75 // (Google C++-like) brace-breaking style.
76 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
77 Style
.BreakBeforeBraces
= FormatStyle::BS_Attach
;
79 verifyFormat("public class SomeEmptyClass {}", Style
);
81 verifyFormat("public class SomeTinyClass {\n"
85 verifyFormat("private class SomeTinyClass {\n"
89 verifyFormat("protected class SomeTinyClass {\n"
93 verifyFormat("internal class SomeTinyClass {\n"
99 TEST_F(FormatTestCSharp
, AccessModifiers
) {
100 verifyFormat("public String toString()\n"
103 verifyFormat("private String toString()\n"
106 verifyFormat("protected String toString()\n"
109 verifyFormat("internal String toString()\n"
113 verifyFormat("public override String toString()\n"
116 verifyFormat("private override String toString()\n"
119 verifyFormat("protected override String toString()\n"
122 verifyFormat("internal override String toString()\n"
126 verifyFormat("internal static String toString()\n"
131 TEST_F(FormatTestCSharp
, NoStringLiteralBreaks
) {
133 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
137 TEST_F(FormatTestCSharp
, CSharpVerbatiumStringLiterals
) {
138 verifyFormat("foo(@\"aaaaaaaa\\abc\\aaaa\");");
139 // @"ABC\" + ToString("B") - handle embedded \ in literal string at
143 * After removal of Lexer change we are currently not able
144 * To handle these cases
145 verifyFormat("string s = @\"ABC\\\" + ToString(\"B\");");
146 verifyFormat("string s = @\"ABC\"\"DEF\"\"GHI\"");
147 verifyFormat("string s = @\"ABC\"\"DEF\"\"\"");
148 verifyFormat("string s = @\"ABC\"\"DEF\"\"\" + abc");
152 TEST_F(FormatTestCSharp
, CSharpInterpolatedStringLiterals
) {
153 verifyFormat("foo($\"aaaaaaaa{aaa}aaaa\");");
154 verifyFormat("foo($\"aaaa{A}\");");
157 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");");
158 verifyFormat("Name = $\"{firstName} {lastName}\";");
160 // $"ABC\" + ToString("B") - handle embedded \ in literal string at
162 verifyFormat("string s = $\"A{abc}BC\" + ToString(\"B\");");
163 verifyFormat("$\"{domain}\\\\{user}\"");
165 "var verbatimInterpolated = $@\"C:\\Users\\{userName}\\Documents\\\";");
168 TEST_F(FormatTestCSharp
, CSharpFatArrows
) {
169 verifyFormat("Task serverTask = Task.Run(async() => {");
170 verifyFormat("public override string ToString() => \"{Name}\\{Age}\";");
173 TEST_F(FormatTestCSharp
, CSharpConditionalExpressions
) {
174 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
175 // conditional expression is not seen as a NullConditional.
176 verifyFormat("var y = A < B ? -1 : 1;", Style
);
179 TEST_F(FormatTestCSharp
, CSharpNullConditional
) {
180 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
181 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Always
;
184 "public Person(string firstName, string lastName, int? age = null)");
186 verifyFormat("foo () {\n"
187 " switch (args?.Length) {}\n"
191 verifyFormat("switch (args?.Length) {}", Style
);
193 verifyFormat("public static void Main(string[] args)\n"
195 " string dirPath = args?[0];\n"
198 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Never
;
200 verifyFormat("switch(args?.Length) {}", Style
);
203 TEST_F(FormatTestCSharp
, Attributes
) {
204 verifyFormat("[STAThread]\n"
205 "static void Main(string[] args)\n"
209 verifyFormat("[TestMethod]\n"
210 "private class Test\n"
214 verifyFormat("[TestMethod]\n"
215 "protected class Test\n"
219 verifyFormat("[TestMethod]\n"
220 "internal class Test\n"
224 verifyFormat("[TestMethod]\n"
229 verifyFormat("[TestMethod]\n"
230 "[DeploymentItem(\"Test.txt\")]\n"
231 "public class Test\n"
235 verifyFormat("[System.AttributeUsage(System.AttributeTargets.Method)]\n"
236 "[System.Runtime.InteropServices.ComVisible(true)]\n"
237 "public sealed class STAThreadAttribute : Attribute\n"
241 verifyFormat("[Verb(\"start\", HelpText = \"Starts the server listening on "
242 "provided port\")]\n"
247 verifyFormat("[TestMethod]\n"
248 "public string Host { set; get; }");
250 // Adjacent properties should not cause line wrapping issues
251 verifyFormat("[JsonProperty(\"foo\")]\n"
252 "public string Foo { set; get; }\n"
253 "[JsonProperty(\"bar\")]\n"
254 "public string Bar { set; get; }\n"
255 "[JsonProperty(\"bar\")]\n"
256 "protected string Bar { set; get; }\n"
257 "[JsonProperty(\"bar\")]\n"
258 "internal string Bar { set; get; }");
260 // Multiple attributes should always be split (not just the first ones)
261 verifyFormat("[XmlIgnore]\n"
262 "[JsonProperty(\"foo\")]\n"
263 "public string Foo { set; get; }");
265 verifyFormat("[XmlIgnore]\n"
266 "[JsonProperty(\"foo\")]\n"
267 "public string Foo { set; get; }\n"
269 "[JsonProperty(\"bar\")]\n"
270 "public string Bar { set; get; }");
272 verifyFormat("[XmlIgnore]\n"
274 "[JsonProperty(\"foo\")]\n"
275 "public string Foo { set; get; }\n"
278 "[JsonProperty(\"bar\")]\n"
279 "public string Bar { set; get; }");
281 verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server "
282 "listening on provided host\")]\n"
283 "public string Host { set; get; }");
286 "[DllImport(\"Hello\", EntryPoint = \"hello_world\")]\n"
287 "// The const char* returned by hello_world must not be deleted.\n"
288 "private static extern IntPtr HelloFromCpp();)");
290 // Class attributes go on their own line and do not affect layout of
291 // interfaces. Line wrapping decisions previously caused each interface to be
293 verifyFormat("[SomeAttribute]\n"
294 "[SomeOtherAttribute]\n"
295 "public class A : IShape, IAnimal, IVehicle\n"
300 // Attributes in a method declaration do not cause line wrapping.
301 verifyFormat("void MethodA([In][Out] ref double x)\n"
305 verifyFormat("void MethodA([In, Out] ref double x)\n"
309 verifyFormat("void MethodA([In, Out] double[] x)\n"
313 verifyFormat("void MethodA([In] double[] x)\n"
317 verifyFormat("void MethodA(int[] x)\n"
320 verifyFormat("void MethodA(int[][] x)\n"
323 verifyFormat("void MethodA([] x)\n"
327 verifyFormat("public void Log([CallerLineNumber] int line = -1, "
328 "[CallerFilePath] string path = null,\n"
329 " [CallerMemberName] string name = null)\n"
333 // [] in an attribute do not cause premature line wrapping or indenting.
337 [SomeAttribute(new[] { RED, GREEN, BLUE }, -1.0f, 1.0f)]
339 public Data MemberVariable;
342 // Unwrappable lines go on a line of their own.
343 // 'target:' is not treated as a label.
344 // Modify Style to enforce a column limit.
345 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
346 Style
.ColumnLimit
= 10;
347 verifyFormat(R
"([assembly:InternalsVisibleTo(
348 "SomeAssembly
, PublicKey
=SomePublicKeyThatExceedsTheColumnLimit
")])",
352 TEST_F(FormatTestCSharp
, CSharpUsing
) {
353 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
354 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Always
;
355 verifyFormat("public void foo () {\n"
356 " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n"
361 // Ensure clang-format affects top-level snippets correctly.
362 verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}",
365 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Never
;
366 verifyFormat("public void foo() {\n"
367 " using(StreamWriter sw = new StreamWriter(filenameB)) {}\n"
372 // Ensure clang-format affects top-level snippets correctly.
373 verifyFormat("using(StreamWriter sw = new StreamWriter(filenameB)) {}",
376 Style
.SpaceBeforeParens
= FormatStyle::SBPO_ControlStatements
;
377 verifyFormat("public void foo() {\n"
378 " using (StreamWriter sw = new StreamWriter(filenameA)) {}\n"
383 // Ensure clang-format affects top-level snippets correctly.
384 verifyFormat("using (StreamWriter sw = new StreamWriter(filenameB)) {}",
387 Style
.SpaceBeforeParens
= FormatStyle::SBPO_NonEmptyParentheses
;
388 verifyFormat("public void foo() {\n"
389 " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n"
394 // Ensure clang-format affects top-level snippets correctly.
395 verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}",
399 TEST_F(FormatTestCSharp
, CSharpRegions
) {
400 verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa "
401 "aaaaaaaaaaaaaaa long region");
404 TEST_F(FormatTestCSharp
, CSharpKeyWordEscaping
) {
405 // AfterEnum is true by default.
406 verifyFormat("public enum var\n"
415 TEST_F(FormatTestCSharp
, CSharpNullCoalescing
) {
416 verifyFormat("var test = ABC ?? DEF");
417 verifyFormat("string myname = name ?? \"ABC\";");
418 verifyFormat("return _name ?? \"DEF\";");
421 TEST_F(FormatTestCSharp
, CSharpNullCoalescingAssignment
) {
422 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
423 Style
.SpaceBeforeAssignmentOperators
= true;
425 verifyFormat(R
"(test ??= ABC;)", Style
);
426 verifyFormat(R
"(test ??= true;)", Style
);
428 Style
.SpaceBeforeAssignmentOperators
= false;
430 verifyFormat(R
"(test??= ABC;)", Style
);
431 verifyFormat(R
"(test??= true;)", Style
);
434 TEST_F(FormatTestCSharp
, CSharpNullForgiving
) {
435 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
437 verifyFormat("var test = null!;", Style
);
438 verifyFormat("string test = someFunctionCall()! + \"ABC\"!", Style
);
439 verifyFormat("int test = (1! + 2 + bar! + foo())!", Style
);
440 verifyFormat(R
"(test ??= !foo!;)", Style
);
441 verifyFormat("test = !bar! ?? !foo!;", Style
);
442 verifyFormat("bool test = !(!true && !true! || !null && !null! || !false && "
443 "!false! && !bar()! + (!foo()))!",
446 // Check that line break keeps identifier with the bang.
447 Style
.ColumnLimit
= 14;
449 verifyFormat("var test =\n"
454 TEST_F(FormatTestCSharp
, AttributesIndentation
) {
455 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
456 Style
.AlwaysBreakAfterReturnType
= FormatStyle::RTBS_None
;
458 verifyFormat("[STAThread]\n"
459 "static void Main(string[] args)\n"
464 verifyFormat("[STAThread]\n"
466 "veryLooooooooooooooongFunctionName(string[] args)\n"
471 verifyFormat("[STAThread]\n"
472 "veryLoooooooooooooooooooongReturnType "
473 "veryLooooooooooooooongFunctionName(string[] args)\n"
478 verifyFormat("[SuppressMessage(\"A\", \"B\", Justification = \"C\")]\n"
479 "public override X Y()\n"
484 verifyFormat("[SuppressMessage]\n"
490 verifyFormat("[SuppressMessage]\n"
491 "public override X Y()\n"
496 verifyFormat("public A(B b) : base(b)\n"
498 " [SuppressMessage]\n"
499 " public override X Y()\n"
505 verifyFormat("public A : Base\n"
514 verifyFormat("namespace\n"
527 TEST_F(FormatTestCSharp
, CSharpSpaceBefore
) {
528 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
529 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Always
;
531 verifyFormat("List<string> list;", Style
);
532 verifyFormat("Dictionary<string, string> dict;", Style
);
534 verifyFormat("for (int i = 0; i < size (); i++) {\n"
537 verifyFormat("foreach (var x in y) {\n"
540 verifyFormat("switch (x) {}", Style
);
541 verifyFormat("do {\n"
545 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Never
;
547 verifyFormat("List<string> list;", Style
);
548 verifyFormat("Dictionary<string, string> dict;", Style
);
550 verifyFormat("for(int i = 0; i < size(); i++) {\n"
553 verifyFormat("foreach(var x in y) {\n"
556 verifyFormat("switch(x) {}", Style
);
557 verifyFormat("do {\n"
562 TEST_F(FormatTestCSharp
, CSharpSpaceAfterCStyleCast
) {
563 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
565 verifyFormat("(int)x / y;", Style
);
567 Style
.SpaceAfterCStyleCast
= true;
568 verifyFormat("(int) x / y;", Style
);
571 TEST_F(FormatTestCSharp
, CSharpEscapedQuotesInVerbatimStrings
) {
572 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
574 verifyFormat(R
"(string str = @"""";)", Style
);
575 verifyFormat(R
"(string str = @"""Hello world
""";)", Style
);
576 verifyFormat(R
"(string str = $@"""Hello
{friend}""";)", Style
);
577 verifyFormat(R
"(return $@"Foo
""/foo
?f
={Request
.Query
["f"]}""";)", Style
);
578 verifyFormat(R
"(return @$"Foo
""/foo
?f
={Request
.Query
["f"]}""";)", Style
);
579 verifyFormat(R
"(return @$"path
\to\
{specifiedFile
}")", Style
);
582 TEST_F(FormatTestCSharp
, CSharpQuotesInInterpolatedStrings
) {
583 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
585 verifyFormat(R
"(string str1 = $"{null
?? "null"}";)", Style
);
586 verifyFormat(R
"(string str2 = $"{{{braceCount
} braces
";)", Style
);
587 verifyFormat(R
"(string str3 = $"{braceCount
}}} braces
";)", Style
);
590 TEST_F(FormatTestCSharp
, CSharpNewlinesInVerbatimStrings
) {
591 // Use MS style as Google Style inserts a line break before multiline strings.
593 // verifyFormat does not understand multiline C# string-literals
594 // so check the format explicitly.
596 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
598 std::string Code
= R
"(string s1 = $@"some code
:
603 EXPECT_EQ(Code
, format(Code
, Style
));
605 // Multiline string in the middle of a function call.
607 var x = foo(className, $@"some code
:
611 y);)"; // y aligned with `className` arg.
613 EXPECT_EQ(Code
, format(Code
, Style
));
615 // Interpolated string with embedded multiline string.
616 Code
= R
"(Console.WriteLine($"{string
.Join(@
",
619 EXPECT_EQ(Code
, format(Code
, Style
));
622 TEST_F(FormatTestCSharp
, CSharpNewOperator
) {
623 FormatStyle Style
= getLLVMStyle(FormatStyle::LK_CSharp
);
625 verifyFormat("public void F() {\n"
626 " var v = new C(() => { var t = 5; });\n"
629 verifyFormat("public void F() {\n"
630 " var v = new C(() => {\n"
640 TEST_F(FormatTestCSharp
, CSharpLambdas
) {
641 FormatStyle GoogleStyle
= getGoogleStyle(FormatStyle::LK_CSharp
);
642 FormatStyle MicrosoftStyle
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
646 Action<string> greet = name => {
647 string greeting = $"Hello
{name
}!";
648 Console.WriteLine(greeting);
654 // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#statement-lambdas
658 Action<string> greet = name =>
660 string greeting = $"Hello
{name
}!";
661 Console.WriteLine(greeting);
666 verifyFormat("void bar()\n"
668 " Function(Val, (Action)(() =>\n"
681 verifyFormat("void baz()\n"
683 " Function(Val, (Action)(() =>\n"
685 " using (var a = new Lock())\n"
696 verifyFormat("void baz()\n"
698 " Function(Val, (Action)(() =>\n"
708 verifyFormat("void baz()\n"
710 " Function(Val, (Action)(() =>\n"
720 verifyFormat("void baz()\n"
722 " Function(Val, (Action)(() =>\n"
723 " { A.Remove(item); }));\n"
727 verifyFormat("void bar()\n"
729 " Function(Val, (() =>\n"
741 verifyFormat("void bar()\n"
756 MicrosoftStyle
.IndentWidth
= 2;
757 verifyFormat("void bar()\n"
771 verifyFormat("void bar() {\n"
772 " Function((() => {\n"
783 TEST_F(FormatTestCSharp
, CSharpLambdasDontBreakFollowingCodeAlignment
) {
784 FormatStyle GoogleStyle
= getGoogleStyle(FormatStyle::LK_CSharp
);
785 FormatStyle MicrosoftStyle
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
794 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
795 CodeThatFollowsLambda();
803 public class Sample {
806 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
807 CodeThatFollowsLambda();
815 TEST_F(FormatTestCSharp
, CSharpLambdasComplexLambdasDontBreakAlignment
) {
816 FormatStyle GoogleStyle
= getGoogleStyle(FormatStyle::LK_CSharp
);
817 FormatStyle MicrosoftStyle
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
822 private static void ComplexLambda(BuildReport protoReport)
825 veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
826 .Select(scene => scene.path)
828 if (allSelectedScenes.Count == 0)
842 private static void ComplexLambda(BuildReport protoReport) {
843 allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
844 .Where(scene => scene.enabled)
845 .Select(scene => scene.path)
847 if (allSelectedScenes.Count == 0) {
859 TEST_F(FormatTestCSharp
, CSharpLambdasMulipleLambdasDontBreakAlignment
) {
860 FormatStyle GoogleStyle
= getGoogleStyle(FormatStyle::LK_CSharp
);
861 FormatStyle MicrosoftStyle
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
866 private static void MultipleLambdas(BuildReport protoReport)
869 veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
870 .Select(scene => scene.path)
872 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
873 if (allSelectedScenes.Count == 0)
887 private static void MultipleLambdas(BuildReport protoReport) {
888 allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
889 .Where(scene => scene.enabled)
890 .Select(scene => scene.path)
892 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
893 if (allSelectedScenes.Count == 0) {
905 TEST_F(FormatTestCSharp
, CSharpObjectInitializers
) {
906 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
908 // Start code fragments with a comment line so that C++ raw string literals
909 // as seen are identical to expected formatted code.
912 Shape[] shapes = new[] {
915 Colour = Colours.Red,
919 Colour = Colours.Yellow,
924 // Omitted final `,`s will change the formatting.
926 Shape[] shapes = new[] { new Circle { Radius = 2.7281, Colour = Colours.Red },
927 new Square { Side = 101.1, Colour = Colours.Yellow } };)",
930 // Lambdas can be supplied as initialiser arguments.
932 private Transformer _transformer = new X.Y {
933 Filler = (Shape shape) => { return new Transform.Fill(shape, RED); },
934 Scaler = (Shape shape) => { return new Transform.Resize(shape, 0.1); },
938 // Dictionary initialisation.
940 var myDict = new Dictionary<string, string> {
942 ["age
"] = Convert.ToString(DateTime.Today.Year - 1934),
948 TEST_F(FormatTestCSharp
, CSharpArrayInitializers
) {
949 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
952 private MySet<Node>[] setPoints = {
959 TEST_F(FormatTestCSharp
, CSharpNamedArguments
) {
960 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
963 PrintOrderDetails(orderNum: 31, productName: "Red Mug
", sellerName: "Gift Shop
");)",
966 // Ensure that trailing comments do not cause problems.
968 PrintOrderDetails(orderNum: 31, productName: "Red Mug
", // comment
969 sellerName: "Gift Shop
");)",
972 verifyFormat(R
"(foreach (var tickCount in task.Begin(seed: 0)) {)", Style
);
975 TEST_F(FormatTestCSharp
, CSharpPropertyAccessors
) {
976 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
978 verifyFormat("int Value { get }", Style
);
979 verifyFormat("int Value { get; }", Style
);
980 verifyFormat("int Value { internal get; }", Style
);
981 verifyFormat("int Value { get; } = 0", Style
);
982 verifyFormat("int Value { set }", Style
);
983 verifyFormat("int Value { set; }", Style
);
984 verifyFormat("int Value { init; }", Style
);
985 verifyFormat("int Value { internal set; }", Style
);
986 verifyFormat("int Value { set; } = 0", Style
);
987 verifyFormat("int Value { get; set }", Style
);
988 verifyFormat("int Value { get; init; }", Style
);
989 verifyFormat("int Value { set; get }", Style
);
990 verifyFormat("int Value { get; private set; }", Style
);
991 verifyFormat("int Value { get; set; }", Style
);
992 verifyFormat("int Value { get; set; } = 0", Style
);
993 verifyFormat("int Value { internal get; internal set; }", Style
);
995 // Do not wrap expression body definitions.
999 set => _name = value;
1003 public string Name {
1004 init => _name = value;
1009 public string Name {
1010 set => _name = value;
1015 // Examples taken from
1016 // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
1018 // Expression body definitions
1019 public class SaleItem {
1020 public decimal Price {
1022 set => _cost = value;
1028 // Properties with backing fields
1030 public double Hours {
1031 get { return _seconds / 3600; }
1033 if (value < 0 || value > 24)
1034 throw new ArgumentOutOfRangeException($"{nameof(value
)} must be between
0 and 24.");
1035 _seconds = value * 3600;
1042 // Auto-implemented properties
1043 public class SaleItem {
1044 public decimal Price { get; set; }
1048 // Add column limit to wrap long lines.
1049 Style
.ColumnLimit
= 100;
1051 // Examples with assignment to default value.
1053 // Long assignment to default value
1055 public override VeryLongNamedTypeIndeed VeryLongNamedValue { get; set } =
1056 VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
1057 DefaultThirdArgument);
1062 // Long assignment to default value with expression body
1064 public override VeryLongNamedTypeIndeed VeryLongNamedValue {
1065 get => veryLongNamedField;
1066 set => veryLongNamedField = value;
1067 } = VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
1068 DefaultThirdArgument);
1072 // Brace wrapping and single-lining of accessor can be controlled by config.
1073 Style
.AllowShortBlocksOnASingleLine
= FormatStyle::SBS_Never
;
1074 Style
.BreakBeforeBraces
= FormatStyle::BS_Custom
;
1075 Style
.BraceWrapping
.AfterFunction
= true;
1082 return _seconds / 3600;
1085 _seconds = value * 3600;
1091 // Microsoft style trivial property accessors have no line break before the
1093 auto MicrosoftStyle
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
1095 public class SaleItem
1097 public decimal Price { get; set; }
1102 TEST_F(FormatTestCSharp
, DefaultLiteral
) {
1103 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1106 "T[] InitializeArray<T>(int length, T initialValue = default) {}", Style
);
1107 verifyFormat("System.Numerics.Complex fillValue = default;", Style
);
1108 verifyFormat("int Value { get } = default;", Style
);
1109 verifyFormat("int Value { get } = default!;", Style
);
1111 public record Person {
1112 public string GetInit { get; init; } = default!;
1116 public record Person {
1117 public string GetSet { get; set; } = default!;
1122 TEST_F(FormatTestCSharp
, CSharpSpaces
) {
1123 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1124 Style
.SpaceBeforeSquareBrackets
= false;
1125 Style
.SpacesInSquareBrackets
= false;
1126 Style
.SpaceBeforeCpp11BracedList
= true;
1127 Style
.Cpp11BracedListStyle
= false;
1128 Style
.SpacesInContainerLiterals
= false;
1129 Style
.SpaceAfterCStyleCast
= false;
1131 verifyFormat(R
"(new Car { "Door
", 0.1 })", Style
);
1132 verifyFormat(R
"(new Car { 0.1, "Door
" })", Style
);
1133 verifyFormat(R
"(new string[] { "A
" })", Style
);
1134 verifyFormat(R
"(new string[] {})", Style
);
1135 verifyFormat(R
"(new Car { someVariableName })", Style
);
1136 verifyFormat(R
"(new Car { someVariableName })", Style
);
1137 verifyFormat(R
"(new Dictionary<string, string> { ["Key
"] = "Value
" };)",
1139 verifyFormat(R
"(Apply(x => x.Name, x => () => x.ID);)", Style
);
1140 verifyFormat(R
"(bool[] xs = { true, true };)", Style
);
1141 verifyFormat(R
"(taskContext.Factory.Run(async () => doThing(args);)", Style
);
1142 verifyFormat(R
"(catch (TestException) when (innerFinallyExecuted))", Style
);
1143 verifyFormat(R
"(private float[,] Values;)", Style
);
1144 verifyFormat(R
"(Result this[Index x] => Foo(x);)", Style
);
1146 verifyFormat(R
"(char[,,] rawCharArray = MakeCharacterGrid();)", Style
);
1147 verifyFormat(R
"(var (key, value))", Style
);
1149 // `&&` is not seen as a reference.
1150 verifyFormat(R
"(A == typeof(X) && someBool)", Style
);
1152 // Not seen as a C-style cast.
1154 foreach ((A a, B b) in someList) {
1158 // space after lock in `lock (processes)`.
1159 verifyFormat("lock (process)", Style
);
1161 Style
.SpacesInSquareBrackets
= true;
1162 verifyFormat(R
"(private float[ , ] Values;)", Style
);
1163 verifyFormat(R
"(string dirPath = args?[ 0 ];)", Style
);
1164 verifyFormat(R
"(char[ ,, ] rawCharArray = MakeCharacterGrid();)", Style
);
1166 // Method returning tuple
1167 verifyFormat(R
"(public (string name, int age) methodTuple() {})", Style
);
1168 verifyFormat(R
"(private (string name, int age) methodTuple() {})", Style
);
1169 verifyFormat(R
"(protected (string name, int age) methodTuple() {})", Style
);
1170 verifyFormat(R
"(virtual (string name, int age) methodTuple() {})", Style
);
1171 verifyFormat(R
"(extern (string name, int age) methodTuple() {})", Style
);
1172 verifyFormat(R
"(static (string name, int age) methodTuple() {})", Style
);
1173 verifyFormat(R
"(internal (string name, int age) methodTuple() {})", Style
);
1174 verifyFormat(R
"(abstract (string name, int age) methodTuple() {})", Style
);
1175 verifyFormat(R
"(sealed (string name, int age) methodTuple() {})", Style
);
1176 verifyFormat(R
"(override (string name, int age) methodTuple() {})", Style
);
1177 verifyFormat(R
"(async (string name, int age) methodTuple() {})", Style
);
1178 verifyFormat(R
"(unsafe (string name, int age) methodTuple() {})", Style
);
1180 Style
.SpacesInSquareBrackets
= false;
1181 Style
.SpaceBeforeSquareBrackets
= true;
1182 verifyFormat("return a is [1, 2, 3];", Style
);
1183 verifyFormat("return a is [..];", Style
);
1184 Style
.SpaceBeforeSquareBrackets
= false;
1185 verifyFormat("return a is [1, 2, 3];", Style
);
1186 verifyFormat("return a is [..];", Style
);
1189 TEST_F(FormatTestCSharp
, CSharpNullableTypes
) {
1190 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1191 Style
.SpacesInSquareBrackets
= false;
1196 int? value = some.bar();
1199 Style
); // int? is nullable not a conditional expression.
1201 verifyFormat(R
"(void foo(int? x, int? y, int? z) {})",
1202 Style
); // Nullables in function definitions.
1204 verifyFormat(R
"(public float? Value;)", Style
); // no space before `?`.
1206 verifyFormat(R
"(int?[] arr = new int?[10];)",
1207 Style
); // An array of a nullable type.
1209 verifyFormat(R
"(var x = (int?)y;)", Style
); // Cast to a nullable type.
1211 verifyFormat(R
"(var x = new MyContainer<int?>();)", Style
); // Generics.
1214 public interface I {
1217 Style
); // Interface methods.
1219 Style
.ColumnLimit
= 10;
1221 public VeryLongType? Function(
1226 Style
); // ? sticks with identifier.
1229 TEST_F(FormatTestCSharp
, CSharpArraySubscripts
) {
1230 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1232 // Do not format array subscript operators as attributes.
1234 if (someThings[index].Contains(myThing)) {
1239 if (someThings[i][j][k].Contains(myThing)) {
1244 TEST_F(FormatTestCSharp
, CSharpGenericTypeConstraints
) {
1245 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1247 EXPECT_TRUE(Style
.BraceWrapping
.SplitEmptyRecord
);
1249 verifyFormat("class ItemFactory<T>\n"
1250 " where T : new() {\n"
1254 verifyFormat("class Dictionary<TKey, TVal>\n"
1255 " where TKey : IComparable<TKey>\n"
1256 " where TVal : IMyInterface {\n"
1257 " public void MyMethod<T>(T t)\n"
1258 " where T : IMyInterface {\n"
1264 verifyFormat("class ItemFactory<T>\n"
1265 " where T : new(), IAnInterface<T>, IAnotherInterface<T>, "
1266 "IAnotherInterfaceStill<T> {\n"
1270 Style
.ColumnLimit
= 50; // Force lines to be wrapped.
1272 class ItemFactory<T, U>
1275 IAnotherInterface<T, U>,
1276 IAnotherInterfaceStill<T, U> {
1280 // In other languages `where` can be used as a normal identifier.
1281 // This example is in C++!
1286 getGoogleStyle(FormatStyle::LK_Cpp
));
1289 TEST_F(FormatTestCSharp
, CSharpAfterEnum
) {
1290 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1291 Style
.BreakBeforeBraces
= FormatStyle::BS_Custom
;
1292 Style
.BraceWrapping
.AfterEnum
= false;
1293 Style
.AllowShortEnumsOnASingleLine
= false;
1295 verifyFormat("enum MyEnum {\n"
1300 verifyFormat("internal enum MyEnum {\n"
1305 verifyFormat("public enum MyEnum {\n"
1310 verifyFormat("protected enum MyEnum {\n"
1315 verifyFormat("private enum MyEnum {\n"
1321 Style
.BraceWrapping
.AfterEnum
= true;
1322 Style
.AllowShortEnumsOnASingleLine
= false;
1324 verifyFormat("enum MyEnum\n"
1330 verifyFormat("internal enum MyEnum\n"
1336 verifyFormat("public enum MyEnum\n"
1342 verifyFormat("protected enum MyEnum\n"
1348 verifyFormat("private enum MyEnum\n"
1354 verifyFormat("/* Foo */ private enum MyEnum\n"
1360 verifyFormat("/* Foo */ /* Bar */ private enum MyEnum\n"
1368 TEST_F(FormatTestCSharp
, CSharpAfterClass
) {
1369 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1370 Style
.BreakBeforeBraces
= FormatStyle::BS_Custom
;
1371 Style
.BraceWrapping
.AfterClass
= false;
1373 verifyFormat("class MyClass {\n"
1378 verifyFormat("internal class MyClass {\n"
1383 verifyFormat("public class MyClass {\n"
1388 verifyFormat("protected class MyClass {\n"
1393 verifyFormat("private class MyClass {\n"
1399 verifyFormat("interface Interface {\n"
1404 verifyFormat("internal interface Interface {\n"
1409 verifyFormat("public interface Interface {\n"
1414 verifyFormat("protected interface Interface {\n"
1419 verifyFormat("private interface Interface {\n"
1425 Style
.BraceWrapping
.AfterClass
= true;
1427 verifyFormat("class MyClass\n"
1433 verifyFormat("internal class MyClass\n"
1439 verifyFormat("public class MyClass\n"
1445 verifyFormat("protected class MyClass\n"
1451 verifyFormat("private class MyClass\n"
1458 verifyFormat("interface MyInterface\n"
1464 verifyFormat("internal interface MyInterface\n"
1470 verifyFormat("public interface MyInterface\n"
1476 verifyFormat("protected interface MyInterface\n"
1482 verifyFormat("private interface MyInterface\n"
1488 verifyFormat("/* Foo */ private interface MyInterface\n"
1494 verifyFormat("/* Foo */ /* Bar */ private interface MyInterface\n"
1502 TEST_F(FormatTestCSharp
, NamespaceIndentation
) {
1503 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
1504 Style
.NamespaceIndentation
= FormatStyle::NI_None
;
1506 verifyFormat("namespace A\n"
1508 "public interface Name1\n"
1514 verifyFormat("namespace A.B\n"
1516 "public interface Name1\n"
1522 Style
.NamespaceIndentation
= FormatStyle::NI_Inner
;
1524 verifyFormat("namespace A\n"
1528 " public interface Name1\n"
1535 Style
.NamespaceIndentation
= FormatStyle::NI_All
;
1537 verifyFormat("namespace A.B\n"
1539 " public interface Name1\n"
1545 verifyFormat("namespace A\n"
1549 " public interface Name1\n"
1557 TEST_F(FormatTestCSharp
, SwitchExpression
) {
1558 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
1559 verifyFormat("int x = a switch {\n"
1560 " 1 => (0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0),\n"
1567 TEST_F(FormatTestCSharp
, EmptyShortBlock
) {
1568 auto Style
= getLLVMStyle();
1569 Style
.AllowShortBlocksOnASingleLine
= FormatStyle::SBS_Empty
;
1571 verifyFormat("try {\n"
1573 "} catch (Exception e) {\n"
1574 " e.printStackTrace();\n"
1578 verifyFormat("try {\n"
1580 "} catch (Exception e) {}\n",
1584 TEST_F(FormatTestCSharp
, ShortFunctions
) {
1585 FormatStyle Style
= getLLVMStyle(FormatStyle::LK_CSharp
);
1586 Style
.NamespaceIndentation
= FormatStyle::NI_All
;
1587 Style
.AllowShortFunctionsOnASingleLine
= FormatStyle::SFS_Inline
;
1588 verifyFormat("interface Interface {\n"
1589 " void f() { return; }\n"
1592 verifyFormat("public interface Interface {\n"
1593 " void f() { return; }\n"
1596 verifyFormat("namespace {\n"
1602 // "union" is not a keyword in C#.
1603 verifyFormat("namespace union {\n"
1611 TEST_F(FormatTestCSharp
, BrokenBrackets
) {
1612 EXPECT_NE("", format("int where b <")); // reduced from crasher
1615 } // namespace format
1616 } // end namespace clang