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