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 verifyFormat(R"(return @$"Foo ""/foo?f={Request.Query["f"]}""";)", Style); 579 verifyFormat(R"(return @$"path\to\{specifiedFile}")", Style); 580 } 581 582 TEST_F(FormatTestCSharp, CSharpQuotesInInterpolatedStrings) { 583 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 584 585 verifyFormat(R"(string str1 = $"{null ?? "null"}";)", Style); 586 verifyFormat(R"(string str2 = $"{{{braceCount} braces";)", Style); 587 verifyFormat(R"(string str3 = $"{braceCount}}} braces";)", Style); 588 } 589 590 TEST_F(FormatTestCSharp, CSharpNewlinesInVerbatimStrings) { 591 // Use MS style as Google Style inserts a line break before multiline strings. 592 593 // verifyFormat does not understand multiline C# string-literals 594 // so check the format explicitly. 595 596 FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 597 598 std::string Code = R"(string s1 = $@"some code: 599 class {className} {{ 600 {className}() {{}} 601 }}";)"; 602 603 EXPECT_EQ(Code, format(Code, Style)); 604 605 // Multiline string in the middle of a function call. 606 Code = R"( 607 var x = foo(className, $@"some code: 608 class {className} {{ 609 {className}() {{}} 610 }}", 611 y);)"; // y aligned with `className` arg. 612 613 EXPECT_EQ(Code, format(Code, Style)); 614 615 // Interpolated string with embedded multiline string. 616 Code = R"(Console.WriteLine($"{string.Join(@", 617 ", values)}");)"; 618 619 EXPECT_EQ(Code, format(Code, Style)); 620 } 621 622 TEST_F(FormatTestCSharp, CSharpNewOperator) { 623 FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp); 624 625 verifyFormat("public void F() {\n" 626 " var v = new C(() => { var t = 5; });\n" 627 "}", 628 Style); 629 verifyFormat("public void F() {\n" 630 " var v = new C(() => {\n" 631 " try {\n" 632 " } catch {\n" 633 " var t = 5;\n" 634 " }\n" 635 " });\n" 636 "}", 637 Style); 638 } 639 640 TEST_F(FormatTestCSharp, CSharpLambdas) { 641 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp); 642 FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp); 643 644 verifyFormat(R"(// 645 class MyClass { 646 Action<string> greet = name => { 647 string greeting = $"Hello {name}!"; 648 Console.WriteLine(greeting); 649 }; 650 })", 651 GoogleStyle); 652 653 // Microsoft Style: 654 // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#statement-lambdas 655 verifyFormat(R"(// 656 class MyClass 657 { 658 Action<string> greet = name => 659 { 660 string greeting = $"Hello {name}!"; 661 Console.WriteLine(greeting); 662 }; 663 })", 664 MicrosoftStyle); 665 666 verifyFormat("void bar()\n" 667 "{\n" 668 " Function(Val, (Action)(() =>\n" 669 " {\n" 670 " lock (mylock)\n" 671 " {\n" 672 " if (true)\n" 673 " {\n" 674 " A.Remove(item);\n" 675 " }\n" 676 " }\n" 677 " }));\n" 678 "}", 679 MicrosoftStyle); 680 681 verifyFormat("void baz()\n" 682 "{\n" 683 " Function(Val, (Action)(() =>\n" 684 " {\n" 685 " using (var a = new Lock())\n" 686 " {\n" 687 " if (true)\n" 688 " {\n" 689 " A.Remove(item);\n" 690 " }\n" 691 " }\n" 692 " }));\n" 693 "}", 694 MicrosoftStyle); 695 696 verifyFormat("void baz()\n" 697 "{\n" 698 " Function(Val, (Action)(() =>\n" 699 " {\n" 700 " if (true)\n" 701 " {\n" 702 " A.Remove(item);\n" 703 " }\n" 704 " }));\n" 705 "}", 706 MicrosoftStyle); 707 708 verifyFormat("void baz()\n" 709 "{\n" 710 " Function(Val, (Action)(() =>\n" 711 " {\n" 712 " do\n" 713 " {\n" 714 " A.Remove(item);\n" 715 " } while (true)\n" 716 " }));\n" 717 "}", 718 MicrosoftStyle); 719 720 verifyFormat("void baz()\n" 721 "{\n" 722 " Function(Val, (Action)(() =>\n" 723 " { A.Remove(item); }));\n" 724 "}", 725 MicrosoftStyle); 726 727 verifyFormat("void bar()\n" 728 "{\n" 729 " Function(Val, (() =>\n" 730 " {\n" 731 " lock (mylock)\n" 732 " {\n" 733 " if (true)\n" 734 " {\n" 735 " A.Remove(item);\n" 736 " }\n" 737 " }\n" 738 " }));\n" 739 "}", 740 MicrosoftStyle); 741 verifyFormat("void bar()\n" 742 "{\n" 743 " Function((() =>\n" 744 " {\n" 745 " lock (mylock)\n" 746 " {\n" 747 " if (true)\n" 748 " {\n" 749 " A.Remove(item);\n" 750 " }\n" 751 " }\n" 752 " }));\n" 753 "}", 754 MicrosoftStyle); 755 756 MicrosoftStyle.IndentWidth = 2; 757 verifyFormat("void bar()\n" 758 "{\n" 759 " Function((() =>\n" 760 " {\n" 761 " lock (mylock)\n" 762 " {\n" 763 " if (true)\n" 764 " {\n" 765 " A.Remove(item);\n" 766 " }\n" 767 " }\n" 768 " }));\n" 769 "}", 770 MicrosoftStyle); 771 verifyFormat("void bar() {\n" 772 " Function((() => {\n" 773 " lock (mylock) {\n" 774 " if (true) {\n" 775 " A.Remove(item);\n" 776 " }\n" 777 " }\n" 778 " }));\n" 779 "}", 780 GoogleStyle); 781 } 782 783 TEST_F(FormatTestCSharp, CSharpLambdasDontBreakFollowingCodeAlignment) { 784 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp); 785 FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp); 786 787 verifyFormat(R"(// 788 public class Sample 789 { 790 public void Test() 791 { 792 while (true) 793 { 794 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext()); 795 CodeThatFollowsLambda(); 796 IsWellAligned(); 797 } 798 } 799 })", 800 MicrosoftStyle); 801 802 verifyFormat(R"(// 803 public class Sample { 804 public void Test() { 805 while (true) { 806 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext()); 807 CodeThatFollowsLambda(); 808 IsWellAligned(); 809 } 810 } 811 })", 812 GoogleStyle); 813 } 814 815 TEST_F(FormatTestCSharp, CSharpLambdasComplexLambdasDontBreakAlignment) { 816 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp); 817 FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp); 818 819 verifyFormat(R"(// 820 public class Test 821 { 822 private static void ComplexLambda(BuildReport protoReport) 823 { 824 allSelectedScenes = 825 veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled) 826 .Select(scene => scene.path) 827 .ToArray(); 828 if (allSelectedScenes.Count == 0) 829 { 830 return; 831 } 832 Functions(); 833 AreWell(); 834 Aligned(); 835 AfterLambdaBlock(); 836 } 837 })", 838 MicrosoftStyle); 839 840 verifyFormat(R"(// 841 public class Test { 842 private static void ComplexLambda(BuildReport protoReport) { 843 allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds 844 .Where(scene => scene.enabled) 845 .Select(scene => scene.path) 846 .ToArray(); 847 if (allSelectedScenes.Count == 0) { 848 return; 849 } 850 Functions(); 851 AreWell(); 852 Aligned(); 853 AfterLambdaBlock(); 854 } 855 })", 856 GoogleStyle); 857 } 858 859 TEST_F(FormatTestCSharp, CSharpLambdasMulipleLambdasDontBreakAlignment) { 860 FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp); 861 FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp); 862 863 verifyFormat(R"(// 864 public class Test 865 { 866 private static void MultipleLambdas(BuildReport protoReport) 867 { 868 allSelectedScenes = 869 veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled) 870 .Select(scene => scene.path) 871 .ToArray(); 872 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext()); 873 if (allSelectedScenes.Count == 0) 874 { 875 return; 876 } 877 Functions(); 878 AreWell(); 879 Aligned(); 880 AfterLambdaBlock(); 881 } 882 })", 883 MicrosoftStyle); 884 885 verifyFormat(R"(// 886 public class Test { 887 private static void MultipleLambdas(BuildReport protoReport) { 888 allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds 889 .Where(scene => scene.enabled) 890 .Select(scene => scene.path) 891 .ToArray(); 892 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext()); 893 if (allSelectedScenes.Count == 0) { 894 return; 895 } 896 Functions(); 897 AreWell(); 898 Aligned(); 899 AfterLambdaBlock(); 900 } 901 })", 902 GoogleStyle); 903 } 904 905 TEST_F(FormatTestCSharp, CSharpObjectInitializers) { 906 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 907 908 // Start code fragments with a comment line so that C++ raw string literals 909 // as seen are identical to expected formatted code. 910 911 verifyFormat(R"(// 912 Shape[] shapes = new[] { 913 new Circle { 914 Radius = 2.7281, 915 Colour = Colours.Red, 916 }, 917 new Square { 918 Side = 101.1, 919 Colour = Colours.Yellow, 920 }, 921 };)", 922 Style); 923 924 // Omitted final `,`s will change the formatting. 925 verifyFormat(R"(// 926 Shape[] shapes = new[] { new Circle { Radius = 2.7281, Colour = Colours.Red }, 927 new Square { Side = 101.1, Colour = Colours.Yellow } };)", 928 Style); 929 930 // Lambdas can be supplied as initialiser arguments. 931 verifyFormat(R"(// 932 private Transformer _transformer = new X.Y { 933 Filler = (Shape shape) => { return new Transform.Fill(shape, RED); }, 934 Scaler = (Shape shape) => { return new Transform.Resize(shape, 0.1); }, 935 };)", 936 Style); 937 938 // Dictionary initialisation. 939 verifyFormat(R"(// 940 var myDict = new Dictionary<string, string> { 941 ["name"] = _donald, 942 ["age"] = Convert.ToString(DateTime.Today.Year - 1934), 943 ["type"] = _duck, 944 };)", 945 Style); 946 } 947 948 TEST_F(FormatTestCSharp, CSharpArrayInitializers) { 949 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 950 951 verifyFormat(R"(// 952 private MySet<Node>[] setPoints = { 953 new Point<Node>(), 954 new Point<Node>(), 955 };)", 956 Style); 957 } 958 959 TEST_F(FormatTestCSharp, CSharpNamedArguments) { 960 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 961 962 verifyFormat(R"(// 963 PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");)", 964 Style); 965 966 // Ensure that trailing comments do not cause problems. 967 verifyFormat(R"(// 968 PrintOrderDetails(orderNum: 31, productName: "Red Mug", // comment 969 sellerName: "Gift Shop");)", 970 Style); 971 972 verifyFormat(R"(foreach (var tickCount in task.Begin(seed: 0)) {)", Style); 973 } 974 975 TEST_F(FormatTestCSharp, CSharpPropertyAccessors) { 976 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 977 978 verifyFormat("int Value { get }", Style); 979 verifyFormat("int Value { get; }", Style); 980 verifyFormat("int Value { internal get; }", Style); 981 verifyFormat("int Value { get; } = 0", Style); 982 verifyFormat("int Value { set }", Style); 983 verifyFormat("int Value { set; }", Style); 984 verifyFormat("int Value { init; }", Style); 985 verifyFormat("int Value { internal set; }", Style); 986 verifyFormat("int Value { set; } = 0", Style); 987 verifyFormat("int Value { get; set }", Style); 988 verifyFormat("int Value { get; init; }", Style); 989 verifyFormat("int Value { set; get }", Style); 990 verifyFormat("int Value { get; private set; }", Style); 991 verifyFormat("int Value { get; set; }", Style); 992 verifyFormat("int Value { get; set; } = 0", Style); 993 verifyFormat("int Value { internal get; internal set; }", Style); 994 995 // Do not wrap expression body definitions. 996 verifyFormat(R"(// 997 public string Name { 998 get => _name; 999 set => _name = value; 1000 })", 1001 Style); 1002 verifyFormat(R"(// 1003 public string Name { 1004 init => _name = value; 1005 get => _name; 1006 })", 1007 Style); 1008 verifyFormat(R"(// 1009 public string Name { 1010 set => _name = value; 1011 get => _name; 1012 })", 1013 Style); 1014 1015 // Examples taken from 1016 // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties 1017 verifyFormat(R"( 1018 // Expression body definitions 1019 public class SaleItem { 1020 public decimal Price { 1021 get => _cost; 1022 set => _cost = value; 1023 } 1024 })", 1025 Style); 1026 1027 verifyFormat(R"( 1028 // Properties with backing fields 1029 class TimePeriod { 1030 public double Hours { 1031 get { return _seconds / 3600; } 1032 set { 1033 if (value < 0 || value > 24) 1034 throw new ArgumentOutOfRangeException($"{nameof(value)} must be between 0 and 24."); 1035 _seconds = value * 3600; 1036 } 1037 } 1038 })", 1039 Style); 1040 1041 verifyFormat(R"( 1042 // Auto-implemented properties 1043 public class SaleItem { 1044 public decimal Price { get; set; } 1045 })", 1046 Style); 1047 1048 // Add column limit to wrap long lines. 1049 Style.ColumnLimit = 100; 1050 1051 // Examples with assignment to default value. 1052 verifyFormat(R"( 1053 // Long assignment to default value 1054 class MyClass { 1055 public override VeryLongNamedTypeIndeed VeryLongNamedValue { get; set } = 1056 VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument, 1057 DefaultThirdArgument); 1058 })", 1059 Style); 1060 1061 verifyFormat(R"( 1062 // Long assignment to default value with expression body 1063 class MyClass { 1064 public override VeryLongNamedTypeIndeed VeryLongNamedValue { 1065 get => veryLongNamedField; 1066 set => veryLongNamedField = value; 1067 } = VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument, 1068 DefaultThirdArgument); 1069 })", 1070 Style); 1071 1072 // Brace wrapping and single-lining of accessor can be controlled by config. 1073 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; 1074 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1075 Style.BraceWrapping.AfterFunction = true; 1076 1077 verifyFormat(R"(// 1078 class TimePeriod { 1079 public double Hours 1080 { 1081 get { 1082 return _seconds / 3600; 1083 } 1084 set { 1085 _seconds = value * 3600; 1086 } 1087 } 1088 })", 1089 Style); 1090 1091 // Microsoft style trivial property accessors have no line break before the 1092 // opening brace. 1093 auto MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp); 1094 verifyFormat(R"(// 1095 public class SaleItem 1096 { 1097 public decimal Price { get; set; } 1098 })", 1099 MicrosoftStyle); 1100 } 1101 1102 TEST_F(FormatTestCSharp, DefaultLiteral) { 1103 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1104 1105 verifyFormat( 1106 "T[] InitializeArray<T>(int length, T initialValue = default) {}", Style); 1107 verifyFormat("System.Numerics.Complex fillValue = default;", Style); 1108 verifyFormat("int Value { get } = default;", Style); 1109 verifyFormat("int Value { get } = default!;", Style); 1110 verifyFormat(R"(// 1111 public record Person { 1112 public string GetInit { get; init; } = default!; 1113 };)", 1114 Style); 1115 verifyFormat(R"(// 1116 public record Person { 1117 public string GetSet { get; set; } = default!; 1118 };)", 1119 Style); 1120 } 1121 1122 TEST_F(FormatTestCSharp, CSharpSpaces) { 1123 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1124 Style.SpaceBeforeSquareBrackets = false; 1125 Style.SpacesInSquareBrackets = false; 1126 Style.SpaceBeforeCpp11BracedList = true; 1127 Style.Cpp11BracedListStyle = false; 1128 Style.SpacesInContainerLiterals = false; 1129 Style.SpaceAfterCStyleCast = false; 1130 1131 verifyFormat(R"(new Car { "Door", 0.1 })", Style); 1132 verifyFormat(R"(new Car { 0.1, "Door" })", Style); 1133 verifyFormat(R"(new string[] { "A" })", Style); 1134 verifyFormat(R"(new string[] {})", Style); 1135 verifyFormat(R"(new Car { someVariableName })", Style); 1136 verifyFormat(R"(new Car { someVariableName })", Style); 1137 verifyFormat(R"(new Dictionary<string, string> { ["Key"] = "Value" };)", 1138 Style); 1139 verifyFormat(R"(Apply(x => x.Name, x => () => x.ID);)", Style); 1140 verifyFormat(R"(bool[] xs = { true, true };)", Style); 1141 verifyFormat(R"(taskContext.Factory.Run(async () => doThing(args);)", Style); 1142 verifyFormat(R"(catch (TestException) when (innerFinallyExecuted))", Style); 1143 verifyFormat(R"(private float[,] Values;)", Style); 1144 verifyFormat(R"(Result this[Index x] => Foo(x);)", Style); 1145 1146 verifyFormat(R"(char[,,] rawCharArray = MakeCharacterGrid();)", Style); 1147 verifyFormat(R"(var (key, value))", Style); 1148 1149 // `&&` is not seen as a reference. 1150 verifyFormat(R"(A == typeof(X) && someBool)", Style); 1151 1152 // Not seen as a C-style cast. 1153 verifyFormat(R"(// 1154 foreach ((A a, B b) in someList) { 1155 })", 1156 Style); 1157 1158 // space after lock in `lock (processes)`. 1159 verifyFormat("lock (process)", Style); 1160 1161 Style.SpacesInSquareBrackets = true; 1162 verifyFormat(R"(private float[ , ] Values;)", Style); 1163 verifyFormat(R"(string dirPath = args?[ 0 ];)", Style); 1164 verifyFormat(R"(char[ ,, ] rawCharArray = MakeCharacterGrid();)", Style); 1165 1166 // Method returning tuple 1167 verifyFormat(R"(public (string name, int age) methodTuple() {})", Style); 1168 verifyFormat(R"(private (string name, int age) methodTuple() {})", Style); 1169 verifyFormat(R"(protected (string name, int age) methodTuple() {})", Style); 1170 verifyFormat(R"(virtual (string name, int age) methodTuple() {})", Style); 1171 verifyFormat(R"(extern (string name, int age) methodTuple() {})", Style); 1172 verifyFormat(R"(static (string name, int age) methodTuple() {})", Style); 1173 verifyFormat(R"(internal (string name, int age) methodTuple() {})", Style); 1174 verifyFormat(R"(abstract (string name, int age) methodTuple() {})", Style); 1175 verifyFormat(R"(sealed (string name, int age) methodTuple() {})", Style); 1176 verifyFormat(R"(override (string name, int age) methodTuple() {})", Style); 1177 verifyFormat(R"(async (string name, int age) methodTuple() {})", Style); 1178 verifyFormat(R"(unsafe (string name, int age) methodTuple() {})", Style); 1179 } 1180 1181 TEST_F(FormatTestCSharp, CSharpNullableTypes) { 1182 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1183 Style.SpacesInSquareBrackets = false; 1184 1185 verifyFormat(R"(// 1186 public class A { 1187 void foo() { 1188 int? value = some.bar(); 1189 } 1190 })", 1191 Style); // int? is nullable not a conditional expression. 1192 1193 verifyFormat(R"(void foo(int? x, int? y, int? z) {})", 1194 Style); // Nullables in function definitions. 1195 1196 verifyFormat(R"(public float? Value;)", Style); // no space before `?`. 1197 1198 verifyFormat(R"(int?[] arr = new int?[10];)", 1199 Style); // An array of a nullable type. 1200 1201 verifyFormat(R"(var x = (int?)y;)", Style); // Cast to a nullable type. 1202 1203 verifyFormat(R"(var x = new MyContainer<int?>();)", Style); // Generics. 1204 1205 verifyFormat(R"(// 1206 public interface I { 1207 int? Function(); 1208 })", 1209 Style); // Interface methods. 1210 1211 Style.ColumnLimit = 10; 1212 verifyFormat(R"(// 1213 public VeryLongType? Function( 1214 int arg1, 1215 int arg2) { 1216 // 1217 })", 1218 Style); // ? sticks with identifier. 1219 } 1220 1221 TEST_F(FormatTestCSharp, CSharpArraySubscripts) { 1222 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1223 1224 // Do not format array subscript operators as attributes. 1225 verifyFormat(R"(// 1226 if (someThings[index].Contains(myThing)) { 1227 })", 1228 Style); 1229 1230 verifyFormat(R"(// 1231 if (someThings[i][j][k].Contains(myThing)) { 1232 })", 1233 Style); 1234 } 1235 1236 TEST_F(FormatTestCSharp, CSharpGenericTypeConstraints) { 1237 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1238 1239 EXPECT_TRUE(Style.BraceWrapping.SplitEmptyRecord); 1240 1241 verifyFormat("class ItemFactory<T>\n" 1242 " where T : new() {\n" 1243 "}", 1244 Style); 1245 1246 verifyFormat("class Dictionary<TKey, TVal>\n" 1247 " where TKey : IComparable<TKey>\n" 1248 " where TVal : IMyInterface {\n" 1249 " public void MyMethod<T>(T t)\n" 1250 " where T : IMyInterface {\n" 1251 " doThing();\n" 1252 " }\n" 1253 "}", 1254 Style); 1255 1256 verifyFormat("class ItemFactory<T>\n" 1257 " where T : new(), IAnInterface<T>, IAnotherInterface<T>, " 1258 "IAnotherInterfaceStill<T> {\n" 1259 "}", 1260 Style); 1261 1262 Style.ColumnLimit = 50; // Force lines to be wrapped. 1263 verifyFormat(R"(// 1264 class ItemFactory<T, U> 1265 where T : new(), 1266 IAnInterface<T>, 1267 IAnotherInterface<T, U>, 1268 IAnotherInterfaceStill<T, U> { 1269 })", 1270 Style); 1271 1272 // In other languages `where` can be used as a normal identifier. 1273 // This example is in C++! 1274 verifyFormat(R"(// 1275 class A { 1276 int f(int where) {} 1277 };)", 1278 getGoogleStyle(FormatStyle::LK_Cpp)); 1279 } 1280 1281 TEST_F(FormatTestCSharp, CSharpAfterEnum) { 1282 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1283 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1284 Style.BraceWrapping.AfterEnum = false; 1285 Style.AllowShortEnumsOnASingleLine = false; 1286 1287 verifyFormat("enum MyEnum {\n" 1288 " Foo,\n" 1289 " Bar,\n" 1290 "}", 1291 Style); 1292 verifyFormat("internal enum MyEnum {\n" 1293 " Foo,\n" 1294 " Bar,\n" 1295 "}", 1296 Style); 1297 verifyFormat("public enum MyEnum {\n" 1298 " Foo,\n" 1299 " Bar,\n" 1300 "}", 1301 Style); 1302 verifyFormat("protected enum MyEnum {\n" 1303 " Foo,\n" 1304 " Bar,\n" 1305 "}", 1306 Style); 1307 verifyFormat("private enum MyEnum {\n" 1308 " Foo,\n" 1309 " Bar,\n" 1310 "}", 1311 Style); 1312 1313 Style.BraceWrapping.AfterEnum = true; 1314 Style.AllowShortEnumsOnASingleLine = false; 1315 1316 verifyFormat("enum MyEnum\n" 1317 "{\n" 1318 " Foo,\n" 1319 " Bar,\n" 1320 "}", 1321 Style); 1322 verifyFormat("internal enum MyEnum\n" 1323 "{\n" 1324 " Foo,\n" 1325 " Bar,\n" 1326 "}", 1327 Style); 1328 verifyFormat("public enum MyEnum\n" 1329 "{\n" 1330 " Foo,\n" 1331 " Bar,\n" 1332 "}", 1333 Style); 1334 verifyFormat("protected enum MyEnum\n" 1335 "{\n" 1336 " Foo,\n" 1337 " Bar,\n" 1338 "}", 1339 Style); 1340 verifyFormat("private enum MyEnum\n" 1341 "{\n" 1342 " Foo,\n" 1343 " Bar,\n" 1344 "}", 1345 Style); 1346 verifyFormat("/* Foo */ private enum MyEnum\n" 1347 "{\n" 1348 " Foo,\n" 1349 " Bar,\n" 1350 "}", 1351 Style); 1352 verifyFormat("/* Foo */ /* Bar */ private enum MyEnum\n" 1353 "{\n" 1354 " Foo,\n" 1355 " Bar,\n" 1356 "}", 1357 Style); 1358 } 1359 1360 TEST_F(FormatTestCSharp, CSharpAfterClass) { 1361 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1362 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1363 Style.BraceWrapping.AfterClass = false; 1364 1365 verifyFormat("class MyClass {\n" 1366 " int a;\n" 1367 " int b;\n" 1368 "}", 1369 Style); 1370 verifyFormat("internal class MyClass {\n" 1371 " int a;\n" 1372 " int b;\n" 1373 "}", 1374 Style); 1375 verifyFormat("public class MyClass {\n" 1376 " int a;\n" 1377 " int b;\n" 1378 "}", 1379 Style); 1380 verifyFormat("protected class MyClass {\n" 1381 " int a;\n" 1382 " int b;\n" 1383 "}", 1384 Style); 1385 verifyFormat("private class MyClass {\n" 1386 " int a;\n" 1387 " int b;\n" 1388 "}", 1389 Style); 1390 1391 verifyFormat("interface Interface {\n" 1392 " int a;\n" 1393 " int b;\n" 1394 "}", 1395 Style); 1396 verifyFormat("internal interface Interface {\n" 1397 " int a;\n" 1398 " int b;\n" 1399 "}", 1400 Style); 1401 verifyFormat("public interface Interface {\n" 1402 " int a;\n" 1403 " int b;\n" 1404 "}", 1405 Style); 1406 verifyFormat("protected interface Interface {\n" 1407 " int a;\n" 1408 " int b;\n" 1409 "}", 1410 Style); 1411 verifyFormat("private interface Interface {\n" 1412 " int a;\n" 1413 " int b;\n" 1414 "}", 1415 Style); 1416 1417 Style.BraceWrapping.AfterClass = true; 1418 1419 verifyFormat("class MyClass\n" 1420 "{\n" 1421 " int a;\n" 1422 " int b;\n" 1423 "}", 1424 Style); 1425 verifyFormat("internal class MyClass\n" 1426 "{\n" 1427 " int a;\n" 1428 " int b;\n" 1429 "}", 1430 Style); 1431 verifyFormat("public class MyClass\n" 1432 "{\n" 1433 " int a;\n" 1434 " int b;\n" 1435 "}", 1436 Style); 1437 verifyFormat("protected class MyClass\n" 1438 "{\n" 1439 " int a;\n" 1440 " int b;\n" 1441 "}", 1442 Style); 1443 verifyFormat("private class MyClass\n" 1444 "{\n" 1445 " int a;\n" 1446 " int b;\n" 1447 "}", 1448 Style); 1449 1450 verifyFormat("interface MyInterface\n" 1451 "{\n" 1452 " int a;\n" 1453 " int b;\n" 1454 "}", 1455 Style); 1456 verifyFormat("internal interface MyInterface\n" 1457 "{\n" 1458 " int a;\n" 1459 " int b;\n" 1460 "}", 1461 Style); 1462 verifyFormat("public interface MyInterface\n" 1463 "{\n" 1464 " int a;\n" 1465 " int b;\n" 1466 "}", 1467 Style); 1468 verifyFormat("protected interface MyInterface\n" 1469 "{\n" 1470 " int a;\n" 1471 " int b;\n" 1472 "}", 1473 Style); 1474 verifyFormat("private interface MyInterface\n" 1475 "{\n" 1476 " int a;\n" 1477 " int b;\n" 1478 "}", 1479 Style); 1480 verifyFormat("/* Foo */ private interface MyInterface\n" 1481 "{\n" 1482 " int a;\n" 1483 " int b;\n" 1484 "}", 1485 Style); 1486 verifyFormat("/* Foo */ /* Bar */ private interface MyInterface\n" 1487 "{\n" 1488 " int a;\n" 1489 " int b;\n" 1490 "}", 1491 Style); 1492 } 1493 1494 TEST_F(FormatTestCSharp, NamespaceIndentation) { 1495 FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 1496 Style.NamespaceIndentation = FormatStyle::NI_None; 1497 1498 verifyFormat("namespace A\n" 1499 "{\n" 1500 "public interface Name1\n" 1501 "{\n" 1502 "}\n" 1503 "}\n", 1504 Style); 1505 1506 verifyFormat("namespace A.B\n" 1507 "{\n" 1508 "public interface Name1\n" 1509 "{\n" 1510 "}\n" 1511 "}\n", 1512 Style); 1513 1514 Style.NamespaceIndentation = FormatStyle::NI_Inner; 1515 1516 verifyFormat("namespace A\n" 1517 "{\n" 1518 "namespace B\n" 1519 "{\n" 1520 " public interface Name1\n" 1521 " {\n" 1522 " }\n" 1523 "}\n" 1524 "}\n", 1525 Style); 1526 1527 Style.NamespaceIndentation = FormatStyle::NI_All; 1528 1529 verifyFormat("namespace A.B\n" 1530 "{\n" 1531 " public interface Name1\n" 1532 " {\n" 1533 " }\n" 1534 "}\n", 1535 Style); 1536 1537 verifyFormat("namespace A\n" 1538 "{\n" 1539 " namespace B\n" 1540 " {\n" 1541 " public interface Name1\n" 1542 " {\n" 1543 " }\n" 1544 " }\n" 1545 "}\n", 1546 Style); 1547 } 1548 1549 TEST_F(FormatTestCSharp, SwitchExpression) { 1550 FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 1551 verifyFormat("int x = a switch {\n" 1552 " 1 => (0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0),\n" 1553 " 2 => 1,\n" 1554 " _ => 2\n" 1555 "};\n", 1556 Style); 1557 } 1558 1559 TEST_F(FormatTestCSharp, EmptyShortBlock) { 1560 auto Style = getLLVMStyle(); 1561 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; 1562 1563 verifyFormat("try {\n" 1564 " doA();\n" 1565 "} catch (Exception e) {\n" 1566 " e.printStackTrace();\n" 1567 "}\n", 1568 Style); 1569 1570 verifyFormat("try {\n" 1571 " doA();\n" 1572 "} catch (Exception e) {}\n", 1573 Style); 1574 } 1575 1576 TEST_F(FormatTestCSharp, ShortFunctions) { 1577 FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp); 1578 Style.NamespaceIndentation = FormatStyle::NI_All; 1579 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1580 verifyFormat("interface Interface {\n" 1581 " void f() { return; }\n" 1582 "};", 1583 Style); 1584 verifyFormat("public interface Interface {\n" 1585 " void f() { return; }\n" 1586 "};", 1587 Style); 1588 verifyFormat("namespace {\n" 1589 " void f() {\n" 1590 " return;\n" 1591 " }\n" 1592 "};", 1593 Style); 1594 // "union" is not a keyword in C#. 1595 verifyFormat("namespace union {\n" 1596 " void f() {\n" 1597 " return;\n" 1598 " }\n" 1599 "};", 1600 Style); 1601 } 1602 1603 } // namespace format 1604 } // end namespace clang 1605