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(llvm::StringRef Code, unsigned Offset, 25 unsigned Length, 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(llvm::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.AlwaysBreakAfterReturnType = 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 verifyFormat("class Dictionary<TKey, TVal>\n" 1308 " where TKey : IComparable<TKey>\n" 1309 " where TVal : IMyInterface {\n" 1310 " public void MyMethod<T>(T t)\n" 1311 " where T : IMyInterface {\n" 1312 " doThing();\n" 1313 " }\n" 1314 "}", 1315 Style); 1316 1317 verifyFormat("class ItemFactory<T>\n" 1318 " where T : new(), IAnInterface<T>, IAnotherInterface<T>, " 1319 "IAnotherInterfaceStill<T> {\n" 1320 "}", 1321 Style); 1322 1323 Style.ColumnLimit = 50; // Force lines to be wrapped. 1324 verifyFormat(R"(// 1325 class ItemFactory<T, U> 1326 where T : new(), 1327 IAnInterface<T>, 1328 IAnotherInterface<T, U>, 1329 IAnotherInterfaceStill<T, U> { 1330 })", 1331 Style); 1332 1333 // In other languages `where` can be used as a normal identifier. 1334 // This example is in C++! 1335 verifyFormat(R"(// 1336 class A { 1337 int f(int where) {} 1338 };)", 1339 getGoogleStyle(FormatStyle::LK_Cpp)); 1340 } 1341 1342 TEST_F(FormatTestCSharp, CSharpAfterEnum) { 1343 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1344 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1345 Style.BraceWrapping.AfterEnum = false; 1346 Style.AllowShortEnumsOnASingleLine = false; 1347 1348 verifyFormat("enum MyEnum {\n" 1349 " Foo,\n" 1350 " Bar,\n" 1351 "}", 1352 Style); 1353 verifyFormat("internal enum MyEnum {\n" 1354 " Foo,\n" 1355 " Bar,\n" 1356 "}", 1357 Style); 1358 verifyFormat("public enum MyEnum {\n" 1359 " Foo,\n" 1360 " Bar,\n" 1361 "}", 1362 Style); 1363 verifyFormat("protected enum MyEnum {\n" 1364 " Foo,\n" 1365 " Bar,\n" 1366 "}", 1367 Style); 1368 verifyFormat("private enum MyEnum {\n" 1369 " Foo,\n" 1370 " Bar,\n" 1371 "}", 1372 Style); 1373 1374 Style.BraceWrapping.AfterEnum = true; 1375 Style.AllowShortEnumsOnASingleLine = false; 1376 1377 verifyFormat("enum MyEnum\n" 1378 "{\n" 1379 " Foo,\n" 1380 " Bar,\n" 1381 "}", 1382 Style); 1383 verifyFormat("internal enum MyEnum\n" 1384 "{\n" 1385 " Foo,\n" 1386 " Bar,\n" 1387 "}", 1388 Style); 1389 verifyFormat("public enum MyEnum\n" 1390 "{\n" 1391 " Foo,\n" 1392 " Bar,\n" 1393 "}", 1394 Style); 1395 verifyFormat("protected enum MyEnum\n" 1396 "{\n" 1397 " Foo,\n" 1398 " Bar,\n" 1399 "}", 1400 Style); 1401 verifyFormat("private enum MyEnum\n" 1402 "{\n" 1403 " Foo,\n" 1404 " Bar,\n" 1405 "}", 1406 Style); 1407 verifyFormat("/* Foo */ private enum MyEnum\n" 1408 "{\n" 1409 " Foo,\n" 1410 " Bar,\n" 1411 "}", 1412 Style); 1413 verifyFormat("/* Foo */ /* Bar */ private enum MyEnum\n" 1414 "{\n" 1415 " Foo,\n" 1416 " Bar,\n" 1417 "}", 1418 Style); 1419 } 1420 1421 TEST_F(FormatTestCSharp, CSharpAfterClass) { 1422 FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1423 Style.BreakBeforeBraces = FormatStyle::BS_Custom; 1424 Style.BraceWrapping.AfterClass = false; 1425 1426 verifyFormat("class MyClass {\n" 1427 " int a;\n" 1428 " int b;\n" 1429 "}", 1430 Style); 1431 verifyFormat("internal class MyClass {\n" 1432 " int a;\n" 1433 " int b;\n" 1434 "}", 1435 Style); 1436 verifyFormat("public class MyClass {\n" 1437 " int a;\n" 1438 " int b;\n" 1439 "}", 1440 Style); 1441 verifyFormat("protected class MyClass {\n" 1442 " int a;\n" 1443 " int b;\n" 1444 "}", 1445 Style); 1446 verifyFormat("private class MyClass {\n" 1447 " int a;\n" 1448 " int b;\n" 1449 "}", 1450 Style); 1451 1452 verifyFormat("interface Interface {\n" 1453 " int a;\n" 1454 " int b;\n" 1455 "}", 1456 Style); 1457 verifyFormat("internal interface Interface {\n" 1458 " int a;\n" 1459 " int b;\n" 1460 "}", 1461 Style); 1462 verifyFormat("public interface Interface {\n" 1463 " int a;\n" 1464 " int b;\n" 1465 "}", 1466 Style); 1467 verifyFormat("protected interface Interface {\n" 1468 " int a;\n" 1469 " int b;\n" 1470 "}", 1471 Style); 1472 verifyFormat("private interface Interface {\n" 1473 " int a;\n" 1474 " int b;\n" 1475 "}", 1476 Style); 1477 1478 Style.BraceWrapping.AfterClass = true; 1479 1480 verifyFormat("class MyClass\n" 1481 "{\n" 1482 " int a;\n" 1483 " int b;\n" 1484 "}", 1485 Style); 1486 verifyFormat("internal class MyClass\n" 1487 "{\n" 1488 " int a;\n" 1489 " int b;\n" 1490 "}", 1491 Style); 1492 verifyFormat("public class MyClass\n" 1493 "{\n" 1494 " int a;\n" 1495 " int b;\n" 1496 "}", 1497 Style); 1498 verifyFormat("protected class MyClass\n" 1499 "{\n" 1500 " int a;\n" 1501 " int b;\n" 1502 "}", 1503 Style); 1504 verifyFormat("private class MyClass\n" 1505 "{\n" 1506 " int a;\n" 1507 " int b;\n" 1508 "}", 1509 Style); 1510 1511 verifyFormat("interface MyInterface\n" 1512 "{\n" 1513 " int a;\n" 1514 " int b;\n" 1515 "}", 1516 Style); 1517 verifyFormat("internal interface MyInterface\n" 1518 "{\n" 1519 " int a;\n" 1520 " int b;\n" 1521 "}", 1522 Style); 1523 verifyFormat("public interface MyInterface\n" 1524 "{\n" 1525 " int a;\n" 1526 " int b;\n" 1527 "}", 1528 Style); 1529 verifyFormat("protected interface MyInterface\n" 1530 "{\n" 1531 " int a;\n" 1532 " int b;\n" 1533 "}", 1534 Style); 1535 verifyFormat("private interface MyInterface\n" 1536 "{\n" 1537 " int a;\n" 1538 " int b;\n" 1539 "}", 1540 Style); 1541 verifyFormat("/* Foo */ private interface MyInterface\n" 1542 "{\n" 1543 " int a;\n" 1544 " int b;\n" 1545 "}", 1546 Style); 1547 verifyFormat("/* Foo */ /* Bar */ private interface MyInterface\n" 1548 "{\n" 1549 " int a;\n" 1550 " int b;\n" 1551 "}", 1552 Style); 1553 } 1554 1555 TEST_F(FormatTestCSharp, NamespaceIndentation) { 1556 FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 1557 Style.NamespaceIndentation = FormatStyle::NI_None; 1558 1559 verifyFormat("namespace A\n" 1560 "{\n" 1561 "public interface Name1\n" 1562 "{\n" 1563 "}\n" 1564 "}", 1565 Style); 1566 1567 verifyFormat("namespace A.B\n" 1568 "{\n" 1569 "public interface Name1\n" 1570 "{\n" 1571 "}\n" 1572 "}", 1573 Style); 1574 1575 Style.NamespaceIndentation = FormatStyle::NI_Inner; 1576 1577 verifyFormat("namespace A\n" 1578 "{\n" 1579 "namespace B\n" 1580 "{\n" 1581 " public interface Name1\n" 1582 " {\n" 1583 " }\n" 1584 "}\n" 1585 "}", 1586 Style); 1587 1588 Style.NamespaceIndentation = FormatStyle::NI_All; 1589 1590 verifyFormat("namespace A.B\n" 1591 "{\n" 1592 " public interface Name1\n" 1593 " {\n" 1594 " }\n" 1595 "}", 1596 Style); 1597 1598 verifyFormat("namespace A\n" 1599 "{\n" 1600 " namespace B\n" 1601 " {\n" 1602 " public interface Name1\n" 1603 " {\n" 1604 " }\n" 1605 " }\n" 1606 "}", 1607 Style); 1608 } 1609 1610 TEST_F(FormatTestCSharp, SwitchExpression) { 1611 FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 1612 verifyFormat("int x = a switch {\n" 1613 " 1 => (0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0),\n" 1614 " 2 => 1,\n" 1615 " _ => 2\n" 1616 "};", 1617 Style); 1618 } 1619 1620 TEST_F(FormatTestCSharp, EmptyShortBlock) { 1621 auto Style = getLLVMStyle(); 1622 Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; 1623 1624 verifyFormat("try {\n" 1625 " doA();\n" 1626 "} catch (Exception e) {\n" 1627 " e.printStackTrace();\n" 1628 "}", 1629 Style); 1630 1631 verifyFormat("try {\n" 1632 " doA();\n" 1633 "} catch (Exception e) {}", 1634 Style); 1635 } 1636 1637 TEST_F(FormatTestCSharp, ShortFunctions) { 1638 FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp); 1639 Style.NamespaceIndentation = FormatStyle::NI_All; 1640 Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; 1641 verifyFormat("interface Interface {\n" 1642 " void f() { return; }\n" 1643 "};", 1644 Style); 1645 verifyFormat("public interface Interface {\n" 1646 " void f() { return; }\n" 1647 "};", 1648 Style); 1649 verifyFormat("namespace {\n" 1650 " void f() {\n" 1651 " return;\n" 1652 " }\n" 1653 "};", 1654 Style); 1655 // "union" is not a keyword in C#. 1656 verifyFormat("namespace union {\n" 1657 " void f() {\n" 1658 " return;\n" 1659 " }\n" 1660 "};", 1661 Style); 1662 } 1663 1664 TEST_F(FormatTestCSharp, BrokenBrackets) { 1665 EXPECT_NE("", format("int where b <")); // reduced from crasher 1666 } 1667 1668 } // namespace 1669 } // namespace test 1670 } // namespace format 1671 } // namespace clang 1672