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 Style.SpacesInSquareBrackets = false; 1181 Style.SpaceBeforeSquareBrackets = true; 1182 verifyFormat("return a is [1, 2, 3];", Style); 1183 verifyFormat("return a is [..];", Style); 1184 Style.SpaceBeforeSquareBrackets = false; 1185 verifyFormat("return a is [1, 2, 3];", Style); 1186 verifyFormat("return a is [..];", Style); 1187 } 1188 1189 TEST_F(FormatTestCSharp, CSharpNullableTypes) { 1190 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1191 Style.SpacesInSquareBrackets = false; 1192 1193 verifyFormat(R"(// 1194 public class A { 1195 void foo() { 1196 int? value = some.bar(); 1197 } 1198 })", 1199 Style); // int? is nullable not a conditional expression. 1200 1201 verifyFormat(R"(void foo(int? x, int? y, int? z) {})", 1202 Style); // Nullables in function definitions. 1203 1204 verifyFormat(R"(public float? Value;)", Style); // no space before `?`. 1205 1206 verifyFormat(R"(int?[] arr = new int?[10];)", 1207 Style); // An array of a nullable type. 1208 1209 verifyFormat(R"(var x = (int?)y;)", Style); // Cast to a nullable type. 1210 1211 verifyFormat(R"(var x = new MyContainer<int?>();)", Style); // Generics. 1212 1213 verifyFormat(R"(// 1214 public interface I { 1215 int? Function(); 1216 })", 1217 Style); // Interface methods. 1218 1219 Style.ColumnLimit = 10; 1220 verifyFormat(R"(// 1221 public VeryLongType? Function( 1222 int arg1, 1223 int arg2) { 1224 // 1225 })", 1226 Style); // ? sticks with identifier. 1227 } 1228 1229 TEST_F(FormatTestCSharp, CSharpArraySubscripts) { 1230 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1231 1232 // Do not format array subscript operators as attributes. 1233 verifyFormat(R"(// 1234 if (someThings[index].Contains(myThing)) { 1235 })", 1236 Style); 1237 1238 verifyFormat(R"(// 1239 if (someThings[i][j][k].Contains(myThing)) { 1240 })", 1241 Style); 1242 } 1243 1244 TEST_F(FormatTestCSharp, CSharpGenericTypeConstraints) { 1245 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1246 1247 EXPECT_TRUE(Style.BraceWrapping.SplitEmptyRecord); 1248 1249 verifyFormat("class ItemFactory<T>\n" 1250 " where T : new() {\n" 1251 "}", 1252 Style); 1253 1254 verifyFormat("class Dictionary<TKey, TVal>\n" 1255 " where TKey : IComparable<TKey>\n" 1256 " where TVal : IMyInterface {\n" 1257 " public void MyMethod<T>(T t)\n" 1258 " where T : IMyInterface {\n" 1259 " doThing();\n" 1260 " }\n" 1261 "}", 1262 Style); 1263 1264 verifyFormat("class ItemFactory<T>\n" 1265 " where T : new(), IAnInterface<T>, IAnotherInterface<T>, " 1266 "IAnotherInterfaceStill<T> {\n" 1267 "}", 1268 Style); 1269 1270 Style.ColumnLimit = 50; // Force lines to be wrapped. 1271 verifyFormat(R"(// 1272 class ItemFactory<T, U> 1273 where T : new(), 1274 IAnInterface<T>, 1275 IAnotherInterface<T, U>, 1276 IAnotherInterfaceStill<T, U> { 1277 })", 1278 Style); 1279 1280 // In other languages `where` can be used as a normal identifier. 1281 // This example is in C++! 1282 verifyFormat(R"(// 1283 class A { 1284 int f(int where) {} 1285 };)", 1286 getGoogleStyle(FormatStyle::LK_Cpp)); 1287 } 1288 1289 TEST_F(FormatTestCSharp, CSharpAfterEnum) { 1290 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1291 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1292 Style.BraceWrapping.AfterEnum = false; 1293 Style.AllowShortEnumsOnASingleLine = false; 1294 1295 verifyFormat("enum MyEnum {\n" 1296 " Foo,\n" 1297 " Bar,\n" 1298 "}", 1299 Style); 1300 verifyFormat("internal enum MyEnum {\n" 1301 " Foo,\n" 1302 " Bar,\n" 1303 "}", 1304 Style); 1305 verifyFormat("public enum MyEnum {\n" 1306 " Foo,\n" 1307 " Bar,\n" 1308 "}", 1309 Style); 1310 verifyFormat("protected enum MyEnum {\n" 1311 " Foo,\n" 1312 " Bar,\n" 1313 "}", 1314 Style); 1315 verifyFormat("private enum MyEnum {\n" 1316 " Foo,\n" 1317 " Bar,\n" 1318 "}", 1319 Style); 1320 1321 Style.BraceWrapping.AfterEnum = true; 1322 Style.AllowShortEnumsOnASingleLine = false; 1323 1324 verifyFormat("enum MyEnum\n" 1325 "{\n" 1326 " Foo,\n" 1327 " Bar,\n" 1328 "}", 1329 Style); 1330 verifyFormat("internal enum MyEnum\n" 1331 "{\n" 1332 " Foo,\n" 1333 " Bar,\n" 1334 "}", 1335 Style); 1336 verifyFormat("public enum MyEnum\n" 1337 "{\n" 1338 " Foo,\n" 1339 " Bar,\n" 1340 "}", 1341 Style); 1342 verifyFormat("protected enum MyEnum\n" 1343 "{\n" 1344 " Foo,\n" 1345 " Bar,\n" 1346 "}", 1347 Style); 1348 verifyFormat("private enum MyEnum\n" 1349 "{\n" 1350 " Foo,\n" 1351 " Bar,\n" 1352 "}", 1353 Style); 1354 verifyFormat("/* Foo */ private enum MyEnum\n" 1355 "{\n" 1356 " Foo,\n" 1357 " Bar,\n" 1358 "}", 1359 Style); 1360 verifyFormat("/* Foo */ /* Bar */ private enum MyEnum\n" 1361 "{\n" 1362 " Foo,\n" 1363 " Bar,\n" 1364 "}", 1365 Style); 1366 } 1367 1368 TEST_F(FormatTestCSharp, CSharpAfterClass) { 1369 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1370 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1371 Style.BraceWrapping.AfterClass = false; 1372 1373 verifyFormat("class MyClass {\n" 1374 " int a;\n" 1375 " int b;\n" 1376 "}", 1377 Style); 1378 verifyFormat("internal class MyClass {\n" 1379 " int a;\n" 1380 " int b;\n" 1381 "}", 1382 Style); 1383 verifyFormat("public class MyClass {\n" 1384 " int a;\n" 1385 " int b;\n" 1386 "}", 1387 Style); 1388 verifyFormat("protected class MyClass {\n" 1389 " int a;\n" 1390 " int b;\n" 1391 "}", 1392 Style); 1393 verifyFormat("private class MyClass {\n" 1394 " int a;\n" 1395 " int b;\n" 1396 "}", 1397 Style); 1398 1399 verifyFormat("interface Interface {\n" 1400 " int a;\n" 1401 " int b;\n" 1402 "}", 1403 Style); 1404 verifyFormat("internal interface Interface {\n" 1405 " int a;\n" 1406 " int b;\n" 1407 "}", 1408 Style); 1409 verifyFormat("public interface Interface {\n" 1410 " int a;\n" 1411 " int b;\n" 1412 "}", 1413 Style); 1414 verifyFormat("protected interface Interface {\n" 1415 " int a;\n" 1416 " int b;\n" 1417 "}", 1418 Style); 1419 verifyFormat("private interface Interface {\n" 1420 " int a;\n" 1421 " int b;\n" 1422 "}", 1423 Style); 1424 1425 Style.BraceWrapping.AfterClass = true; 1426 1427 verifyFormat("class MyClass\n" 1428 "{\n" 1429 " int a;\n" 1430 " int b;\n" 1431 "}", 1432 Style); 1433 verifyFormat("internal class MyClass\n" 1434 "{\n" 1435 " int a;\n" 1436 " int b;\n" 1437 "}", 1438 Style); 1439 verifyFormat("public class MyClass\n" 1440 "{\n" 1441 " int a;\n" 1442 " int b;\n" 1443 "}", 1444 Style); 1445 verifyFormat("protected class MyClass\n" 1446 "{\n" 1447 " int a;\n" 1448 " int b;\n" 1449 "}", 1450 Style); 1451 verifyFormat("private class MyClass\n" 1452 "{\n" 1453 " int a;\n" 1454 " int b;\n" 1455 "}", 1456 Style); 1457 1458 verifyFormat("interface MyInterface\n" 1459 "{\n" 1460 " int a;\n" 1461 " int b;\n" 1462 "}", 1463 Style); 1464 verifyFormat("internal interface MyInterface\n" 1465 "{\n" 1466 " int a;\n" 1467 " int b;\n" 1468 "}", 1469 Style); 1470 verifyFormat("public interface MyInterface\n" 1471 "{\n" 1472 " int a;\n" 1473 " int b;\n" 1474 "}", 1475 Style); 1476 verifyFormat("protected interface MyInterface\n" 1477 "{\n" 1478 " int a;\n" 1479 " int b;\n" 1480 "}", 1481 Style); 1482 verifyFormat("private interface MyInterface\n" 1483 "{\n" 1484 " int a;\n" 1485 " int b;\n" 1486 "}", 1487 Style); 1488 verifyFormat("/* Foo */ private interface MyInterface\n" 1489 "{\n" 1490 " int a;\n" 1491 " int b;\n" 1492 "}", 1493 Style); 1494 verifyFormat("/* Foo */ /* Bar */ private interface MyInterface\n" 1495 "{\n" 1496 " int a;\n" 1497 " int b;\n" 1498 "}", 1499 Style); 1500 } 1501 1502 TEST_F(FormatTestCSharp, NamespaceIndentation) { 1503 FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 1504 Style.NamespaceIndentation = FormatStyle::NI_None; 1505 1506 verifyFormat("namespace A\n" 1507 "{\n" 1508 "public interface Name1\n" 1509 "{\n" 1510 "}\n" 1511 "}\n", 1512 Style); 1513 1514 verifyFormat("namespace A.B\n" 1515 "{\n" 1516 "public interface Name1\n" 1517 "{\n" 1518 "}\n" 1519 "}\n", 1520 Style); 1521 1522 Style.NamespaceIndentation = FormatStyle::NI_Inner; 1523 1524 verifyFormat("namespace A\n" 1525 "{\n" 1526 "namespace B\n" 1527 "{\n" 1528 " public interface Name1\n" 1529 " {\n" 1530 " }\n" 1531 "}\n" 1532 "}\n", 1533 Style); 1534 1535 Style.NamespaceIndentation = FormatStyle::NI_All; 1536 1537 verifyFormat("namespace A.B\n" 1538 "{\n" 1539 " public interface Name1\n" 1540 " {\n" 1541 " }\n" 1542 "}\n", 1543 Style); 1544 1545 verifyFormat("namespace A\n" 1546 "{\n" 1547 " namespace B\n" 1548 " {\n" 1549 " public interface Name1\n" 1550 " {\n" 1551 " }\n" 1552 " }\n" 1553 "}\n", 1554 Style); 1555 } 1556 1557 TEST_F(FormatTestCSharp, SwitchExpression) { 1558 FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 1559 verifyFormat("int x = a switch {\n" 1560 " 1 => (0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0),\n" 1561 " 2 => 1,\n" 1562 " _ => 2\n" 1563 "};\n", 1564 Style); 1565 } 1566 1567 TEST_F(FormatTestCSharp, EmptyShortBlock) { 1568 auto Style = getLLVMStyle(); 1569 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; 1570 1571 verifyFormat("try {\n" 1572 " doA();\n" 1573 "} catch (Exception e) {\n" 1574 " e.printStackTrace();\n" 1575 "}\n", 1576 Style); 1577 1578 verifyFormat("try {\n" 1579 " doA();\n" 1580 "} catch (Exception e) {}\n", 1581 Style); 1582 } 1583 1584 TEST_F(FormatTestCSharp, ShortFunctions) { 1585 FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp); 1586 Style.NamespaceIndentation = FormatStyle::NI_All; 1587 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1588 verifyFormat("interface Interface {\n" 1589 " void f() { return; }\n" 1590 "};", 1591 Style); 1592 verifyFormat("public interface Interface {\n" 1593 " void f() { return; }\n" 1594 "};", 1595 Style); 1596 verifyFormat("namespace {\n" 1597 " void f() {\n" 1598 " return;\n" 1599 " }\n" 1600 "};", 1601 Style); 1602 // "union" is not a keyword in C#. 1603 verifyFormat("namespace union {\n" 1604 " void f() {\n" 1605 " return;\n" 1606 " }\n" 1607 "};", 1608 Style); 1609 } 1610 1611 TEST_F(FormatTestCSharp, BrokenBrackets) { 1612 EXPECT_NE("", format("int where b <")); // reduced from crasher 1613 } 1614 1615 } // namespace format 1616 } // end namespace clang 1617