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