1//===- unittest/Format/FormatTestCSharp.cpp - Formatting tests for CSharp -===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "FormatTestBase.h"
10
11#define DEBUG_TYPE "format-test"
12
13namespace clang {
14namespace format {
15namespace test {
16namespace {
17
18class FormatTestCSharp : public test::FormatTestBase {
19protected:
20 FormatStyle getDefaultStyle() const override {
21 return getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
22 }
23
24 static std::string format(StringRef Code, unsigned Offset, unsigned Length,
25 const FormatStyle &Style) {
26 LLVM_DEBUG(llvm::errs() << "---\n");
27 LLVM_DEBUG(llvm::errs() << Code << "\n\n");
28 std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
29 tooling::Replacements Replaces = reformat(Style, Code, Ranges);
30 auto Result = applyAllReplacements(Code, Replaces);
31 EXPECT_TRUE(static_cast<bool>(Result));
32 LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
33 return *Result;
34 }
35
36 static std::string
37 format(StringRef Code,
38 const FormatStyle &Style = getMicrosoftStyle(Language: FormatStyle::LK_CSharp)) {
39 return format(Code, Offset: 0, Length: Code.size(), Style);
40 }
41
42 static FormatStyle getStyleWithColumns(unsigned ColumnLimit) {
43 FormatStyle Style = getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
44 Style.ColumnLimit = ColumnLimit;
45 return Style;
46 }
47};
48
49TEST_F(FormatTestCSharp, CSharpClass) {
50 verifyFormat("public class SomeClass\n"
51 "{\n"
52 " void f()\n"
53 " {\n"
54 " }\n"
55 " int g()\n"
56 " {\n"
57 " return 0;\n"
58 " }\n"
59 " void h()\n"
60 " {\n"
61 " while (true)\n"
62 " f();\n"
63 " for (;;)\n"
64 " f();\n"
65 " if (true)\n"
66 " f();\n"
67 " }\n"
68 "}");
69
70 // Ensure that small and empty classes are handled correctly with condensed
71 // (Google C++-like) brace-breaking style.
72 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
73 Style.BreakBeforeBraces = FormatStyle::BS_Attach;
74
75 verifyFormat("public class SomeEmptyClass {}", Style);
76
77 verifyFormat("public class SomeTinyClass {\n"
78 " int X;\n"
79 "}",
80 Style);
81 verifyFormat("private class SomeTinyClass {\n"
82 " int X;\n"
83 "}",
84 Style);
85 verifyFormat("protected class SomeTinyClass {\n"
86 " int X;\n"
87 "}",
88 Style);
89 verifyFormat("internal class SomeTinyClass {\n"
90 " int X;\n"
91 "}",
92 Style);
93}
94
95TEST_F(FormatTestCSharp, AccessModifiers) {
96 verifyFormat("public String toString()\n"
97 "{\n"
98 "}");
99 verifyFormat("private String toString()\n"
100 "{\n"
101 "}");
102 verifyFormat("protected String toString()\n"
103 "{\n"
104 "}");
105 verifyFormat("internal String toString()\n"
106 "{\n"
107 "}");
108
109 verifyFormat("public override String toString()\n"
110 "{\n"
111 "}");
112 verifyFormat("private override String toString()\n"
113 "{\n"
114 "}");
115 verifyFormat("protected override String toString()\n"
116 "{\n"
117 "}");
118 verifyFormat("internal override String toString()\n"
119 "{\n"
120 "}");
121
122 verifyFormat("internal static String toString()\n"
123 "{\n"
124 "}");
125}
126
127TEST_F(FormatTestCSharp, NoStringLiteralBreaks) {
128 // Breaking of interpolated strings is not implemented.
129 auto Style = getDefaultStyle();
130 Style.ColumnLimit = 40;
131 Style.BreakStringLiterals = true;
132 verifyFormat("foo("
133 "$\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
134 "aaaaaaa\");",
135 Style);
136}
137
138TEST_F(FormatTestCSharp, StringLiteralBreaks) {
139 // The line is 75 characters long. The default limit for the Microsoft style
140 // is 120.
141 auto Style = getDefaultStyle();
142 Style.BreakStringLiterals = true;
143 verifyFormat("foo("
144 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
145 "aaaaaa\");",
146 Style);
147 // When the column limit is smaller, the string should get broken.
148 Style.ColumnLimit = 40;
149 verifyFormat(R"(foo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
150 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
151 "aaa");)",
152 "foo("
153 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
154 "aaaaaa\");",
155 Style);
156 // The new quotes should be the same as the original.
157 verifyFormat(R"(foo(@"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
158 @"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
159 @"aaaaa");)",
160 "foo("
161 "@\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
162 "aaaaaaa\");",
163 Style);
164 // The operators can be on either line.
165 Style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
166 verifyFormat(R"(foo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
167 + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
168 + "a");)",
169 "foo("
170 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
171 "aaaaaa\");",
172 Style);
173 Style.AlignOperands = FormatStyle::OAS_AlignAfterOperator;
174 verifyFormat(R"(foo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
175 + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
176 + "a");)",
177 "foo("
178 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
179 "aaaaaa\");",
180 Style);
181 verifyFormat(R"(x = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
182 + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";)",
183 "x = "
184 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
185 "aaaaaa\";",
186 Style);
187}
188
189TEST_F(FormatTestCSharp, CSharpVerbatiumStringLiterals) {
190 verifyFormat("foo(@\"aaaaaaaa\\abc\\aaaa\");");
191 // @"ABC\" + ToString("B") - handle embedded \ in literal string at
192 // the end
193 //
194 /*
195 * After removal of Lexer change we are currently not able
196 * To handle these cases
197 verifyFormat("string s = @\"ABC\\\" + ToString(\"B\");");
198 verifyFormat("string s = @\"ABC\"\"DEF\"\"GHI\"");
199 verifyFormat("string s = @\"ABC\"\"DEF\"\"\"");
200 verifyFormat("string s = @\"ABC\"\"DEF\"\"\" + abc");
201 */
202}
203
204TEST_F(FormatTestCSharp, CSharpInterpolatedStringLiterals) {
205 verifyFormat("foo($\"aaaaaaaa{aaa}aaaa\");");
206 verifyFormat("foo($\"aaaa{A}\");");
207 verifyFormat(
208 "foo($\"aaaa{A}"
209 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");");
210 verifyFormat("Name = $\"{firstName} {lastName}\";");
211
212 // $"ABC\" + ToString("B") - handle embedded \ in literal string at
213 // the end
214 verifyFormat("string s = $\"A{abc}BC\" + ToString(\"B\");");
215 verifyFormat("$\"{domain}\\\\{user}\"");
216 verifyFormat(
217 "var verbatimInterpolated = $@\"C:\\Users\\{userName}\\Documents\\\";");
218}
219
220TEST_F(FormatTestCSharp, CSharpFatArrows) {
221 verifyIncompleteFormat("Task serverTask = Task.Run(async() => {");
222 verifyFormat("public override string ToString() => \"{Name}\\{Age}\";");
223}
224
225TEST_F(FormatTestCSharp, CSharpConditionalExpressions) {
226 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
227 // conditional expression is not seen as a NullConditional.
228 verifyFormat("var y = A < B ? -1 : 1;", Style);
229}
230
231TEST_F(FormatTestCSharp, CSharpNullConditional) {
232 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
233 Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
234
235 verifyFormat(
236 "public Person(string firstName, string lastName, int? age = null)");
237
238 verifyFormat("foo () {\n"
239 " switch (args?.Length) {}\n"
240 "}",
241 Style);
242
243 verifyFormat("switch (args?.Length) {}", Style);
244
245 verifyFormat("public static void Main(string[] args)\n"
246 "{\n"
247 " string dirPath = args?[0];\n"
248 "}");
249
250 Style.SpaceBeforeParens = FormatStyle::SBPO_Never;
251
252 verifyFormat("switch(args?.Length) {}", Style);
253}
254
255TEST_F(FormatTestCSharp, Attributes) {
256 verifyFormat("[STAThread]\n"
257 "static void Main(string[] args)\n"
258 "{\n"
259 "}");
260
261 verifyFormat("[TestMethod]\n"
262 "private class Test\n"
263 "{\n"
264 "}");
265
266 verifyFormat("[TestMethod]\n"
267 "protected class Test\n"
268 "{\n"
269 "}");
270
271 verifyFormat("[TestMethod]\n"
272 "internal class Test\n"
273 "{\n"
274 "}");
275
276 verifyFormat("[TestMethod]\n"
277 "class Test\n"
278 "{\n"
279 "}");
280
281 verifyFormat("[TestMethod]\n"
282 "[DeploymentItem(\"Test.txt\")]\n"
283 "public class Test\n"
284 "{\n"
285 "}");
286
287 verifyFormat("[System.AttributeUsage(System.AttributeTargets.Method)]\n"
288 "[System.Runtime.InteropServices.ComVisible(true)]\n"
289 "public sealed class STAThreadAttribute : Attribute\n"
290 "{\n"
291 "}");
292
293 verifyFormat("[Verb(\"start\", HelpText = \"Starts the server listening on "
294 "provided port\")]\n"
295 "class Test\n"
296 "{\n"
297 "}");
298
299 verifyFormat("[TestMethod]\n"
300 "public string Host { set; get; }");
301
302 // Adjacent properties should not cause line wrapping issues
303 verifyFormat("[JsonProperty(\"foo\")]\n"
304 "public string Foo { set; get; }\n"
305 "[JsonProperty(\"bar\")]\n"
306 "public string Bar { set; get; }\n"
307 "[JsonProperty(\"bar\")]\n"
308 "protected string Bar { set; get; }\n"
309 "[JsonProperty(\"bar\")]\n"
310 "internal string Bar { set; get; }");
311
312 // Multiple attributes should always be split (not just the first ones)
313 verifyFormat("[XmlIgnore]\n"
314 "[JsonProperty(\"foo\")]\n"
315 "public string Foo { set; get; }");
316
317 verifyFormat("[XmlIgnore]\n"
318 "[JsonProperty(\"foo\")]\n"
319 "public string Foo { set; get; }\n"
320 "[XmlIgnore]\n"
321 "[JsonProperty(\"bar\")]\n"
322 "public string Bar { set; get; }");
323
324 verifyFormat("[XmlIgnore]\n"
325 "[ScriptIgnore]\n"
326 "[JsonProperty(\"foo\")]\n"
327 "public string Foo { set; get; }\n"
328 "[XmlIgnore]\n"
329 "[ScriptIgnore]\n"
330 "[JsonProperty(\"bar\")]\n"
331 "public string Bar { set; get; }");
332
333 verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server "
334 "listening on provided host\")]\n"
335 "public string Host { set; get; }");
336
337 verifyIncompleteFormat(
338 "[DllImport(\"Hello\", EntryPoint = \"hello_world\")]\n"
339 "// The const char* returned by hello_world must not be deleted.\n"
340 "private static extern IntPtr HelloFromCpp();)");
341
342 // Class attributes go on their own line and do not affect layout of
343 // interfaces. Line wrapping decisions previously caused each interface to be
344 // on its own line.
345 verifyFormat("[SomeAttribute]\n"
346 "[SomeOtherAttribute]\n"
347 "public class A : IShape, IAnimal, IVehicle\n"
348 "{\n"
349 " int X;\n"
350 "}");
351
352 // Attributes in a method declaration do not cause line wrapping.
353 verifyFormat("void MethodA([In][Out] ref double x)\n"
354 "{\n"
355 "}");
356
357 verifyFormat("void MethodA([In, Out] ref double x)\n"
358 "{\n"
359 "}");
360
361 verifyFormat("void MethodA([In, Out] double[] x)\n"
362 "{\n"
363 "}");
364
365 verifyFormat("void MethodA([In] double[] x)\n"
366 "{\n"
367 "}");
368
369 verifyFormat("void MethodA(int[] x)\n"
370 "{\n"
371 "}");
372 verifyFormat("void MethodA(int[][] x)\n"
373 "{\n"
374 "}");
375 verifyFormat("void MethodA([] x)\n"
376 "{\n"
377 "}");
378
379 verifyFormat("public void Log([CallerLineNumber] int line = -1, "
380 "[CallerFilePath] string path = null,\n"
381 " [CallerMemberName] string name = null)\n"
382 "{\n"
383 "}");
384
385 // [] in an attribute do not cause premature line wrapping or indenting.
386 verifyFormat(R"(//
387public class A
388{
389 [SomeAttribute(new[] { RED, GREEN, BLUE }, -1.0f, 1.0f)]
390 [DoNotSerialize]
391 public Data MemberVariable;
392})");
393
394 // Unwrappable lines go on a line of their own.
395 // 'target:' is not treated as a label.
396 // Modify Style to enforce a column limit.
397 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
398 Style.ColumnLimit = 10;
399 verifyFormat(R"([assembly:InternalsVisibleTo(
400 "SomeAssembly, PublicKey=SomePublicKeyThatExceedsTheColumnLimit")])",
401 Style);
402}
403
404TEST_F(FormatTestCSharp, CSharpUsing) {
405 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
406 Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
407 verifyFormat("public void foo () {\n"
408 " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n"
409 " using () {}\n"
410 "}",
411 Style);
412
413 // Ensure clang-format affects top-level snippets correctly.
414 verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}",
415 Style);
416
417 Style.SpaceBeforeParens = FormatStyle::SBPO_Never;
418 verifyFormat("public void foo() {\n"
419 " using(StreamWriter sw = new StreamWriter(filenameB)) {}\n"
420 " using() {}\n"
421 "}",
422 Style);
423
424 // Ensure clang-format affects top-level snippets correctly.
425 verifyFormat("using(StreamWriter sw = new StreamWriter(filenameB)) {}",
426 Style);
427
428 Style.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
429 verifyFormat("public void foo() {\n"
430 " using (StreamWriter sw = new StreamWriter(filenameA)) {}\n"
431 " using () {}\n"
432 "}",
433 Style);
434
435 // Ensure clang-format affects top-level snippets correctly.
436 verifyFormat("using (StreamWriter sw = new StreamWriter(filenameB)) {}",
437 Style);
438
439 Style.SpaceBeforeParens = FormatStyle::SBPO_NonEmptyParentheses;
440 verifyFormat("public void foo() {\n"
441 " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n"
442 " using() {}\n"
443 "}",
444 Style);
445
446 // Ensure clang-format affects top-level snippets correctly.
447 verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}",
448 Style);
449}
450
451TEST_F(FormatTestCSharp, CSharpRegions) {
452 verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa "
453 "aaaaaaaaaaaaaaa long region");
454}
455
456TEST_F(FormatTestCSharp, CSharpKeyWordEscaping) {
457 // AfterEnum is true by default.
458 verifyFormat("public enum var\n"
459 "{\n"
460 " none,\n"
461 " @string,\n"
462 " bool,\n"
463 " @enum\n"
464 "}");
465}
466
467TEST_F(FormatTestCSharp, CSharpNullCoalescing) {
468 verifyFormat("var test = ABC ?? DEF");
469 verifyFormat("string myname = name ?? \"ABC\";");
470 verifyFormat("return _name ?? \"DEF\";");
471}
472
473TEST_F(FormatTestCSharp, CSharpNullCoalescingAssignment) {
474 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
475 Style.SpaceBeforeAssignmentOperators = true;
476
477 verifyFormat(R"(test ??= ABC;)", Style);
478 verifyFormat(R"(test ??= true;)", Style);
479
480 Style.SpaceBeforeAssignmentOperators = false;
481
482 verifyFormat(R"(test??= ABC;)", Style);
483 verifyFormat(R"(test??= true;)", Style);
484}
485
486TEST_F(FormatTestCSharp, CSharpNullForgiving) {
487 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
488
489 verifyFormat("var test = null!;", Style);
490 verifyFormat("string test = someFunctionCall()! + \"ABC\"!", Style);
491 verifyFormat("int test = (1! + 2 + bar! + foo())!", Style);
492 verifyFormat(R"(test ??= !foo!;)", Style);
493 verifyFormat("test = !bar! ?? !foo!;", Style);
494 verifyFormat("bool test = !(!true && !true! || !null && !null! || !false && "
495 "!false! && !bar()! + (!foo()))!",
496 Style);
497
498 // Check that line break keeps identifier with the bang.
499 Style.ColumnLimit = 14;
500
501 verifyFormat("var test =\n"
502 " foo!;",
503 Style);
504}
505
506TEST_F(FormatTestCSharp, AttributesIndentation) {
507 FormatStyle Style = getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
508 Style.BreakAfterReturnType = FormatStyle::RTBS_None;
509
510 verifyFormat("[STAThread]\n"
511 "static void Main(string[] args)\n"
512 "{\n"
513 "}",
514 Style);
515
516 verifyFormat("[STAThread]\n"
517 "void "
518 "veryLooooooooooooooongFunctionName(string[] args)\n"
519 "{\n"
520 "}",
521 Style);
522
523 verifyFormat("[STAThread]\n"
524 "veryLoooooooooooooooooooongReturnType "
525 "veryLooooooooooooooongFunctionName(string[] args)\n"
526 "{\n"
527 "}",
528 Style);
529
530 verifyFormat("[SuppressMessage(\"A\", \"B\", Justification = \"C\")]\n"
531 "public override X Y()\n"
532 "{\n"
533 "}",
534 Style);
535
536 verifyFormat("[SuppressMessage]\n"
537 "public X Y()\n"
538 "{\n"
539 "}",
540 Style);
541
542 verifyFormat("[SuppressMessage]\n"
543 "public override X Y()\n"
544 "{\n"
545 "}",
546 Style);
547
548 verifyFormat("public A(B b) : base(b)\n"
549 "{\n"
550 " [SuppressMessage]\n"
551 " public override X Y()\n"
552 " {\n"
553 " }\n"
554 "}",
555 Style);
556
557 verifyFormat("public A : Base\n"
558 "{\n"
559 "}\n"
560 "[Test]\n"
561 "public Foo()\n"
562 "{\n"
563 "}",
564 Style);
565
566 verifyFormat("namespace\n"
567 "{\n"
568 "public A : Base\n"
569 "{\n"
570 "}\n"
571 "[Test]\n"
572 "public Foo()\n"
573 "{\n"
574 "}\n"
575 "}",
576 Style);
577}
578
579TEST_F(FormatTestCSharp, CSharpSpaceBefore) {
580 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
581 Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
582
583 verifyFormat("List<string> list;", Style);
584 verifyFormat("Dictionary<string, string> dict;", Style);
585
586 verifyFormat("for (int i = 0; i < size (); i++) {\n"
587 "}",
588 Style);
589 verifyFormat("foreach (var x in y) {\n"
590 "}",
591 Style);
592 verifyFormat("switch (x) {}", Style);
593 verifyFormat("do {\n"
594 "} while (x);",
595 Style);
596
597 Style.SpaceBeforeParens = FormatStyle::SBPO_Never;
598
599 verifyFormat("List<string> list;", Style);
600 verifyFormat("Dictionary<string, string> dict;", Style);
601
602 verifyFormat("for(int i = 0; i < size(); i++) {\n"
603 "}",
604 Style);
605 verifyFormat("foreach(var x in y) {\n"
606 "}",
607 Style);
608 verifyFormat("switch(x) {}", Style);
609 verifyFormat("do {\n"
610 "} while(x);",
611 Style);
612}
613
614TEST_F(FormatTestCSharp, CSharpSpaceAfterCStyleCast) {
615 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
616
617 verifyFormat("(int)x / y;", Style);
618
619 Style.SpaceAfterCStyleCast = true;
620 verifyFormat("(int) x / y;", Style);
621}
622
623TEST_F(FormatTestCSharp, CSharpEscapedQuotesInVerbatimStrings) {
624 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
625
626 verifyFormat(R"(string str = @"""";)", Style);
627 verifyFormat(R"(string str = @"""Hello world""";)", Style);
628 verifyFormat(R"(string str = $@"""Hello {friend}""";)", Style);
629 verifyFormat(R"(return $@"Foo ""/foo?f={Request.Query["f"]}""";)", Style);
630 verifyFormat(R"(return @$"Foo ""/foo?f={Request.Query["f"]}""";)", Style);
631 verifyFormat(R"(return @$"path\to\{specifiedFile}")", Style);
632}
633
634TEST_F(FormatTestCSharp, CSharpQuotesInInterpolatedStrings) {
635 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
636
637 verifyFormat(R"(string str1 = $"{null ?? "null"}";)", Style);
638 verifyFormat(R"(string str2 = $"{{{braceCount} braces";)", Style);
639 verifyFormat(R"(string str3 = $"{braceCount}}} braces";)", Style);
640}
641
642TEST_F(FormatTestCSharp, CSharpNewlinesInVerbatimStrings) {
643 // Use MS style as Google Style inserts a line break before multiline strings.
644
645 // verifyFormat does not understand multiline C# string-literals
646 // so check the format explicitly.
647
648 FormatStyle Style = getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
649
650 std::string Code = R"(string s1 = $@"some code:
651 class {className} {{
652 {className}() {{}}
653 }}";)";
654
655 EXPECT_EQ(Code, format(Code, Style));
656
657 // Multiline string in the middle of a function call.
658 Code = R"(
659var x = foo(className, $@"some code:
660 class {className} {{
661 {className}() {{}}
662 }}",
663 y);)"; // y aligned with `className` arg.
664
665 EXPECT_EQ(Code, format(Code, Style));
666
667 // Interpolated string with embedded multiline string.
668 Code = R"(Console.WriteLine($"{string.Join(@",
669 ", values)}");)";
670
671 EXPECT_EQ(Code, format(Code, Style));
672}
673
674TEST_F(FormatTestCSharp, CSharpNewOperator) {
675 FormatStyle Style = getLLVMStyle(Language: FormatStyle::LK_CSharp);
676
677 verifyFormat("public void F() {\n"
678 " var v = new C(() => { var t = 5; });\n"
679 "}",
680 Style);
681 verifyFormat("public void F() {\n"
682 " var v = new C(() => {\n"
683 " try {\n"
684 " } catch {\n"
685 " var t = 5;\n"
686 " }\n"
687 " });\n"
688 "}",
689 Style);
690}
691
692TEST_F(FormatTestCSharp, NewModifier) {
693 verifyFormat("public new class NestedC {\n"
694 " public int x = 100;\n"
695 "}",
696 getLLVMStyle(FormatStyle::LK_CSharp));
697}
698
699TEST_F(FormatTestCSharp, CSharpLambdas) {
700 FormatStyle GoogleStyle = getGoogleStyle(Language: FormatStyle::LK_CSharp);
701 FormatStyle MicrosoftStyle = getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
702
703 verifyFormat(R"(//
704class MyClass {
705 Action<string> greet = name => {
706 string greeting = $"Hello {name}!";
707 Console.WriteLine(greeting);
708 };
709})",
710 GoogleStyle);
711
712 // Microsoft Style:
713 // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#statement-lambdas
714 verifyFormat(R"(//
715class MyClass
716{
717 Action<string> greet = name =>
718 {
719 string greeting = $"Hello {name}!";
720 Console.WriteLine(greeting);
721 };
722})",
723 MicrosoftStyle);
724
725 verifyFormat("void bar()\n"
726 "{\n"
727 " Function(Val, (Action)(() =>\n"
728 " {\n"
729 " lock (mylock)\n"
730 " {\n"
731 " if (true)\n"
732 " {\n"
733 " A.Remove(item);\n"
734 " }\n"
735 " }\n"
736 " }));\n"
737 "}",
738 MicrosoftStyle);
739
740 verifyFormat("void baz()\n"
741 "{\n"
742 " Function(Val, (Action)(() =>\n"
743 " {\n"
744 " using (var a = new Lock())\n"
745 " {\n"
746 " if (true)\n"
747 " {\n"
748 " A.Remove(item);\n"
749 " }\n"
750 " }\n"
751 " }));\n"
752 "}",
753 MicrosoftStyle);
754
755 verifyFormat("void baz()\n"
756 "{\n"
757 " Function(Val, (Action)(() =>\n"
758 " {\n"
759 " if (true)\n"
760 " {\n"
761 " A.Remove(item);\n"
762 " }\n"
763 " }));\n"
764 "}",
765 MicrosoftStyle);
766
767 verifyFormat("void baz()\n"
768 "{\n"
769 " Function(Val, (Action)(() =>\n"
770 " {\n"
771 " do\n"
772 " {\n"
773 " A.Remove(item);\n"
774 " } while (true)\n"
775 " }));\n"
776 "}",
777 MicrosoftStyle);
778
779 verifyFormat("void baz()\n"
780 "{\n"
781 " Function(Val, (Action)(() =>\n"
782 " { A.Remove(item); }));\n"
783 "}",
784 MicrosoftStyle);
785
786 verifyFormat("void bar()\n"
787 "{\n"
788 " Function(Val, (() =>\n"
789 " {\n"
790 " lock (mylock)\n"
791 " {\n"
792 " if (true)\n"
793 " {\n"
794 " A.Remove(item);\n"
795 " }\n"
796 " }\n"
797 " }));\n"
798 "}",
799 MicrosoftStyle);
800 verifyFormat("void bar()\n"
801 "{\n"
802 " Function((() =>\n"
803 " {\n"
804 " lock (mylock)\n"
805 " {\n"
806 " if (true)\n"
807 " {\n"
808 " A.Remove(item);\n"
809 " }\n"
810 " }\n"
811 " }));\n"
812 "}",
813 MicrosoftStyle);
814
815 MicrosoftStyle.IndentWidth = 2;
816 verifyFormat("void bar()\n"
817 "{\n"
818 " Function((() =>\n"
819 " {\n"
820 " lock (mylock)\n"
821 " {\n"
822 " if (true)\n"
823 " {\n"
824 " A.Remove(item);\n"
825 " }\n"
826 " }\n"
827 " }));\n"
828 "}",
829 MicrosoftStyle);
830 verifyFormat("void bar() {\n"
831 " Function((() => {\n"
832 " lock (mylock) {\n"
833 " if (true) {\n"
834 " A.Remove(item);\n"
835 " }\n"
836 " }\n"
837 " }));\n"
838 "}",
839 GoogleStyle);
840}
841
842TEST_F(FormatTestCSharp, CSharpLambdasDontBreakFollowingCodeAlignment) {
843 FormatStyle GoogleStyle = getGoogleStyle(Language: FormatStyle::LK_CSharp);
844 FormatStyle MicrosoftStyle = getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
845
846 verifyFormat(R"(//
847public class Sample
848{
849 public void Test()
850 {
851 while (true)
852 {
853 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
854 CodeThatFollowsLambda();
855 IsWellAligned();
856 }
857 }
858})",
859 MicrosoftStyle);
860
861 verifyFormat(R"(//
862public class Sample {
863 public void Test() {
864 while (true) {
865 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
866 CodeThatFollowsLambda();
867 IsWellAligned();
868 }
869 }
870})",
871 GoogleStyle);
872}
873
874TEST_F(FormatTestCSharp, CSharpLambdasComplexLambdasDontBreakAlignment) {
875 FormatStyle GoogleStyle = getGoogleStyle(Language: FormatStyle::LK_CSharp);
876 FormatStyle MicrosoftStyle = getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
877
878 verifyFormat(R"(//
879public class Test
880{
881 private static void ComplexLambda(BuildReport protoReport)
882 {
883 allSelectedScenes =
884 veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
885 .Select(scene => scene.path)
886 .ToArray();
887 if (allSelectedScenes.Count == 0)
888 {
889 return;
890 }
891 Functions();
892 AreWell();
893 Aligned();
894 AfterLambdaBlock();
895 }
896})",
897 MicrosoftStyle);
898
899 verifyFormat(R"(//
900public class Test {
901 private static void ComplexLambda(BuildReport protoReport) {
902 allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
903 .Where(scene => scene.enabled)
904 .Select(scene => scene.path)
905 .ToArray();
906 if (allSelectedScenes.Count == 0) {
907 return;
908 }
909 Functions();
910 AreWell();
911 Aligned();
912 AfterLambdaBlock();
913 }
914})",
915 GoogleStyle);
916}
917
918TEST_F(FormatTestCSharp, CSharpLambdasMulipleLambdasDontBreakAlignment) {
919 FormatStyle GoogleStyle = getGoogleStyle(Language: FormatStyle::LK_CSharp);
920 FormatStyle MicrosoftStyle = getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
921
922 verifyFormat(R"(//
923public class Test
924{
925 private static void MultipleLambdas(BuildReport protoReport)
926 {
927 allSelectedScenes =
928 veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
929 .Select(scene => scene.path)
930 .ToArray();
931 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
932 if (allSelectedScenes.Count == 0)
933 {
934 return;
935 }
936 Functions();
937 AreWell();
938 Aligned();
939 AfterLambdaBlock();
940 }
941})",
942 MicrosoftStyle);
943
944 verifyFormat(R"(//
945public class Test {
946 private static void MultipleLambdas(BuildReport protoReport) {
947 allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
948 .Where(scene => scene.enabled)
949 .Select(scene => scene.path)
950 .ToArray();
951 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
952 if (allSelectedScenes.Count == 0) {
953 return;
954 }
955 Functions();
956 AreWell();
957 Aligned();
958 AfterLambdaBlock();
959 }
960})",
961 GoogleStyle);
962}
963
964TEST_F(FormatTestCSharp, CSharpObjectInitializers) {
965 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
966
967 // Start code fragments with a comment line so that C++ raw string literals
968 // as seen are identical to expected formatted code.
969
970 verifyFormat(R"(//
971Shape[] shapes = new[] {
972 new Circle {
973 Radius = 2.7281,
974 Colour = Colours.Red,
975 },
976 new Square {
977 Side = 101.1,
978 Colour = Colours.Yellow,
979 },
980};)",
981 Style);
982
983 // Omitted final `,`s will change the formatting.
984 verifyFormat(R"(//
985Shape[] shapes = new[] { new Circle { Radius = 2.7281, Colour = Colours.Red },
986 new Square { Side = 101.1, Colour = Colours.Yellow } };)",
987 Style);
988
989 // Lambdas can be supplied as initialiser arguments.
990 verifyFormat(R"(//
991private Transformer _transformer = new X.Y {
992 Filler = (Shape shape) => { return new Transform.Fill(shape, RED); },
993 Scaler = (Shape shape) => { return new Transform.Resize(shape, 0.1); },
994};)",
995 Style);
996
997 // Dictionary initialisation.
998 verifyFormat(R"(//
999var myDict = new Dictionary<string, string> {
1000 ["name"] = _donald,
1001 ["age"] = Convert.ToString(DateTime.Today.Year - 1934),
1002 ["type"] = _duck,
1003};)",
1004 Style);
1005}
1006
1007TEST_F(FormatTestCSharp, CSharpArrayInitializers) {
1008 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
1009
1010 verifyFormat(R"(//
1011private MySet<Node>[] setPoints = {
1012 new Point<Node>(),
1013 new Point<Node>(),
1014};)",
1015 Style);
1016}
1017
1018TEST_F(FormatTestCSharp, CSharpNamedArguments) {
1019 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
1020
1021 verifyFormat(R"(//
1022PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");)",
1023 Style);
1024
1025 // Ensure that trailing comments do not cause problems.
1026 verifyFormat(R"(//
1027PrintOrderDetails(orderNum: 31, productName: "Red Mug", // comment
1028 sellerName: "Gift Shop");)",
1029 Style);
1030
1031 verifyFormat(R"(foreach (var tickCount in task.Begin(seed: 0)) {)", Style);
1032}
1033
1034TEST_F(FormatTestCSharp, CSharpPropertyAccessors) {
1035 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
1036
1037 verifyFormat("int Value { get }", Style);
1038 verifyFormat("int Value { get; }", Style);
1039 verifyFormat("int Value { internal get; }", Style);
1040 verifyFormat("int Value { get; } = 0", Style);
1041 verifyFormat("int Value { set }", Style);
1042 verifyFormat("int Value { set; }", Style);
1043 verifyFormat("int Value { init; }", Style);
1044 verifyFormat("int Value { internal set; }", Style);
1045 verifyFormat("int Value { set; } = 0", Style);
1046 verifyFormat("int Value { get; set }", Style);
1047 verifyFormat("int Value { get; init; }", Style);
1048 verifyFormat("int Value { set; get }", Style);
1049 verifyFormat("int Value { get; private set; }", Style);
1050 verifyFormat("int Value { get; set; }", Style);
1051 verifyFormat("int Value { get; set; } = 0", Style);
1052 verifyFormat("int Value { internal get; internal set; }", Style);
1053
1054 // Do not wrap expression body definitions.
1055 verifyFormat(R"(//
1056public string Name {
1057 get => _name;
1058 set => _name = value;
1059})",
1060 Style);
1061 verifyFormat(R"(//
1062public string Name {
1063 init => _name = value;
1064 get => _name;
1065})",
1066 Style);
1067 verifyFormat(R"(//
1068public string Name {
1069 set => _name = value;
1070 get => _name;
1071})",
1072 Style);
1073
1074 // Examples taken from
1075 // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
1076 verifyFormat(R"(
1077// Expression body definitions
1078public class SaleItem {
1079 public decimal Price {
1080 get => _cost;
1081 set => _cost = value;
1082 }
1083})",
1084 Style);
1085
1086 verifyFormat(R"(
1087// Properties with backing fields
1088class TimePeriod {
1089 public double Hours {
1090 get { return _seconds / 3600; }
1091 set {
1092 if (value < 0 || value > 24)
1093 throw new ArgumentOutOfRangeException($"{nameof(value)} must be between 0 and 24.");
1094 _seconds = value * 3600;
1095 }
1096 }
1097})",
1098 Style);
1099
1100 verifyFormat(R"(
1101// Auto-implemented properties
1102public class SaleItem {
1103 public decimal Price { get; set; }
1104})",
1105 Style);
1106
1107 // Add column limit to wrap long lines.
1108 Style.ColumnLimit = 100;
1109
1110 // Examples with assignment to default value.
1111 verifyFormat(R"(
1112// Long assignment to default value
1113class MyClass {
1114 public override VeryLongNamedTypeIndeed VeryLongNamedValue { get; set } =
1115 VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
1116 DefaultThirdArgument);
1117})",
1118 Style);
1119
1120 verifyFormat(R"(
1121// Long assignment to default value with expression body
1122class MyClass {
1123 public override VeryLongNamedTypeIndeed VeryLongNamedValue {
1124 get => veryLongNamedField;
1125 set => veryLongNamedField = value;
1126 } = VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
1127 DefaultThirdArgument);
1128})",
1129 Style);
1130
1131 // Brace wrapping and single-lining of accessor can be controlled by config.
1132 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
1133 Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1134 Style.BraceWrapping.AfterFunction = true;
1135
1136 verifyFormat(R"(//
1137class TimePeriod {
1138 public double Hours
1139 {
1140 get {
1141 return _seconds / 3600;
1142 }
1143 set {
1144 _seconds = value * 3600;
1145 }
1146 }
1147})",
1148 Style);
1149
1150 // Microsoft style trivial property accessors have no line break before the
1151 // opening brace.
1152 auto MicrosoftStyle = getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
1153 verifyFormat(R"(//
1154public class SaleItem
1155{
1156 public decimal Price { get; set; }
1157})",
1158 MicrosoftStyle);
1159
1160 verifyFormat("internal class Program\n"
1161 "{\n"
1162 " bool AutoAllowKnownApps\n"
1163 " {\n"
1164 " get;\n"
1165 " [Simple]\n"
1166 " set;\n"
1167 " }\n"
1168 "}",
1169 MicrosoftStyle);
1170}
1171
1172TEST_F(FormatTestCSharp, DefaultLiteral) {
1173 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
1174
1175 verifyFormat(
1176 "T[] InitializeArray<T>(int length, T initialValue = default) {}", Style);
1177 verifyFormat("System.Numerics.Complex fillValue = default;", Style);
1178 verifyFormat("int Value { get } = default;", Style);
1179 verifyFormat("int Value { get } = default!;", Style);
1180 verifyFormat(R"(//
1181public record Person {
1182 public string GetInit { get; init; } = default!;
1183};)",
1184 Style);
1185 verifyFormat(R"(//
1186public record Person {
1187 public string GetSet { get; set; } = default!;
1188};)",
1189 Style);
1190}
1191
1192TEST_F(FormatTestCSharp, CSharpSpaces) {
1193 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
1194 Style.SpaceBeforeSquareBrackets = false;
1195 Style.SpacesInSquareBrackets = false;
1196 Style.SpaceBeforeCpp11BracedList = true;
1197 Style.Cpp11BracedListStyle = false;
1198 Style.SpacesInContainerLiterals = false;
1199 Style.SpaceAfterCStyleCast = false;
1200
1201 verifyFormat(R"(new Car { "Door", 0.1 })", Style);
1202 verifyFormat(R"(new Car { 0.1, "Door" })", Style);
1203 verifyFormat(R"(new string[] { "A" })", Style);
1204 verifyFormat(R"(new string[] {})", Style);
1205 verifyFormat(R"(new Car { someVariableName })", Style);
1206 verifyFormat(R"(new Car { someVariableName })", Style);
1207 verifyFormat(R"(new Dictionary<string, string> { ["Key"] = "Value" };)",
1208 Style);
1209 verifyFormat(R"(Apply(x => x.Name, x => () => x.ID);)", Style);
1210 verifyFormat(R"(bool[] xs = { true, true };)", Style);
1211 verifyIncompleteFormat(
1212 R"(taskContext.Factory.Run(async () => doThing(args);)", Style);
1213 verifyFormat(R"(catch (TestException) when (innerFinallyExecuted))", Style);
1214 verifyFormat(R"(private float[,] Values;)", Style);
1215 verifyFormat(R"(Result this[Index x] => Foo(x);)", Style);
1216
1217 verifyFormat(R"(char[,,] rawCharArray = MakeCharacterGrid();)", Style);
1218 verifyFormat(R"(var (key, value))", Style);
1219
1220 // `&&` is not seen as a reference.
1221 verifyFormat(R"(A == typeof(X) && someBool)", Style);
1222
1223 // Not seen as a C-style cast.
1224 verifyFormat(R"(//
1225foreach ((A a, B b) in someList) {
1226})",
1227 Style);
1228
1229 // space after lock in `lock (processes)`.
1230 verifyFormat("lock (process)", Style);
1231
1232 Style.SpacesInSquareBrackets = true;
1233 verifyFormat(R"(private float[ , ] Values;)", Style);
1234 verifyFormat(R"(string dirPath = args?[ 0 ];)", Style);
1235 verifyFormat(R"(char[ ,, ] rawCharArray = MakeCharacterGrid();)", Style);
1236
1237 // Method returning tuple
1238 verifyFormat(R"(public (string name, int age) methodTuple() {})", Style);
1239 verifyFormat(R"(private (string name, int age) methodTuple() {})", Style);
1240 verifyFormat(R"(protected (string name, int age) methodTuple() {})", Style);
1241 verifyFormat(R"(virtual (string name, int age) methodTuple() {})", Style);
1242 verifyFormat(R"(extern (string name, int age) methodTuple() {})", Style);
1243 verifyFormat(R"(static (string name, int age) methodTuple() {})", Style);
1244 verifyFormat(R"(internal (string name, int age) methodTuple() {})", Style);
1245 verifyFormat(R"(abstract (string name, int age) methodTuple() {})", Style);
1246 verifyFormat(R"(sealed (string name, int age) methodTuple() {})", Style);
1247 verifyFormat(R"(override (string name, int age) methodTuple() {})", Style);
1248 verifyFormat(R"(async (string name, int age) methodTuple() {})", Style);
1249 verifyFormat(R"(unsafe (string name, int age) methodTuple() {})", Style);
1250
1251 Style.SpacesInSquareBrackets = false;
1252 Style.SpaceBeforeSquareBrackets = true;
1253 verifyFormat("return a is [1, 2, 3];", Style);
1254 verifyFormat("return a is [..];", Style);
1255 Style.SpaceBeforeSquareBrackets = false;
1256 verifyFormat("return a is [1, 2, 3];", Style);
1257 verifyFormat("return a is [..];", Style);
1258}
1259
1260TEST_F(FormatTestCSharp, CSharpNullableTypes) {
1261 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
1262 Style.SpacesInSquareBrackets = false;
1263
1264 verifyFormat(R"(//
1265public class A {
1266 void foo() {
1267 int? value = some.bar();
1268 }
1269})",
1270 Style); // int? is nullable not a conditional expression.
1271
1272 verifyFormat(R"(void foo(int? x, int? y, int? z) {})",
1273 Style); // Nullables in function definitions.
1274
1275 verifyFormat(R"(public float? Value;)", Style); // no space before `?`.
1276
1277 verifyFormat(R"(int?[] arr = new int?[10];)",
1278 Style); // An array of a nullable type.
1279
1280 verifyFormat(R"(var x = (int?)y;)", Style); // Cast to a nullable type.
1281
1282 verifyFormat(R"(var x = new MyContainer<int?>();)", Style); // Generics.
1283
1284 verifyFormat(R"(//
1285public interface I {
1286 int? Function();
1287})",
1288 Style); // Interface methods.
1289
1290 Style.ColumnLimit = 10;
1291 verifyFormat(R"(//
1292public VeryLongType? Function(
1293 int arg1,
1294 int arg2) {
1295 //
1296})",
1297 Style); // ? sticks with identifier.
1298}
1299
1300TEST_F(FormatTestCSharp, CSharpArraySubscripts) {
1301 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
1302
1303 // Do not format array subscript operators as attributes.
1304 verifyFormat(R"(//
1305if (someThings[index].Contains(myThing)) {
1306})",
1307 Style);
1308
1309 verifyFormat(R"(//
1310if (someThings[i][j][k].Contains(myThing)) {
1311})",
1312 Style);
1313}
1314
1315TEST_F(FormatTestCSharp, CSharpGenericTypeConstraints) {
1316 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
1317
1318 EXPECT_TRUE(Style.BraceWrapping.SplitEmptyRecord);
1319
1320 verifyFormat("class ItemFactory<T>\n"
1321 " where T : new() {\n"
1322 "}",
1323 Style);
1324
1325 verifyFormat("namespace A {\n"
1326 " delegate T MyDelegate<T>()\n"
1327 " where T : new();\n"
1328 "}",
1329 Style);
1330
1331 // When the "where" line is not to be formatted, following lines should not
1332 // take on its indentation.
1333 verifyFormat("class ItemFactory<T>\n"
1334 " where T : new() {\n"
1335 " int f() {}\n"
1336 "}",
1337 "class ItemFactory<T>\n"
1338 " where T : new() {\n"
1339 " int f() {}\n"
1340 "}",
1341 Style, {tooling::Range(43, 13)});
1342
1343 verifyFormat("class Dictionary<TKey, TVal>\n"
1344 " where TKey : IComparable<TKey>\n"
1345 " where TVal : IMyInterface {\n"
1346 " public void MyMethod<T>(T t)\n"
1347 " where T : IMyInterface {\n"
1348 " doThing();\n"
1349 " }\n"
1350 "}",
1351 Style);
1352
1353 verifyFormat("class ItemFactory<T>\n"
1354 " where T : new(), IAnInterface<T>, IAnotherInterface<T>, "
1355 "IAnotherInterfaceStill<T> {\n"
1356 "}",
1357 Style);
1358
1359 Style.ColumnLimit = 50; // Force lines to be wrapped.
1360 verifyFormat(R"(//
1361class ItemFactory<T, U>
1362 where T : new(),
1363 IAnInterface<T>,
1364 IAnotherInterface<T, U>,
1365 IAnotherInterfaceStill<T, U> {
1366})",
1367 Style);
1368
1369 // In other languages `where` can be used as a normal identifier.
1370 // This example is in C++!
1371 verifyFormat(R"(//
1372class A {
1373 int f(int where) {}
1374};)",
1375 getGoogleStyle(FormatStyle::LK_Cpp));
1376}
1377
1378TEST_F(FormatTestCSharp, CSharpAfterEnum) {
1379 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
1380 Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1381 Style.BraceWrapping.AfterEnum = false;
1382 Style.AllowShortEnumsOnASingleLine = false;
1383
1384 verifyFormat("enum MyEnum {\n"
1385 " Foo,\n"
1386 " Bar,\n"
1387 "}",
1388 Style);
1389 verifyFormat("internal enum MyEnum {\n"
1390 " Foo,\n"
1391 " Bar,\n"
1392 "}",
1393 Style);
1394 verifyFormat("public enum MyEnum {\n"
1395 " Foo,\n"
1396 " Bar,\n"
1397 "}",
1398 Style);
1399 verifyFormat("protected enum MyEnum {\n"
1400 " Foo,\n"
1401 " Bar,\n"
1402 "}",
1403 Style);
1404 verifyFormat("private enum MyEnum {\n"
1405 " Foo,\n"
1406 " Bar,\n"
1407 "}",
1408 Style);
1409
1410 Style.BraceWrapping.AfterEnum = true;
1411 Style.AllowShortEnumsOnASingleLine = false;
1412
1413 verifyFormat("enum MyEnum\n"
1414 "{\n"
1415 " Foo,\n"
1416 " Bar,\n"
1417 "}",
1418 Style);
1419 verifyFormat("internal enum MyEnum\n"
1420 "{\n"
1421 " Foo,\n"
1422 " Bar,\n"
1423 "}",
1424 Style);
1425 verifyFormat("public enum MyEnum\n"
1426 "{\n"
1427 " Foo,\n"
1428 " Bar,\n"
1429 "}",
1430 Style);
1431 verifyFormat("protected enum MyEnum\n"
1432 "{\n"
1433 " Foo,\n"
1434 " Bar,\n"
1435 "}",
1436 Style);
1437 verifyFormat("private enum MyEnum\n"
1438 "{\n"
1439 " Foo,\n"
1440 " Bar,\n"
1441 "}",
1442 Style);
1443 verifyFormat("/* Foo */ private enum MyEnum\n"
1444 "{\n"
1445 " Foo,\n"
1446 " Bar,\n"
1447 "}",
1448 Style);
1449 verifyFormat("/* Foo */ /* Bar */ private enum MyEnum\n"
1450 "{\n"
1451 " Foo,\n"
1452 " Bar,\n"
1453 "}",
1454 Style);
1455}
1456
1457TEST_F(FormatTestCSharp, CSharpAfterClass) {
1458 FormatStyle Style = getGoogleStyle(Language: FormatStyle::LK_CSharp);
1459 Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1460 Style.BraceWrapping.AfterClass = false;
1461
1462 verifyFormat("class MyClass {\n"
1463 " int a;\n"
1464 " int b;\n"
1465 "}",
1466 Style);
1467 verifyFormat("internal class MyClass {\n"
1468 " int a;\n"
1469 " int b;\n"
1470 "}",
1471 Style);
1472 verifyFormat("public class MyClass {\n"
1473 " int a;\n"
1474 " int b;\n"
1475 "}",
1476 Style);
1477 verifyFormat("protected class MyClass {\n"
1478 " int a;\n"
1479 " int b;\n"
1480 "}",
1481 Style);
1482 verifyFormat("private class MyClass {\n"
1483 " int a;\n"
1484 " int b;\n"
1485 "}",
1486 Style);
1487
1488 verifyFormat("interface Interface {\n"
1489 " int a;\n"
1490 " int b;\n"
1491 "}",
1492 Style);
1493 verifyFormat("internal interface Interface {\n"
1494 " int a;\n"
1495 " int b;\n"
1496 "}",
1497 Style);
1498 verifyFormat("public interface Interface {\n"
1499 " int a;\n"
1500 " int b;\n"
1501 "}",
1502 Style);
1503 verifyFormat("protected interface Interface {\n"
1504 " int a;\n"
1505 " int b;\n"
1506 "}",
1507 Style);
1508 verifyFormat("private interface Interface {\n"
1509 " int a;\n"
1510 " int b;\n"
1511 "}",
1512 Style);
1513
1514 Style.BraceWrapping.AfterClass = true;
1515
1516 verifyFormat("class MyClass\n"
1517 "{\n"
1518 " int a;\n"
1519 " int b;\n"
1520 "}",
1521 Style);
1522 verifyFormat("internal class MyClass\n"
1523 "{\n"
1524 " int a;\n"
1525 " int b;\n"
1526 "}",
1527 Style);
1528 verifyFormat("public class MyClass\n"
1529 "{\n"
1530 " int a;\n"
1531 " int b;\n"
1532 "}",
1533 Style);
1534 verifyFormat("protected class MyClass\n"
1535 "{\n"
1536 " int a;\n"
1537 " int b;\n"
1538 "}",
1539 Style);
1540 verifyFormat("private class MyClass\n"
1541 "{\n"
1542 " int a;\n"
1543 " int b;\n"
1544 "}",
1545 Style);
1546
1547 verifyFormat("interface MyInterface\n"
1548 "{\n"
1549 " int a;\n"
1550 " int b;\n"
1551 "}",
1552 Style);
1553 verifyFormat("internal interface MyInterface\n"
1554 "{\n"
1555 " int a;\n"
1556 " int b;\n"
1557 "}",
1558 Style);
1559 verifyFormat("public interface MyInterface\n"
1560 "{\n"
1561 " int a;\n"
1562 " int b;\n"
1563 "}",
1564 Style);
1565 verifyFormat("protected interface MyInterface\n"
1566 "{\n"
1567 " int a;\n"
1568 " int b;\n"
1569 "}",
1570 Style);
1571 verifyFormat("private interface MyInterface\n"
1572 "{\n"
1573 " int a;\n"
1574 " int b;\n"
1575 "}",
1576 Style);
1577 verifyFormat("/* Foo */ private interface MyInterface\n"
1578 "{\n"
1579 " int a;\n"
1580 " int b;\n"
1581 "}",
1582 Style);
1583 verifyFormat("/* Foo */ /* Bar */ private interface MyInterface\n"
1584 "{\n"
1585 " int a;\n"
1586 " int b;\n"
1587 "}",
1588 Style);
1589}
1590
1591TEST_F(FormatTestCSharp, NamespaceIndentation) {
1592 FormatStyle Style = getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
1593 Style.NamespaceIndentation = FormatStyle::NI_None;
1594
1595 verifyFormat("namespace A\n"
1596 "{\n"
1597 "public interface Name1\n"
1598 "{\n"
1599 "}\n"
1600 "}",
1601 Style);
1602
1603 verifyFormat("namespace A.B\n"
1604 "{\n"
1605 "public interface Name1\n"
1606 "{\n"
1607 "}\n"
1608 "}",
1609 Style);
1610
1611 Style.NamespaceIndentation = FormatStyle::NI_Inner;
1612
1613 verifyFormat("namespace A\n"
1614 "{\n"
1615 "namespace B\n"
1616 "{\n"
1617 " public interface Name1\n"
1618 " {\n"
1619 " }\n"
1620 "}\n"
1621 "}",
1622 Style);
1623
1624 Style.NamespaceIndentation = FormatStyle::NI_All;
1625
1626 verifyFormat("namespace A.B\n"
1627 "{\n"
1628 " public interface Name1\n"
1629 " {\n"
1630 " }\n"
1631 "}",
1632 Style);
1633
1634 verifyFormat("namespace A\n"
1635 "{\n"
1636 " namespace B\n"
1637 " {\n"
1638 " public interface Name1\n"
1639 " {\n"
1640 " }\n"
1641 " }\n"
1642 "}",
1643 Style);
1644}
1645
1646TEST_F(FormatTestCSharp, SwitchExpression) {
1647 FormatStyle Style = getMicrosoftStyle(Language: FormatStyle::LK_CSharp);
1648 verifyFormat("int x = a switch {\n"
1649 " 1 => (0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0),\n"
1650 " 2 => 1,\n"
1651 " _ => 2\n"
1652 "};",
1653 Style);
1654}
1655
1656TEST_F(FormatTestCSharp, EmptyShortBlock) {
1657 auto Style = getLLVMStyle();
1658 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
1659
1660 verifyFormat("try {\n"
1661 " doA();\n"
1662 "} catch (Exception e) {\n"
1663 " e.printStackTrace();\n"
1664 "}",
1665 Style);
1666
1667 verifyFormat("try {\n"
1668 " doA();\n"
1669 "} catch (Exception e) {}",
1670 Style);
1671}
1672
1673TEST_F(FormatTestCSharp, ShortFunctions) {
1674 FormatStyle Style = getLLVMStyle(Language: FormatStyle::LK_CSharp);
1675 Style.NamespaceIndentation = FormatStyle::NI_All;
1676 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
1677 verifyFormat("interface Interface {\n"
1678 " void f() { return; }\n"
1679 "};",
1680 Style);
1681 verifyFormat("public interface Interface {\n"
1682 " void f() { return; }\n"
1683 "};",
1684 Style);
1685 verifyFormat("namespace {\n"
1686 " void f() {\n"
1687 " return;\n"
1688 " }\n"
1689 "};",
1690 Style);
1691 // "union" is not a keyword in C#.
1692 verifyFormat("namespace union {\n"
1693 " void f() {\n"
1694 " return;\n"
1695 " }\n"
1696 "};",
1697 Style);
1698}
1699
1700TEST_F(FormatTestCSharp, BrokenBrackets) {
1701 EXPECT_NE("", format("int where b <")); // reduced from crasher
1702}
1703
1704TEST_F(FormatTestCSharp, GotoCaseLabel) {
1705 verifyFormat("switch (i)\n"
1706 "{\n"
1707 "case 0:\n"
1708 " goto case 1;\n"
1709 "case 1:\n"
1710 " j = 0;\n"
1711 " {\n"
1712 " break;\n"
1713 " }\n"
1714 "}",
1715 "switch (i) {\n"
1716 "case 0:\n"
1717 " goto case 1;\n"
1718 "case 1:\n"
1719 " j = 0;\n"
1720 " {\n"
1721 " break;\n"
1722 " }\n"
1723 "}");
1724}
1725
1726} // namespace
1727} // namespace test
1728} // namespace format
1729} // namespace clang
1730

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/unittests/Format/FormatTestCSharp.cpp