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 "}"); 73f40a7972SJonathan Coe 74f40a7972SJonathan Coe // Ensure that small and empty classes are handled correctly with condensed 75f40a7972SJonathan Coe // (Google C++-like) brace-breaking style. 76f40a7972SJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 77f40a7972SJonathan Coe Style.BreakBeforeBraces = FormatStyle::BS_Attach; 78f40a7972SJonathan Coe 79f40a7972SJonathan Coe verifyFormat("public class SomeEmptyClass {}", Style); 80f40a7972SJonathan Coe 81f40a7972SJonathan Coe verifyFormat("public class SomeTinyClass {\n" 82f40a7972SJonathan Coe " int X;\n" 83f40a7972SJonathan Coe "}", 84f40a7972SJonathan Coe Style); 85f40a7972SJonathan Coe verifyFormat("private class SomeTinyClass {\n" 86f40a7972SJonathan Coe " int X;\n" 87f40a7972SJonathan Coe "}", 88f40a7972SJonathan Coe Style); 89f40a7972SJonathan Coe verifyFormat("protected class SomeTinyClass {\n" 90f40a7972SJonathan Coe " int X;\n" 91f40a7972SJonathan Coe "}", 92f40a7972SJonathan Coe Style); 93f40a7972SJonathan Coe verifyFormat("internal class SomeTinyClass {\n" 94f40a7972SJonathan Coe " int X;\n" 95f40a7972SJonathan Coe "}", 96f40a7972SJonathan Coe Style); 97cbb726d0SPaul Hoad } 98cbb726d0SPaul Hoad 99cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, AccessModifiers) { 100a2f963bbSPaul Hoad verifyFormat("public String toString()\n" 101a2f963bbSPaul Hoad "{\n" 102a2f963bbSPaul Hoad "}"); 103a2f963bbSPaul Hoad verifyFormat("private String toString()\n" 104a2f963bbSPaul Hoad "{\n" 105a2f963bbSPaul Hoad "}"); 106a2f963bbSPaul Hoad verifyFormat("protected String toString()\n" 107a2f963bbSPaul Hoad "{\n" 108a2f963bbSPaul Hoad "}"); 109a2f963bbSPaul Hoad verifyFormat("internal String toString()\n" 110a2f963bbSPaul Hoad "{\n" 111a2f963bbSPaul Hoad "}"); 112cbb726d0SPaul Hoad 113a2f963bbSPaul Hoad verifyFormat("public override String toString()\n" 114a2f963bbSPaul Hoad "{\n" 115a2f963bbSPaul Hoad "}"); 116a2f963bbSPaul Hoad verifyFormat("private override String toString()\n" 117a2f963bbSPaul Hoad "{\n" 118a2f963bbSPaul Hoad "}"); 119a2f963bbSPaul Hoad verifyFormat("protected override String toString()\n" 120a2f963bbSPaul Hoad "{\n" 121a2f963bbSPaul Hoad "}"); 122a2f963bbSPaul Hoad verifyFormat("internal override String toString()\n" 123a2f963bbSPaul Hoad "{\n" 124a2f963bbSPaul Hoad "}"); 125cbb726d0SPaul Hoad 126a2f963bbSPaul Hoad verifyFormat("internal static String toString()\n" 127a2f963bbSPaul Hoad "{\n" 128a2f963bbSPaul Hoad "}"); 129cbb726d0SPaul Hoad } 130cbb726d0SPaul Hoad 131cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, NoStringLiteralBreaks) { 132cbb726d0SPaul Hoad verifyFormat("foo(" 133cbb726d0SPaul Hoad "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 134cbb726d0SPaul Hoad "aaaaaa\");"); 135cbb726d0SPaul Hoad } 136cbb726d0SPaul Hoad 137cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpVerbatiumStringLiterals) { 138cbb726d0SPaul Hoad verifyFormat("foo(@\"aaaaaaaa\\abc\\aaaa\");"); 139cbb726d0SPaul Hoad // @"ABC\" + ToString("B") - handle embedded \ in literal string at 140cbb726d0SPaul Hoad // the end 141cbb726d0SPaul Hoad // 142cbb726d0SPaul Hoad /* 143cbb726d0SPaul Hoad * After removal of Lexer change we are currently not able 144cbb726d0SPaul Hoad * To handle these cases 145cbb726d0SPaul Hoad verifyFormat("string s = @\"ABC\\\" + ToString(\"B\");"); 146cbb726d0SPaul Hoad verifyFormat("string s = @\"ABC\"\"DEF\"\"GHI\""); 147cbb726d0SPaul Hoad verifyFormat("string s = @\"ABC\"\"DEF\"\"\""); 148cbb726d0SPaul Hoad verifyFormat("string s = @\"ABC\"\"DEF\"\"\" + abc"); 149cbb726d0SPaul Hoad */ 150cbb726d0SPaul Hoad } 151cbb726d0SPaul Hoad 152cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpInterpolatedStringLiterals) { 153cbb726d0SPaul Hoad verifyFormat("foo($\"aaaaaaaa{aaa}aaaa\");"); 154cbb726d0SPaul Hoad verifyFormat("foo($\"aaaa{A}\");"); 155cbb726d0SPaul Hoad verifyFormat( 156cbb726d0SPaul Hoad "foo($\"aaaa{A}" 157cbb726d0SPaul Hoad "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");"); 158cbb726d0SPaul Hoad verifyFormat("Name = $\"{firstName} {lastName}\";"); 159cbb726d0SPaul Hoad 160cbb726d0SPaul Hoad // $"ABC\" + ToString("B") - handle embedded \ in literal string at 161cbb726d0SPaul Hoad // the end 162cbb726d0SPaul Hoad verifyFormat("string s = $\"A{abc}BC\" + ToString(\"B\");"); 163cbb726d0SPaul Hoad verifyFormat("$\"{domain}\\\\{user}\""); 164cbb726d0SPaul Hoad verifyFormat( 165cbb726d0SPaul Hoad "var verbatimInterpolated = $@\"C:\\Users\\{userName}\\Documents\\\";"); 166cbb726d0SPaul Hoad } 167cbb726d0SPaul Hoad 168cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpFatArrows) { 169cbb726d0SPaul Hoad verifyFormat("Task serverTask = Task.Run(async() => {"); 170cbb726d0SPaul Hoad verifyFormat("public override string ToString() => \"{Name}\\{Age}\";"); 171cbb726d0SPaul Hoad } 172cbb726d0SPaul Hoad 173c3af063cSJonathan Coe TEST_F(FormatTestCSharp, CSharpConditionalExpressions) { 174c3af063cSJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 175c3af063cSJonathan Coe // conditional expression is not seen as a NullConditional. 176c3af063cSJonathan Coe verifyFormat("var y = A < B ? -1 : 1;", Style); 177c3af063cSJonathan Coe } 178c3af063cSJonathan Coe 179cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpNullConditional) { 1804c056583SPaul Hoad FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 1814c056583SPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 1824c056583SPaul Hoad 183cbb726d0SPaul Hoad verifyFormat( 184cbb726d0SPaul Hoad "public Person(string firstName, string lastName, int? age = null)"); 185cbb726d0SPaul Hoad 1864c056583SPaul Hoad verifyFormat("foo () {\n" 1874c056583SPaul Hoad " switch (args?.Length) {}\n" 1884c056583SPaul Hoad "}", 1894c056583SPaul Hoad Style); 1904c056583SPaul Hoad 1914c056583SPaul Hoad verifyFormat("switch (args?.Length) {}", Style); 192cbb726d0SPaul Hoad 193a2f963bbSPaul Hoad verifyFormat("public static void Main(string[] args)\n" 194a2f963bbSPaul Hoad "{\n" 195a2f963bbSPaul Hoad " string dirPath = args?[0];\n" 196a2f963bbSPaul Hoad "}"); 1974c056583SPaul Hoad 1984c056583SPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Never; 1994c056583SPaul Hoad 2004c056583SPaul Hoad verifyFormat("switch(args?.Length) {}", Style); 201cbb726d0SPaul Hoad } 202cbb726d0SPaul Hoad 203cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, Attributes) { 204cbb726d0SPaul Hoad verifyFormat("[STAThread]\n" 205a2f963bbSPaul Hoad "static void Main(string[] args)\n" 206a2f963bbSPaul Hoad "{\n" 207a2f963bbSPaul Hoad "}"); 208cbb726d0SPaul Hoad 209cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 210a2f963bbSPaul Hoad "private class Test\n" 211a2f963bbSPaul Hoad "{\n" 212a2f963bbSPaul Hoad "}"); 213cbb726d0SPaul Hoad 214cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 215a2f963bbSPaul Hoad "protected class Test\n" 216a2f963bbSPaul Hoad "{\n" 217a2f963bbSPaul Hoad "}"); 218cbb726d0SPaul Hoad 219cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 220a2f963bbSPaul Hoad "internal class Test\n" 221a2f963bbSPaul Hoad "{\n" 222a2f963bbSPaul Hoad "}"); 223cbb726d0SPaul Hoad 224cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 225a2f963bbSPaul Hoad "class Test\n" 226a2f963bbSPaul Hoad "{\n" 227a2f963bbSPaul Hoad "}"); 228cbb726d0SPaul Hoad 229cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 230cbb726d0SPaul Hoad "[DeploymentItem(\"Test.txt\")]\n" 231a2f963bbSPaul Hoad "public class Test\n" 232a2f963bbSPaul Hoad "{\n" 233a2f963bbSPaul Hoad "}"); 234cbb726d0SPaul Hoad 235cbb726d0SPaul Hoad verifyFormat("[System.AttributeUsage(System.AttributeTargets.Method)]\n" 236cbb726d0SPaul Hoad "[System.Runtime.InteropServices.ComVisible(true)]\n" 237a2f963bbSPaul Hoad "public sealed class STAThreadAttribute : Attribute\n" 238a2f963bbSPaul Hoad "{\n" 239a2f963bbSPaul Hoad "}"); 240cbb726d0SPaul Hoad 241cbb726d0SPaul Hoad verifyFormat("[Verb(\"start\", HelpText = \"Starts the server listening on " 242cbb726d0SPaul Hoad "provided port\")]\n" 243a2f963bbSPaul Hoad "class Test\n" 244a2f963bbSPaul Hoad "{\n" 245a2f963bbSPaul Hoad "}"); 246cbb726d0SPaul Hoad 247cbb726d0SPaul Hoad verifyFormat("[TestMethod]\n" 248a2f963bbSPaul Hoad "public string Host\n" 2492bd6974aSJonathan Coe "{ set; get; }"); 250cbb726d0SPaul Hoad 251cbb726d0SPaul Hoad verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server " 252cbb726d0SPaul Hoad "listening on provided host\")]\n" 253a2f963bbSPaul Hoad "public string Host\n" 2542bd6974aSJonathan Coe "{ set; get; }"); 25550d8977cSJonathan Coe 25650d8977cSJonathan Coe verifyFormat( 25750d8977cSJonathan Coe "[DllImport(\"Hello\", EntryPoint = \"hello_world\")]\n" 25850d8977cSJonathan Coe "// The const char* returned by hello_world must not be deleted.\n" 25950d8977cSJonathan Coe "private static extern IntPtr HelloFromCpp();)"); 260ca1fd460SJonathan Coe 261b46f925dSJonathan Coe // Class attributes go on their own line and do not affect layout of 262b46f925dSJonathan Coe // interfaces. Line wrapping decisions previously caused each interface to be 263b46f925dSJonathan Coe // on its own line. 264b46f925dSJonathan Coe verifyFormat("[SomeAttribute]\n" 265b46f925dSJonathan Coe "[SomeOtherAttribute]\n" 266b46f925dSJonathan Coe "public class A : IShape, IAnimal, IVehicle\n" 267b46f925dSJonathan Coe "{\n" 268b46f925dSJonathan Coe " int X;\n" 269b46f925dSJonathan Coe "}"); 270b46f925dSJonathan Coe 271b46f925dSJonathan Coe // Attributes in a method declaration do not cause line wrapping. 272b46f925dSJonathan Coe verifyFormat("void MethodA([In][Out] ref double x)\n" 273b46f925dSJonathan Coe "{\n" 274b46f925dSJonathan Coe "}"); 275b46f925dSJonathan Coe 2769f8a7e82SJonathan Coe // [] in an attribute do not cause premature line wrapping or indenting. 2779f8a7e82SJonathan Coe verifyFormat(R"(// 2789f8a7e82SJonathan Coe public class A 2799f8a7e82SJonathan Coe { 2809f8a7e82SJonathan Coe [SomeAttribute(new[] { RED, GREEN, BLUE }, -1.0f, 1.0f)] 2819f8a7e82SJonathan Coe [DoNotSerialize] 2829f8a7e82SJonathan Coe public Data MemberVariable; 2839f8a7e82SJonathan Coe })"); 2849f8a7e82SJonathan Coe 285ca1fd460SJonathan Coe // Unwrappable lines go on a line of their own. 286ca1fd460SJonathan Coe // 'target:' is not treated as a label. 287ca1fd460SJonathan Coe // Modify Style to enforce a column limit. 288ca1fd460SJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 289ca1fd460SJonathan Coe Style.ColumnLimit = 10; 290ca1fd460SJonathan Coe verifyFormat(R"([assembly:InternalsVisibleTo( 291ca1fd460SJonathan Coe "SomeAssembly, PublicKey=SomePublicKeyThatExceedsTheColumnLimit")])", 292ca1fd460SJonathan Coe Style); 293cbb726d0SPaul Hoad } 294cbb726d0SPaul Hoad 295719087bbSPaul Hoad TEST_F(FormatTestCSharp, CSharpUsing) { 296719087bbSPaul Hoad FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 297719087bbSPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 298719087bbSPaul Hoad verifyFormat("public void foo () {\n" 299719087bbSPaul Hoad " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n" 3001e0174a9SKrasimir Georgiev " using () {}\n" 301719087bbSPaul Hoad "}", 302719087bbSPaul Hoad Style); 303719087bbSPaul Hoad 3041e0174a9SKrasimir Georgiev // Ensure clang-format affects top-level snippets correctly. 3054c056583SPaul Hoad verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}", 3064c056583SPaul Hoad Style); 3074c056583SPaul Hoad 308719087bbSPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Never; 309719087bbSPaul Hoad verifyFormat("public void foo() {\n" 310719087bbSPaul Hoad " using(StreamWriter sw = new StreamWriter(filenameB)) {}\n" 3111e0174a9SKrasimir Georgiev " using() {}\n" 312719087bbSPaul Hoad "}", 313719087bbSPaul Hoad Style); 3144c056583SPaul Hoad 3151e0174a9SKrasimir Georgiev // Ensure clang-format affects top-level snippets correctly. 3161e0174a9SKrasimir Georgiev verifyFormat("using(StreamWriter sw = new StreamWriter(filenameB)) {}", 3171e0174a9SKrasimir Georgiev Style); 3181e0174a9SKrasimir Georgiev 3191e0174a9SKrasimir Georgiev Style.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; 3201e0174a9SKrasimir Georgiev verifyFormat("public void foo() {\n" 3211e0174a9SKrasimir Georgiev " using (StreamWriter sw = new StreamWriter(filenameA)) {}\n" 3221e0174a9SKrasimir Georgiev " using () {}\n" 3231e0174a9SKrasimir Georgiev "}", 3241e0174a9SKrasimir Georgiev Style); 3251e0174a9SKrasimir Georgiev 3261e0174a9SKrasimir Georgiev // Ensure clang-format affects top-level snippets correctly. 3271e0174a9SKrasimir Georgiev verifyFormat("using (StreamWriter sw = new StreamWriter(filenameB)) {}", 3281e0174a9SKrasimir Georgiev Style); 3291e0174a9SKrasimir Georgiev 3301e0174a9SKrasimir Georgiev Style.SpaceBeforeParens = FormatStyle::SBPO_NonEmptyParentheses; 3311e0174a9SKrasimir Georgiev verifyFormat("public void foo() {\n" 3321e0174a9SKrasimir Georgiev " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n" 3331e0174a9SKrasimir Georgiev " using() {}\n" 3341e0174a9SKrasimir Georgiev "}", 3351e0174a9SKrasimir Georgiev Style); 3361e0174a9SKrasimir Georgiev 3371e0174a9SKrasimir Georgiev // Ensure clang-format affects top-level snippets correctly. 3384c056583SPaul Hoad verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}", 3394c056583SPaul Hoad Style); 340719087bbSPaul Hoad } 341719087bbSPaul Hoad 342cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpRegions) { 343cbb726d0SPaul Hoad verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa " 344cbb726d0SPaul Hoad "aaaaaaaaaaaaaaa long region"); 345cbb726d0SPaul Hoad } 346cbb726d0SPaul Hoad 347cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpKeyWordEscaping) { 348cbb726d0SPaul Hoad verifyFormat("public enum var { none, @string, bool, @enum }"); 349cbb726d0SPaul Hoad } 350cbb726d0SPaul Hoad 351cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpNullCoalescing) { 352cbb726d0SPaul Hoad verifyFormat("var test = ABC ?? DEF"); 353cbb726d0SPaul Hoad verifyFormat("string myname = name ?? \"ABC\";"); 354cbb726d0SPaul Hoad verifyFormat("return _name ?? \"DEF\";"); 355cbb726d0SPaul Hoad } 356cbb726d0SPaul Hoad 357a2f963bbSPaul Hoad TEST_F(FormatTestCSharp, AttributesIndentation) { 358a2f963bbSPaul Hoad FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 359a2f963bbSPaul Hoad Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; 360a2f963bbSPaul Hoad 361a2f963bbSPaul Hoad verifyFormat("[STAThread]\n" 362a2f963bbSPaul Hoad "static void Main(string[] args)\n" 363a2f963bbSPaul Hoad "{\n" 364a2f963bbSPaul Hoad "}", 365a2f963bbSPaul Hoad Style); 366a2f963bbSPaul Hoad 367a2f963bbSPaul Hoad verifyFormat("[STAThread]\n" 368a2f963bbSPaul Hoad "void " 369a2f963bbSPaul Hoad "veryLooooooooooooooongFunctionName(string[] args)\n" 370a2f963bbSPaul Hoad "{\n" 371a2f963bbSPaul Hoad "}", 372a2f963bbSPaul Hoad Style); 373a2f963bbSPaul Hoad 374a2f963bbSPaul Hoad verifyFormat("[STAThread]\n" 375a2f963bbSPaul Hoad "veryLoooooooooooooooooooongReturnType " 376a2f963bbSPaul Hoad "veryLooooooooooooooongFunctionName(string[] args)\n" 377a2f963bbSPaul Hoad "{\n" 378a2f963bbSPaul Hoad "}", 379a2f963bbSPaul Hoad Style); 380a2f963bbSPaul Hoad 381a2f963bbSPaul Hoad verifyFormat("[SuppressMessage(\"A\", \"B\", Justification = \"C\")]\n" 382a2f963bbSPaul Hoad "public override X Y()\n" 383a2f963bbSPaul Hoad "{\n" 384a2f963bbSPaul Hoad "}\n", 385a2f963bbSPaul Hoad Style); 386a2f963bbSPaul Hoad 387a2f963bbSPaul Hoad verifyFormat("[SuppressMessage]\n" 388a2f963bbSPaul Hoad "public X Y()\n" 389a2f963bbSPaul Hoad "{\n" 390a2f963bbSPaul Hoad "}\n", 391a2f963bbSPaul Hoad Style); 392a2f963bbSPaul Hoad 393a2f963bbSPaul Hoad verifyFormat("[SuppressMessage]\n" 394a2f963bbSPaul Hoad "public override X Y()\n" 395a2f963bbSPaul Hoad "{\n" 396a2f963bbSPaul Hoad "}\n", 397a2f963bbSPaul Hoad Style); 398a2f963bbSPaul Hoad 399a2f963bbSPaul Hoad verifyFormat("public A(B b) : base(b)\n" 400a2f963bbSPaul Hoad "{\n" 401a2f963bbSPaul Hoad " [SuppressMessage]\n" 402a2f963bbSPaul Hoad " public override X Y()\n" 403a2f963bbSPaul Hoad " {\n" 404a2f963bbSPaul Hoad " }\n" 405a2f963bbSPaul Hoad "}\n", 406a2f963bbSPaul Hoad Style); 4072f209ccfSmydeveloperday 4082f209ccfSmydeveloperday verifyFormat("public A : Base\n" 4092f209ccfSmydeveloperday "{\n" 4102f209ccfSmydeveloperday "}\n" 4112f209ccfSmydeveloperday "[Test]\n" 4122f209ccfSmydeveloperday "public Foo()\n" 4132f209ccfSmydeveloperday "{\n" 4142f209ccfSmydeveloperday "}\n", 4152f209ccfSmydeveloperday Style); 4162f209ccfSmydeveloperday 4172f209ccfSmydeveloperday verifyFormat("namespace\n" 4182f209ccfSmydeveloperday "{\n" 4192f209ccfSmydeveloperday "public A : Base\n" 4202f209ccfSmydeveloperday "{\n" 4212f209ccfSmydeveloperday "}\n" 4222f209ccfSmydeveloperday "[Test]\n" 4232f209ccfSmydeveloperday "public Foo()\n" 4242f209ccfSmydeveloperday "{\n" 4252f209ccfSmydeveloperday "}\n" 4262f209ccfSmydeveloperday "}\n", 4272f209ccfSmydeveloperday Style); 428a2f963bbSPaul Hoad } 429a2f963bbSPaul Hoad 4304c056583SPaul Hoad TEST_F(FormatTestCSharp, CSharpSpaceBefore) { 4314c056583SPaul Hoad FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 4324c056583SPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Always; 4334c056583SPaul Hoad 4344c056583SPaul Hoad verifyFormat("List<string> list;", Style); 4354c056583SPaul Hoad verifyFormat("Dictionary<string, string> dict;", Style); 4364c056583SPaul Hoad 4374c056583SPaul Hoad verifyFormat("for (int i = 0; i < size (); i++) {\n" 4384c056583SPaul Hoad "}", 4394c056583SPaul Hoad Style); 4404c056583SPaul Hoad verifyFormat("foreach (var x in y) {\n" 4414c056583SPaul Hoad "}", 4424c056583SPaul Hoad Style); 4434c056583SPaul Hoad verifyFormat("switch (x) {}", Style); 4444c056583SPaul Hoad verifyFormat("do {\n" 4454c056583SPaul Hoad "} while (x);", 4464c056583SPaul Hoad Style); 4474c056583SPaul Hoad 4484c056583SPaul Hoad Style.SpaceBeforeParens = FormatStyle::SBPO_Never; 4494c056583SPaul Hoad 4504c056583SPaul Hoad verifyFormat("List<string> list;", Style); 4514c056583SPaul Hoad verifyFormat("Dictionary<string, string> dict;", Style); 4524c056583SPaul Hoad 4534c056583SPaul Hoad verifyFormat("for(int i = 0; i < size(); i++) {\n" 4544c056583SPaul Hoad "}", 4554c056583SPaul Hoad Style); 4564c056583SPaul Hoad verifyFormat("foreach(var x in y) {\n" 4574c056583SPaul Hoad "}", 4584c056583SPaul Hoad Style); 4594c056583SPaul Hoad verifyFormat("switch(x) {}", Style); 4604c056583SPaul Hoad verifyFormat("do {\n" 4614c056583SPaul Hoad "} while(x);", 4624c056583SPaul Hoad Style); 4634c056583SPaul Hoad } 4644c056583SPaul Hoad 465d82adf32Smydeveloperday TEST_F(FormatTestCSharp, CSharpSpaceAfterCStyleCast) { 466d82adf32Smydeveloperday FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 467d82adf32Smydeveloperday 468d82adf32Smydeveloperday verifyFormat("(int)x / y;", Style); 469d82adf32Smydeveloperday 470d82adf32Smydeveloperday Style.SpaceAfterCStyleCast = true; 471d82adf32Smydeveloperday verifyFormat("(int) x / y;", Style); 472d82adf32Smydeveloperday } 473d82adf32Smydeveloperday 47436a8f7f6SKrasimir Georgiev TEST_F(FormatTestCSharp, CSharpEscapedQuotesInVerbatimStrings) { 47536a8f7f6SKrasimir Georgiev FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 47636a8f7f6SKrasimir Georgiev 477f9f0919dSJonathan Coe verifyFormat(R"(string str = @"""";)", Style); 478f9f0919dSJonathan Coe verifyFormat(R"(string str = @"""Hello world""";)", Style); 479f9f0919dSJonathan Coe verifyFormat(R"(string str = $@"""Hello {friend}""";)", Style); 48036a8f7f6SKrasimir Georgiev } 48136a8f7f6SKrasimir Georgiev 4829d212e83SJonathan Coe TEST_F(FormatTestCSharp, CSharpQuotesInInterpolatedStrings) { 4839d212e83SJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 4849d212e83SJonathan Coe 4859d212e83SJonathan Coe verifyFormat(R"(string str1 = $"{null ?? "null"}";)", Style); 4869d212e83SJonathan Coe verifyFormat(R"(string str2 = $"{{{braceCount} braces";)", Style); 4879d212e83SJonathan Coe verifyFormat(R"(string str3 = $"{braceCount}}} braces";)", Style); 4889d212e83SJonathan Coe } 4899d212e83SJonathan Coe 490f9f0919dSJonathan Coe TEST_F(FormatTestCSharp, CSharpNewlinesInVerbatimStrings) { 491f9f0919dSJonathan Coe // Use MS style as Google Style inserts a line break before multiline strings. 492f9f0919dSJonathan Coe 493f9f0919dSJonathan Coe // verifyFormat does not understand multiline C# string-literals 494f9f0919dSJonathan Coe // so check the format explicitly. 495f9f0919dSJonathan Coe 496f9f0919dSJonathan Coe FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); 497f9f0919dSJonathan Coe 498f9f0919dSJonathan Coe std::string Code = R"(string s1 = $@"some code: 499f9f0919dSJonathan Coe class {className} {{ 500f9f0919dSJonathan Coe {className}() {{}} 501f9f0919dSJonathan Coe }}";)"; 502f9f0919dSJonathan Coe 503f9f0919dSJonathan Coe EXPECT_EQ(Code, format(Code, Style)); 504f9f0919dSJonathan Coe 505f9f0919dSJonathan Coe // Multiline string in the middle of a function call. 506f9f0919dSJonathan Coe Code = R"( 507f9f0919dSJonathan Coe var x = foo(className, $@"some code: 508f9f0919dSJonathan Coe class {className} {{ 509f9f0919dSJonathan Coe {className}() {{}} 510f9f0919dSJonathan Coe }}", 511f9f0919dSJonathan Coe y);)"; // y aligned with `className` arg. 512f9f0919dSJonathan Coe 513f9f0919dSJonathan Coe EXPECT_EQ(Code, format(Code, Style)); 514f9f0919dSJonathan Coe 515f9f0919dSJonathan Coe // Interpolated string with embedded multiline string. 516f9f0919dSJonathan Coe Code = R"(Console.WriteLine($"{string.Join(@", 517f9f0919dSJonathan Coe ", values)}");)"; 518f9f0919dSJonathan Coe 519f9f0919dSJonathan Coe EXPECT_EQ(Code, format(Code, Style)); 520f9f0919dSJonathan Coe } 521f9f0919dSJonathan Coe 5220bb60e29SJonathan Coe TEST_F(FormatTestCSharp, CSharpObjectInitializers) { 5230bb60e29SJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 5240bb60e29SJonathan Coe 525a11ff39bSJonathan Coe // Start code fragments with a comment line so that C++ raw string literals 5260bb60e29SJonathan Coe // as seen are identical to expected formatted code. 5270bb60e29SJonathan Coe 5280bb60e29SJonathan Coe verifyFormat(R"(// 5290bb60e29SJonathan Coe Shape[] shapes = new[] { 5300bb60e29SJonathan Coe new Circle { 5310bb60e29SJonathan Coe Radius = 2.7281, 5320bb60e29SJonathan Coe Colour = Colours.Red, 5330bb60e29SJonathan Coe }, 5340bb60e29SJonathan Coe new Square { 5350bb60e29SJonathan Coe Side = 101.1, 5360bb60e29SJonathan Coe Colour = Colours.Yellow, 5370bb60e29SJonathan Coe }, 5380bb60e29SJonathan Coe };)", 5390bb60e29SJonathan Coe Style); 5400bb60e29SJonathan Coe 5410bb60e29SJonathan Coe // Omitted final `,`s will change the formatting. 5420bb60e29SJonathan Coe verifyFormat(R"(// 5430bb60e29SJonathan Coe Shape[] shapes = new[] { new Circle { Radius = 2.7281, Colour = Colours.Red }, 544eb682b80SJonathan Coe new Square { Side = 101.1, Colour = Colours.Yellow } };)", 5450bb60e29SJonathan Coe Style); 5467d2fdd3fSJonathan Coe 5477d2fdd3fSJonathan Coe // Lambdas can be supplied as initialiser arguments. 5487d2fdd3fSJonathan Coe verifyFormat(R"(// 5497d2fdd3fSJonathan Coe private Transformer _transformer = new X.Y { 5507d2fdd3fSJonathan Coe Filler = (Shape shape) => { return new Transform.Fill(shape, RED); }, 5517d2fdd3fSJonathan Coe Scaler = (Shape shape) => { return new Transform.Resize(shape, 0.1); }, 5527d2fdd3fSJonathan Coe };)", 5537d2fdd3fSJonathan Coe Style); 5540c28a093SJonathan Coe 5550c28a093SJonathan Coe // Dictionary initialisation. 5560c28a093SJonathan Coe verifyFormat(R"(// 5570c28a093SJonathan Coe var myDict = new Dictionary<string, string> { 5580c28a093SJonathan Coe ["name"] = _donald, 5590c28a093SJonathan Coe ["age"] = Convert.ToString(DateTime.Today.Year - 1934), 5600c28a093SJonathan Coe ["type"] = _duck, 5610c28a093SJonathan Coe };)", 5620c28a093SJonathan Coe Style); 5630bb60e29SJonathan Coe } 5640bb60e29SJonathan Coe 5655e1a026cSJonathan Coe TEST_F(FormatTestCSharp, CSharpArrayInitializers) { 5665e1a026cSJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 5675e1a026cSJonathan Coe 5685e1a026cSJonathan Coe verifyFormat(R"(// 5695e1a026cSJonathan Coe private MySet<Node>[] setPoints = { 5705e1a026cSJonathan Coe new Point<Node>(), 5715e1a026cSJonathan Coe new Point<Node>(), 5725e1a026cSJonathan Coe };)", 5735e1a026cSJonathan Coe Style); 5745e1a026cSJonathan Coe } 5755e1a026cSJonathan Coe 576a11ff39bSJonathan Coe TEST_F(FormatTestCSharp, CSharpNamedArguments) { 577a11ff39bSJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 578a11ff39bSJonathan Coe 579a11ff39bSJonathan Coe verifyFormat(R"(// 580a11ff39bSJonathan Coe PrintOrderDetails(orderNum: 31, productName: "Red Mug", 581a11ff39bSJonathan Coe sellerName: "Gift Shop");)", 582a11ff39bSJonathan Coe Style); 583a11ff39bSJonathan Coe 584a11ff39bSJonathan Coe // Ensure that trailing comments do not cause problems. 585a11ff39bSJonathan Coe verifyFormat(R"(// 586a11ff39bSJonathan Coe PrintOrderDetails(orderNum: 31, productName: "Red Mug", // comment 587a11ff39bSJonathan Coe sellerName: "Gift Shop");)", 588a11ff39bSJonathan Coe Style); 5897dfe0cc7SJonathan Coe 5907dfe0cc7SJonathan Coe verifyFormat(R"(foreach (var tickCount in task.Begin(seed: 0)) {)", Style); 591a11ff39bSJonathan Coe } 592a11ff39bSJonathan Coe 5932bd6974aSJonathan Coe TEST_F(FormatTestCSharp, CSharpPropertyAccessors) { 5942bd6974aSJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 5952bd6974aSJonathan Coe 5962bd6974aSJonathan Coe verifyFormat("int Value { get }", Style); 5972bd6974aSJonathan Coe verifyFormat("int Value { get; }", Style); 5982bd6974aSJonathan Coe verifyFormat("int Value { internal get; }", Style); 5992bd6974aSJonathan Coe verifyFormat("int Value { get; } = 0", Style); 6002bd6974aSJonathan Coe verifyFormat("int Value { set }", Style); 6012bd6974aSJonathan Coe verifyFormat("int Value { set; }", Style); 6022bd6974aSJonathan Coe verifyFormat("int Value { internal set; }", Style); 6032bd6974aSJonathan Coe verifyFormat("int Value { set; } = 0", Style); 6042bd6974aSJonathan Coe verifyFormat("int Value { get; set }", Style); 6052bd6974aSJonathan Coe verifyFormat("int Value { set; get }", Style); 6062bd6974aSJonathan Coe verifyFormat("int Value { get; private set; }", Style); 6072bd6974aSJonathan Coe verifyFormat("int Value { get; set; }", Style); 6082bd6974aSJonathan Coe verifyFormat("int Value { get; set; } = 0", Style); 6092bd6974aSJonathan Coe verifyFormat("int Value { internal get; internal set; }", Style); 6102bd6974aSJonathan Coe 6112bd6974aSJonathan Coe // Do not wrap expression body definitions. 6122bd6974aSJonathan Coe verifyFormat(R"(// 6132bd6974aSJonathan Coe public string Name { 6142bd6974aSJonathan Coe get => _name; 6152bd6974aSJonathan Coe set => _name = value; 6162bd6974aSJonathan Coe })", 6172bd6974aSJonathan Coe Style); 618e8c5fea2SJonathan Coe } 619e8c5fea2SJonathan Coe 620e8c5fea2SJonathan Coe TEST_F(FormatTestCSharp, CSharpSpaces) { 621e8c5fea2SJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 622e8c5fea2SJonathan Coe Style.SpaceBeforeSquareBrackets = false; 623e8c5fea2SJonathan Coe Style.SpacesInSquareBrackets = false; 624e8c5fea2SJonathan Coe Style.SpaceBeforeCpp11BracedList = true; 625e8c5fea2SJonathan Coe Style.Cpp11BracedListStyle = false; 626e8c5fea2SJonathan Coe Style.SpacesInContainerLiterals = false; 627*07c1978bSJonathan Coe Style.SpaceAfterCStyleCast = false; 628e8c5fea2SJonathan Coe 629e8c5fea2SJonathan Coe verifyFormat(R"(new Car { "Door", 0.1 })", Style); 630e8c5fea2SJonathan Coe verifyFormat(R"(new Car { 0.1, "Door" })", Style); 631e8c5fea2SJonathan Coe verifyFormat(R"(new string[] { "A" })", Style); 632e8c5fea2SJonathan Coe verifyFormat(R"(new string[] {})", Style); 633e8c5fea2SJonathan Coe verifyFormat(R"(new Car { someVariableName })", Style); 634e8c5fea2SJonathan Coe verifyFormat(R"(new Car { someVariableName })", Style); 635e8c5fea2SJonathan Coe verifyFormat(R"(new Dictionary<string, string> { ["Key"] = "Value" };)", 636e8c5fea2SJonathan Coe Style); 637e8c5fea2SJonathan Coe verifyFormat(R"(Apply(x => x.Name, x => () => x.ID);)", Style); 638e8c5fea2SJonathan Coe verifyFormat(R"(bool[] xs = { true, true };)", Style); 639e8c5fea2SJonathan Coe verifyFormat(R"(taskContext.Factory.Run(async () => doThing(args);)", Style); 640e8c5fea2SJonathan Coe verifyFormat(R"(catch (TestException) when (innerFinallyExecuted))", Style); 641548e540dSJonathan Coe verifyFormat(R"(private float[,] Values;)", Style); 6425c917bd9SJonathan Coe verifyFormat(R"(Result this[Index x] => Foo(x);)", Style); 643548e540dSJonathan Coe 64404336adaSJonathan Coe verifyFormat(R"(char[,,] rawCharArray = MakeCharacterGrid();)", Style); 64504336adaSJonathan Coe 646*07c1978bSJonathan Coe // Not seen as a C-style cast. 647*07c1978bSJonathan Coe verifyFormat(R"(// 648*07c1978bSJonathan Coe foreach ((A a, B b) in someList) { 649*07c1978bSJonathan Coe })", 650*07c1978bSJonathan Coe Style); 651*07c1978bSJonathan Coe 652548e540dSJonathan Coe Style.SpacesInSquareBrackets = true; 653548e540dSJonathan Coe verifyFormat(R"(private float[ , ] Values;)", Style); 6549c4afce7SJonathan Coe verifyFormat(R"(string dirPath = args?[ 0 ];)", Style); 65504336adaSJonathan Coe verifyFormat(R"(char[ ,, ] rawCharArray = MakeCharacterGrid();)", Style); 6565f52a93bSJonathan Coe } 6575f52a93bSJonathan Coe 6585f52a93bSJonathan Coe TEST_F(FormatTestCSharp, CSharpNullableTypes) { 6595f52a93bSJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 6605f52a93bSJonathan Coe Style.SpacesInSquareBrackets = false; 6615f52a93bSJonathan Coe 662fe61bc1aSJonathan Coe verifyFormat(R"(// 663fe61bc1aSJonathan Coe public class A { 664fe61bc1aSJonathan Coe void foo() { int? value = some.bar(); } 665fe61bc1aSJonathan Coe })", 666fe61bc1aSJonathan Coe Style); // int? is nullable not a conditional expression. 667fe61bc1aSJonathan Coe 668fe61bc1aSJonathan Coe verifyFormat(R"(void foo(int? x, int? y, int? z) {})", 669fe61bc1aSJonathan Coe Style); // Nullables in function definitions. 670fe61bc1aSJonathan Coe 6715f52a93bSJonathan Coe verifyFormat(R"(public float? Value;)", Style); // no space before `?`. 672fe61bc1aSJonathan Coe 6735f52a93bSJonathan Coe verifyFormat(R"(int?[] arr = new int?[10];)", 6745f52a93bSJonathan Coe Style); // An array of a nullable type. 6751fb9c298SJonathan Coe 6761fb9c298SJonathan Coe verifyFormat(R"(var x = (int?)y;)", Style); // Cast to a nullable type. 6771fb9c298SJonathan Coe 6781fb9c298SJonathan Coe verifyFormat(R"(var x = new MyContainer<int?>();)", Style); // Generics. 6792bd6974aSJonathan Coe } 6802bd6974aSJonathan Coe 681736fef97SJonathan Coe TEST_F(FormatTestCSharp, CSharpArraySubscripts) { 682736fef97SJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 683736fef97SJonathan Coe 684736fef97SJonathan Coe // Do not format array subscript operators as attributes. 685b28ed9ceSJonathan Coe verifyFormat(R"(// 686b28ed9ceSJonathan Coe if (someThings[index].Contains(myThing)) { 687b28ed9ceSJonathan Coe })", 688b28ed9ceSJonathan Coe Style); 689b28ed9ceSJonathan Coe 690b28ed9ceSJonathan Coe verifyFormat(R"(// 691b28ed9ceSJonathan Coe if (someThings[i][j][k].Contains(myThing)) { 692b28ed9ceSJonathan Coe })", 693b28ed9ceSJonathan Coe Style); 694736fef97SJonathan Coe } 695736fef97SJonathan Coe 696dcbcec48SJonathan Coe TEST_F(FormatTestCSharp, CSharpGenericTypeConstraints) { 697dcbcec48SJonathan Coe FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); 698dcbcec48SJonathan Coe 699dcbcec48SJonathan Coe verifyFormat(R"(// 700dcbcec48SJonathan Coe class ItemFactory<T> 701dcbcec48SJonathan Coe where T : new() {})", Style); 702dcbcec48SJonathan Coe 703dcbcec48SJonathan Coe verifyFormat(R"(// 704dcbcec48SJonathan Coe class Dictionary<TKey, TVal> 705dcbcec48SJonathan Coe where TKey : IComparable<TKey> 706dcbcec48SJonathan Coe where TVal : IMyInterface { 707dcbcec48SJonathan Coe public void MyMethod<T>(T t) 708dcbcec48SJonathan Coe where T : IMyInterface { doThing(); } 709dcbcec48SJonathan Coe })", 710dcbcec48SJonathan Coe Style); 71178e2a3c6SJonathan Coe 71278e2a3c6SJonathan Coe verifyFormat(R"(// 71378e2a3c6SJonathan Coe class ItemFactory<T> 71478e2a3c6SJonathan Coe where T : new(), 71578e2a3c6SJonathan Coe IAnInterface<T>, 71678e2a3c6SJonathan Coe IAnotherInterface<T>, 71778e2a3c6SJonathan Coe IAnotherInterfaceStill<T> {})", 718d1b412aeSJonathan Coe Style); 719d1b412aeSJonathan Coe 720d1b412aeSJonathan Coe Style.ColumnLimit = 50; // Force lines to be wrapped. 721d1b412aeSJonathan Coe verifyFormat(R"(// 722d1b412aeSJonathan Coe class ItemFactory<T, U> 723d1b412aeSJonathan Coe where T : new(), 724d1b412aeSJonathan Coe IAnInterface<T>, 725d1b412aeSJonathan Coe IAnotherInterface<T, U>, 726d1b412aeSJonathan Coe IAnotherInterfaceStill<T, U> {})", 72778e2a3c6SJonathan Coe Style); 7280574030cSKrasimir Georgiev 7290574030cSKrasimir Georgiev // In other languages `where` can be used as a normal identifier. 7300574030cSKrasimir Georgiev // This example is in C++! 7310574030cSKrasimir Georgiev verifyFormat(R"(// 7320574030cSKrasimir Georgiev class A { 7330574030cSKrasimir Georgiev int f(int where) {} 7340574030cSKrasimir Georgiev };)", 7350574030cSKrasimir Georgiev getGoogleStyle(FormatStyle::LK_Cpp)); 736dcbcec48SJonathan Coe } 737dcbcec48SJonathan Coe 738cbb726d0SPaul Hoad } // namespace format 739cbb726d0SPaul Hoad } // end namespace clang 740