blob: 801adb28bd9127ccbaf35b5539401d486f88b497 [file] [log] [blame]
Paul Hoadcbb726d2019-03-21 13:09:22 +00001//===- 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
16namespace clang {
17namespace format {
18
19class FormatTestCSharp : public ::testing::Test {
20protected:
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
53TEST_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
65TEST_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
79TEST_F(FormatTestCSharp, NoStringLiteralBreaks) {
80 verifyFormat("foo("
81 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
82 "aaaaaa\");");
83}
84
85TEST_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
100TEST_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
116TEST_F(FormatTestCSharp, CSharpFatArrows) {
117 verifyFormat("Task serverTask = Task.Run(async() => {");
118 verifyFormat("public override string ToString() => \"{Name}\\{Age}\";");
119}
120
121TEST_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
131TEST_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
168TEST_F(FormatTestCSharp, CSharpRegions) {
169 verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa "
170 "aaaaaaaaaaaaaaa long region");
171}
172
173TEST_F(FormatTestCSharp, CSharpKeyWordEscaping) {
174 verifyFormat("public enum var { none, @string, bool, @enum }");
175}
176
177TEST_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