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