xref: /llvm-project/clang/unittests/Format/FormatTestCSharp.cpp (revision cbb726d0c5384c029196d4c7160fa91dc3b3f0da)
1 //===- unittest/Format/FormatTestCSharp.cpp - Formatting tests for CSharp -===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "FormatTestUtils.h"
10 #include "clang/Format/Format.h"
11 #include "llvm/Support/Debug.h"
12 #include "gtest/gtest.h"
13 
14 #define DEBUG_TYPE "format-test"
15 
16 namespace clang {
17 namespace format {
18 
19 class FormatTestCSharp : public ::testing::Test {
20 protected:
21   static std::string format(llvm::StringRef Code, unsigned Offset,
22                             unsigned Length, const FormatStyle &Style) {
23     LLVM_DEBUG(llvm::errs() << "---\n");
24     LLVM_DEBUG(llvm::errs() << Code << "\n\n");
25     std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
26     tooling::Replacements Replaces = reformat(Style, Code, Ranges);
27     auto Result = applyAllReplacements(Code, Replaces);
28     EXPECT_TRUE(static_cast<bool>(Result));
29     LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
30     return *Result;
31   }
32 
33   static std::string
34   format(llvm::StringRef Code,
35          const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_CSharp)) {
36     return format(Code, 0, Code.size(), Style);
37   }
38 
39   static FormatStyle getStyleWithColumns(unsigned ColumnLimit) {
40     FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
41     Style.ColumnLimit = ColumnLimit;
42     return Style;
43   }
44 
45   static void verifyFormat(
46       llvm::StringRef Code,
47       const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_CSharp)) {
48     EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
49     EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
50   }
51 };
52 
53 TEST_F(FormatTestCSharp, CSharpClass) {
54   verifyFormat("public class SomeClass {\n"
55                "  void f() {}\n"
56                "  int g() { return 0; }\n"
57                "  void h() {\n"
58                "    while (true) f();\n"
59                "    for (;;) f();\n"
60                "    if (true) f();\n"
61                "  }\n"
62                "}");
63 }
64 
65 TEST_F(FormatTestCSharp, AccessModifiers) {
66   verifyFormat("public String toString() {}");
67   verifyFormat("private String toString() {}");
68   verifyFormat("protected String toString() {}");
69   verifyFormat("internal String toString() {}");
70 
71   verifyFormat("public override String toString() {}");
72   verifyFormat("private override String toString() {}");
73   verifyFormat("protected override String toString() {}");
74   verifyFormat("internal override String toString() {}");
75 
76   verifyFormat("internal static String toString() {}");
77 }
78 
79 TEST_F(FormatTestCSharp, NoStringLiteralBreaks) {
80   verifyFormat("foo("
81                "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
82                "aaaaaa\");");
83 }
84 
85 TEST_F(FormatTestCSharp, CSharpVerbatiumStringLiterals) {
86   verifyFormat("foo(@\"aaaaaaaa\\abc\\aaaa\");");
87   // @"ABC\" + ToString("B") - handle embedded \ in literal string at
88   // the end
89   //
90   /*
91    * After removal of Lexer change we are currently not able
92    * To handle these cases
93    verifyFormat("string s = @\"ABC\\\" + ToString(\"B\");");
94    verifyFormat("string s = @\"ABC\"\"DEF\"\"GHI\"");
95    verifyFormat("string s = @\"ABC\"\"DEF\"\"\"");
96    verifyFormat("string s = @\"ABC\"\"DEF\"\"\" + abc");
97   */
98 }
99 
100 TEST_F(FormatTestCSharp, CSharpInterpolatedStringLiterals) {
101   verifyFormat("foo($\"aaaaaaaa{aaa}aaaa\");");
102   verifyFormat("foo($\"aaaa{A}\");");
103   verifyFormat(
104       "foo($\"aaaa{A}"
105       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");");
106   verifyFormat("Name = $\"{firstName} {lastName}\";");
107 
108   // $"ABC\" + ToString("B") - handle embedded \ in literal string at
109   // the end
110   verifyFormat("string s = $\"A{abc}BC\" + ToString(\"B\");");
111   verifyFormat("$\"{domain}\\\\{user}\"");
112   verifyFormat(
113       "var verbatimInterpolated = $@\"C:\\Users\\{userName}\\Documents\\\";");
114 }
115 
116 TEST_F(FormatTestCSharp, CSharpFatArrows) {
117   verifyFormat("Task serverTask = Task.Run(async() => {");
118   verifyFormat("public override string ToString() => \"{Name}\\{Age}\";");
119 }
120 
121 TEST_F(FormatTestCSharp, CSharpNullConditional) {
122   verifyFormat(
123       "public Person(string firstName, string lastName, int? age=null)");
124 
125   verifyFormat("switch(args?.Length)");
126 
127   verifyFormat("public static void Main(string[] args) { string dirPath "
128                "= args?[0]; }");
129 }
130 
131 TEST_F(FormatTestCSharp, Attributes) {
132   verifyFormat("[STAThread]\n"
133                "static void\n"
134                "Main(string[] args) {}");
135 
136   verifyFormat("[TestMethod]\n"
137                "private class Test {}");
138 
139   verifyFormat("[TestMethod]\n"
140                "protected class Test {}");
141 
142   verifyFormat("[TestMethod]\n"
143                "internal class Test {}");
144 
145   verifyFormat("[TestMethod]\n"
146                "class Test {}");
147 
148   verifyFormat("[TestMethod]\n"
149                "[DeploymentItem(\"Test.txt\")]\n"
150                "public class Test {}");
151 
152   verifyFormat("[System.AttributeUsage(System.AttributeTargets.Method)]\n"
153                "[System.Runtime.InteropServices.ComVisible(true)]\n"
154                "public sealed class STAThreadAttribute : Attribute {}");
155 
156   verifyFormat("[Verb(\"start\", HelpText = \"Starts the server listening on "
157                "provided port\")]\n"
158                "class Test {}");
159 
160   verifyFormat("[TestMethod]\n"
161                "public string Host {\n  set;\n  get;\n}");
162 
163   verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server "
164                "listening on provided host\")]\n"
165                "public string Host {\n  set;\n  get;\n}");
166 }
167 
168 TEST_F(FormatTestCSharp, CSharpRegions) {
169   verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa "
170                "aaaaaaaaaaaaaaa long region");
171 }
172 
173 TEST_F(FormatTestCSharp, CSharpKeyWordEscaping) {
174   verifyFormat("public enum var { none, @string, bool, @enum }");
175 }
176 
177 TEST_F(FormatTestCSharp, CSharpNullCoalescing) {
178   verifyFormat("var test = ABC ?? DEF");
179   verifyFormat("string myname = name ?? \"ABC\";");
180   verifyFormat("return _name ?? \"DEF\";");
181 }
182 
183 } // namespace format
184 } // end namespace clang
185