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