xref: /llvm-project/clang/unittests/Format/FormatTestCSharp.cpp (revision d005be33ee776c5d788693f5c1cf4f6bc242e13c)
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 
9ddc80637Ssstwcw #include "FormatTestBase.h"
10cbb726d0SPaul Hoad 
11cbb726d0SPaul Hoad #define DEBUG_TYPE "format-test"
12cbb726d0SPaul Hoad 
13cbb726d0SPaul Hoad namespace clang {
14cbb726d0SPaul Hoad namespace format {
15ddc80637Ssstwcw namespace test {
16ddc80637Ssstwcw namespace {
17cbb726d0SPaul Hoad 
18ddc80637Ssstwcw class FormatTestCSharp : public test::FormatTestBase {
19cbb726d0SPaul Hoad protected:
20ddc80637Ssstwcw   FormatStyle getDefaultStyle() const override {
21ddc80637Ssstwcw     return getMicrosoftStyle(FormatStyle::LK_CSharp);
22ddc80637Ssstwcw   }
23ddc80637Ssstwcw 
241c58208dSOwen Pan   static std::string format(StringRef Code, unsigned Offset, unsigned Length,
251c58208dSOwen Pan                             const FormatStyle &Style) {
26cbb726d0SPaul Hoad     LLVM_DEBUG(llvm::errs() << "---\n");
27cbb726d0SPaul Hoad     LLVM_DEBUG(llvm::errs() << Code << "\n\n");
28cbb726d0SPaul Hoad     std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
29cbb726d0SPaul Hoad     tooling::Replacements Replaces = reformat(Style, Code, Ranges);
30cbb726d0SPaul Hoad     auto Result = applyAllReplacements(Code, Replaces);
31cbb726d0SPaul Hoad     EXPECT_TRUE(static_cast<bool>(Result));
32cbb726d0SPaul Hoad     LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
33cbb726d0SPaul Hoad     return *Result;
34cbb726d0SPaul Hoad   }
35cbb726d0SPaul Hoad 
36cbb726d0SPaul Hoad   static std::string
371c58208dSOwen Pan   format(StringRef Code,
38a2f963bbSPaul Hoad          const FormatStyle &Style = getMicrosoftStyle(FormatStyle::LK_CSharp)) {
39cbb726d0SPaul Hoad     return format(Code, 0, Code.size(), Style);
40cbb726d0SPaul Hoad   }
41cbb726d0SPaul Hoad 
42cbb726d0SPaul Hoad   static FormatStyle getStyleWithColumns(unsigned ColumnLimit) {
43a2f963bbSPaul Hoad     FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
44cbb726d0SPaul Hoad     Style.ColumnLimit = ColumnLimit;
45cbb726d0SPaul Hoad     return Style;
46cbb726d0SPaul Hoad   }
47cbb726d0SPaul Hoad };
48cbb726d0SPaul Hoad 
49cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpClass) {
50a2f963bbSPaul Hoad   verifyFormat("public class SomeClass\n"
51a2f963bbSPaul Hoad                "{\n"
52a2f963bbSPaul Hoad                "    void f()\n"
53a2f963bbSPaul Hoad                "    {\n"
54a2f963bbSPaul Hoad                "    }\n"
55a2f963bbSPaul Hoad                "    int g()\n"
56a2f963bbSPaul Hoad                "    {\n"
57a2f963bbSPaul Hoad                "        return 0;\n"
58a2f963bbSPaul Hoad                "    }\n"
59a2f963bbSPaul Hoad                "    void h()\n"
60a2f963bbSPaul Hoad                "    {\n"
61a2f963bbSPaul Hoad                "        while (true)\n"
62a2f963bbSPaul Hoad                "            f();\n"
63a2f963bbSPaul Hoad                "        for (;;)\n"
64a2f963bbSPaul Hoad                "            f();\n"
65a2f963bbSPaul Hoad                "        if (true)\n"
66a2f963bbSPaul Hoad                "            f();\n"
67cbb726d0SPaul Hoad                "    }\n"
68cbb726d0SPaul Hoad                "}");
69f40a7972SJonathan Coe 
70f40a7972SJonathan Coe   // Ensure that small and empty classes are handled correctly with condensed
71f40a7972SJonathan Coe   // (Google C++-like) brace-breaking style.
72f40a7972SJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
73f40a7972SJonathan Coe   Style.BreakBeforeBraces = FormatStyle::BS_Attach;
74f40a7972SJonathan Coe 
75f40a7972SJonathan Coe   verifyFormat("public class SomeEmptyClass {}", Style);
76f40a7972SJonathan Coe 
77f40a7972SJonathan Coe   verifyFormat("public class SomeTinyClass {\n"
78f40a7972SJonathan Coe                "  int X;\n"
79f40a7972SJonathan Coe                "}",
80f40a7972SJonathan Coe                Style);
81f40a7972SJonathan Coe   verifyFormat("private class SomeTinyClass {\n"
82f40a7972SJonathan Coe                "  int X;\n"
83f40a7972SJonathan Coe                "}",
84f40a7972SJonathan Coe                Style);
85f40a7972SJonathan Coe   verifyFormat("protected class SomeTinyClass {\n"
86f40a7972SJonathan Coe                "  int X;\n"
87f40a7972SJonathan Coe                "}",
88f40a7972SJonathan Coe                Style);
89f40a7972SJonathan Coe   verifyFormat("internal class SomeTinyClass {\n"
90f40a7972SJonathan Coe                "  int X;\n"
91f40a7972SJonathan Coe                "}",
92f40a7972SJonathan Coe                Style);
93cbb726d0SPaul Hoad }
94cbb726d0SPaul Hoad 
95cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, AccessModifiers) {
96a2f963bbSPaul Hoad   verifyFormat("public String toString()\n"
97a2f963bbSPaul Hoad                "{\n"
98a2f963bbSPaul Hoad                "}");
99a2f963bbSPaul Hoad   verifyFormat("private String toString()\n"
100a2f963bbSPaul Hoad                "{\n"
101a2f963bbSPaul Hoad                "}");
102a2f963bbSPaul Hoad   verifyFormat("protected String toString()\n"
103a2f963bbSPaul Hoad                "{\n"
104a2f963bbSPaul Hoad                "}");
105a2f963bbSPaul Hoad   verifyFormat("internal String toString()\n"
106a2f963bbSPaul Hoad                "{\n"
107a2f963bbSPaul Hoad                "}");
108cbb726d0SPaul Hoad 
109a2f963bbSPaul Hoad   verifyFormat("public override String toString()\n"
110a2f963bbSPaul Hoad                "{\n"
111a2f963bbSPaul Hoad                "}");
112a2f963bbSPaul Hoad   verifyFormat("private override String toString()\n"
113a2f963bbSPaul Hoad                "{\n"
114a2f963bbSPaul Hoad                "}");
115a2f963bbSPaul Hoad   verifyFormat("protected override String toString()\n"
116a2f963bbSPaul Hoad                "{\n"
117a2f963bbSPaul Hoad                "}");
118a2f963bbSPaul Hoad   verifyFormat("internal override String toString()\n"
119a2f963bbSPaul Hoad                "{\n"
120a2f963bbSPaul Hoad                "}");
121cbb726d0SPaul Hoad 
122a2f963bbSPaul Hoad   verifyFormat("internal static String toString()\n"
123a2f963bbSPaul Hoad                "{\n"
124a2f963bbSPaul Hoad                "}");
125cbb726d0SPaul Hoad }
126cbb726d0SPaul Hoad 
127cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, NoStringLiteralBreaks) {
128ddc80637Ssstwcw   // Breaking of interpolated strings is not implemented.
129ddc80637Ssstwcw   auto Style = getDefaultStyle();
130ddc80637Ssstwcw   Style.ColumnLimit = 40;
131ddc80637Ssstwcw   Style.BreakStringLiterals = true;
132ddc80637Ssstwcw   verifyFormat("foo("
133ddc80637Ssstwcw                "$\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
134ddc80637Ssstwcw                "aaaaaaa\");",
135ddc80637Ssstwcw                Style);
136ddc80637Ssstwcw }
137ddc80637Ssstwcw 
138ddc80637Ssstwcw TEST_F(FormatTestCSharp, StringLiteralBreaks) {
139ddc80637Ssstwcw   // The line is 75 characters long.  The default limit for the Microsoft style
140ddc80637Ssstwcw   // is 120.
141ddc80637Ssstwcw   auto Style = getDefaultStyle();
142ddc80637Ssstwcw   Style.BreakStringLiterals = true;
143cbb726d0SPaul Hoad   verifyFormat("foo("
144cbb726d0SPaul Hoad                "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
145ddc80637Ssstwcw                "aaaaaa\");",
146ddc80637Ssstwcw                Style);
147ddc80637Ssstwcw   // When the column limit is smaller, the string should get broken.
148ddc80637Ssstwcw   Style.ColumnLimit = 40;
149ddc80637Ssstwcw   verifyFormat(R"(foo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
150ddc80637Ssstwcw     "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
151ddc80637Ssstwcw     "aaa");)",
152ddc80637Ssstwcw                "foo("
153ddc80637Ssstwcw                "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
154ddc80637Ssstwcw                "aaaaaa\");",
155ddc80637Ssstwcw                Style);
156ddc80637Ssstwcw   // The new quotes should be the same as the original.
157ddc80637Ssstwcw   verifyFormat(R"(foo(@"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
158ddc80637Ssstwcw     @"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
159ddc80637Ssstwcw     @"aaaaa");)",
160ddc80637Ssstwcw                "foo("
161ddc80637Ssstwcw                "@\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
162ddc80637Ssstwcw                "aaaaaaa\");",
163ddc80637Ssstwcw                Style);
164ddc80637Ssstwcw   // The operators can be on either line.
165ddc80637Ssstwcw   Style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
166ddc80637Ssstwcw   verifyFormat(R"(foo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
167ddc80637Ssstwcw     + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
168ddc80637Ssstwcw     + "a");)",
169ddc80637Ssstwcw                "foo("
170ddc80637Ssstwcw                "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
171ddc80637Ssstwcw                "aaaaaa\");",
172ddc80637Ssstwcw                Style);
173ddc80637Ssstwcw   Style.AlignOperands = FormatStyle::OAS_AlignAfterOperator;
174ddc80637Ssstwcw   verifyFormat(R"(foo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
175ddc80637Ssstwcw     + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
176ddc80637Ssstwcw     + "a");)",
177ddc80637Ssstwcw                "foo("
178ddc80637Ssstwcw                "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
179ddc80637Ssstwcw                "aaaaaa\");",
180ddc80637Ssstwcw                Style);
181ddc80637Ssstwcw   verifyFormat(R"(x = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
182ddc80637Ssstwcw   + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";)",
183ddc80637Ssstwcw                "x = "
184ddc80637Ssstwcw                "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
185ddc80637Ssstwcw                "aaaaaa\";",
186ddc80637Ssstwcw                Style);
187cbb726d0SPaul Hoad }
188cbb726d0SPaul Hoad 
189cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpVerbatiumStringLiterals) {
190cbb726d0SPaul Hoad   verifyFormat("foo(@\"aaaaaaaa\\abc\\aaaa\");");
191cbb726d0SPaul Hoad   // @"ABC\" + ToString("B") - handle embedded \ in literal string at
192cbb726d0SPaul Hoad   // the end
193cbb726d0SPaul Hoad   //
194cbb726d0SPaul Hoad   /*
195cbb726d0SPaul Hoad    * After removal of Lexer change we are currently not able
196cbb726d0SPaul Hoad    * To handle these cases
197cbb726d0SPaul Hoad    verifyFormat("string s = @\"ABC\\\" + ToString(\"B\");");
198cbb726d0SPaul Hoad    verifyFormat("string s = @\"ABC\"\"DEF\"\"GHI\"");
199cbb726d0SPaul Hoad    verifyFormat("string s = @\"ABC\"\"DEF\"\"\"");
200cbb726d0SPaul Hoad    verifyFormat("string s = @\"ABC\"\"DEF\"\"\" + abc");
201cbb726d0SPaul Hoad   */
202cbb726d0SPaul Hoad }
203cbb726d0SPaul Hoad 
204cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpInterpolatedStringLiterals) {
205cbb726d0SPaul Hoad   verifyFormat("foo($\"aaaaaaaa{aaa}aaaa\");");
206cbb726d0SPaul Hoad   verifyFormat("foo($\"aaaa{A}\");");
207cbb726d0SPaul Hoad   verifyFormat(
208cbb726d0SPaul Hoad       "foo($\"aaaa{A}"
209cbb726d0SPaul Hoad       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");");
210cbb726d0SPaul Hoad   verifyFormat("Name = $\"{firstName} {lastName}\";");
211cbb726d0SPaul Hoad 
212cbb726d0SPaul Hoad   // $"ABC\" + ToString("B") - handle embedded \ in literal string at
213cbb726d0SPaul Hoad   // the end
214cbb726d0SPaul Hoad   verifyFormat("string s = $\"A{abc}BC\" + ToString(\"B\");");
215cbb726d0SPaul Hoad   verifyFormat("$\"{domain}\\\\{user}\"");
216cbb726d0SPaul Hoad   verifyFormat(
217cbb726d0SPaul Hoad       "var verbatimInterpolated = $@\"C:\\Users\\{userName}\\Documents\\\";");
218cbb726d0SPaul Hoad }
219cbb726d0SPaul Hoad 
220cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpFatArrows) {
221ddc80637Ssstwcw   verifyIncompleteFormat("Task serverTask = Task.Run(async() => {");
222cbb726d0SPaul Hoad   verifyFormat("public override string ToString() => \"{Name}\\{Age}\";");
223cbb726d0SPaul Hoad }
224cbb726d0SPaul Hoad 
225c3af063cSJonathan Coe TEST_F(FormatTestCSharp, CSharpConditionalExpressions) {
226c3af063cSJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
227c3af063cSJonathan Coe   // conditional expression is not seen as a NullConditional.
228c3af063cSJonathan Coe   verifyFormat("var y = A < B ? -1 : 1;", Style);
229c3af063cSJonathan Coe }
230c3af063cSJonathan Coe 
231cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpNullConditional) {
2324c056583SPaul Hoad   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
2334c056583SPaul Hoad   Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
2344c056583SPaul Hoad 
235cbb726d0SPaul Hoad   verifyFormat(
236cbb726d0SPaul Hoad       "public Person(string firstName, string lastName, int? age = null)");
237cbb726d0SPaul Hoad 
2384c056583SPaul Hoad   verifyFormat("foo () {\n"
2394c056583SPaul Hoad                "  switch (args?.Length) {}\n"
2404c056583SPaul Hoad                "}",
2414c056583SPaul Hoad                Style);
2424c056583SPaul Hoad 
2434c056583SPaul Hoad   verifyFormat("switch (args?.Length) {}", Style);
244cbb726d0SPaul Hoad 
245a2f963bbSPaul Hoad   verifyFormat("public static void Main(string[] args)\n"
246a2f963bbSPaul Hoad                "{\n"
247a2f963bbSPaul Hoad                "    string dirPath = args?[0];\n"
248a2f963bbSPaul Hoad                "}");
2494c056583SPaul Hoad 
2504c056583SPaul Hoad   Style.SpaceBeforeParens = FormatStyle::SBPO_Never;
2514c056583SPaul Hoad 
2524c056583SPaul Hoad   verifyFormat("switch(args?.Length) {}", Style);
253cbb726d0SPaul Hoad }
254cbb726d0SPaul Hoad 
255cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, Attributes) {
256cbb726d0SPaul Hoad   verifyFormat("[STAThread]\n"
257a2f963bbSPaul Hoad                "static void Main(string[] args)\n"
258a2f963bbSPaul Hoad                "{\n"
259a2f963bbSPaul Hoad                "}");
260cbb726d0SPaul Hoad 
261cbb726d0SPaul Hoad   verifyFormat("[TestMethod]\n"
262a2f963bbSPaul Hoad                "private class Test\n"
263a2f963bbSPaul Hoad                "{\n"
264a2f963bbSPaul Hoad                "}");
265cbb726d0SPaul Hoad 
266cbb726d0SPaul Hoad   verifyFormat("[TestMethod]\n"
267a2f963bbSPaul Hoad                "protected class Test\n"
268a2f963bbSPaul Hoad                "{\n"
269a2f963bbSPaul Hoad                "}");
270cbb726d0SPaul Hoad 
271cbb726d0SPaul Hoad   verifyFormat("[TestMethod]\n"
272a2f963bbSPaul Hoad                "internal class Test\n"
273a2f963bbSPaul Hoad                "{\n"
274a2f963bbSPaul Hoad                "}");
275cbb726d0SPaul Hoad 
276cbb726d0SPaul Hoad   verifyFormat("[TestMethod]\n"
277a2f963bbSPaul Hoad                "class Test\n"
278a2f963bbSPaul Hoad                "{\n"
279a2f963bbSPaul Hoad                "}");
280cbb726d0SPaul Hoad 
281cbb726d0SPaul Hoad   verifyFormat("[TestMethod]\n"
282cbb726d0SPaul Hoad                "[DeploymentItem(\"Test.txt\")]\n"
283a2f963bbSPaul Hoad                "public class Test\n"
284a2f963bbSPaul Hoad                "{\n"
285a2f963bbSPaul Hoad                "}");
286cbb726d0SPaul Hoad 
287cbb726d0SPaul Hoad   verifyFormat("[System.AttributeUsage(System.AttributeTargets.Method)]\n"
288cbb726d0SPaul Hoad                "[System.Runtime.InteropServices.ComVisible(true)]\n"
289a2f963bbSPaul Hoad                "public sealed class STAThreadAttribute : Attribute\n"
290a2f963bbSPaul Hoad                "{\n"
291a2f963bbSPaul Hoad                "}");
292cbb726d0SPaul Hoad 
293cbb726d0SPaul Hoad   verifyFormat("[Verb(\"start\", HelpText = \"Starts the server listening on "
294cbb726d0SPaul Hoad                "provided port\")]\n"
295a2f963bbSPaul Hoad                "class Test\n"
296a2f963bbSPaul Hoad                "{\n"
297a2f963bbSPaul Hoad                "}");
298cbb726d0SPaul Hoad 
299cbb726d0SPaul Hoad   verifyFormat("[TestMethod]\n"
300f22b0727SJonathan Coe                "public string Host { set; get; }");
301cbb726d0SPaul Hoad 
302ffb48d48Smydeveloperday   // Adjacent properties should not cause line wrapping issues
303ffb48d48Smydeveloperday   verifyFormat("[JsonProperty(\"foo\")]\n"
304ffb48d48Smydeveloperday                "public string Foo { set; get; }\n"
305ffb48d48Smydeveloperday                "[JsonProperty(\"bar\")]\n"
306ffb48d48Smydeveloperday                "public string Bar { set; get; }\n"
307ffb48d48Smydeveloperday                "[JsonProperty(\"bar\")]\n"
308ffb48d48Smydeveloperday                "protected string Bar { set; get; }\n"
309ffb48d48Smydeveloperday                "[JsonProperty(\"bar\")]\n"
310ffb48d48Smydeveloperday                "internal string Bar { set; get; }");
311ffb48d48Smydeveloperday 
312ffb48d48Smydeveloperday   // Multiple attributes should always be split (not just the first ones)
313ffb48d48Smydeveloperday   verifyFormat("[XmlIgnore]\n"
314ffb48d48Smydeveloperday                "[JsonProperty(\"foo\")]\n"
315ffb48d48Smydeveloperday                "public string Foo { set; get; }");
316ffb48d48Smydeveloperday 
317ffb48d48Smydeveloperday   verifyFormat("[XmlIgnore]\n"
318ffb48d48Smydeveloperday                "[JsonProperty(\"foo\")]\n"
319ffb48d48Smydeveloperday                "public string Foo { set; get; }\n"
320ffb48d48Smydeveloperday                "[XmlIgnore]\n"
321ffb48d48Smydeveloperday                "[JsonProperty(\"bar\")]\n"
322ffb48d48Smydeveloperday                "public string Bar { set; get; }");
323ffb48d48Smydeveloperday 
324ffb48d48Smydeveloperday   verifyFormat("[XmlIgnore]\n"
325ffb48d48Smydeveloperday                "[ScriptIgnore]\n"
326ffb48d48Smydeveloperday                "[JsonProperty(\"foo\")]\n"
327ffb48d48Smydeveloperday                "public string Foo { set; get; }\n"
328ffb48d48Smydeveloperday                "[XmlIgnore]\n"
329ffb48d48Smydeveloperday                "[ScriptIgnore]\n"
330ffb48d48Smydeveloperday                "[JsonProperty(\"bar\")]\n"
331ffb48d48Smydeveloperday                "public string Bar { set; get; }");
332ffb48d48Smydeveloperday 
333cbb726d0SPaul Hoad   verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server "
334cbb726d0SPaul Hoad                "listening on provided host\")]\n"
335f22b0727SJonathan Coe                "public string Host { set; get; }");
33650d8977cSJonathan Coe 
337ddc80637Ssstwcw   verifyIncompleteFormat(
33850d8977cSJonathan Coe       "[DllImport(\"Hello\", EntryPoint = \"hello_world\")]\n"
33950d8977cSJonathan Coe       "// The const char* returned by hello_world must not be deleted.\n"
34050d8977cSJonathan Coe       "private static extern IntPtr HelloFromCpp();)");
341ca1fd460SJonathan Coe 
342b46f925dSJonathan Coe   // Class attributes go on their own line and do not affect layout of
343b46f925dSJonathan Coe   // interfaces. Line wrapping decisions previously caused each interface to be
344b46f925dSJonathan Coe   // on its own line.
345b46f925dSJonathan Coe   verifyFormat("[SomeAttribute]\n"
346b46f925dSJonathan Coe                "[SomeOtherAttribute]\n"
347b46f925dSJonathan Coe                "public class A : IShape, IAnimal, IVehicle\n"
348b46f925dSJonathan Coe                "{\n"
349b46f925dSJonathan Coe                "    int X;\n"
350b46f925dSJonathan Coe                "}");
351b46f925dSJonathan Coe 
352b46f925dSJonathan Coe   // Attributes in a method declaration do not cause line wrapping.
353b46f925dSJonathan Coe   verifyFormat("void MethodA([In][Out] ref double x)\n"
354b46f925dSJonathan Coe                "{\n"
355b46f925dSJonathan Coe                "}");
356b46f925dSJonathan Coe 
357ffb48d48Smydeveloperday   verifyFormat("void MethodA([In, Out] ref double x)\n"
358ffb48d48Smydeveloperday                "{\n"
359ffb48d48Smydeveloperday                "}");
360ffb48d48Smydeveloperday 
361ffb48d48Smydeveloperday   verifyFormat("void MethodA([In, Out] double[] x)\n"
362ffb48d48Smydeveloperday                "{\n"
363ffb48d48Smydeveloperday                "}");
364ffb48d48Smydeveloperday 
365ffb48d48Smydeveloperday   verifyFormat("void MethodA([In] double[] x)\n"
366ffb48d48Smydeveloperday                "{\n"
367ffb48d48Smydeveloperday                "}");
368ffb48d48Smydeveloperday 
369ffb48d48Smydeveloperday   verifyFormat("void MethodA(int[] x)\n"
370ffb48d48Smydeveloperday                "{\n"
371ffb48d48Smydeveloperday                "}");
372ffb48d48Smydeveloperday   verifyFormat("void MethodA(int[][] x)\n"
373ffb48d48Smydeveloperday                "{\n"
374ffb48d48Smydeveloperday                "}");
375ffb48d48Smydeveloperday   verifyFormat("void MethodA([] x)\n"
376ffb48d48Smydeveloperday                "{\n"
377ffb48d48Smydeveloperday                "}");
378ffb48d48Smydeveloperday 
379ffb48d48Smydeveloperday   verifyFormat("public void Log([CallerLineNumber] int line = -1, "
380ffb48d48Smydeveloperday                "[CallerFilePath] string path = null,\n"
381ffb48d48Smydeveloperday                "                [CallerMemberName] string name = null)\n"
382ffb48d48Smydeveloperday                "{\n"
383ffb48d48Smydeveloperday                "}");
384ffb48d48Smydeveloperday 
3859f8a7e82SJonathan Coe   // [] in an attribute do not cause premature line wrapping or indenting.
3869f8a7e82SJonathan Coe   verifyFormat(R"(//
3879f8a7e82SJonathan Coe public class A
3889f8a7e82SJonathan Coe {
3899f8a7e82SJonathan Coe     [SomeAttribute(new[] { RED, GREEN, BLUE }, -1.0f, 1.0f)]
3909f8a7e82SJonathan Coe     [DoNotSerialize]
3919f8a7e82SJonathan Coe     public Data MemberVariable;
3929f8a7e82SJonathan Coe })");
3939f8a7e82SJonathan Coe 
394ca1fd460SJonathan Coe   //  Unwrappable lines go on a line of their own.
395ca1fd460SJonathan Coe   // 'target:' is not treated as a label.
396ca1fd460SJonathan Coe   // Modify Style to enforce a column limit.
397ca1fd460SJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
398ca1fd460SJonathan Coe   Style.ColumnLimit = 10;
399ca1fd460SJonathan Coe   verifyFormat(R"([assembly:InternalsVisibleTo(
400ca1fd460SJonathan Coe     "SomeAssembly, PublicKey=SomePublicKeyThatExceedsTheColumnLimit")])",
401ca1fd460SJonathan Coe                Style);
402cbb726d0SPaul Hoad }
403cbb726d0SPaul Hoad 
404719087bbSPaul Hoad TEST_F(FormatTestCSharp, CSharpUsing) {
405719087bbSPaul Hoad   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
406719087bbSPaul Hoad   Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
407719087bbSPaul Hoad   verifyFormat("public void foo () {\n"
408719087bbSPaul Hoad                "  using (StreamWriter sw = new StreamWriter (filenameA)) {}\n"
4091e0174a9SKrasimir Georgiev                "  using () {}\n"
410719087bbSPaul Hoad                "}",
411719087bbSPaul Hoad                Style);
412719087bbSPaul Hoad 
4131e0174a9SKrasimir Georgiev   // Ensure clang-format affects top-level snippets correctly.
4144c056583SPaul Hoad   verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}",
4154c056583SPaul Hoad                Style);
4164c056583SPaul Hoad 
417719087bbSPaul Hoad   Style.SpaceBeforeParens = FormatStyle::SBPO_Never;
418719087bbSPaul Hoad   verifyFormat("public void foo() {\n"
419719087bbSPaul Hoad                "  using(StreamWriter sw = new StreamWriter(filenameB)) {}\n"
4201e0174a9SKrasimir Georgiev                "  using() {}\n"
421719087bbSPaul Hoad                "}",
422719087bbSPaul Hoad                Style);
4234c056583SPaul Hoad 
4241e0174a9SKrasimir Georgiev   // Ensure clang-format affects top-level snippets correctly.
4251e0174a9SKrasimir Georgiev   verifyFormat("using(StreamWriter sw = new StreamWriter(filenameB)) {}",
4261e0174a9SKrasimir Georgiev                Style);
4271e0174a9SKrasimir Georgiev 
4281e0174a9SKrasimir Georgiev   Style.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
4291e0174a9SKrasimir Georgiev   verifyFormat("public void foo() {\n"
4301e0174a9SKrasimir Georgiev                "  using (StreamWriter sw = new StreamWriter(filenameA)) {}\n"
4311e0174a9SKrasimir Georgiev                "  using () {}\n"
4321e0174a9SKrasimir Georgiev                "}",
4331e0174a9SKrasimir Georgiev                Style);
4341e0174a9SKrasimir Georgiev 
4351e0174a9SKrasimir Georgiev   // Ensure clang-format affects top-level snippets correctly.
4361e0174a9SKrasimir Georgiev   verifyFormat("using (StreamWriter sw = new StreamWriter(filenameB)) {}",
4371e0174a9SKrasimir Georgiev                Style);
4381e0174a9SKrasimir Georgiev 
4391e0174a9SKrasimir Georgiev   Style.SpaceBeforeParens = FormatStyle::SBPO_NonEmptyParentheses;
4401e0174a9SKrasimir Georgiev   verifyFormat("public void foo() {\n"
4411e0174a9SKrasimir Georgiev                "  using (StreamWriter sw = new StreamWriter (filenameA)) {}\n"
4421e0174a9SKrasimir Georgiev                "  using() {}\n"
4431e0174a9SKrasimir Georgiev                "}",
4441e0174a9SKrasimir Georgiev                Style);
4451e0174a9SKrasimir Georgiev 
4461e0174a9SKrasimir Georgiev   // Ensure clang-format affects top-level snippets correctly.
4474c056583SPaul Hoad   verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}",
4484c056583SPaul Hoad                Style);
449719087bbSPaul Hoad }
450719087bbSPaul Hoad 
451cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpRegions) {
452cbb726d0SPaul Hoad   verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa "
453cbb726d0SPaul Hoad                "aaaaaaaaaaaaaaa long region");
454cbb726d0SPaul Hoad }
455cbb726d0SPaul Hoad 
456cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpKeyWordEscaping) {
457ed367b9dSmydeveloperday   // AfterEnum is true by default.
458ed367b9dSmydeveloperday   verifyFormat("public enum var\n"
459ed367b9dSmydeveloperday                "{\n"
460292058a5SAaron Smith                "    none,\n"
461292058a5SAaron Smith                "    @string,\n"
462292058a5SAaron Smith                "    bool,\n"
463292058a5SAaron Smith                "    @enum\n"
464292058a5SAaron Smith                "}");
465cbb726d0SPaul Hoad }
466cbb726d0SPaul Hoad 
467cbb726d0SPaul Hoad TEST_F(FormatTestCSharp, CSharpNullCoalescing) {
468cbb726d0SPaul Hoad   verifyFormat("var test = ABC ?? DEF");
469cbb726d0SPaul Hoad   verifyFormat("string myname = name ?? \"ABC\";");
470cbb726d0SPaul Hoad   verifyFormat("return _name ?? \"DEF\";");
471cbb726d0SPaul Hoad }
472cbb726d0SPaul Hoad 
473a437befaSEliza Velasquez TEST_F(FormatTestCSharp, CSharpNullCoalescingAssignment) {
474a437befaSEliza Velasquez   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
475a437befaSEliza Velasquez   Style.SpaceBeforeAssignmentOperators = true;
476a437befaSEliza Velasquez 
477a437befaSEliza Velasquez   verifyFormat(R"(test ??= ABC;)", Style);
478a437befaSEliza Velasquez   verifyFormat(R"(test ??= true;)", Style);
479a437befaSEliza Velasquez 
480a437befaSEliza Velasquez   Style.SpaceBeforeAssignmentOperators = false;
481a437befaSEliza Velasquez 
482a437befaSEliza Velasquez   verifyFormat(R"(test??= ABC;)", Style);
483a437befaSEliza Velasquez   verifyFormat(R"(test??= true;)", Style);
484a437befaSEliza Velasquez }
485a437befaSEliza Velasquez 
486a437befaSEliza Velasquez TEST_F(FormatTestCSharp, CSharpNullForgiving) {
487a437befaSEliza Velasquez   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
488a437befaSEliza Velasquez 
489a437befaSEliza Velasquez   verifyFormat("var test = null!;", Style);
490a437befaSEliza Velasquez   verifyFormat("string test = someFunctionCall()! + \"ABC\"!", Style);
491a437befaSEliza Velasquez   verifyFormat("int test = (1! + 2 + bar! + foo())!", Style);
492a437befaSEliza Velasquez   verifyFormat(R"(test ??= !foo!;)", Style);
493a437befaSEliza Velasquez   verifyFormat("test = !bar! ?? !foo!;", Style);
494a437befaSEliza Velasquez   verifyFormat("bool test = !(!true && !true! || !null && !null! || !false && "
495a437befaSEliza Velasquez                "!false! && !bar()! + (!foo()))!",
496a437befaSEliza Velasquez                Style);
497a437befaSEliza Velasquez 
498a437befaSEliza Velasquez   // Check that line break keeps identifier with the bang.
499a437befaSEliza Velasquez   Style.ColumnLimit = 14;
500a437befaSEliza Velasquez 
501a437befaSEliza Velasquez   verifyFormat("var test =\n"
502a437befaSEliza Velasquez                "    foo!;",
503a437befaSEliza Velasquez                Style);
504a437befaSEliza Velasquez }
505a437befaSEliza Velasquez 
506a2f963bbSPaul Hoad TEST_F(FormatTestCSharp, AttributesIndentation) {
507a2f963bbSPaul Hoad   FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
508d821650eSrmarker   Style.BreakAfterReturnType = FormatStyle::RTBS_None;
509a2f963bbSPaul Hoad 
510a2f963bbSPaul Hoad   verifyFormat("[STAThread]\n"
511a2f963bbSPaul Hoad                "static void Main(string[] args)\n"
512a2f963bbSPaul Hoad                "{\n"
513a2f963bbSPaul Hoad                "}",
514a2f963bbSPaul Hoad                Style);
515a2f963bbSPaul Hoad 
516a2f963bbSPaul Hoad   verifyFormat("[STAThread]\n"
517a2f963bbSPaul Hoad                "void "
518a2f963bbSPaul Hoad                "veryLooooooooooooooongFunctionName(string[] args)\n"
519a2f963bbSPaul Hoad                "{\n"
520a2f963bbSPaul Hoad                "}",
521a2f963bbSPaul Hoad                Style);
522a2f963bbSPaul Hoad 
523a2f963bbSPaul Hoad   verifyFormat("[STAThread]\n"
524a2f963bbSPaul Hoad                "veryLoooooooooooooooooooongReturnType "
525a2f963bbSPaul Hoad                "veryLooooooooooooooongFunctionName(string[] args)\n"
526a2f963bbSPaul Hoad                "{\n"
527a2f963bbSPaul Hoad                "}",
528a2f963bbSPaul Hoad                Style);
529a2f963bbSPaul Hoad 
530a2f963bbSPaul Hoad   verifyFormat("[SuppressMessage(\"A\", \"B\", Justification = \"C\")]\n"
531a2f963bbSPaul Hoad                "public override X Y()\n"
532a2f963bbSPaul Hoad                "{\n"
53388934a82SOwen Pan                "}",
534a2f963bbSPaul Hoad                Style);
535a2f963bbSPaul Hoad 
536a2f963bbSPaul Hoad   verifyFormat("[SuppressMessage]\n"
537a2f963bbSPaul Hoad                "public X Y()\n"
538a2f963bbSPaul Hoad                "{\n"
53988934a82SOwen Pan                "}",
540a2f963bbSPaul Hoad                Style);
541a2f963bbSPaul Hoad 
542a2f963bbSPaul Hoad   verifyFormat("[SuppressMessage]\n"
543a2f963bbSPaul Hoad                "public override X Y()\n"
544a2f963bbSPaul Hoad                "{\n"
54588934a82SOwen Pan                "}",
546a2f963bbSPaul Hoad                Style);
547a2f963bbSPaul Hoad 
548a2f963bbSPaul Hoad   verifyFormat("public A(B b) : base(b)\n"
549a2f963bbSPaul Hoad                "{\n"
550a2f963bbSPaul Hoad                "    [SuppressMessage]\n"
551a2f963bbSPaul Hoad                "    public override X Y()\n"
552a2f963bbSPaul Hoad                "    {\n"
553a2f963bbSPaul Hoad                "    }\n"
55488934a82SOwen Pan                "}",
555a2f963bbSPaul Hoad                Style);
5562f209ccfSmydeveloperday 
5572f209ccfSmydeveloperday   verifyFormat("public A : Base\n"
5582f209ccfSmydeveloperday                "{\n"
5592f209ccfSmydeveloperday                "}\n"
5602f209ccfSmydeveloperday                "[Test]\n"
5612f209ccfSmydeveloperday                "public Foo()\n"
5622f209ccfSmydeveloperday                "{\n"
56388934a82SOwen Pan                "}",
5642f209ccfSmydeveloperday                Style);
5652f209ccfSmydeveloperday 
5662f209ccfSmydeveloperday   verifyFormat("namespace\n"
5672f209ccfSmydeveloperday                "{\n"
5682f209ccfSmydeveloperday                "public A : Base\n"
5692f209ccfSmydeveloperday                "{\n"
5702f209ccfSmydeveloperday                "}\n"
5712f209ccfSmydeveloperday                "[Test]\n"
5722f209ccfSmydeveloperday                "public Foo()\n"
5732f209ccfSmydeveloperday                "{\n"
5742f209ccfSmydeveloperday                "}\n"
57588934a82SOwen Pan                "}",
5762f209ccfSmydeveloperday                Style);
577a2f963bbSPaul Hoad }
578a2f963bbSPaul Hoad 
5794c056583SPaul Hoad TEST_F(FormatTestCSharp, CSharpSpaceBefore) {
5804c056583SPaul Hoad   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
5814c056583SPaul Hoad   Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
5824c056583SPaul Hoad 
5834c056583SPaul Hoad   verifyFormat("List<string> list;", Style);
5844c056583SPaul Hoad   verifyFormat("Dictionary<string, string> dict;", Style);
5854c056583SPaul Hoad 
5864c056583SPaul Hoad   verifyFormat("for (int i = 0; i < size (); i++) {\n"
5874c056583SPaul Hoad                "}",
5884c056583SPaul Hoad                Style);
5894c056583SPaul Hoad   verifyFormat("foreach (var x in y) {\n"
5904c056583SPaul Hoad                "}",
5914c056583SPaul Hoad                Style);
5924c056583SPaul Hoad   verifyFormat("switch (x) {}", Style);
5934c056583SPaul Hoad   verifyFormat("do {\n"
5944c056583SPaul Hoad                "} while (x);",
5954c056583SPaul Hoad                Style);
5964c056583SPaul Hoad 
5974c056583SPaul Hoad   Style.SpaceBeforeParens = FormatStyle::SBPO_Never;
5984c056583SPaul Hoad 
5994c056583SPaul Hoad   verifyFormat("List<string> list;", Style);
6004c056583SPaul Hoad   verifyFormat("Dictionary<string, string> dict;", Style);
6014c056583SPaul Hoad 
6024c056583SPaul Hoad   verifyFormat("for(int i = 0; i < size(); i++) {\n"
6034c056583SPaul Hoad                "}",
6044c056583SPaul Hoad                Style);
6054c056583SPaul Hoad   verifyFormat("foreach(var x in y) {\n"
6064c056583SPaul Hoad                "}",
6074c056583SPaul Hoad                Style);
6084c056583SPaul Hoad   verifyFormat("switch(x) {}", Style);
6094c056583SPaul Hoad   verifyFormat("do {\n"
6104c056583SPaul Hoad                "} while(x);",
6114c056583SPaul Hoad                Style);
6124c056583SPaul Hoad }
6134c056583SPaul Hoad 
614d82adf32Smydeveloperday TEST_F(FormatTestCSharp, CSharpSpaceAfterCStyleCast) {
615d82adf32Smydeveloperday   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
616d82adf32Smydeveloperday 
617d82adf32Smydeveloperday   verifyFormat("(int)x / y;", Style);
618d82adf32Smydeveloperday 
619d82adf32Smydeveloperday   Style.SpaceAfterCStyleCast = true;
620d82adf32Smydeveloperday   verifyFormat("(int) x / y;", Style);
621d82adf32Smydeveloperday }
622d82adf32Smydeveloperday 
62336a8f7f6SKrasimir Georgiev TEST_F(FormatTestCSharp, CSharpEscapedQuotesInVerbatimStrings) {
62436a8f7f6SKrasimir Georgiev   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
62536a8f7f6SKrasimir Georgiev 
626f9f0919dSJonathan Coe   verifyFormat(R"(string str = @"""";)", Style);
627f9f0919dSJonathan Coe   verifyFormat(R"(string str = @"""Hello world""";)", Style);
628f9f0919dSJonathan Coe   verifyFormat(R"(string str = $@"""Hello {friend}""";)", Style);
6290ffb3dd3Sowenca   verifyFormat(R"(return $@"Foo ""/foo?f={Request.Query["f"]}""";)", Style);
630b60e7a7fSowenca   verifyFormat(R"(return @$"Foo ""/foo?f={Request.Query["f"]}""";)", Style);
631b60e7a7fSowenca   verifyFormat(R"(return @$"path\to\{specifiedFile}")", Style);
63236a8f7f6SKrasimir Georgiev }
63336a8f7f6SKrasimir Georgiev 
6349d212e83SJonathan Coe TEST_F(FormatTestCSharp, CSharpQuotesInInterpolatedStrings) {
6359d212e83SJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
6369d212e83SJonathan Coe 
6379d212e83SJonathan Coe   verifyFormat(R"(string str1 = $"{null ?? "null"}";)", Style);
6389d212e83SJonathan Coe   verifyFormat(R"(string str2 = $"{{{braceCount} braces";)", Style);
6399d212e83SJonathan Coe   verifyFormat(R"(string str3 = $"{braceCount}}} braces";)", Style);
6409d212e83SJonathan Coe }
6419d212e83SJonathan Coe 
642f9f0919dSJonathan Coe TEST_F(FormatTestCSharp, CSharpNewlinesInVerbatimStrings) {
643f9f0919dSJonathan Coe   // Use MS style as Google Style inserts a line break before multiline strings.
644f9f0919dSJonathan Coe 
645f9f0919dSJonathan Coe   // verifyFormat does not understand multiline C# string-literals
646f9f0919dSJonathan Coe   // so check the format explicitly.
647f9f0919dSJonathan Coe 
648f9f0919dSJonathan Coe   FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
649f9f0919dSJonathan Coe 
650f9f0919dSJonathan Coe   std::string Code = R"(string s1 = $@"some code:
651f9f0919dSJonathan Coe   class {className} {{
652f9f0919dSJonathan Coe     {className}() {{}}
653f9f0919dSJonathan Coe   }}";)";
654f9f0919dSJonathan Coe 
655f9f0919dSJonathan Coe   EXPECT_EQ(Code, format(Code, Style));
656f9f0919dSJonathan Coe 
657f9f0919dSJonathan Coe   // Multiline string in the middle of a function call.
658f9f0919dSJonathan Coe   Code = R"(
659f9f0919dSJonathan Coe var x = foo(className, $@"some code:
660f9f0919dSJonathan Coe   class {className} {{
661f9f0919dSJonathan Coe     {className}() {{}}
662f9f0919dSJonathan Coe   }}",
663f9f0919dSJonathan Coe             y);)"; // y aligned with `className` arg.
664f9f0919dSJonathan Coe 
665f9f0919dSJonathan Coe   EXPECT_EQ(Code, format(Code, Style));
666f9f0919dSJonathan Coe 
667f9f0919dSJonathan Coe   // Interpolated string with embedded multiline string.
668f9f0919dSJonathan Coe   Code = R"(Console.WriteLine($"{string.Join(@",
669f9f0919dSJonathan Coe 		", values)}");)";
670f9f0919dSJonathan Coe 
671f9f0919dSJonathan Coe   EXPECT_EQ(Code, format(Code, Style));
672f9f0919dSJonathan Coe }
673f9f0919dSJonathan Coe 
674258d7b86SDanil Sidoruk TEST_F(FormatTestCSharp, CSharpNewOperator) {
675258d7b86SDanil Sidoruk   FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp);
676258d7b86SDanil Sidoruk 
677258d7b86SDanil Sidoruk   verifyFormat("public void F() {\n"
678258d7b86SDanil Sidoruk                "  var v = new C(() => { var t = 5; });\n"
679258d7b86SDanil Sidoruk                "}",
680258d7b86SDanil Sidoruk                Style);
681258d7b86SDanil Sidoruk   verifyFormat("public void F() {\n"
682258d7b86SDanil Sidoruk                "  var v = new C(() => {\n"
683258d7b86SDanil Sidoruk                "    try {\n"
684258d7b86SDanil Sidoruk                "    } catch {\n"
685258d7b86SDanil Sidoruk                "      var t = 5;\n"
686258d7b86SDanil Sidoruk                "    }\n"
687258d7b86SDanil Sidoruk                "  });\n"
688258d7b86SDanil Sidoruk                "}",
689258d7b86SDanil Sidoruk                Style);
690258d7b86SDanil Sidoruk }
691258d7b86SDanil Sidoruk 
6927117066bSJonathan Coe TEST_F(FormatTestCSharp, CSharpLambdas) {
6937117066bSJonathan Coe   FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
6947117066bSJonathan Coe   FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
6957117066bSJonathan Coe 
6967117066bSJonathan Coe   verifyFormat(R"(//
6977117066bSJonathan Coe class MyClass {
6987117066bSJonathan Coe   Action<string> greet = name => {
6997117066bSJonathan Coe     string greeting = $"Hello {name}!";
7007117066bSJonathan Coe     Console.WriteLine(greeting);
7017117066bSJonathan Coe   };
7027117066bSJonathan Coe })",
7037117066bSJonathan Coe                GoogleStyle);
7047117066bSJonathan Coe 
7057117066bSJonathan Coe   // Microsoft Style:
7067117066bSJonathan Coe   // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#statement-lambdas
7077117066bSJonathan Coe   verifyFormat(R"(//
7087117066bSJonathan Coe class MyClass
7097117066bSJonathan Coe {
7107117066bSJonathan Coe     Action<string> greet = name =>
7117117066bSJonathan Coe     {
7127117066bSJonathan Coe         string greeting = $"Hello {name}!";
7137117066bSJonathan Coe         Console.WriteLine(greeting);
7147117066bSJonathan Coe     };
7157117066bSJonathan Coe })",
7167117066bSJonathan Coe                MicrosoftStyle);
717f9937106Smydeveloperday 
718f9937106Smydeveloperday   verifyFormat("void bar()\n"
719f9937106Smydeveloperday                "{\n"
720f9937106Smydeveloperday                "    Function(Val, (Action)(() =>\n"
721f9937106Smydeveloperday                "                           {\n"
722f9937106Smydeveloperday                "                               lock (mylock)\n"
723f9937106Smydeveloperday                "                               {\n"
724f9937106Smydeveloperday                "                                   if (true)\n"
725f9937106Smydeveloperday                "                                   {\n"
726f9937106Smydeveloperday                "                                       A.Remove(item);\n"
727f9937106Smydeveloperday                "                                   }\n"
728f9937106Smydeveloperday                "                               }\n"
729f9937106Smydeveloperday                "                           }));\n"
730f9937106Smydeveloperday                "}",
731f9937106Smydeveloperday                MicrosoftStyle);
732f9937106Smydeveloperday 
733f9937106Smydeveloperday   verifyFormat("void baz()\n"
734f9937106Smydeveloperday                "{\n"
735f9937106Smydeveloperday                "    Function(Val, (Action)(() =>\n"
736f9937106Smydeveloperday                "                           {\n"
737f9937106Smydeveloperday                "                               using (var a = new Lock())\n"
738f9937106Smydeveloperday                "                               {\n"
739f9937106Smydeveloperday                "                                   if (true)\n"
740f9937106Smydeveloperday                "                                   {\n"
741f9937106Smydeveloperday                "                                       A.Remove(item);\n"
742f9937106Smydeveloperday                "                                   }\n"
743f9937106Smydeveloperday                "                               }\n"
744f9937106Smydeveloperday                "                           }));\n"
745f9937106Smydeveloperday                "}",
746f9937106Smydeveloperday                MicrosoftStyle);
747f9937106Smydeveloperday 
748f9937106Smydeveloperday   verifyFormat("void baz()\n"
749f9937106Smydeveloperday                "{\n"
750f9937106Smydeveloperday                "    Function(Val, (Action)(() =>\n"
751f9937106Smydeveloperday                "                           {\n"
752f9937106Smydeveloperday                "                               if (true)\n"
753f9937106Smydeveloperday                "                               {\n"
754f9937106Smydeveloperday                "                                   A.Remove(item);\n"
755f9937106Smydeveloperday                "                               }\n"
756f9937106Smydeveloperday                "                           }));\n"
757f9937106Smydeveloperday                "}",
758f9937106Smydeveloperday                MicrosoftStyle);
759f9937106Smydeveloperday 
760f9937106Smydeveloperday   verifyFormat("void baz()\n"
761f9937106Smydeveloperday                "{\n"
762f9937106Smydeveloperday                "    Function(Val, (Action)(() =>\n"
763f9937106Smydeveloperday                "                           {\n"
764f9937106Smydeveloperday                "                               do\n"
765f9937106Smydeveloperday                "                               {\n"
766f9937106Smydeveloperday                "                                   A.Remove(item);\n"
767f9937106Smydeveloperday                "                               } while (true)\n"
768f9937106Smydeveloperday                "                           }));\n"
769f9937106Smydeveloperday                "}",
770f9937106Smydeveloperday                MicrosoftStyle);
771f9937106Smydeveloperday 
772f9937106Smydeveloperday   verifyFormat("void baz()\n"
773f9937106Smydeveloperday                "{\n"
774f9937106Smydeveloperday                "    Function(Val, (Action)(() =>\n"
775f9937106Smydeveloperday                "                           { A.Remove(item); }));\n"
776f9937106Smydeveloperday                "}",
777f9937106Smydeveloperday                MicrosoftStyle);
778f9937106Smydeveloperday 
779f9937106Smydeveloperday   verifyFormat("void bar()\n"
780f9937106Smydeveloperday                "{\n"
781f9937106Smydeveloperday                "    Function(Val, (() =>\n"
782f9937106Smydeveloperday                "                   {\n"
783f9937106Smydeveloperday                "                       lock (mylock)\n"
784f9937106Smydeveloperday                "                       {\n"
785f9937106Smydeveloperday                "                           if (true)\n"
786f9937106Smydeveloperday                "                           {\n"
787f9937106Smydeveloperday                "                               A.Remove(item);\n"
788f9937106Smydeveloperday                "                           }\n"
789f9937106Smydeveloperday                "                       }\n"
790f9937106Smydeveloperday                "                   }));\n"
791f9937106Smydeveloperday                "}",
792f9937106Smydeveloperday                MicrosoftStyle);
793f9937106Smydeveloperday   verifyFormat("void bar()\n"
794f9937106Smydeveloperday                "{\n"
795f9937106Smydeveloperday                "    Function((() =>\n"
796f9937106Smydeveloperday                "              {\n"
797f9937106Smydeveloperday                "                  lock (mylock)\n"
798f9937106Smydeveloperday                "                  {\n"
799f9937106Smydeveloperday                "                      if (true)\n"
800f9937106Smydeveloperday                "                      {\n"
801f9937106Smydeveloperday                "                          A.Remove(item);\n"
802f9937106Smydeveloperday                "                      }\n"
803f9937106Smydeveloperday                "                  }\n"
804f9937106Smydeveloperday                "              }));\n"
805f9937106Smydeveloperday                "}",
806f9937106Smydeveloperday                MicrosoftStyle);
807f9937106Smydeveloperday 
808f9937106Smydeveloperday   MicrosoftStyle.IndentWidth = 2;
809f9937106Smydeveloperday   verifyFormat("void bar()\n"
810f9937106Smydeveloperday                "{\n"
811f9937106Smydeveloperday                "  Function((() =>\n"
812f9937106Smydeveloperday                "            {\n"
813f9937106Smydeveloperday                "              lock (mylock)\n"
814f9937106Smydeveloperday                "              {\n"
815f9937106Smydeveloperday                "                if (true)\n"
816f9937106Smydeveloperday                "                {\n"
817f9937106Smydeveloperday                "                  A.Remove(item);\n"
818f9937106Smydeveloperday                "                }\n"
819f9937106Smydeveloperday                "              }\n"
820f9937106Smydeveloperday                "            }));\n"
821f9937106Smydeveloperday                "}",
822f9937106Smydeveloperday                MicrosoftStyle);
823f9937106Smydeveloperday   verifyFormat("void bar() {\n"
824f9937106Smydeveloperday                "  Function((() => {\n"
825f9937106Smydeveloperday                "    lock (mylock) {\n"
826f9937106Smydeveloperday                "      if (true) {\n"
827f9937106Smydeveloperday                "        A.Remove(item);\n"
828f9937106Smydeveloperday                "      }\n"
829f9937106Smydeveloperday                "    }\n"
830f9937106Smydeveloperday                "  }));\n"
831f9937106Smydeveloperday                "}",
832f9937106Smydeveloperday                GoogleStyle);
8337117066bSJonathan Coe }
8347117066bSJonathan Coe 
835163c13feSPeter Stys TEST_F(FormatTestCSharp, CSharpLambdasDontBreakFollowingCodeAlignment) {
836163c13feSPeter Stys   FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
837163c13feSPeter Stys   FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
838163c13feSPeter Stys 
839163c13feSPeter Stys   verifyFormat(R"(//
840163c13feSPeter Stys public class Sample
841163c13feSPeter Stys {
842163c13feSPeter Stys     public void Test()
843163c13feSPeter Stys     {
844163c13feSPeter Stys         while (true)
845163c13feSPeter Stys         {
846163c13feSPeter Stys             preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
847163c13feSPeter Stys             CodeThatFollowsLambda();
848163c13feSPeter Stys             IsWellAligned();
849163c13feSPeter Stys         }
850163c13feSPeter Stys     }
851163c13feSPeter Stys })",
852163c13feSPeter Stys                MicrosoftStyle);
853163c13feSPeter Stys 
854163c13feSPeter Stys   verifyFormat(R"(//
855163c13feSPeter Stys public class Sample {
856163c13feSPeter Stys   public void Test() {
857163c13feSPeter Stys     while (true) {
858163c13feSPeter Stys       preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
859163c13feSPeter Stys       CodeThatFollowsLambda();
860163c13feSPeter Stys       IsWellAligned();
861163c13feSPeter Stys     }
862163c13feSPeter Stys   }
863163c13feSPeter Stys })",
864163c13feSPeter Stys                GoogleStyle);
865163c13feSPeter Stys }
866163c13feSPeter Stys 
867163c13feSPeter Stys TEST_F(FormatTestCSharp, CSharpLambdasComplexLambdasDontBreakAlignment) {
868163c13feSPeter Stys   FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
869163c13feSPeter Stys   FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
870163c13feSPeter Stys 
871163c13feSPeter Stys   verifyFormat(R"(//
872163c13feSPeter Stys public class Test
873163c13feSPeter Stys {
874163c13feSPeter Stys     private static void ComplexLambda(BuildReport protoReport)
875163c13feSPeter Stys     {
876163c13feSPeter Stys         allSelectedScenes =
877163c13feSPeter Stys             veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
878163c13feSPeter Stys                 .Select(scene => scene.path)
879163c13feSPeter Stys                 .ToArray();
880163c13feSPeter Stys         if (allSelectedScenes.Count == 0)
881163c13feSPeter Stys         {
882163c13feSPeter Stys             return;
883163c13feSPeter Stys         }
884163c13feSPeter Stys         Functions();
885163c13feSPeter Stys         AreWell();
886163c13feSPeter Stys         Aligned();
887163c13feSPeter Stys         AfterLambdaBlock();
888163c13feSPeter Stys     }
889163c13feSPeter Stys })",
890163c13feSPeter Stys                MicrosoftStyle);
891163c13feSPeter Stys 
892163c13feSPeter Stys   verifyFormat(R"(//
893163c13feSPeter Stys public class Test {
894163c13feSPeter Stys   private static void ComplexLambda(BuildReport protoReport) {
895163c13feSPeter Stys     allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
896163c13feSPeter Stys                             .Where(scene => scene.enabled)
897163c13feSPeter Stys                             .Select(scene => scene.path)
898163c13feSPeter Stys                             .ToArray();
899163c13feSPeter Stys     if (allSelectedScenes.Count == 0) {
900163c13feSPeter Stys       return;
901163c13feSPeter Stys     }
902163c13feSPeter Stys     Functions();
903163c13feSPeter Stys     AreWell();
904163c13feSPeter Stys     Aligned();
905163c13feSPeter Stys     AfterLambdaBlock();
906163c13feSPeter Stys   }
907163c13feSPeter Stys })",
908163c13feSPeter Stys                GoogleStyle);
909163c13feSPeter Stys }
910163c13feSPeter Stys 
911163c13feSPeter Stys TEST_F(FormatTestCSharp, CSharpLambdasMulipleLambdasDontBreakAlignment) {
912163c13feSPeter Stys   FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_CSharp);
913163c13feSPeter Stys   FormatStyle MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
914163c13feSPeter Stys 
915163c13feSPeter Stys   verifyFormat(R"(//
916163c13feSPeter Stys public class Test
917163c13feSPeter Stys {
918163c13feSPeter Stys     private static void MultipleLambdas(BuildReport protoReport)
919163c13feSPeter Stys     {
920163c13feSPeter Stys         allSelectedScenes =
921163c13feSPeter Stys             veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
922163c13feSPeter Stys                 .Select(scene => scene.path)
923163c13feSPeter Stys                 .ToArray();
924163c13feSPeter Stys         preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
925163c13feSPeter Stys         if (allSelectedScenes.Count == 0)
926163c13feSPeter Stys         {
927163c13feSPeter Stys             return;
928163c13feSPeter Stys         }
929163c13feSPeter Stys         Functions();
930163c13feSPeter Stys         AreWell();
931163c13feSPeter Stys         Aligned();
932163c13feSPeter Stys         AfterLambdaBlock();
933163c13feSPeter Stys     }
934163c13feSPeter Stys })",
935163c13feSPeter Stys                MicrosoftStyle);
936163c13feSPeter Stys 
937163c13feSPeter Stys   verifyFormat(R"(//
938163c13feSPeter Stys public class Test {
939163c13feSPeter Stys   private static void MultipleLambdas(BuildReport protoReport) {
940163c13feSPeter Stys     allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
941163c13feSPeter Stys                             .Where(scene => scene.enabled)
942163c13feSPeter Stys                             .Select(scene => scene.path)
943163c13feSPeter Stys                             .ToArray();
944163c13feSPeter Stys     preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
945163c13feSPeter Stys     if (allSelectedScenes.Count == 0) {
946163c13feSPeter Stys       return;
947163c13feSPeter Stys     }
948163c13feSPeter Stys     Functions();
949163c13feSPeter Stys     AreWell();
950163c13feSPeter Stys     Aligned();
951163c13feSPeter Stys     AfterLambdaBlock();
952163c13feSPeter Stys   }
953163c13feSPeter Stys })",
954163c13feSPeter Stys                GoogleStyle);
955163c13feSPeter Stys }
956163c13feSPeter Stys 
9570bb60e29SJonathan Coe TEST_F(FormatTestCSharp, CSharpObjectInitializers) {
9580bb60e29SJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
9590bb60e29SJonathan Coe 
960a11ff39bSJonathan Coe   // Start code fragments with a comment line so that C++ raw string literals
9610bb60e29SJonathan Coe   // as seen are identical to expected formatted code.
9620bb60e29SJonathan Coe 
9630bb60e29SJonathan Coe   verifyFormat(R"(//
9640bb60e29SJonathan Coe Shape[] shapes = new[] {
9650bb60e29SJonathan Coe   new Circle {
9660bb60e29SJonathan Coe     Radius = 2.7281,
9670bb60e29SJonathan Coe     Colour = Colours.Red,
9680bb60e29SJonathan Coe   },
9690bb60e29SJonathan Coe   new Square {
9700bb60e29SJonathan Coe     Side = 101.1,
9710bb60e29SJonathan Coe     Colour = Colours.Yellow,
9720bb60e29SJonathan Coe   },
9730bb60e29SJonathan Coe };)",
9740bb60e29SJonathan Coe                Style);
9750bb60e29SJonathan Coe 
9760bb60e29SJonathan Coe   // Omitted final `,`s will change the formatting.
9770bb60e29SJonathan Coe   verifyFormat(R"(//
9780bb60e29SJonathan Coe Shape[] shapes = new[] { new Circle { Radius = 2.7281, Colour = Colours.Red },
979eb682b80SJonathan Coe                          new Square { Side = 101.1, Colour = Colours.Yellow } };)",
9800bb60e29SJonathan Coe                Style);
9817d2fdd3fSJonathan Coe 
9827d2fdd3fSJonathan Coe   // Lambdas can be supplied as initialiser arguments.
9837d2fdd3fSJonathan Coe   verifyFormat(R"(//
9847d2fdd3fSJonathan Coe private Transformer _transformer = new X.Y {
9857d2fdd3fSJonathan Coe   Filler = (Shape shape) => { return new Transform.Fill(shape, RED); },
9867d2fdd3fSJonathan Coe   Scaler = (Shape shape) => { return new Transform.Resize(shape, 0.1); },
9877d2fdd3fSJonathan Coe };)",
9887d2fdd3fSJonathan Coe                Style);
9890c28a093SJonathan Coe 
9900c28a093SJonathan Coe   // Dictionary initialisation.
9910c28a093SJonathan Coe   verifyFormat(R"(//
9920c28a093SJonathan Coe var myDict = new Dictionary<string, string> {
9930c28a093SJonathan Coe   ["name"] = _donald,
9940c28a093SJonathan Coe   ["age"] = Convert.ToString(DateTime.Today.Year - 1934),
9950c28a093SJonathan Coe   ["type"] = _duck,
9960c28a093SJonathan Coe };)",
9970c28a093SJonathan Coe                Style);
9980bb60e29SJonathan Coe }
9990bb60e29SJonathan Coe 
10005e1a026cSJonathan Coe TEST_F(FormatTestCSharp, CSharpArrayInitializers) {
10015e1a026cSJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
10025e1a026cSJonathan Coe 
10035e1a026cSJonathan Coe   verifyFormat(R"(//
10045e1a026cSJonathan Coe private MySet<Node>[] setPoints = {
10055e1a026cSJonathan Coe   new Point<Node>(),
10065e1a026cSJonathan Coe   new Point<Node>(),
10075e1a026cSJonathan Coe };)",
10085e1a026cSJonathan Coe                Style);
10095e1a026cSJonathan Coe }
10105e1a026cSJonathan Coe 
1011a11ff39bSJonathan Coe TEST_F(FormatTestCSharp, CSharpNamedArguments) {
1012a11ff39bSJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1013a11ff39bSJonathan Coe 
1014a11ff39bSJonathan Coe   verifyFormat(R"(//
10159520bf14SJonathan Coe PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");)",
1016a11ff39bSJonathan Coe                Style);
1017a11ff39bSJonathan Coe 
1018a11ff39bSJonathan Coe   // Ensure that trailing comments do not cause problems.
1019a11ff39bSJonathan Coe   verifyFormat(R"(//
1020a11ff39bSJonathan Coe PrintOrderDetails(orderNum: 31, productName: "Red Mug",  // comment
1021a11ff39bSJonathan Coe                   sellerName: "Gift Shop");)",
1022a11ff39bSJonathan Coe                Style);
10237dfe0cc7SJonathan Coe 
10247dfe0cc7SJonathan Coe   verifyFormat(R"(foreach (var tickCount in task.Begin(seed: 0)) {)", Style);
1025a11ff39bSJonathan Coe }
1026a11ff39bSJonathan Coe 
10272bd6974aSJonathan Coe TEST_F(FormatTestCSharp, CSharpPropertyAccessors) {
10282bd6974aSJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
10292bd6974aSJonathan Coe 
10302bd6974aSJonathan Coe   verifyFormat("int Value { get }", Style);
10312bd6974aSJonathan Coe   verifyFormat("int Value { get; }", Style);
10322bd6974aSJonathan Coe   verifyFormat("int Value { internal get; }", Style);
10332bd6974aSJonathan Coe   verifyFormat("int Value { get; } = 0", Style);
10342bd6974aSJonathan Coe   verifyFormat("int Value { set }", Style);
10352bd6974aSJonathan Coe   verifyFormat("int Value { set; }", Style);
10367a54fcebSMarek Kurdej   verifyFormat("int Value { init; }", Style);
10372bd6974aSJonathan Coe   verifyFormat("int Value { internal set; }", Style);
10382bd6974aSJonathan Coe   verifyFormat("int Value { set; } = 0", Style);
10392bd6974aSJonathan Coe   verifyFormat("int Value { get; set }", Style);
10407a54fcebSMarek Kurdej   verifyFormat("int Value { get; init; }", Style);
10412bd6974aSJonathan Coe   verifyFormat("int Value { set; get }", Style);
10422bd6974aSJonathan Coe   verifyFormat("int Value { get; private set; }", Style);
10432bd6974aSJonathan Coe   verifyFormat("int Value { get; set; }", Style);
10442bd6974aSJonathan Coe   verifyFormat("int Value { get; set; } = 0", Style);
10452bd6974aSJonathan Coe   verifyFormat("int Value { internal get; internal set; }", Style);
10462bd6974aSJonathan Coe 
10472bd6974aSJonathan Coe   // Do not wrap expression body definitions.
10482bd6974aSJonathan Coe   verifyFormat(R"(//
10492bd6974aSJonathan Coe public string Name {
10502bd6974aSJonathan Coe   get => _name;
10512bd6974aSJonathan Coe   set => _name = value;
10522bd6974aSJonathan Coe })",
10532bd6974aSJonathan Coe                Style);
10547a54fcebSMarek Kurdej   verifyFormat(R"(//
10557a54fcebSMarek Kurdej public string Name {
10567a54fcebSMarek Kurdej   init => _name = value;
10577a54fcebSMarek Kurdej   get => _name;
10587a54fcebSMarek Kurdej })",
10597a54fcebSMarek Kurdej                Style);
10607a54fcebSMarek Kurdej   verifyFormat(R"(//
10617a54fcebSMarek Kurdej public string Name {
10627a54fcebSMarek Kurdej   set => _name = value;
10637a54fcebSMarek Kurdej   get => _name;
10647a54fcebSMarek Kurdej })",
10657a54fcebSMarek Kurdej                Style);
106644ad58b9SJonathan Coe 
106744ad58b9SJonathan Coe   // Examples taken from
106844ad58b9SJonathan Coe   // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
106944ad58b9SJonathan Coe   verifyFormat(R"(
107044ad58b9SJonathan Coe // Expression body definitions
107144ad58b9SJonathan Coe public class SaleItem {
107244ad58b9SJonathan Coe   public decimal Price {
107344ad58b9SJonathan Coe     get => _cost;
107444ad58b9SJonathan Coe     set => _cost = value;
107544ad58b9SJonathan Coe   }
107644ad58b9SJonathan Coe })",
107744ad58b9SJonathan Coe                Style);
107844ad58b9SJonathan Coe 
107944ad58b9SJonathan Coe   verifyFormat(R"(
108044ad58b9SJonathan Coe // Properties with backing fields
108144ad58b9SJonathan Coe class TimePeriod {
108244ad58b9SJonathan Coe   public double Hours {
108344ad58b9SJonathan Coe     get { return _seconds / 3600; }
108444ad58b9SJonathan Coe     set {
108544ad58b9SJonathan Coe       if (value < 0 || value > 24)
10869520bf14SJonathan Coe         throw new ArgumentOutOfRangeException($"{nameof(value)} must be between 0 and 24.");
108744ad58b9SJonathan Coe       _seconds = value * 3600;
108844ad58b9SJonathan Coe     }
108944ad58b9SJonathan Coe   }
109044ad58b9SJonathan Coe })",
109144ad58b9SJonathan Coe                Style);
109244ad58b9SJonathan Coe 
109344ad58b9SJonathan Coe   verifyFormat(R"(
109444ad58b9SJonathan Coe // Auto-implemented properties
109544ad58b9SJonathan Coe public class SaleItem {
109644ad58b9SJonathan Coe   public decimal Price { get; set; }
109744ad58b9SJonathan Coe })",
109844ad58b9SJonathan Coe                Style);
109944ad58b9SJonathan Coe 
110044ad58b9SJonathan Coe   // Add column limit to wrap long lines.
110144ad58b9SJonathan Coe   Style.ColumnLimit = 100;
110244ad58b9SJonathan Coe 
110344ad58b9SJonathan Coe   // Examples with assignment to default value.
110444ad58b9SJonathan Coe   verifyFormat(R"(
110544ad58b9SJonathan Coe // Long assignment to default value
110644ad58b9SJonathan Coe class MyClass {
110744ad58b9SJonathan Coe   public override VeryLongNamedTypeIndeed VeryLongNamedValue { get; set } =
110844ad58b9SJonathan Coe       VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
110944ad58b9SJonathan Coe                                      DefaultThirdArgument);
111044ad58b9SJonathan Coe })",
111144ad58b9SJonathan Coe                Style);
111244ad58b9SJonathan Coe 
111344ad58b9SJonathan Coe   verifyFormat(R"(
111444ad58b9SJonathan Coe // Long assignment to default value with expression body
111544ad58b9SJonathan Coe class MyClass {
111644ad58b9SJonathan Coe   public override VeryLongNamedTypeIndeed VeryLongNamedValue {
111744ad58b9SJonathan Coe     get => veryLongNamedField;
111844ad58b9SJonathan Coe     set => veryLongNamedField = value;
111944ad58b9SJonathan Coe   } = VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
112044ad58b9SJonathan Coe                                      DefaultThirdArgument);
112144ad58b9SJonathan Coe })",
112244ad58b9SJonathan Coe                Style);
11238fa743abSJonathan Coe 
11248fa743abSJonathan Coe   // Brace wrapping and single-lining of accessor can be controlled by config.
11258fa743abSJonathan Coe   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
11268fa743abSJonathan Coe   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
11278fa743abSJonathan Coe   Style.BraceWrapping.AfterFunction = true;
11288fa743abSJonathan Coe 
11298fa743abSJonathan Coe   verifyFormat(R"(//
11308fa743abSJonathan Coe class TimePeriod {
11318fa743abSJonathan Coe   public double Hours
11328fa743abSJonathan Coe   {
11338fa743abSJonathan Coe     get {
11348fa743abSJonathan Coe       return _seconds / 3600;
11358fa743abSJonathan Coe     }
11368fa743abSJonathan Coe     set {
11378fa743abSJonathan Coe       _seconds = value * 3600;
11388fa743abSJonathan Coe     }
11398fa743abSJonathan Coe   }
11408fa743abSJonathan Coe })",
11418fa743abSJonathan Coe                Style);
1142f22b0727SJonathan Coe 
1143f22b0727SJonathan Coe   // Microsoft style trivial property accessors have no line break before the
1144f22b0727SJonathan Coe   // opening brace.
1145f22b0727SJonathan Coe   auto MicrosoftStyle = getMicrosoftStyle(FormatStyle::LK_CSharp);
1146f22b0727SJonathan Coe   verifyFormat(R"(//
1147f22b0727SJonathan Coe public class SaleItem
1148f22b0727SJonathan Coe {
1149f22b0727SJonathan Coe     public decimal Price { get; set; }
1150f22b0727SJonathan Coe })",
1151f22b0727SJonathan Coe                MicrosoftStyle);
1152d990cc45SOwen Pan 
1153d990cc45SOwen Pan   verifyFormat("internal class Program\n"
1154d990cc45SOwen Pan                "{\n"
1155d990cc45SOwen Pan                "    bool AutoAllowKnownApps\n"
1156d990cc45SOwen Pan                "    {\n"
1157d990cc45SOwen Pan                "        get;\n"
1158d990cc45SOwen Pan                "        [Simple]\n"
1159d990cc45SOwen Pan                "        set;\n"
1160d990cc45SOwen Pan                "    }\n"
1161d990cc45SOwen Pan                "}",
1162d990cc45SOwen Pan                MicrosoftStyle);
1163e8c5fea2SJonathan Coe }
1164e8c5fea2SJonathan Coe 
1165f537a409SMarek Kurdej TEST_F(FormatTestCSharp, DefaultLiteral) {
1166f537a409SMarek Kurdej   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1167f537a409SMarek Kurdej 
1168f537a409SMarek Kurdej   verifyFormat(
1169f537a409SMarek Kurdej       "T[] InitializeArray<T>(int length, T initialValue = default) {}", Style);
1170f537a409SMarek Kurdej   verifyFormat("System.Numerics.Complex fillValue = default;", Style);
1171f537a409SMarek Kurdej   verifyFormat("int Value { get } = default;", Style);
1172f537a409SMarek Kurdej   verifyFormat("int Value { get } = default!;", Style);
1173f537a409SMarek Kurdej   verifyFormat(R"(//
1174f537a409SMarek Kurdej public record Person {
1175f537a409SMarek Kurdej   public string GetInit { get; init; } = default!;
1176f537a409SMarek Kurdej };)",
1177f537a409SMarek Kurdej                Style);
1178f537a409SMarek Kurdej   verifyFormat(R"(//
1179f537a409SMarek Kurdej public record Person {
1180f537a409SMarek Kurdej   public string GetSet { get; set; } = default!;
1181f537a409SMarek Kurdej };)",
1182f537a409SMarek Kurdej                Style);
1183f537a409SMarek Kurdej }
1184f537a409SMarek Kurdej 
1185e8c5fea2SJonathan Coe TEST_F(FormatTestCSharp, CSharpSpaces) {
1186e8c5fea2SJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1187e8c5fea2SJonathan Coe   Style.SpaceBeforeSquareBrackets = false;
1188e8c5fea2SJonathan Coe   Style.SpacesInSquareBrackets = false;
1189e8c5fea2SJonathan Coe   Style.SpaceBeforeCpp11BracedList = true;
1190e8c5fea2SJonathan Coe   Style.Cpp11BracedListStyle = false;
1191e8c5fea2SJonathan Coe   Style.SpacesInContainerLiterals = false;
119207c1978bSJonathan Coe   Style.SpaceAfterCStyleCast = false;
1193e8c5fea2SJonathan Coe 
1194e8c5fea2SJonathan Coe   verifyFormat(R"(new Car { "Door", 0.1 })", Style);
1195e8c5fea2SJonathan Coe   verifyFormat(R"(new Car { 0.1, "Door" })", Style);
1196e8c5fea2SJonathan Coe   verifyFormat(R"(new string[] { "A" })", Style);
1197e8c5fea2SJonathan Coe   verifyFormat(R"(new string[] {})", Style);
1198e8c5fea2SJonathan Coe   verifyFormat(R"(new Car { someVariableName })", Style);
1199e8c5fea2SJonathan Coe   verifyFormat(R"(new Car { someVariableName })", Style);
1200e8c5fea2SJonathan Coe   verifyFormat(R"(new Dictionary<string, string> { ["Key"] = "Value" };)",
1201e8c5fea2SJonathan Coe                Style);
1202e8c5fea2SJonathan Coe   verifyFormat(R"(Apply(x => x.Name, x => () => x.ID);)", Style);
1203e8c5fea2SJonathan Coe   verifyFormat(R"(bool[] xs = { true, true };)", Style);
1204ddc80637Ssstwcw   verifyIncompleteFormat(
1205ddc80637Ssstwcw       R"(taskContext.Factory.Run(async () => doThing(args);)", Style);
1206e8c5fea2SJonathan Coe   verifyFormat(R"(catch (TestException) when (innerFinallyExecuted))", Style);
1207548e540dSJonathan Coe   verifyFormat(R"(private float[,] Values;)", Style);
12085c917bd9SJonathan Coe   verifyFormat(R"(Result this[Index x] => Foo(x);)", Style);
1209548e540dSJonathan Coe 
121004336adaSJonathan Coe   verifyFormat(R"(char[,,] rawCharArray = MakeCharacterGrid();)", Style);
12117443f86eSJonathan Coe   verifyFormat(R"(var (key, value))", Style);
121204336adaSJonathan Coe 
1213047898c9SJonathan Coe   // `&&` is not seen as a reference.
1214047898c9SJonathan Coe   verifyFormat(R"(A == typeof(X) && someBool)", Style);
1215047898c9SJonathan Coe 
121607c1978bSJonathan Coe   // Not seen as a C-style cast.
121707c1978bSJonathan Coe   verifyFormat(R"(//
121807c1978bSJonathan Coe foreach ((A a, B b) in someList) {
121907c1978bSJonathan Coe })",
122007c1978bSJonathan Coe                Style);
122107c1978bSJonathan Coe 
1222a6794991SJonathan Coe   // space after lock in `lock (processes)`.
1223a6794991SJonathan Coe   verifyFormat("lock (process)", Style);
1224a6794991SJonathan Coe 
1225548e540dSJonathan Coe   Style.SpacesInSquareBrackets = true;
1226548e540dSJonathan Coe   verifyFormat(R"(private float[ , ] Values;)", Style);
12279c4afce7SJonathan Coe   verifyFormat(R"(string dirPath = args?[ 0 ];)", Style);
122804336adaSJonathan Coe   verifyFormat(R"(char[ ,, ] rawCharArray = MakeCharacterGrid();)", Style);
12295f104a80SŁukasz Krawczyk 
12305f104a80SŁukasz Krawczyk   // Method returning tuple
12315f104a80SŁukasz Krawczyk   verifyFormat(R"(public (string name, int age) methodTuple() {})", Style);
12325f104a80SŁukasz Krawczyk   verifyFormat(R"(private (string name, int age) methodTuple() {})", Style);
12335f104a80SŁukasz Krawczyk   verifyFormat(R"(protected (string name, int age) methodTuple() {})", Style);
12345f104a80SŁukasz Krawczyk   verifyFormat(R"(virtual (string name, int age) methodTuple() {})", Style);
12355f104a80SŁukasz Krawczyk   verifyFormat(R"(extern (string name, int age) methodTuple() {})", Style);
12365f104a80SŁukasz Krawczyk   verifyFormat(R"(static (string name, int age) methodTuple() {})", Style);
12375f104a80SŁukasz Krawczyk   verifyFormat(R"(internal (string name, int age) methodTuple() {})", Style);
12385f104a80SŁukasz Krawczyk   verifyFormat(R"(abstract (string name, int age) methodTuple() {})", Style);
12395f104a80SŁukasz Krawczyk   verifyFormat(R"(sealed (string name, int age) methodTuple() {})", Style);
12405f104a80SŁukasz Krawczyk   verifyFormat(R"(override (string name, int age) methodTuple() {})", Style);
12415f104a80SŁukasz Krawczyk   verifyFormat(R"(async (string name, int age) methodTuple() {})", Style);
12425f104a80SŁukasz Krawczyk   verifyFormat(R"(unsafe (string name, int age) methodTuple() {})", Style);
124363395cb0Smydeveloperday 
124463395cb0Smydeveloperday   Style.SpacesInSquareBrackets = false;
124563395cb0Smydeveloperday   Style.SpaceBeforeSquareBrackets = true;
124663395cb0Smydeveloperday   verifyFormat("return a is [1, 2, 3];", Style);
124763395cb0Smydeveloperday   verifyFormat("return a is [..];", Style);
124863395cb0Smydeveloperday   Style.SpaceBeforeSquareBrackets = false;
124963395cb0Smydeveloperday   verifyFormat("return a is [1, 2, 3];", Style);
125063395cb0Smydeveloperday   verifyFormat("return a is [..];", Style);
12515f52a93bSJonathan Coe }
12525f52a93bSJonathan Coe 
12535f52a93bSJonathan Coe TEST_F(FormatTestCSharp, CSharpNullableTypes) {
12545f52a93bSJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
12555f52a93bSJonathan Coe   Style.SpacesInSquareBrackets = false;
12565f52a93bSJonathan Coe 
1257fe61bc1aSJonathan Coe   verifyFormat(R"(//
1258fe61bc1aSJonathan Coe public class A {
12599520bf14SJonathan Coe   void foo() {
12609520bf14SJonathan Coe     int? value = some.bar();
12619520bf14SJonathan Coe   }
1262fe61bc1aSJonathan Coe })",
1263fe61bc1aSJonathan Coe                Style); // int? is nullable not a conditional expression.
1264fe61bc1aSJonathan Coe 
1265fe61bc1aSJonathan Coe   verifyFormat(R"(void foo(int? x, int? y, int? z) {})",
1266fe61bc1aSJonathan Coe                Style); // Nullables in function definitions.
1267fe61bc1aSJonathan Coe 
12685f52a93bSJonathan Coe   verifyFormat(R"(public float? Value;)", Style); // no space before `?`.
1269fe61bc1aSJonathan Coe 
12705f52a93bSJonathan Coe   verifyFormat(R"(int?[] arr = new int?[10];)",
12715f52a93bSJonathan Coe                Style); // An array of a nullable type.
12721fb9c298SJonathan Coe 
12731fb9c298SJonathan Coe   verifyFormat(R"(var x = (int?)y;)", Style); // Cast to a nullable type.
12741fb9c298SJonathan Coe 
12751fb9c298SJonathan Coe   verifyFormat(R"(var x = new MyContainer<int?>();)", Style); // Generics.
1276ec725b30SEliza Velasquez 
1277ec725b30SEliza Velasquez   verifyFormat(R"(//
1278ec725b30SEliza Velasquez public interface I {
1279ec725b30SEliza Velasquez   int? Function();
1280ec725b30SEliza Velasquez })",
1281ec725b30SEliza Velasquez                Style); // Interface methods.
1282ec725b30SEliza Velasquez 
1283ec725b30SEliza Velasquez   Style.ColumnLimit = 10;
1284ec725b30SEliza Velasquez   verifyFormat(R"(//
1285ec725b30SEliza Velasquez public VeryLongType? Function(
1286ec725b30SEliza Velasquez     int arg1,
1287ec725b30SEliza Velasquez     int arg2) {
1288ec725b30SEliza Velasquez   //
1289ec725b30SEliza Velasquez })",
1290ec725b30SEliza Velasquez                Style); // ? sticks with identifier.
12912bd6974aSJonathan Coe }
12922bd6974aSJonathan Coe 
1293736fef97SJonathan Coe TEST_F(FormatTestCSharp, CSharpArraySubscripts) {
1294736fef97SJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1295736fef97SJonathan Coe 
1296736fef97SJonathan Coe   // Do not format array subscript operators as attributes.
1297b28ed9ceSJonathan Coe   verifyFormat(R"(//
1298b28ed9ceSJonathan Coe if (someThings[index].Contains(myThing)) {
1299b28ed9ceSJonathan Coe })",
1300b28ed9ceSJonathan Coe                Style);
1301b28ed9ceSJonathan Coe 
1302b28ed9ceSJonathan Coe   verifyFormat(R"(//
1303b28ed9ceSJonathan Coe if (someThings[i][j][k].Contains(myThing)) {
1304b28ed9ceSJonathan Coe })",
1305b28ed9ceSJonathan Coe                Style);
1306736fef97SJonathan Coe }
1307736fef97SJonathan Coe 
1308dcbcec48SJonathan Coe TEST_F(FormatTestCSharp, CSharpGenericTypeConstraints) {
1309dcbcec48SJonathan Coe   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1310dcbcec48SJonathan Coe 
131100dc97f1Smydeveloperday   EXPECT_TRUE(Style.BraceWrapping.SplitEmptyRecord);
131200dc97f1Smydeveloperday 
131300dc97f1Smydeveloperday   verifyFormat("class ItemFactory<T>\n"
131400dc97f1Smydeveloperday                "    where T : new() {\n"
131500dc97f1Smydeveloperday                "}",
1316ece7e95fSmydeveloperday                Style);
1317dcbcec48SJonathan Coe 
1318e3acfbc4Ssstwcw   // When the "where" line is not to be formatted, following lines should not
1319e3acfbc4Ssstwcw   // take on its indentation.
1320e3acfbc4Ssstwcw   verifyFormat("class ItemFactory<T>\n"
1321e3acfbc4Ssstwcw                "    where T : new() {\n"
1322e3acfbc4Ssstwcw                "  int f() {}\n"
1323e3acfbc4Ssstwcw                "}",
1324e3acfbc4Ssstwcw                "class ItemFactory<T>\n"
1325e3acfbc4Ssstwcw                "    where T : new() {\n"
1326e3acfbc4Ssstwcw                "  int f() {}\n"
1327e3acfbc4Ssstwcw                "}",
1328e3acfbc4Ssstwcw                Style, {tooling::Range(43, 13)});
1329e3acfbc4Ssstwcw 
133000dc97f1Smydeveloperday   verifyFormat("class Dictionary<TKey, TVal>\n"
133100dc97f1Smydeveloperday                "    where TKey : IComparable<TKey>\n"
133200dc97f1Smydeveloperday                "    where TVal : IMyInterface {\n"
133300dc97f1Smydeveloperday                "  public void MyMethod<T>(T t)\n"
133400dc97f1Smydeveloperday                "      where T : IMyInterface {\n"
133500dc97f1Smydeveloperday                "    doThing();\n"
133600dc97f1Smydeveloperday                "  }\n"
133700dc97f1Smydeveloperday                "}",
1338dcbcec48SJonathan Coe                Style);
133978e2a3c6SJonathan Coe 
134000dc97f1Smydeveloperday   verifyFormat("class ItemFactory<T>\n"
134100dc97f1Smydeveloperday                "    where T : new(), IAnInterface<T>, IAnotherInterface<T>, "
134200dc97f1Smydeveloperday                "IAnotherInterfaceStill<T> {\n"
134300dc97f1Smydeveloperday                "}",
1344d1b412aeSJonathan Coe                Style);
1345d1b412aeSJonathan Coe 
1346d1b412aeSJonathan Coe   Style.ColumnLimit = 50; // Force lines to be wrapped.
1347d1b412aeSJonathan Coe   verifyFormat(R"(//
1348d1b412aeSJonathan Coe class ItemFactory<T, U>
1349d1b412aeSJonathan Coe     where T : new(),
1350d1b412aeSJonathan Coe               IAnInterface<T>,
1351d1b412aeSJonathan Coe               IAnotherInterface<T, U>,
135200dc97f1Smydeveloperday               IAnotherInterfaceStill<T, U> {
135300dc97f1Smydeveloperday })",
135478e2a3c6SJonathan Coe                Style);
13550574030cSKrasimir Georgiev 
13560574030cSKrasimir Georgiev   // In other languages `where` can be used as a normal identifier.
13570574030cSKrasimir Georgiev   // This example is in C++!
13580574030cSKrasimir Georgiev   verifyFormat(R"(//
13590574030cSKrasimir Georgiev class A {
13600574030cSKrasimir Georgiev   int f(int where) {}
13610574030cSKrasimir Georgiev };)",
13620574030cSKrasimir Georgiev                getGoogleStyle(FormatStyle::LK_Cpp));
1363dcbcec48SJonathan Coe }
1364dcbcec48SJonathan Coe 
1365ed367b9dSmydeveloperday TEST_F(FormatTestCSharp, CSharpAfterEnum) {
1366ed367b9dSmydeveloperday   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1367ed367b9dSmydeveloperday   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1368ed367b9dSmydeveloperday   Style.BraceWrapping.AfterEnum = false;
1369ed367b9dSmydeveloperday   Style.AllowShortEnumsOnASingleLine = false;
1370ed367b9dSmydeveloperday 
1371ed367b9dSmydeveloperday   verifyFormat("enum MyEnum {\n"
1372ed367b9dSmydeveloperday                "  Foo,\n"
1373ed367b9dSmydeveloperday                "  Bar,\n"
1374ed367b9dSmydeveloperday                "}",
1375ed367b9dSmydeveloperday                Style);
1376ed367b9dSmydeveloperday   verifyFormat("internal enum MyEnum {\n"
1377ed367b9dSmydeveloperday                "  Foo,\n"
1378ed367b9dSmydeveloperday                "  Bar,\n"
1379ed367b9dSmydeveloperday                "}",
1380ed367b9dSmydeveloperday                Style);
1381ed367b9dSmydeveloperday   verifyFormat("public enum MyEnum {\n"
1382ed367b9dSmydeveloperday                "  Foo,\n"
1383ed367b9dSmydeveloperday                "  Bar,\n"
1384ed367b9dSmydeveloperday                "}",
1385ed367b9dSmydeveloperday                Style);
1386ed367b9dSmydeveloperday   verifyFormat("protected enum MyEnum {\n"
1387ed367b9dSmydeveloperday                "  Foo,\n"
1388ed367b9dSmydeveloperday                "  Bar,\n"
1389ed367b9dSmydeveloperday                "}",
1390ed367b9dSmydeveloperday                Style);
1391ed367b9dSmydeveloperday   verifyFormat("private enum MyEnum {\n"
1392ed367b9dSmydeveloperday                "  Foo,\n"
1393ed367b9dSmydeveloperday                "  Bar,\n"
1394ed367b9dSmydeveloperday                "}",
1395ed367b9dSmydeveloperday                Style);
1396ed367b9dSmydeveloperday 
1397ed367b9dSmydeveloperday   Style.BraceWrapping.AfterEnum = true;
1398ed367b9dSmydeveloperday   Style.AllowShortEnumsOnASingleLine = false;
1399ed367b9dSmydeveloperday 
1400ed367b9dSmydeveloperday   verifyFormat("enum MyEnum\n"
1401ed367b9dSmydeveloperday                "{\n"
1402ed367b9dSmydeveloperday                "  Foo,\n"
1403ed367b9dSmydeveloperday                "  Bar,\n"
1404ed367b9dSmydeveloperday                "}",
1405ed367b9dSmydeveloperday                Style);
1406ed367b9dSmydeveloperday   verifyFormat("internal enum MyEnum\n"
1407ed367b9dSmydeveloperday                "{\n"
1408ed367b9dSmydeveloperday                "  Foo,\n"
1409ed367b9dSmydeveloperday                "  Bar,\n"
1410ed367b9dSmydeveloperday                "}",
1411ed367b9dSmydeveloperday                Style);
1412ed367b9dSmydeveloperday   verifyFormat("public enum MyEnum\n"
1413ed367b9dSmydeveloperday                "{\n"
1414ed367b9dSmydeveloperday                "  Foo,\n"
1415ed367b9dSmydeveloperday                "  Bar,\n"
1416ed367b9dSmydeveloperday                "}",
1417ed367b9dSmydeveloperday                Style);
1418ed367b9dSmydeveloperday   verifyFormat("protected enum MyEnum\n"
1419ed367b9dSmydeveloperday                "{\n"
1420ed367b9dSmydeveloperday                "  Foo,\n"
1421ed367b9dSmydeveloperday                "  Bar,\n"
1422ed367b9dSmydeveloperday                "}",
1423ed367b9dSmydeveloperday                Style);
1424ed367b9dSmydeveloperday   verifyFormat("private enum MyEnum\n"
1425ed367b9dSmydeveloperday                "{\n"
1426ed367b9dSmydeveloperday                "  Foo,\n"
1427ed367b9dSmydeveloperday                "  Bar,\n"
1428ed367b9dSmydeveloperday                "}",
1429ed367b9dSmydeveloperday                Style);
1430ed367b9dSmydeveloperday   verifyFormat("/* Foo */ private enum MyEnum\n"
1431ed367b9dSmydeveloperday                "{\n"
1432ed367b9dSmydeveloperday                "  Foo,\n"
1433ed367b9dSmydeveloperday                "  Bar,\n"
1434ed367b9dSmydeveloperday                "}",
1435ed367b9dSmydeveloperday                Style);
1436ed367b9dSmydeveloperday   verifyFormat("/* Foo */ /* Bar */ private enum MyEnum\n"
1437ed367b9dSmydeveloperday                "{\n"
1438ed367b9dSmydeveloperday                "  Foo,\n"
1439ed367b9dSmydeveloperday                "  Bar,\n"
1440ed367b9dSmydeveloperday                "}",
1441ed367b9dSmydeveloperday                Style);
1442ed367b9dSmydeveloperday }
1443ed367b9dSmydeveloperday 
1444ed367b9dSmydeveloperday TEST_F(FormatTestCSharp, CSharpAfterClass) {
1445ed367b9dSmydeveloperday   FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
1446ed367b9dSmydeveloperday   Style.BreakBeforeBraces = FormatStyle::BS_Custom;
1447ed367b9dSmydeveloperday   Style.BraceWrapping.AfterClass = false;
1448ed367b9dSmydeveloperday 
1449ed367b9dSmydeveloperday   verifyFormat("class MyClass {\n"
1450ed367b9dSmydeveloperday                "  int a;\n"
1451ed367b9dSmydeveloperday                "  int b;\n"
1452ed367b9dSmydeveloperday                "}",
1453ed367b9dSmydeveloperday                Style);
1454ed367b9dSmydeveloperday   verifyFormat("internal class MyClass {\n"
1455ed367b9dSmydeveloperday                "  int a;\n"
1456ed367b9dSmydeveloperday                "  int b;\n"
1457ed367b9dSmydeveloperday                "}",
1458ed367b9dSmydeveloperday                Style);
1459ed367b9dSmydeveloperday   verifyFormat("public class MyClass {\n"
1460ed367b9dSmydeveloperday                "  int a;\n"
1461ed367b9dSmydeveloperday                "  int b;\n"
1462ed367b9dSmydeveloperday                "}",
1463ed367b9dSmydeveloperday                Style);
1464ed367b9dSmydeveloperday   verifyFormat("protected class MyClass {\n"
1465ed367b9dSmydeveloperday                "  int a;\n"
1466ed367b9dSmydeveloperday                "  int b;\n"
1467ed367b9dSmydeveloperday                "}",
1468ed367b9dSmydeveloperday                Style);
1469ed367b9dSmydeveloperday   verifyFormat("private class MyClass {\n"
1470ed367b9dSmydeveloperday                "  int a;\n"
1471ed367b9dSmydeveloperday                "  int b;\n"
1472ed367b9dSmydeveloperday                "}",
1473ed367b9dSmydeveloperday                Style);
1474ed367b9dSmydeveloperday 
1475ed367b9dSmydeveloperday   verifyFormat("interface Interface {\n"
1476ed367b9dSmydeveloperday                "  int a;\n"
1477ed367b9dSmydeveloperday                "  int b;\n"
1478ed367b9dSmydeveloperday                "}",
1479ed367b9dSmydeveloperday                Style);
1480ed367b9dSmydeveloperday   verifyFormat("internal interface Interface {\n"
1481ed367b9dSmydeveloperday                "  int a;\n"
1482ed367b9dSmydeveloperday                "  int b;\n"
1483ed367b9dSmydeveloperday                "}",
1484ed367b9dSmydeveloperday                Style);
1485ed367b9dSmydeveloperday   verifyFormat("public interface Interface {\n"
1486ed367b9dSmydeveloperday                "  int a;\n"
1487ed367b9dSmydeveloperday                "  int b;\n"
1488ed367b9dSmydeveloperday                "}",
1489ed367b9dSmydeveloperday                Style);
1490ed367b9dSmydeveloperday   verifyFormat("protected interface Interface {\n"
1491ed367b9dSmydeveloperday                "  int a;\n"
1492ed367b9dSmydeveloperday                "  int b;\n"
1493ed367b9dSmydeveloperday                "}",
1494ed367b9dSmydeveloperday                Style);
1495ed367b9dSmydeveloperday   verifyFormat("private interface Interface {\n"
1496ed367b9dSmydeveloperday                "  int a;\n"
1497ed367b9dSmydeveloperday                "  int b;\n"
1498ed367b9dSmydeveloperday                "}",
1499ed367b9dSmydeveloperday                Style);
1500ed367b9dSmydeveloperday 
1501ed367b9dSmydeveloperday   Style.BraceWrapping.AfterClass = true;
1502ed367b9dSmydeveloperday 
1503ed367b9dSmydeveloperday   verifyFormat("class MyClass\n"
1504ed367b9dSmydeveloperday                "{\n"
1505ed367b9dSmydeveloperday                "  int a;\n"
1506ed367b9dSmydeveloperday                "  int b;\n"
1507ed367b9dSmydeveloperday                "}",
1508ed367b9dSmydeveloperday                Style);
1509ed367b9dSmydeveloperday   verifyFormat("internal class MyClass\n"
1510ed367b9dSmydeveloperday                "{\n"
1511ed367b9dSmydeveloperday                "  int a;\n"
1512ed367b9dSmydeveloperday                "  int b;\n"
1513ed367b9dSmydeveloperday                "}",
1514ed367b9dSmydeveloperday                Style);
1515ed367b9dSmydeveloperday   verifyFormat("public class MyClass\n"
1516ed367b9dSmydeveloperday                "{\n"
1517ed367b9dSmydeveloperday                "  int a;\n"
1518ed367b9dSmydeveloperday                "  int b;\n"
1519ed367b9dSmydeveloperday                "}",
1520ed367b9dSmydeveloperday                Style);
1521ed367b9dSmydeveloperday   verifyFormat("protected class MyClass\n"
1522ed367b9dSmydeveloperday                "{\n"
1523ed367b9dSmydeveloperday                "  int a;\n"
1524ed367b9dSmydeveloperday                "  int b;\n"
1525ed367b9dSmydeveloperday                "}",
1526ed367b9dSmydeveloperday                Style);
1527ed367b9dSmydeveloperday   verifyFormat("private class MyClass\n"
1528ed367b9dSmydeveloperday                "{\n"
1529ed367b9dSmydeveloperday                "  int a;\n"
1530ed367b9dSmydeveloperday                "  int b;\n"
1531ed367b9dSmydeveloperday                "}",
1532ed367b9dSmydeveloperday                Style);
1533ed367b9dSmydeveloperday 
1534ed367b9dSmydeveloperday   verifyFormat("interface MyInterface\n"
1535ed367b9dSmydeveloperday                "{\n"
1536ed367b9dSmydeveloperday                "  int a;\n"
1537ed367b9dSmydeveloperday                "  int b;\n"
1538ed367b9dSmydeveloperday                "}",
1539ed367b9dSmydeveloperday                Style);
1540ed367b9dSmydeveloperday   verifyFormat("internal interface MyInterface\n"
1541ed367b9dSmydeveloperday                "{\n"
1542ed367b9dSmydeveloperday                "  int a;\n"
1543ed367b9dSmydeveloperday                "  int b;\n"
1544ed367b9dSmydeveloperday                "}",
1545ed367b9dSmydeveloperday                Style);
1546ed367b9dSmydeveloperday   verifyFormat("public interface MyInterface\n"
1547ed367b9dSmydeveloperday                "{\n"
1548ed367b9dSmydeveloperday                "  int a;\n"
1549ed367b9dSmydeveloperday                "  int b;\n"
1550ed367b9dSmydeveloperday                "}",
1551ed367b9dSmydeveloperday                Style);
1552ed367b9dSmydeveloperday   verifyFormat("protected interface MyInterface\n"
1553ed367b9dSmydeveloperday                "{\n"
1554ed367b9dSmydeveloperday                "  int a;\n"
1555ed367b9dSmydeveloperday                "  int b;\n"
1556ed367b9dSmydeveloperday                "}",
1557ed367b9dSmydeveloperday                Style);
1558ed367b9dSmydeveloperday   verifyFormat("private interface MyInterface\n"
1559ed367b9dSmydeveloperday                "{\n"
1560ed367b9dSmydeveloperday                "  int a;\n"
1561ed367b9dSmydeveloperday                "  int b;\n"
1562ed367b9dSmydeveloperday                "}",
1563ed367b9dSmydeveloperday                Style);
1564ed367b9dSmydeveloperday   verifyFormat("/* Foo */ private interface MyInterface\n"
1565ed367b9dSmydeveloperday                "{\n"
1566ed367b9dSmydeveloperday                "  int a;\n"
1567ed367b9dSmydeveloperday                "  int b;\n"
1568ed367b9dSmydeveloperday                "}",
1569ed367b9dSmydeveloperday                Style);
1570ed367b9dSmydeveloperday   verifyFormat("/* Foo */ /* Bar */ private interface MyInterface\n"
1571ed367b9dSmydeveloperday                "{\n"
1572ed367b9dSmydeveloperday                "  int a;\n"
1573ed367b9dSmydeveloperday                "  int b;\n"
1574ed367b9dSmydeveloperday                "}",
1575ed367b9dSmydeveloperday                Style);
1576ed367b9dSmydeveloperday }
1577ed367b9dSmydeveloperday 
15786e58d14eSmydeveloperday TEST_F(FormatTestCSharp, NamespaceIndentation) {
15796e58d14eSmydeveloperday   FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
15806e58d14eSmydeveloperday   Style.NamespaceIndentation = FormatStyle::NI_None;
15816e58d14eSmydeveloperday 
15826e58d14eSmydeveloperday   verifyFormat("namespace A\n"
15836e58d14eSmydeveloperday                "{\n"
15846e58d14eSmydeveloperday                "public interface Name1\n"
15856e58d14eSmydeveloperday                "{\n"
15866e58d14eSmydeveloperday                "}\n"
158788934a82SOwen Pan                "}",
15886e58d14eSmydeveloperday                Style);
15896e58d14eSmydeveloperday 
15906e58d14eSmydeveloperday   verifyFormat("namespace A.B\n"
15916e58d14eSmydeveloperday                "{\n"
15926e58d14eSmydeveloperday                "public interface Name1\n"
15936e58d14eSmydeveloperday                "{\n"
15946e58d14eSmydeveloperday                "}\n"
159588934a82SOwen Pan                "}",
15966e58d14eSmydeveloperday                Style);
15976e58d14eSmydeveloperday 
15986e58d14eSmydeveloperday   Style.NamespaceIndentation = FormatStyle::NI_Inner;
15996e58d14eSmydeveloperday 
16006e58d14eSmydeveloperday   verifyFormat("namespace A\n"
16016e58d14eSmydeveloperday                "{\n"
16026e58d14eSmydeveloperday                "namespace B\n"
16036e58d14eSmydeveloperday                "{\n"
16046e58d14eSmydeveloperday                "    public interface Name1\n"
16056e58d14eSmydeveloperday                "    {\n"
16066e58d14eSmydeveloperday                "    }\n"
16076e58d14eSmydeveloperday                "}\n"
160888934a82SOwen Pan                "}",
16096e58d14eSmydeveloperday                Style);
16106e58d14eSmydeveloperday 
16116e58d14eSmydeveloperday   Style.NamespaceIndentation = FormatStyle::NI_All;
16126e58d14eSmydeveloperday 
16136e58d14eSmydeveloperday   verifyFormat("namespace A.B\n"
16146e58d14eSmydeveloperday                "{\n"
16156e58d14eSmydeveloperday                "    public interface Name1\n"
16166e58d14eSmydeveloperday                "    {\n"
16176e58d14eSmydeveloperday                "    }\n"
161888934a82SOwen Pan                "}",
16196e58d14eSmydeveloperday                Style);
16206e58d14eSmydeveloperday 
16216e58d14eSmydeveloperday   verifyFormat("namespace A\n"
16226e58d14eSmydeveloperday                "{\n"
16236e58d14eSmydeveloperday                "    namespace B\n"
16246e58d14eSmydeveloperday                "    {\n"
16256e58d14eSmydeveloperday                "        public interface Name1\n"
16266e58d14eSmydeveloperday                "        {\n"
16276e58d14eSmydeveloperday                "        }\n"
16286e58d14eSmydeveloperday                "    }\n"
162988934a82SOwen Pan                "}",
16306e58d14eSmydeveloperday                Style);
16316e58d14eSmydeveloperday }
16326e58d14eSmydeveloperday 
1633ebed0ca7Smydeveloperday TEST_F(FormatTestCSharp, SwitchExpression) {
1634ebed0ca7Smydeveloperday   FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
1635ebed0ca7Smydeveloperday   verifyFormat("int x = a switch {\n"
1636ebed0ca7Smydeveloperday                "    1 => (0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0),\n"
1637ebed0ca7Smydeveloperday                "    2 => 1,\n"
1638ebed0ca7Smydeveloperday                "    _ => 2\n"
163988934a82SOwen Pan                "};",
1640ebed0ca7Smydeveloperday                Style);
1641ebed0ca7Smydeveloperday }
1642ebed0ca7Smydeveloperday 
1643a94aab12Smydeveloperday TEST_F(FormatTestCSharp, EmptyShortBlock) {
1644a94aab12Smydeveloperday   auto Style = getLLVMStyle();
1645a94aab12Smydeveloperday   Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty;
1646a94aab12Smydeveloperday 
1647a94aab12Smydeveloperday   verifyFormat("try {\n"
1648a94aab12Smydeveloperday                "  doA();\n"
1649a94aab12Smydeveloperday                "} catch (Exception e) {\n"
1650a94aab12Smydeveloperday                "  e.printStackTrace();\n"
165188934a82SOwen Pan                "}",
1652a94aab12Smydeveloperday                Style);
1653a94aab12Smydeveloperday 
1654a94aab12Smydeveloperday   verifyFormat("try {\n"
1655a94aab12Smydeveloperday                "  doA();\n"
165688934a82SOwen Pan                "} catch (Exception e) {}",
1657a94aab12Smydeveloperday                Style);
1658a94aab12Smydeveloperday }
1659a94aab12Smydeveloperday 
16607af11989SMarek Kurdej TEST_F(FormatTestCSharp, ShortFunctions) {
16617af11989SMarek Kurdej   FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp);
16627af11989SMarek Kurdej   Style.NamespaceIndentation = FormatStyle::NI_All;
16637af11989SMarek Kurdej   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
16647af11989SMarek Kurdej   verifyFormat("interface Interface {\n"
16657af11989SMarek Kurdej                "  void f() { return; }\n"
16667af11989SMarek Kurdej                "};",
16677af11989SMarek Kurdej                Style);
16687af11989SMarek Kurdej   verifyFormat("public interface Interface {\n"
16697af11989SMarek Kurdej                "  void f() { return; }\n"
16707af11989SMarek Kurdej                "};",
16717af11989SMarek Kurdej                Style);
16727af11989SMarek Kurdej   verifyFormat("namespace {\n"
16737af11989SMarek Kurdej                "  void f() {\n"
16747af11989SMarek Kurdej                "    return;\n"
16757af11989SMarek Kurdej                "  }\n"
16767af11989SMarek Kurdej                "};",
16777af11989SMarek Kurdej                Style);
16787af11989SMarek Kurdej   // "union" is not a keyword in C#.
16797af11989SMarek Kurdej   verifyFormat("namespace union {\n"
16807af11989SMarek Kurdej                "  void f() {\n"
16817af11989SMarek Kurdej                "    return;\n"
16827af11989SMarek Kurdej                "  }\n"
16837af11989SMarek Kurdej                "};",
16847af11989SMarek Kurdej                Style);
16857af11989SMarek Kurdej }
16867af11989SMarek Kurdej 
1687a72609caSSam McCall TEST_F(FormatTestCSharp, BrokenBrackets) {
1688a72609caSSam McCall   EXPECT_NE("", format("int where b <")); // reduced from crasher
1689a72609caSSam McCall }
1690a72609caSSam McCall 
1691b5bcdb5cSOwen Pan TEST_F(FormatTestCSharp, GotoCaseLabel) {
1692*d005be33SOwen Pan   verifyFormat("switch (i)\n"
1693*d005be33SOwen Pan                "{\n"
1694*d005be33SOwen Pan                "case 0:\n"
1695*d005be33SOwen Pan                "    goto case 1;\n"
1696*d005be33SOwen Pan                "case 1:\n"
1697*d005be33SOwen Pan                "    j = 0;\n"
1698*d005be33SOwen Pan                "    {\n"
1699*d005be33SOwen Pan                "        break;\n"
1700*d005be33SOwen Pan                "    }\n"
1701*d005be33SOwen Pan                "}",
1702*d005be33SOwen Pan                "switch (i) {\n"
1703b5bcdb5cSOwen Pan                "case 0:\n"
1704b5bcdb5cSOwen Pan                "  goto case 1;\n"
1705b5bcdb5cSOwen Pan                "case 1:\n"
1706b5bcdb5cSOwen Pan                "  j = 0;\n"
1707b5bcdb5cSOwen Pan                "  {\n"
1708b5bcdb5cSOwen Pan                "    break;\n"
1709b5bcdb5cSOwen Pan                "  }\n"
1710b5bcdb5cSOwen Pan                "}");
1711b5bcdb5cSOwen Pan }
1712b5bcdb5cSOwen Pan 
1713ddc80637Ssstwcw } // namespace
1714ddc80637Ssstwcw } // namespace test
1715cbb726d0SPaul Hoad } // namespace format
1716ddc80637Ssstwcw } // namespace clang
1717