1cbb726d0SPaul Hoad //===- unittest/Format/FormatTestCSharp.cpp - Formatting tests for CSharp -===// 2cbb726d0SPaul Hoad // 3cbb726d0SPaul Hoad // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4cbb726d0SPaul Hoad // See https://llvm.org/LICENSE.txt for license information. 5cbb726d0SPaul Hoad // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6cbb726d0SPaul Hoad // 7cbb726d0SPaul Hoad //===----------------------------------------------------------------------===// 8cbb726d0SPaul Hoad 9cbb726d0SPaul Hoad #include "FormatTestUtils.h" 10cbb726d0SPaul Hoad #include "clang/Format/Format.h" 11cbb726d0SPaul Hoad #include "llvm/Support/Debug.h" 12cbb726d0SPaul Hoad #include "gtest/gtest.h" 13cbb726d0SPaul Hoad 14cbb726d0SPaul Hoad #define DEBUG_TYPE "format-test" 15cbb726d0SPaul Hoad 16cbb726d0SPaul Hoad namespace clang { 17cbb726d0SPaul Hoad namespace format { 18cbb726d0SPaul Hoad 19cbb726d0SPaul Hoad class FormatTestCSharp : public ::testing::Test { 20cbb726d0SPaul Hoad protected: 21cbb726d0SPaul Hoad static std::string format(llvm::StringRef Code, unsigned Offset, 22cbb726d0SPaul Hoad unsigned Length, const FormatStyle &Style) { 23cbb726d0SPaul Hoad LLVM_DEBUG(llvm::errs() << "---\n"); 24cbb726d0SPaul Hoad LLVM_DEBUG(llvm::errs() << Code << "\n\n"); 25cbb726d0SPaul Hoad std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length)); 26cbb726d0SPaul Hoad tooling::Replacements Replaces = reformat(Style, Code, Ranges); 27cbb726d0SPaul Hoad auto Result = applyAllReplacements(Code, Replaces); 28cbb726d0SPaul Hoad EXPECT_TRUE(static_cast<bool>(Result)); 29cbb726d0SPaul Hoad LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); 30cbb726d0SPaul Hoad return *Result; 31cbb726d0SPaul Hoad } 32cbb726d0SPaul Hoad 33cbb726d0SPaul Hoad static std::string 34cbb726d0SPaul Hoad format(llvm::StringRef Code, 35a2f963bbSPaul Hoad const FormatStyle &Style = getMicrosoftStyle(FormatStyle::LK_CSharp)) { 36cbb726d0SPaul Hoad return format(Code, 0, Code.size(), Style); 37cbb726d0SPaul Hoad } 38cbb726d0SPaul Hoad 39cbb726d0SPaul Hoad static FormatStyle getStyleWithColumns(unsigned ColumnLimit) { 40a2f963bbSPaul Hoad FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 41cbb726d0SPaul Hoad Style.ColumnLimit = ColumnLimit; 42cbb726d0SPaul Hoad return Style; 43cbb726d0SPaul Hoad } 44cbb726d0SPaul Hoad 45cbb726d0SPaul Hoad static void verifyFormat( 46cbb726d0SPaul Hoad llvm::StringRef Code, 47a2f963bbSPaul Hoad const FormatStyle &Style = getMicrosoftStyle(FormatStyle::LK_CSharp)) { 48cbb726d0SPaul Hoad EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable"; 49cbb726d0SPaul Hoad EXPECT_EQ(Code.str(), format(test::messUp(Code), Style)); 50cbb726d0SPaul Hoad } 51cbb726d0SPaul Hoad }; 52cbb726d0SPaul Hoad 53cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpClass) { 54a2f963bbSPaul Hoad verifyFormat("public class SomeClass\n" 55a2f963bbSPaul Hoad "{\n" 56a2f963bbSPaul Hoad " void f()\n" 57a2f963bbSPaul Hoad " {\n" 58a2f963bbSPaul Hoad " }\n" 59a2f963bbSPaul Hoad " int g()\n" 60a2f963bbSPaul Hoad " {\n" 61a2f963bbSPaul Hoad " return 0;\n" 62a2f963bbSPaul Hoad " }\n" 63a2f963bbSPaul Hoad " void h()\n" 64a2f963bbSPaul Hoad " {\n" 65a2f963bbSPaul Hoad " while (true)\n" 66a2f963bbSPaul Hoad " f();\n" 67a2f963bbSPaul Hoad " for (;;)\n" 68a2f963bbSPaul Hoad " f();\n" 69a2f963bbSPaul Hoad " if (true)\n" 70a2f963bbSPaul Hoad " f();\n" 71cbb726d0SPaul Hoad " }\n" 72cbb726d0SPaul Hoad "}"); 73cbb726d0SPaul Hoad } 74cbb726d0SPaul Hoad 75cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, AccessModifiers) { 76a2f963bbSPaul Hoad verifyFormat("public String toString()\n" 77a2f963bbSPaul Hoad "{\n" 78a2f963bbSPaul Hoad "}"); 79a2f963bbSPaul Hoad verifyFormat("private String toString()\n" 80a2f963bbSPaul Hoad "{\n" 81a2f963bbSPaul Hoad "}"); 82a2f963bbSPaul Hoad verifyFormat("protected String toString()\n" 83a2f963bbSPaul Hoad "{\n" 84a2f963bbSPaul Hoad "}"); 85a2f963bbSPaul Hoad verifyFormat("internal String toString()\n" 86a2f963bbSPaul Hoad "{\n" 87a2f963bbSPaul Hoad "}"); 88cbb726d0SPaul Hoad 89a2f963bbSPaul Hoad verifyFormat("public override String toString()\n" 90a2f963bbSPaul Hoad "{\n" 91a2f963bbSPaul Hoad "}"); 92a2f963bbSPaul Hoad verifyFormat("private override String toString()\n" 93a2f963bbSPaul Hoad "{\n" 94a2f963bbSPaul Hoad "}"); 95a2f963bbSPaul Hoad verifyFormat("protected override String toString()\n" 96a2f963bbSPaul Hoad "{\n" 97a2f963bbSPaul Hoad "}"); 98a2f963bbSPaul Hoad verifyFormat("internal override String toString()\n" 99a2f963bbSPaul Hoad "{\n" 100a2f963bbSPaul Hoad "}"); 101cbb726d0SPaul Hoad 102a2f963bbSPaul Hoad verifyFormat("internal static String toString()\n" 103a2f963bbSPaul Hoad "{\n" 104a2f963bbSPaul Hoad "}"); 105cbb726d0SPaul Hoad } 106cbb726d0SPaul Hoad 107cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, NoStringLiteralBreaks) { 108cbb726d0SPaul Hoad verifyFormat("foo(" 109cbb726d0SPaul Hoad "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 110cbb726d0SPaul Hoad "aaaaaa\");"); 111cbb726d0SPaul Hoad } 112cbb726d0SPaul Hoad 113cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpVerbatiumStringLiterals) { 114cbb726d0SPaul Hoad verifyFormat("foo(@\"aaaaaaaa\\abc\\aaaa\");"); 115cbb726d0SPaul Hoad // @"ABC\" + ToString("B") - handle embedded \ in literal string at 116cbb726d0SPaul Hoad // the end 117cbb726d0SPaul Hoad // 118cbb726d0SPaul Hoad /* 119cbb726d0SPaul Hoad * After removal of Lexer change we are currently not able 120cbb726d0SPaul Hoad * To handle these cases 121cbb726d0SPaul Hoad verifyFormat("string s = @\"ABC\\\" + ToString(\"B\");"); 122cbb726d0SPaul Hoad verifyFormat("string s = @\"ABC\"\"DEF\"\"GHI\""); 123cbb726d0SPaul Hoad verifyFormat("string s = @\"ABC\"\"DEF\"\"\""); 124cbb726d0SPaul Hoad verifyFormat("string s = @\"ABC\"\"DEF\"\"\" + abc"); 125cbb726d0SPaul Hoad */ 126cbb726d0SPaul Hoad } 127cbb726d0SPaul Hoad 128cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpInterpolatedStringLiterals) { 129cbb726d0SPaul Hoad verifyFormat("foo($\"aaaaaaaa{aaa}aaaa\");"); 130cbb726d0SPaul Hoad verifyFormat("foo($\"aaaa{A}\");"); 131cbb726d0SPaul Hoad verifyFormat( 132cbb726d0SPaul Hoad "foo($\"aaaa{A}" 133cbb726d0SPaul Hoad "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");"); 134cbb726d0SPaul Hoad verifyFormat("Name = $\"{firstName} {lastName}\";"); 135cbb726d0SPaul Hoad 136cbb726d0SPaul Hoad // $"ABC\" + ToString("B") - handle embedded \ in literal string at 137cbb726d0SPaul Hoad // the end 138cbb726d0SPaul Hoad verifyFormat("string s = $\"A{abc}BC\" + ToString(\"B\");"); 139cbb726d0SPaul Hoad verifyFormat("$\"{domain}\\\\{user}\""); 140cbb726d0SPaul Hoad verifyFormat( 141cbb726d0SPaul Hoad "var verbatimInterpolated = $@\"C:\\Users\\{userName}\\Documents\\\";"); 142cbb726d0SPaul Hoad } 143cbb726d0SPaul Hoad 144cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpFatArrows) { 145cbb726d0SPaul Hoad verifyFormat("Task serverTask = Task.Run(async() => {"); 146cbb726d0SPaul Hoad verifyFormat("public override string ToString() => \"{Name}\\{Age}\";"); 147cbb726d0SPaul Hoad } 148cbb726d0SPaul Hoad 149cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpNullConditional) { 1504c056583SPaul Hoad FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1514c056583SPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 1524c056583SPaul Hoad 153cbb726d0SPaul Hoad verifyFormat( 154cbb726d0SPaul Hoad "public Person(string firstName, string lastName, int? age=null)"); 155cbb726d0SPaul Hoad 1564c056583SPaul Hoad verifyFormat("foo () {\n" 1574c056583SPaul Hoad " switch (args?.Length) {}\n" 1584c056583SPaul Hoad "}", 1594c056583SPaul Hoad Style); 1604c056583SPaul Hoad 1614c056583SPaul Hoad verifyFormat("switch (args?.Length) {}", Style); 162cbb726d0SPaul Hoad 163a2f963bbSPaul Hoad verifyFormat("public static void Main(string[] args)\n" 164a2f963bbSPaul Hoad "{\n" 165a2f963bbSPaul Hoad " string dirPath = args?[0];\n" 166a2f963bbSPaul Hoad "}"); 1674c056583SPaul Hoad 1684c056583SPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Never; 1694c056583SPaul Hoad 1704c056583SPaul Hoad verifyFormat("switch(args?.Length) {}", Style); 171cbb726d0SPaul Hoad } 172cbb726d0SPaul Hoad 173cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, Attributes) { 174cbb726d0SPaul Hoad verifyFormat("[STAThread]\n" 175a2f963bbSPaul Hoad "static void Main(string[] args)\n" 176a2f963bbSPaul Hoad "{\n" 177a2f963bbSPaul Hoad "}"); 178cbb726d0SPaul Hoad 179cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 180a2f963bbSPaul Hoad "private class Test\n" 181a2f963bbSPaul Hoad "{\n" 182a2f963bbSPaul Hoad "}"); 183cbb726d0SPaul Hoad 184cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 185a2f963bbSPaul Hoad "protected class Test\n" 186a2f963bbSPaul Hoad "{\n" 187a2f963bbSPaul Hoad "}"); 188cbb726d0SPaul Hoad 189cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 190a2f963bbSPaul Hoad "internal class Test\n" 191a2f963bbSPaul Hoad "{\n" 192a2f963bbSPaul Hoad "}"); 193cbb726d0SPaul Hoad 194cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 195a2f963bbSPaul Hoad "class Test\n" 196a2f963bbSPaul Hoad "{\n" 197a2f963bbSPaul Hoad "}"); 198cbb726d0SPaul Hoad 199cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 200cbb726d0SPaul Hoad "[DeploymentItem(\"Test.txt\")]\n" 201a2f963bbSPaul Hoad "public class Test\n" 202a2f963bbSPaul Hoad "{\n" 203a2f963bbSPaul Hoad "}"); 204cbb726d0SPaul Hoad 205cbb726d0SPaul Hoad verifyFormat("[System.AttributeUsage(System.AttributeTargets.Method)]\n" 206cbb726d0SPaul Hoad "[System.Runtime.InteropServices.ComVisible(true)]\n" 207a2f963bbSPaul Hoad "public sealed class STAThreadAttribute : Attribute\n" 208a2f963bbSPaul Hoad "{\n" 209a2f963bbSPaul Hoad "}"); 210cbb726d0SPaul Hoad 211cbb726d0SPaul Hoad verifyFormat("[Verb(\"start\", HelpText = \"Starts the server listening on " 212cbb726d0SPaul Hoad "provided port\")]\n" 213a2f963bbSPaul Hoad "class Test\n" 214a2f963bbSPaul Hoad "{\n" 215a2f963bbSPaul Hoad "}"); 216cbb726d0SPaul Hoad 217cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 218a2f963bbSPaul Hoad "public string Host\n" 219a2f963bbSPaul Hoad "{\n" 220a2f963bbSPaul Hoad " set;\n" 221a2f963bbSPaul Hoad " get;\n" 222a2f963bbSPaul Hoad "}"); 223cbb726d0SPaul Hoad 224cbb726d0SPaul Hoad verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server " 225cbb726d0SPaul Hoad "listening on provided host\")]\n" 226a2f963bbSPaul Hoad "public string Host\n" 227a2f963bbSPaul Hoad "{\n" 228a2f963bbSPaul Hoad " set;\n" 229a2f963bbSPaul Hoad " get;\n" 230a2f963bbSPaul Hoad "}"); 231cbb726d0SPaul Hoad } 232cbb726d0SPaul Hoad 233719087bbSPaul Hoad TEST_F(FormatTestCSharp, CSharpUsing) { 234719087bbSPaul Hoad FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 235719087bbSPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 236719087bbSPaul Hoad verifyFormat("public void foo () {\n" 237719087bbSPaul Hoad " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n" 2381e0174a9SKrasimir Georgiev " using () {}\n" 239719087bbSPaul Hoad "}", 240719087bbSPaul Hoad Style); 241719087bbSPaul Hoad 2421e0174a9SKrasimir Georgiev // Ensure clang-format affects top-level snippets correctly. 2434c056583SPaul Hoad verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}", 2444c056583SPaul Hoad Style); 2454c056583SPaul Hoad 246719087bbSPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Never; 247719087bbSPaul Hoad verifyFormat("public void foo() {\n" 248719087bbSPaul Hoad " using(StreamWriter sw = new StreamWriter(filenameB)) {}\n" 2491e0174a9SKrasimir Georgiev " using() {}\n" 250719087bbSPaul Hoad "}", 251719087bbSPaul Hoad Style); 2524c056583SPaul Hoad 2531e0174a9SKrasimir Georgiev // Ensure clang-format affects top-level snippets correctly. 2541e0174a9SKrasimir Georgiev verifyFormat("using(StreamWriter sw = new StreamWriter(filenameB)) {}", 2551e0174a9SKrasimir Georgiev Style); 2561e0174a9SKrasimir Georgiev 2571e0174a9SKrasimir Georgiev Style.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; 2581e0174a9SKrasimir Georgiev verifyFormat("public void foo() {\n" 2591e0174a9SKrasimir Georgiev " using (StreamWriter sw = new StreamWriter(filenameA)) {}\n" 2601e0174a9SKrasimir Georgiev " using () {}\n" 2611e0174a9SKrasimir Georgiev "}", 2621e0174a9SKrasimir Georgiev Style); 2631e0174a9SKrasimir Georgiev 2641e0174a9SKrasimir Georgiev // Ensure clang-format affects top-level snippets correctly. 2651e0174a9SKrasimir Georgiev verifyFormat("using (StreamWriter sw = new StreamWriter(filenameB)) {}", 2661e0174a9SKrasimir Georgiev Style); 2671e0174a9SKrasimir Georgiev 2681e0174a9SKrasimir Georgiev Style.SpaceBeforeParens = FormatStyle::SBPO_NonEmptyParentheses; 2691e0174a9SKrasimir Georgiev verifyFormat("public void foo() {\n" 2701e0174a9SKrasimir Georgiev " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n" 2711e0174a9SKrasimir Georgiev " using() {}\n" 2721e0174a9SKrasimir Georgiev "}", 2731e0174a9SKrasimir Georgiev Style); 2741e0174a9SKrasimir Georgiev 2751e0174a9SKrasimir Georgiev // Ensure clang-format affects top-level snippets correctly. 2764c056583SPaul Hoad verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}", 2774c056583SPaul Hoad Style); 278719087bbSPaul Hoad } 279719087bbSPaul Hoad 280cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpRegions) { 281cbb726d0SPaul Hoad verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa " 282cbb726d0SPaul Hoad "aaaaaaaaaaaaaaa long region"); 283cbb726d0SPaul Hoad } 284cbb726d0SPaul Hoad 285cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpKeyWordEscaping) { 286cbb726d0SPaul Hoad verifyFormat("public enum var { none, @string, bool, @enum }"); 287cbb726d0SPaul Hoad } 288cbb726d0SPaul Hoad 289cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpNullCoalescing) { 290cbb726d0SPaul Hoad verifyFormat("var test = ABC ?? DEF"); 291cbb726d0SPaul Hoad verifyFormat("string myname = name ?? \"ABC\";"); 292cbb726d0SPaul Hoad verifyFormat("return _name ?? \"DEF\";"); 293cbb726d0SPaul Hoad } 294cbb726d0SPaul Hoad 295a2f963bbSPaul Hoad TEST_F(FormatTestCSharp, AttributesIndentation) { 296a2f963bbSPaul Hoad FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 297a2f963bbSPaul Hoad Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 298a2f963bbSPaul Hoad 299a2f963bbSPaul Hoad verifyFormat("[STAThread]\n" 300a2f963bbSPaul Hoad "static void Main(string[] args)\n" 301a2f963bbSPaul Hoad "{\n" 302a2f963bbSPaul Hoad "}", 303a2f963bbSPaul Hoad Style); 304a2f963bbSPaul Hoad 305a2f963bbSPaul Hoad verifyFormat("[STAThread]\n" 306a2f963bbSPaul Hoad "void " 307a2f963bbSPaul Hoad "veryLooooooooooooooongFunctionName(string[] args)\n" 308a2f963bbSPaul Hoad "{\n" 309a2f963bbSPaul Hoad "}", 310a2f963bbSPaul Hoad Style); 311a2f963bbSPaul Hoad 312a2f963bbSPaul Hoad verifyFormat("[STAThread]\n" 313a2f963bbSPaul Hoad "veryLoooooooooooooooooooongReturnType " 314a2f963bbSPaul Hoad "veryLooooooooooooooongFunctionName(string[] args)\n" 315a2f963bbSPaul Hoad "{\n" 316a2f963bbSPaul Hoad "}", 317a2f963bbSPaul Hoad Style); 318a2f963bbSPaul Hoad 319a2f963bbSPaul Hoad verifyFormat("[SuppressMessage(\"A\", \"B\", Justification = \"C\")]\n" 320a2f963bbSPaul Hoad "public override X Y()\n" 321a2f963bbSPaul Hoad "{\n" 322a2f963bbSPaul Hoad "}\n", 323a2f963bbSPaul Hoad Style); 324a2f963bbSPaul Hoad 325a2f963bbSPaul Hoad verifyFormat("[SuppressMessage]\n" 326a2f963bbSPaul Hoad "public X Y()\n" 327a2f963bbSPaul Hoad "{\n" 328a2f963bbSPaul Hoad "}\n", 329a2f963bbSPaul Hoad Style); 330a2f963bbSPaul Hoad 331a2f963bbSPaul Hoad verifyFormat("[SuppressMessage]\n" 332a2f963bbSPaul Hoad "public override X Y()\n" 333a2f963bbSPaul Hoad "{\n" 334a2f963bbSPaul Hoad "}\n", 335a2f963bbSPaul Hoad Style); 336a2f963bbSPaul Hoad 337a2f963bbSPaul Hoad verifyFormat("public A(B b) : base(b)\n" 338a2f963bbSPaul Hoad "{\n" 339a2f963bbSPaul Hoad " [SuppressMessage]\n" 340a2f963bbSPaul Hoad " public override X Y()\n" 341a2f963bbSPaul Hoad " {\n" 342a2f963bbSPaul Hoad " }\n" 343a2f963bbSPaul Hoad "}\n", 344a2f963bbSPaul Hoad Style); 3452f209ccfSmydeveloperday 3462f209ccfSmydeveloperday verifyFormat("public A : Base\n" 3472f209ccfSmydeveloperday "{\n" 3482f209ccfSmydeveloperday "}\n" 3492f209ccfSmydeveloperday "[Test]\n" 3502f209ccfSmydeveloperday "public Foo()\n" 3512f209ccfSmydeveloperday "{\n" 3522f209ccfSmydeveloperday "}\n", 3532f209ccfSmydeveloperday Style); 3542f209ccfSmydeveloperday 3552f209ccfSmydeveloperday verifyFormat("namespace\n" 3562f209ccfSmydeveloperday "{\n" 3572f209ccfSmydeveloperday "public A : Base\n" 3582f209ccfSmydeveloperday "{\n" 3592f209ccfSmydeveloperday "}\n" 3602f209ccfSmydeveloperday "[Test]\n" 3612f209ccfSmydeveloperday "public Foo()\n" 3622f209ccfSmydeveloperday "{\n" 3632f209ccfSmydeveloperday "}\n" 3642f209ccfSmydeveloperday "}\n", 3652f209ccfSmydeveloperday Style); 366a2f963bbSPaul Hoad } 367a2f963bbSPaul Hoad 3684c056583SPaul Hoad TEST_F(FormatTestCSharp, CSharpSpaceBefore) { 3694c056583SPaul Hoad FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 3704c056583SPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 3714c056583SPaul Hoad 3724c056583SPaul Hoad verifyFormat("List<string> list;", Style); 3734c056583SPaul Hoad verifyFormat("Dictionary<string, string> dict;", Style); 3744c056583SPaul Hoad 3754c056583SPaul Hoad verifyFormat("for (int i = 0; i < size (); i++) {\n" 3764c056583SPaul Hoad "}", 3774c056583SPaul Hoad Style); 3784c056583SPaul Hoad verifyFormat("foreach (var x in y) {\n" 3794c056583SPaul Hoad "}", 3804c056583SPaul Hoad Style); 3814c056583SPaul Hoad verifyFormat("switch (x) {}", Style); 3824c056583SPaul Hoad verifyFormat("do {\n" 3834c056583SPaul Hoad "} while (x);", 3844c056583SPaul Hoad Style); 3854c056583SPaul Hoad 3864c056583SPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Never; 3874c056583SPaul Hoad 3884c056583SPaul Hoad verifyFormat("List<string> list;", Style); 3894c056583SPaul Hoad verifyFormat("Dictionary<string, string> dict;", Style); 3904c056583SPaul Hoad 3914c056583SPaul Hoad verifyFormat("for(int i = 0; i < size(); i++) {\n" 3924c056583SPaul Hoad "}", 3934c056583SPaul Hoad Style); 3944c056583SPaul Hoad verifyFormat("foreach(var x in y) {\n" 3954c056583SPaul Hoad "}", 3964c056583SPaul Hoad Style); 3974c056583SPaul Hoad verifyFormat("switch(x) {}", Style); 3984c056583SPaul Hoad verifyFormat("do {\n" 3994c056583SPaul Hoad "} while(x);", 4004c056583SPaul Hoad Style); 4014c056583SPaul Hoad } 4024c056583SPaul Hoad 403d82adf32Smydeveloperday TEST_F(FormatTestCSharp, CSharpSpaceAfterCStyleCast) { 404d82adf32Smydeveloperday FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 405d82adf32Smydeveloperday 406d82adf32Smydeveloperday verifyFormat("(int)x / y;", Style); 407d82adf32Smydeveloperday 408d82adf32Smydeveloperday Style.SpaceAfterCStyleCast = true; 409d82adf32Smydeveloperday verifyFormat("(int) x / y;", Style); 410d82adf32Smydeveloperday } 411d82adf32Smydeveloperday 41236a8f7f6SKrasimir Georgiev TEST_F(FormatTestCSharp, CSharpEscapedQuotesInVerbatimStrings) { 41336a8f7f6SKrasimir Georgiev FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 41436a8f7f6SKrasimir Georgiev 415f9f0919dSJonathan Coe verifyFormat(R"(string str = @"""";)", Style); 416f9f0919dSJonathan Coe verifyFormat(R"(string str = @"""Hello world""";)", Style); 417f9f0919dSJonathan Coe verifyFormat(R"(string str = $@"""Hello {friend}""";)", Style); 41836a8f7f6SKrasimir Georgiev } 41936a8f7f6SKrasimir Georgiev 4209d212e83SJonathan Coe TEST_F(FormatTestCSharp, CSharpQuotesInInterpolatedStrings) { 4219d212e83SJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 4229d212e83SJonathan Coe 4239d212e83SJonathan Coe verifyFormat(R"(string str1 = $"{null ?? "null"}";)", Style); 4249d212e83SJonathan Coe verifyFormat(R"(string str2 = $"{{{braceCount} braces";)", Style); 4259d212e83SJonathan Coe verifyFormat(R"(string str3 = $"{braceCount}}} braces";)", Style); 4269d212e83SJonathan Coe } 4279d212e83SJonathan Coe 428f9f0919dSJonathan Coe TEST_F(FormatTestCSharp, CSharpNewlinesInVerbatimStrings) { 429f9f0919dSJonathan Coe // Use MS style as Google Style inserts a line break before multiline strings. 430f9f0919dSJonathan Coe 431f9f0919dSJonathan Coe // verifyFormat does not understand multiline C# string-literals 432f9f0919dSJonathan Coe // so check the format explicitly. 433f9f0919dSJonathan Coe 434f9f0919dSJonathan Coe FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 435f9f0919dSJonathan Coe 436f9f0919dSJonathan Coe std::string Code = R"(string s1 = $@"some code: 437f9f0919dSJonathan Coe class {className} {{ 438f9f0919dSJonathan Coe {className}() {{}} 439f9f0919dSJonathan Coe }}";)"; 440f9f0919dSJonathan Coe 441f9f0919dSJonathan Coe EXPECT_EQ(Code, format(Code, Style)); 442f9f0919dSJonathan Coe 443f9f0919dSJonathan Coe // Multiline string in the middle of a function call. 444f9f0919dSJonathan Coe Code = R"( 445f9f0919dSJonathan Coe var x = foo(className, $@"some code: 446f9f0919dSJonathan Coe class {className} {{ 447f9f0919dSJonathan Coe {className}() {{}} 448f9f0919dSJonathan Coe }}", 449f9f0919dSJonathan Coe y);)"; // y aligned with `className` arg. 450f9f0919dSJonathan Coe 451f9f0919dSJonathan Coe EXPECT_EQ(Code, format(Code, Style)); 452f9f0919dSJonathan Coe 453f9f0919dSJonathan Coe // Interpolated string with embedded multiline string. 454f9f0919dSJonathan Coe Code = R"(Console.WriteLine($"{string.Join(@", 455f9f0919dSJonathan Coe ", values)}");)"; 456f9f0919dSJonathan Coe 457f9f0919dSJonathan Coe EXPECT_EQ(Code, format(Code, Style)); 458f9f0919dSJonathan Coe } 459f9f0919dSJonathan Coe 460*0bb60e29SJonathan Coe TEST_F(FormatTestCSharp, CSharpObjectInitializers) { 461*0bb60e29SJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 462*0bb60e29SJonathan Coe 463*0bb60e29SJonathan Coe // Start code fragemnts with a comment line so that C++ raw string literals 464*0bb60e29SJonathan Coe // as seen are identical to expected formatted code. 465*0bb60e29SJonathan Coe 466*0bb60e29SJonathan Coe verifyFormat(R"(// 467*0bb60e29SJonathan Coe Shape[] shapes = new[] { 468*0bb60e29SJonathan Coe new Circle { 469*0bb60e29SJonathan Coe Radius = 2.7281, 470*0bb60e29SJonathan Coe Colour = Colours.Red, 471*0bb60e29SJonathan Coe }, 472*0bb60e29SJonathan Coe new Square { 473*0bb60e29SJonathan Coe Side = 101.1, 474*0bb60e29SJonathan Coe Colour = Colours.Yellow, 475*0bb60e29SJonathan Coe }, 476*0bb60e29SJonathan Coe };)", 477*0bb60e29SJonathan Coe Style); 478*0bb60e29SJonathan Coe 479*0bb60e29SJonathan Coe // Omitted final `,`s will change the formatting. 480*0bb60e29SJonathan Coe verifyFormat(R"(// 481*0bb60e29SJonathan Coe Shape[] shapes = new[] {new Circle {Radius = 2.7281, Colour = Colours.Red}, 482*0bb60e29SJonathan Coe new Square { 483*0bb60e29SJonathan Coe Side = 101.1, 484*0bb60e29SJonathan Coe Colour = Colours.Yellow, 485*0bb60e29SJonathan Coe }};)", 486*0bb60e29SJonathan Coe Style); 487*0bb60e29SJonathan Coe } 488*0bb60e29SJonathan Coe 489cbb726d0SPaul Hoad } // namespace format 490cbb726d0SPaul Hoad } // end namespace clang 491