xref: /llvm-project/clang/unittests/Format/FormatTestCSharp.cpp (revision d005be33ee776c5d788693f5c1cf4f6bc242e13c)
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 
13 namespace clang {
14 namespace format {
15 namespace test {
16 namespace {
17 
18 class FormatTestCSharp : public test::FormatTestBase {
19 protected:
20   FormatStyle getDefaultStyle() const override {
21     return getMicrosoftStyle(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(FormatStyle::LK_CSharp)) {
39     return format(Code, 0, Code.size(), Style);
40   }
41 
42   static FormatStyle getStyleWithColumns(unsigned ColumnLimit) {
43     FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
44     Style.ColumnLimit = ColumnLimit;
45     return Style;
46   }
47 };
48 
49 TEST_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(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 
95 TEST_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 
127 TEST_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 
138 TEST_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 
189 TEST_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 
204 TEST_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 
220 TEST_F(FormatTestCSharp, CSharpFatArrows) {
221   verifyIncompleteFormat("Task serverTask = Task.Run(async() => {");
222   verifyFormat("public override string ToString() => \"{Name}\\{Age}\";");
223 }
224 
225 TEST_F(FormatTestCSharp, CSharpConditionalExpressions) {
226   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
227   // conditional expression is not seen as a NullConditional.
228   verifyFormat("var y = A < B ? -1 : 1;", Style);
229 }
230 
231 TEST_F(FormatTestCSharp, CSharpNullConditional) {
232   FormatStyle Style = getGoogleStyle(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 
255 TEST_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"(//
387 public 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(FormatStyle::LK_CSharp);
398   Style.ColumnLimit = 10;
399   verifyFormat(R"([assembly:InternalsVisibleTo(
400     "SomeAssembly, PublicKey=SomePublicKeyThatExceedsTheColumnLimit")])",
401                Style);
402 }
403 
404 TEST_F(FormatTestCSharp, CSharpUsing) {
405   FormatStyle Style = getGoogleStyle(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 
451 TEST_F(FormatTestCSharp, CSharpRegions) {
452   verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa "
453                "aaaaaaaaaaaaaaa long region");
454 }
455 
456 TEST_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 
467 TEST_F(FormatTestCSharp, CSharpNullCoalescing) {
468   verifyFormat("var test = ABC ?? DEF");
469   verifyFormat("string myname = name ?? \"ABC\";");
470   verifyFormat("return _name ?? \"DEF\";");
471 }
472 
473 TEST_F(FormatTestCSharp, CSharpNullCoalescingAssignment) {
474   FormatStyle Style = getGoogleStyle(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 
486 TEST_F(FormatTestCSharp, CSharpNullForgiving) {
487   FormatStyle Style = getGoogleStyle(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 
506 TEST_F(FormatTestCSharp, AttributesIndentation) {
507   FormatStyle Style = getMicrosoftStyle(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 
579 TEST_F(FormatTestCSharp, CSharpSpaceBefore) {
580   FormatStyle Style = getGoogleStyle(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 
614 TEST_F(FormatTestCSharp, CSharpSpaceAfterCStyleCast) {
615   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
616 
617   verifyFormat("(int)x / y;", Style);
618 
619   Style.SpaceAfterCStyleCast = true;
620   verifyFormat("(int) x / y;", Style);
621 }
622 
623 TEST_F(FormatTestCSharp, CSharpEscapedQuotesInVerbatimStrings) {
624   FormatStyle Style = getGoogleStyle(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 
634 TEST_F(FormatTestCSharp, CSharpQuotesInInterpolatedStrings) {
635   FormatStyle Style = getGoogleStyle(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 
642 TEST_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(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"(
659 var 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 
674 TEST_F(FormatTestCSharp, CSharpNewOperator) {
675   FormatStyle Style = getLLVMStyle(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 
692 TEST_F(FormatTestCSharp, CSharpLambdas) {
693   FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
694   FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
695 
696   verifyFormat(R"(//
697 class MyClass {
698   Action<string> greet = name => {
699     string greeting = $"Hello {name}!";
700     Console.WriteLine(greeting);
701   };
702 })",
703                GoogleStyle);
704 
705   // Microsoft Style:
706   // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#statement-lambdas
707   verifyFormat(R"(//
708 class MyClass
709 {
710     Action<string> greet = name =>
711     {
712         string greeting = $"Hello {name}!";
713         Console.WriteLine(greeting);
714     };
715 })",
716                MicrosoftStyle);
717 
718   verifyFormat("void bar()\n"
719                "{\n"
720                "    Function(Val, (Action)(() =>\n"
721                "                           {\n"
722                "                               lock (mylock)\n"
723                "                               {\n"
724                "                                   if (true)\n"
725                "                                   {\n"
726                "                                       A.Remove(item);\n"
727                "                                   }\n"
728                "                               }\n"
729                "                           }));\n"
730                "}",
731                MicrosoftStyle);
732 
733   verifyFormat("void baz()\n"
734                "{\n"
735                "    Function(Val, (Action)(() =>\n"
736                "                           {\n"
737                "                               using (var a = new Lock())\n"
738                "                               {\n"
739                "                                   if (true)\n"
740                "                                   {\n"
741                "                                       A.Remove(item);\n"
742                "                                   }\n"
743                "                               }\n"
744                "                           }));\n"
745                "}",
746                MicrosoftStyle);
747 
748   verifyFormat("void baz()\n"
749                "{\n"
750                "    Function(Val, (Action)(() =>\n"
751                "                           {\n"
752                "                               if (true)\n"
753                "                               {\n"
754                "                                   A.Remove(item);\n"
755                "                               }\n"
756                "                           }));\n"
757                "}",
758                MicrosoftStyle);
759 
760   verifyFormat("void baz()\n"
761                "{\n"
762                "    Function(Val, (Action)(() =>\n"
763                "                           {\n"
764                "                               do\n"
765                "                               {\n"
766                "                                   A.Remove(item);\n"
767                "                               } while (true)\n"
768                "                           }));\n"
769                "}",
770                MicrosoftStyle);
771 
772   verifyFormat("void baz()\n"
773                "{\n"
774                "    Function(Val, (Action)(() =>\n"
775                "                           { A.Remove(item); }));\n"
776                "}",
777                MicrosoftStyle);
778 
779   verifyFormat("void bar()\n"
780                "{\n"
781                "    Function(Val, (() =>\n"
782                "                   {\n"
783                "                       lock (mylock)\n"
784                "                       {\n"
785                "                           if (true)\n"
786                "                           {\n"
787                "                               A.Remove(item);\n"
788                "                           }\n"
789                "                       }\n"
790                "                   }));\n"
791                "}",
792                MicrosoftStyle);
793   verifyFormat("void bar()\n"
794                "{\n"
795                "    Function((() =>\n"
796                "              {\n"
797                "                  lock (mylock)\n"
798                "                  {\n"
799                "                      if (true)\n"
800                "                      {\n"
801                "                          A.Remove(item);\n"
802                "                      }\n"
803                "                  }\n"
804                "              }));\n"
805                "}",
806                MicrosoftStyle);
807 
808   MicrosoftStyle.IndentWidth = 2;
809   verifyFormat("void bar()\n"
810                "{\n"
811                "  Function((() =>\n"
812                "            {\n"
813                "              lock (mylock)\n"
814                "              {\n"
815                "                if (true)\n"
816                "                {\n"
817                "                  A.Remove(item);\n"
818                "                }\n"
819                "              }\n"
820                "            }));\n"
821                "}",
822                MicrosoftStyle);
823   verifyFormat("void bar() {\n"
824                "  Function((() => {\n"
825                "    lock (mylock) {\n"
826                "      if (true) {\n"
827                "        A.Remove(item);\n"
828                "      }\n"
829                "    }\n"
830                "  }));\n"
831                "}",
832                GoogleStyle);
833 }
834 
835 TEST_F(FormatTestCSharp, CSharpLambdasDontBreakFollowingCodeAlignment) {
836   FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
837   FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
838 
839   verifyFormat(R"(//
840 public class Sample
841 {
842     public void Test()
843     {
844         while (true)
845         {
846             preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
847             CodeThatFollowsLambda();
848             IsWellAligned();
849         }
850     }
851 })",
852                MicrosoftStyle);
853 
854   verifyFormat(R"(//
855 public class Sample {
856   public void Test() {
857     while (true) {
858       preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
859       CodeThatFollowsLambda();
860       IsWellAligned();
861     }
862   }
863 })",
864                GoogleStyle);
865 }
866 
867 TEST_F(FormatTestCSharp, CSharpLambdasComplexLambdasDontBreakAlignment) {
868   FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
869   FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
870 
871   verifyFormat(R"(//
872 public class Test
873 {
874     private static void ComplexLambda(BuildReport protoReport)
875     {
876         allSelectedScenes =
877             veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
878                 .Select(scene => scene.path)
879                 .ToArray();
880         if (allSelectedScenes.Count == 0)
881         {
882             return;
883         }
884         Functions();
885         AreWell();
886         Aligned();
887         AfterLambdaBlock();
888     }
889 })",
890                MicrosoftStyle);
891 
892   verifyFormat(R"(//
893 public class Test {
894   private static void ComplexLambda(BuildReport protoReport) {
895     allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
896                             .Where(scene => scene.enabled)
897                             .Select(scene => scene.path)
898                             .ToArray();
899     if (allSelectedScenes.Count == 0) {
900       return;
901     }
902     Functions();
903     AreWell();
904     Aligned();
905     AfterLambdaBlock();
906   }
907 })",
908                GoogleStyle);
909 }
910 
911 TEST_F(FormatTestCSharp, CSharpLambdasMulipleLambdasDontBreakAlignment) {
912   FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
913   FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
914 
915   verifyFormat(R"(//
916 public class Test
917 {
918     private static void MultipleLambdas(BuildReport protoReport)
919     {
920         allSelectedScenes =
921             veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
922                 .Select(scene => scene.path)
923                 .ToArray();
924         preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
925         if (allSelectedScenes.Count == 0)
926         {
927             return;
928         }
929         Functions();
930         AreWell();
931         Aligned();
932         AfterLambdaBlock();
933     }
934 })",
935                MicrosoftStyle);
936 
937   verifyFormat(R"(//
938 public class Test {
939   private static void MultipleLambdas(BuildReport protoReport) {
940     allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
941                             .Where(scene => scene.enabled)
942                             .Select(scene => scene.path)
943                             .ToArray();
944     preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
945     if (allSelectedScenes.Count == 0) {
946       return;
947     }
948     Functions();
949     AreWell();
950     Aligned();
951     AfterLambdaBlock();
952   }
953 })",
954                GoogleStyle);
955 }
956 
957 TEST_F(FormatTestCSharp, CSharpObjectInitializers) {
958   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
959 
960   // Start code fragments with a comment line so that C++ raw string literals
961   // as seen are identical to expected formatted code.
962 
963   verifyFormat(R"(//
964 Shape[] shapes = new[] {
965   new Circle {
966     Radius = 2.7281,
967     Colour = Colours.Red,
968   },
969   new Square {
970     Side = 101.1,
971     Colour = Colours.Yellow,
972   },
973 };)",
974                Style);
975 
976   // Omitted final `,`s will change the formatting.
977   verifyFormat(R"(//
978 Shape[] shapes = new[] { new Circle { Radius = 2.7281, Colour = Colours.Red },
979                          new Square { Side = 101.1, Colour = Colours.Yellow } };)",
980                Style);
981 
982   // Lambdas can be supplied as initialiser arguments.
983   verifyFormat(R"(//
984 private Transformer _transformer = new X.Y {
985   Filler = (Shape shape) => { return new Transform.Fill(shape, RED); },
986   Scaler = (Shape shape) => { return new Transform.Resize(shape, 0.1); },
987 };)",
988                Style);
989 
990   // Dictionary initialisation.
991   verifyFormat(R"(//
992 var myDict = new Dictionary<string, string> {
993   ["name"] = _donald,
994   ["age"] = Convert.ToString(DateTime.Today.Year - 1934),
995   ["type"] = _duck,
996 };)",
997                Style);
998 }
999 
1000 TEST_F(FormatTestCSharp, CSharpArrayInitializers) {
1001   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1002 
1003   verifyFormat(R"(//
1004 private MySet<Node>[] setPoints = {
1005   new Point<Node>(),
1006   new Point<Node>(),
1007 };)",
1008                Style);
1009 }
1010 
1011 TEST_F(FormatTestCSharp, CSharpNamedArguments) {
1012   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1013 
1014   verifyFormat(R"(//
1015 PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");)",
1016                Style);
1017 
1018   // Ensure that trailing comments do not cause problems.
1019   verifyFormat(R"(//
1020 PrintOrderDetails(orderNum: 31, productName: "Red Mug",  // comment
1021                   sellerName: "Gift Shop");)",
1022                Style);
1023 
1024   verifyFormat(R"(foreach (var tickCount in task.Begin(seed: 0)) {)", Style);
1025 }
1026 
1027 TEST_F(FormatTestCSharp, CSharpPropertyAccessors) {
1028   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1029 
1030   verifyFormat("int Value { get }", Style);
1031   verifyFormat("int Value { get; }", Style);
1032   verifyFormat("int Value { internal get; }", Style);
1033   verifyFormat("int Value { get; } = 0", Style);
1034   verifyFormat("int Value { set }", Style);
1035   verifyFormat("int Value { set; }", Style);
1036   verifyFormat("int Value { init; }", Style);
1037   verifyFormat("int Value { internal set; }", Style);
1038   verifyFormat("int Value { set; } = 0", Style);
1039   verifyFormat("int Value { get; set }", Style);
1040   verifyFormat("int Value { get; init; }", Style);
1041   verifyFormat("int Value { set; get }", Style);
1042   verifyFormat("int Value { get; private set; }", Style);
1043   verifyFormat("int Value { get; set; }", Style);
1044   verifyFormat("int Value { get; set; } = 0", Style);
1045   verifyFormat("int Value { internal get; internal set; }", Style);
1046 
1047   // Do not wrap expression body definitions.
1048   verifyFormat(R"(//
1049 public string Name {
1050   get => _name;
1051   set => _name = value;
1052 })",
1053                Style);
1054   verifyFormat(R"(//
1055 public string Name {
1056   init => _name = value;
1057   get => _name;
1058 })",
1059                Style);
1060   verifyFormat(R"(//
1061 public string Name {
1062   set => _name = value;
1063   get => _name;
1064 })",
1065                Style);
1066 
1067   // Examples taken from
1068   // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
1069   verifyFormat(R"(
1070 // Expression body definitions
1071 public class SaleItem {
1072   public decimal Price {
1073     get => _cost;
1074     set => _cost = value;
1075   }
1076 })",
1077                Style);
1078 
1079   verifyFormat(R"(
1080 // Properties with backing fields
1081 class TimePeriod {
1082   public double Hours {
1083     get { return _seconds / 3600; }
1084     set {
1085       if (value < 0 || value > 24)
1086         throw new ArgumentOutOfRangeException($"{nameof(value)} must be between 0 and 24.");
1087       _seconds = value * 3600;
1088     }
1089   }
1090 })",
1091                Style);
1092 
1093   verifyFormat(R"(
1094 // Auto-implemented properties
1095 public class SaleItem {
1096   public decimal Price { get; set; }
1097 })",
1098                Style);
1099 
1100   // Add column limit to wrap long lines.
1101   Style.ColumnLimit = 100;
1102 
1103   // Examples with assignment to default value.
1104   verifyFormat(R"(
1105 // Long assignment to default value
1106 class MyClass {
1107   public override VeryLongNamedTypeIndeed VeryLongNamedValue { get; set } =
1108       VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
1109                                      DefaultThirdArgument);
1110 })",
1111                Style);
1112 
1113   verifyFormat(R"(
1114 // Long assignment to default value with expression body
1115 class MyClass {
1116   public override VeryLongNamedTypeIndeed VeryLongNamedValue {
1117     get => veryLongNamedField;
1118     set => veryLongNamedField = value;
1119   } = VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
1120                                      DefaultThirdArgument);
1121 })",
1122                Style);
1123 
1124   // Brace wrapping and single-lining of accessor can be controlled by config.
1125   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
1126   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1127   Style.BraceWrapping.AfterFunction = true;
1128 
1129   verifyFormat(R"(//
1130 class TimePeriod {
1131   public double Hours
1132   {
1133     get {
1134       return _seconds / 3600;
1135     }
1136     set {
1137       _seconds = value * 3600;
1138     }
1139   }
1140 })",
1141                Style);
1142 
1143   // Microsoft style trivial property accessors have no line break before the
1144   // opening brace.
1145   auto MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
1146   verifyFormat(R"(//
1147 public class SaleItem
1148 {
1149     public decimal Price { get; set; }
1150 })",
1151                MicrosoftStyle);
1152 
1153   verifyFormat("internal class Program\n"
1154                "{\n"
1155                "    bool AutoAllowKnownApps\n"
1156                "    {\n"
1157                "        get;\n"
1158                "        [Simple]\n"
1159                "        set;\n"
1160                "    }\n"
1161                "}",
1162                MicrosoftStyle);
1163 }
1164 
1165 TEST_F(FormatTestCSharp, DefaultLiteral) {
1166   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1167 
1168   verifyFormat(
1169       "T[] InitializeArray<T>(int length, T initialValue = default) {}", Style);
1170   verifyFormat("System.Numerics.Complex fillValue = default;", Style);
1171   verifyFormat("int Value { get } = default;", Style);
1172   verifyFormat("int Value { get } = default!;", Style);
1173   verifyFormat(R"(//
1174 public record Person {
1175   public string GetInit { get; init; } = default!;
1176 };)",
1177                Style);
1178   verifyFormat(R"(//
1179 public record Person {
1180   public string GetSet { get; set; } = default!;
1181 };)",
1182                Style);
1183 }
1184 
1185 TEST_F(FormatTestCSharp, CSharpSpaces) {
1186   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1187   Style.SpaceBeforeSquareBrackets = false;
1188   Style.SpacesInSquareBrackets = false;
1189   Style.SpaceBeforeCpp11BracedList = true;
1190   Style.Cpp11BracedListStyle = false;
1191   Style.SpacesInContainerLiterals = false;
1192   Style.SpaceAfterCStyleCast = false;
1193 
1194   verifyFormat(R"(new Car { "Door", 0.1 })", Style);
1195   verifyFormat(R"(new Car { 0.1, "Door" })", Style);
1196   verifyFormat(R"(new string[] { "A" })", Style);
1197   verifyFormat(R"(new string[] {})", Style);
1198   verifyFormat(R"(new Car { someVariableName })", Style);
1199   verifyFormat(R"(new Car { someVariableName })", Style);
1200   verifyFormat(R"(new Dictionary<string, string> { ["Key"] = "Value" };)",
1201                Style);
1202   verifyFormat(R"(Apply(x => x.Name, x => () => x.ID);)", Style);
1203   verifyFormat(R"(bool[] xs = { true, true };)", Style);
1204   verifyIncompleteFormat(
1205       R"(taskContext.Factory.Run(async () => doThing(args);)", Style);
1206   verifyFormat(R"(catch (TestException) when (innerFinallyExecuted))", Style);
1207   verifyFormat(R"(private float[,] Values;)", Style);
1208   verifyFormat(R"(Result this[Index x] => Foo(x);)", Style);
1209 
1210   verifyFormat(R"(char[,,] rawCharArray = MakeCharacterGrid();)", Style);
1211   verifyFormat(R"(var (key, value))", Style);
1212 
1213   // `&&` is not seen as a reference.
1214   verifyFormat(R"(A == typeof(X) && someBool)", Style);
1215 
1216   // Not seen as a C-style cast.
1217   verifyFormat(R"(//
1218 foreach ((A a, B b) in someList) {
1219 })",
1220                Style);
1221 
1222   // space after lock in `lock (processes)`.
1223   verifyFormat("lock (process)", Style);
1224 
1225   Style.SpacesInSquareBrackets = true;
1226   verifyFormat(R"(private float[ , ] Values;)", Style);
1227   verifyFormat(R"(string dirPath = args?[ 0 ];)", Style);
1228   verifyFormat(R"(char[ ,, ] rawCharArray = MakeCharacterGrid();)", Style);
1229 
1230   // Method returning tuple
1231   verifyFormat(R"(public (string name, int age) methodTuple() {})", Style);
1232   verifyFormat(R"(private (string name, int age) methodTuple() {})", Style);
1233   verifyFormat(R"(protected (string name, int age) methodTuple() {})", Style);
1234   verifyFormat(R"(virtual (string name, int age) methodTuple() {})", Style);
1235   verifyFormat(R"(extern (string name, int age) methodTuple() {})", Style);
1236   verifyFormat(R"(static (string name, int age) methodTuple() {})", Style);
1237   verifyFormat(R"(internal (string name, int age) methodTuple() {})", Style);
1238   verifyFormat(R"(abstract (string name, int age) methodTuple() {})", Style);
1239   verifyFormat(R"(sealed (string name, int age) methodTuple() {})", Style);
1240   verifyFormat(R"(override (string name, int age) methodTuple() {})", Style);
1241   verifyFormat(R"(async (string name, int age) methodTuple() {})", Style);
1242   verifyFormat(R"(unsafe (string name, int age) methodTuple() {})", Style);
1243 
1244   Style.SpacesInSquareBrackets = false;
1245   Style.SpaceBeforeSquareBrackets = true;
1246   verifyFormat("return a is [1, 2, 3];", Style);
1247   verifyFormat("return a is [..];", Style);
1248   Style.SpaceBeforeSquareBrackets = false;
1249   verifyFormat("return a is [1, 2, 3];", Style);
1250   verifyFormat("return a is [..];", Style);
1251 }
1252 
1253 TEST_F(FormatTestCSharp, CSharpNullableTypes) {
1254   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1255   Style.SpacesInSquareBrackets = false;
1256 
1257   verifyFormat(R"(//
1258 public class A {
1259   void foo() {
1260     int? value = some.bar();
1261   }
1262 })",
1263                Style); // int? is nullable not a conditional expression.
1264 
1265   verifyFormat(R"(void foo(int? x, int? y, int? z) {})",
1266                Style); // Nullables in function definitions.
1267 
1268   verifyFormat(R"(public float? Value;)", Style); // no space before `?`.
1269 
1270   verifyFormat(R"(int?[] arr = new int?[10];)",
1271                Style); // An array of a nullable type.
1272 
1273   verifyFormat(R"(var x = (int?)y;)", Style); // Cast to a nullable type.
1274 
1275   verifyFormat(R"(var x = new MyContainer<int?>();)", Style); // Generics.
1276 
1277   verifyFormat(R"(//
1278 public interface I {
1279   int? Function();
1280 })",
1281                Style); // Interface methods.
1282 
1283   Style.ColumnLimit = 10;
1284   verifyFormat(R"(//
1285 public VeryLongType? Function(
1286     int arg1,
1287     int arg2) {
1288   //
1289 })",
1290                Style); // ? sticks with identifier.
1291 }
1292 
1293 TEST_F(FormatTestCSharp, CSharpArraySubscripts) {
1294   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1295 
1296   // Do not format array subscript operators as attributes.
1297   verifyFormat(R"(//
1298 if (someThings[index].Contains(myThing)) {
1299 })",
1300                Style);
1301 
1302   verifyFormat(R"(//
1303 if (someThings[i][j][k].Contains(myThing)) {
1304 })",
1305                Style);
1306 }
1307 
1308 TEST_F(FormatTestCSharp, CSharpGenericTypeConstraints) {
1309   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1310 
1311   EXPECT_TRUE(Style.BraceWrapping.SplitEmptyRecord);
1312 
1313   verifyFormat("class ItemFactory<T>\n"
1314                "    where T : new() {\n"
1315                "}",
1316                Style);
1317 
1318   // When the "where" line is not to be formatted, following lines should not
1319   // take on its indentation.
1320   verifyFormat("class ItemFactory<T>\n"
1321                "    where T : new() {\n"
1322                "  int f() {}\n"
1323                "}",
1324                "class ItemFactory<T>\n"
1325                "    where T : new() {\n"
1326                "  int f() {}\n"
1327                "}",
1328                Style, {tooling::Range(43, 13)});
1329 
1330   verifyFormat("class Dictionary<TKey, TVal>\n"
1331                "    where TKey : IComparable<TKey>\n"
1332                "    where TVal : IMyInterface {\n"
1333                "  public void MyMethod<T>(T t)\n"
1334                "      where T : IMyInterface {\n"
1335                "    doThing();\n"
1336                "  }\n"
1337                "}",
1338                Style);
1339 
1340   verifyFormat("class ItemFactory<T>\n"
1341                "    where T : new(), IAnInterface<T>, IAnotherInterface<T>, "
1342                "IAnotherInterfaceStill<T> {\n"
1343                "}",
1344                Style);
1345 
1346   Style.ColumnLimit = 50; // Force lines to be wrapped.
1347   verifyFormat(R"(//
1348 class ItemFactory<T, U>
1349     where T : new(),
1350               IAnInterface<T>,
1351               IAnotherInterface<T, U>,
1352               IAnotherInterfaceStill<T, U> {
1353 })",
1354                Style);
1355 
1356   // In other languages `where` can be used as a normal identifier.
1357   // This example is in C++!
1358   verifyFormat(R"(//
1359 class A {
1360   int f(int where) {}
1361 };)",
1362                getGoogleStyle(FormatStyle::LK_Cpp));
1363 }
1364 
1365 TEST_F(FormatTestCSharp, CSharpAfterEnum) {
1366   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1367   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1368   Style.BraceWrapping.AfterEnum = false;
1369   Style.AllowShortEnumsOnASingleLine = false;
1370 
1371   verifyFormat("enum MyEnum {\n"
1372                "  Foo,\n"
1373                "  Bar,\n"
1374                "}",
1375                Style);
1376   verifyFormat("internal enum MyEnum {\n"
1377                "  Foo,\n"
1378                "  Bar,\n"
1379                "}",
1380                Style);
1381   verifyFormat("public enum MyEnum {\n"
1382                "  Foo,\n"
1383                "  Bar,\n"
1384                "}",
1385                Style);
1386   verifyFormat("protected enum MyEnum {\n"
1387                "  Foo,\n"
1388                "  Bar,\n"
1389                "}",
1390                Style);
1391   verifyFormat("private enum MyEnum {\n"
1392                "  Foo,\n"
1393                "  Bar,\n"
1394                "}",
1395                Style);
1396 
1397   Style.BraceWrapping.AfterEnum = true;
1398   Style.AllowShortEnumsOnASingleLine = false;
1399 
1400   verifyFormat("enum MyEnum\n"
1401                "{\n"
1402                "  Foo,\n"
1403                "  Bar,\n"
1404                "}",
1405                Style);
1406   verifyFormat("internal enum MyEnum\n"
1407                "{\n"
1408                "  Foo,\n"
1409                "  Bar,\n"
1410                "}",
1411                Style);
1412   verifyFormat("public enum MyEnum\n"
1413                "{\n"
1414                "  Foo,\n"
1415                "  Bar,\n"
1416                "}",
1417                Style);
1418   verifyFormat("protected enum MyEnum\n"
1419                "{\n"
1420                "  Foo,\n"
1421                "  Bar,\n"
1422                "}",
1423                Style);
1424   verifyFormat("private enum MyEnum\n"
1425                "{\n"
1426                "  Foo,\n"
1427                "  Bar,\n"
1428                "}",
1429                Style);
1430   verifyFormat("/* Foo */ private enum MyEnum\n"
1431                "{\n"
1432                "  Foo,\n"
1433                "  Bar,\n"
1434                "}",
1435                Style);
1436   verifyFormat("/* Foo */ /* Bar */ private enum MyEnum\n"
1437                "{\n"
1438                "  Foo,\n"
1439                "  Bar,\n"
1440                "}",
1441                Style);
1442 }
1443 
1444 TEST_F(FormatTestCSharp, CSharpAfterClass) {
1445   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1446   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1447   Style.BraceWrapping.AfterClass = false;
1448 
1449   verifyFormat("class MyClass {\n"
1450                "  int a;\n"
1451                "  int b;\n"
1452                "}",
1453                Style);
1454   verifyFormat("internal class MyClass {\n"
1455                "  int a;\n"
1456                "  int b;\n"
1457                "}",
1458                Style);
1459   verifyFormat("public class MyClass {\n"
1460                "  int a;\n"
1461                "  int b;\n"
1462                "}",
1463                Style);
1464   verifyFormat("protected class MyClass {\n"
1465                "  int a;\n"
1466                "  int b;\n"
1467                "}",
1468                Style);
1469   verifyFormat("private class MyClass {\n"
1470                "  int a;\n"
1471                "  int b;\n"
1472                "}",
1473                Style);
1474 
1475   verifyFormat("interface Interface {\n"
1476                "  int a;\n"
1477                "  int b;\n"
1478                "}",
1479                Style);
1480   verifyFormat("internal interface Interface {\n"
1481                "  int a;\n"
1482                "  int b;\n"
1483                "}",
1484                Style);
1485   verifyFormat("public interface Interface {\n"
1486                "  int a;\n"
1487                "  int b;\n"
1488                "}",
1489                Style);
1490   verifyFormat("protected interface Interface {\n"
1491                "  int a;\n"
1492                "  int b;\n"
1493                "}",
1494                Style);
1495   verifyFormat("private interface Interface {\n"
1496                "  int a;\n"
1497                "  int b;\n"
1498                "}",
1499                Style);
1500 
1501   Style.BraceWrapping.AfterClass = true;
1502 
1503   verifyFormat("class MyClass\n"
1504                "{\n"
1505                "  int a;\n"
1506                "  int b;\n"
1507                "}",
1508                Style);
1509   verifyFormat("internal class MyClass\n"
1510                "{\n"
1511                "  int a;\n"
1512                "  int b;\n"
1513                "}",
1514                Style);
1515   verifyFormat("public class MyClass\n"
1516                "{\n"
1517                "  int a;\n"
1518                "  int b;\n"
1519                "}",
1520                Style);
1521   verifyFormat("protected class MyClass\n"
1522                "{\n"
1523                "  int a;\n"
1524                "  int b;\n"
1525                "}",
1526                Style);
1527   verifyFormat("private class MyClass\n"
1528                "{\n"
1529                "  int a;\n"
1530                "  int b;\n"
1531                "}",
1532                Style);
1533 
1534   verifyFormat("interface MyInterface\n"
1535                "{\n"
1536                "  int a;\n"
1537                "  int b;\n"
1538                "}",
1539                Style);
1540   verifyFormat("internal interface MyInterface\n"
1541                "{\n"
1542                "  int a;\n"
1543                "  int b;\n"
1544                "}",
1545                Style);
1546   verifyFormat("public interface MyInterface\n"
1547                "{\n"
1548                "  int a;\n"
1549                "  int b;\n"
1550                "}",
1551                Style);
1552   verifyFormat("protected interface MyInterface\n"
1553                "{\n"
1554                "  int a;\n"
1555                "  int b;\n"
1556                "}",
1557                Style);
1558   verifyFormat("private interface MyInterface\n"
1559                "{\n"
1560                "  int a;\n"
1561                "  int b;\n"
1562                "}",
1563                Style);
1564   verifyFormat("/* Foo */ private interface MyInterface\n"
1565                "{\n"
1566                "  int a;\n"
1567                "  int b;\n"
1568                "}",
1569                Style);
1570   verifyFormat("/* Foo */ /* Bar */ private interface MyInterface\n"
1571                "{\n"
1572                "  int a;\n"
1573                "  int b;\n"
1574                "}",
1575                Style);
1576 }
1577 
1578 TEST_F(FormatTestCSharp, NamespaceIndentation) {
1579   FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
1580   Style.NamespaceIndentation = FormatStyle::NI_None;
1581 
1582   verifyFormat("namespace A\n"
1583                "{\n"
1584                "public interface Name1\n"
1585                "{\n"
1586                "}\n"
1587                "}",
1588                Style);
1589 
1590   verifyFormat("namespace A.B\n"
1591                "{\n"
1592                "public interface Name1\n"
1593                "{\n"
1594                "}\n"
1595                "}",
1596                Style);
1597 
1598   Style.NamespaceIndentation = FormatStyle::NI_Inner;
1599 
1600   verifyFormat("namespace A\n"
1601                "{\n"
1602                "namespace B\n"
1603                "{\n"
1604                "    public interface Name1\n"
1605                "    {\n"
1606                "    }\n"
1607                "}\n"
1608                "}",
1609                Style);
1610 
1611   Style.NamespaceIndentation = FormatStyle::NI_All;
1612 
1613   verifyFormat("namespace A.B\n"
1614                "{\n"
1615                "    public interface Name1\n"
1616                "    {\n"
1617                "    }\n"
1618                "}",
1619                Style);
1620 
1621   verifyFormat("namespace A\n"
1622                "{\n"
1623                "    namespace B\n"
1624                "    {\n"
1625                "        public interface Name1\n"
1626                "        {\n"
1627                "        }\n"
1628                "    }\n"
1629                "}",
1630                Style);
1631 }
1632 
1633 TEST_F(FormatTestCSharp, SwitchExpression) {
1634   FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
1635   verifyFormat("int x = a switch {\n"
1636                "    1 => (0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0),\n"
1637                "    2 => 1,\n"
1638                "    _ => 2\n"
1639                "};",
1640                Style);
1641 }
1642 
1643 TEST_F(FormatTestCSharp, EmptyShortBlock) {
1644   auto Style = getLLVMStyle();
1645   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
1646 
1647   verifyFormat("try {\n"
1648                "  doA();\n"
1649                "} catch (Exception e) {\n"
1650                "  e.printStackTrace();\n"
1651                "}",
1652                Style);
1653 
1654   verifyFormat("try {\n"
1655                "  doA();\n"
1656                "} catch (Exception e) {}",
1657                Style);
1658 }
1659 
1660 TEST_F(FormatTestCSharp, ShortFunctions) {
1661   FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp);
1662   Style.NamespaceIndentation = FormatStyle::NI_All;
1663   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
1664   verifyFormat("interface Interface {\n"
1665                "  void f() { return; }\n"
1666                "};",
1667                Style);
1668   verifyFormat("public interface Interface {\n"
1669                "  void f() { return; }\n"
1670                "};",
1671                Style);
1672   verifyFormat("namespace {\n"
1673                "  void f() {\n"
1674                "    return;\n"
1675                "  }\n"
1676                "};",
1677                Style);
1678   // "union" is not a keyword in C#.
1679   verifyFormat("namespace union {\n"
1680                "  void f() {\n"
1681                "    return;\n"
1682                "  }\n"
1683                "};",
1684                Style);
1685 }
1686 
1687 TEST_F(FormatTestCSharp, BrokenBrackets) {
1688   EXPECT_NE("", format("int where b <")); // reduced from crasher
1689 }
1690 
1691 TEST_F(FormatTestCSharp, GotoCaseLabel) {
1692   verifyFormat("switch (i)\n"
1693                "{\n"
1694                "case 0:\n"
1695                "    goto case 1;\n"
1696                "case 1:\n"
1697                "    j = 0;\n"
1698                "    {\n"
1699                "        break;\n"
1700                "    }\n"
1701                "}",
1702                "switch (i) {\n"
1703                "case 0:\n"
1704                "  goto case 1;\n"
1705                "case 1:\n"
1706                "  j = 0;\n"
1707                "  {\n"
1708                "    break;\n"
1709                "  }\n"
1710                "}");
1711 }
1712 
1713 } // namespace
1714 } // namespace test
1715 } // namespace format
1716 } // namespace clang
1717