FormatTestCSharp.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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. #include "FormatTestUtils.h"
  9. #include "clang/Format/Format.h"
  10. #include "llvm/Support/Debug.h"
  11. #include "gtest/gtest.h"
  12. #define DEBUG_TYPE "format-test"
  13. namespace clang {
  14. namespace format {
  15. class FormatTestCSharp : public ::testing::Test {
  16. protected:
  17. static std::string format(llvm::StringRef Code, unsigned Offset,
  18. unsigned Length, const FormatStyle &Style) {
  19. LLVM_DEBUG(llvm::errs() << "---\n");
  20. LLVM_DEBUG(llvm::errs() << Code << "\n\n");
  21. std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
  22. tooling::Replacements Replaces = reformat(Style, Code, Ranges);
  23. auto Result = applyAllReplacements(Code, Replaces);
  24. EXPECT_TRUE(static_cast<bool>(Result));
  25. LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
  26. return *Result;
  27. }
  28. static std::string
  29. format(llvm::StringRef Code,
  30. const FormatStyle &Style = getMicrosoftStyle(FormatStyle::LK_CSharp)) {
  31. return format(Code, 0, Code.size(), Style);
  32. }
  33. static FormatStyle getStyleWithColumns(unsigned ColumnLimit) {
  34. FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
  35. Style.ColumnLimit = ColumnLimit;
  36. return Style;
  37. }
  38. static void verifyFormat(
  39. llvm::StringRef Code,
  40. const FormatStyle &Style = getMicrosoftStyle(FormatStyle::LK_CSharp)) {
  41. EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
  42. EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
  43. }
  44. };
  45. TEST_F(FormatTestCSharp, CSharpClass) {
  46. verifyFormat("public class SomeClass\n"
  47. "{\n"
  48. " void f()\n"
  49. " {\n"
  50. " }\n"
  51. " int g()\n"
  52. " {\n"
  53. " return 0;\n"
  54. " }\n"
  55. " void h()\n"
  56. " {\n"
  57. " while (true)\n"
  58. " f();\n"
  59. " for (;;)\n"
  60. " f();\n"
  61. " if (true)\n"
  62. " f();\n"
  63. " }\n"
  64. "}");
  65. }
  66. TEST_F(FormatTestCSharp, AccessModifiers) {
  67. verifyFormat("public String toString()\n"
  68. "{\n"
  69. "}");
  70. verifyFormat("private String toString()\n"
  71. "{\n"
  72. "}");
  73. verifyFormat("protected String toString()\n"
  74. "{\n"
  75. "}");
  76. verifyFormat("internal String toString()\n"
  77. "{\n"
  78. "}");
  79. verifyFormat("public override String toString()\n"
  80. "{\n"
  81. "}");
  82. verifyFormat("private override String toString()\n"
  83. "{\n"
  84. "}");
  85. verifyFormat("protected override String toString()\n"
  86. "{\n"
  87. "}");
  88. verifyFormat("internal override String toString()\n"
  89. "{\n"
  90. "}");
  91. verifyFormat("internal static String toString()\n"
  92. "{\n"
  93. "}");
  94. }
  95. TEST_F(FormatTestCSharp, NoStringLiteralBreaks) {
  96. verifyFormat("foo("
  97. "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  98. "aaaaaa\");");
  99. }
  100. TEST_F(FormatTestCSharp, CSharpVerbatiumStringLiterals) {
  101. verifyFormat("foo(@\"aaaaaaaa\\abc\\aaaa\");");
  102. // @"ABC\" + ToString("B") - handle embedded \ in literal string at
  103. // the end
  104. //
  105. /*
  106. * After removal of Lexer change we are currently not able
  107. * To handle these cases
  108. verifyFormat("string s = @\"ABC\\\" + ToString(\"B\");");
  109. verifyFormat("string s = @\"ABC\"\"DEF\"\"GHI\"");
  110. verifyFormat("string s = @\"ABC\"\"DEF\"\"\"");
  111. verifyFormat("string s = @\"ABC\"\"DEF\"\"\" + abc");
  112. */
  113. }
  114. TEST_F(FormatTestCSharp, CSharpInterpolatedStringLiterals) {
  115. verifyFormat("foo($\"aaaaaaaa{aaa}aaaa\");");
  116. verifyFormat("foo($\"aaaa{A}\");");
  117. verifyFormat(
  118. "foo($\"aaaa{A}"
  119. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");");
  120. verifyFormat("Name = $\"{firstName} {lastName}\";");
  121. // $"ABC\" + ToString("B") - handle embedded \ in literal string at
  122. // the end
  123. verifyFormat("string s = $\"A{abc}BC\" + ToString(\"B\");");
  124. verifyFormat("$\"{domain}\\\\{user}\"");
  125. verifyFormat(
  126. "var verbatimInterpolated = $@\"C:\\Users\\{userName}\\Documents\\\";");
  127. }
  128. TEST_F(FormatTestCSharp, CSharpFatArrows) {
  129. verifyFormat("Task serverTask = Task.Run(async() => {");
  130. verifyFormat("public override string ToString() => \"{Name}\\{Age}\";");
  131. }
  132. TEST_F(FormatTestCSharp, CSharpNullConditional) {
  133. verifyFormat(
  134. "public Person(string firstName, string lastName, int? age=null)");
  135. verifyFormat("switch(args?.Length)");
  136. verifyFormat("public static void Main(string[] args)\n"
  137. "{\n"
  138. " string dirPath = args?[0];\n"
  139. "}");
  140. }
  141. TEST_F(FormatTestCSharp, Attributes) {
  142. verifyFormat("[STAThread]\n"
  143. "static void Main(string[] args)\n"
  144. "{\n"
  145. "}");
  146. verifyFormat("[TestMethod]\n"
  147. "private class Test\n"
  148. "{\n"
  149. "}");
  150. verifyFormat("[TestMethod]\n"
  151. "protected class Test\n"
  152. "{\n"
  153. "}");
  154. verifyFormat("[TestMethod]\n"
  155. "internal class Test\n"
  156. "{\n"
  157. "}");
  158. verifyFormat("[TestMethod]\n"
  159. "class Test\n"
  160. "{\n"
  161. "}");
  162. verifyFormat("[TestMethod]\n"
  163. "[DeploymentItem(\"Test.txt\")]\n"
  164. "public class Test\n"
  165. "{\n"
  166. "}");
  167. verifyFormat("[System.AttributeUsage(System.AttributeTargets.Method)]\n"
  168. "[System.Runtime.InteropServices.ComVisible(true)]\n"
  169. "public sealed class STAThreadAttribute : Attribute\n"
  170. "{\n"
  171. "}");
  172. verifyFormat("[Verb(\"start\", HelpText = \"Starts the server listening on "
  173. "provided port\")]\n"
  174. "class Test\n"
  175. "{\n"
  176. "}");
  177. verifyFormat("[TestMethod]\n"
  178. "public string Host\n"
  179. "{\n"
  180. " set;\n"
  181. " get;\n"
  182. "}");
  183. verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server "
  184. "listening on provided host\")]\n"
  185. "public string Host\n"
  186. "{\n"
  187. " set;\n"
  188. " get;\n"
  189. "}");
  190. }
  191. TEST_F(FormatTestCSharp, CSharpUsing) {
  192. FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
  193. Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
  194. verifyFormat("public void foo() {\n"
  195. " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n"
  196. "}",
  197. Style);
  198. Style.SpaceBeforeParens = FormatStyle::SBPO_Never;
  199. verifyFormat("public void foo() {\n"
  200. " using(StreamWriter sw = new StreamWriter(filenameB)) {}\n"
  201. "}",
  202. Style);
  203. }
  204. TEST_F(FormatTestCSharp, CSharpRegions) {
  205. verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa "
  206. "aaaaaaaaaaaaaaa long region");
  207. }
  208. TEST_F(FormatTestCSharp, CSharpKeyWordEscaping) {
  209. verifyFormat("public enum var { none, @string, bool, @enum }");
  210. }
  211. TEST_F(FormatTestCSharp, CSharpNullCoalescing) {
  212. verifyFormat("var test = ABC ?? DEF");
  213. verifyFormat("string myname = name ?? \"ABC\";");
  214. verifyFormat("return _name ?? \"DEF\";");
  215. }
  216. TEST_F(FormatTestCSharp, AttributesIndentation) {
  217. FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
  218. Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
  219. verifyFormat("[STAThread]\n"
  220. "static void Main(string[] args)\n"
  221. "{\n"
  222. "}",
  223. Style);
  224. verifyFormat("[STAThread]\n"
  225. "void "
  226. "veryLooooooooooooooongFunctionName(string[] args)\n"
  227. "{\n"
  228. "}",
  229. Style);
  230. verifyFormat("[STAThread]\n"
  231. "veryLoooooooooooooooooooongReturnType "
  232. "veryLooooooooooooooongFunctionName(string[] args)\n"
  233. "{\n"
  234. "}",
  235. Style);
  236. verifyFormat("[SuppressMessage(\"A\", \"B\", Justification = \"C\")]\n"
  237. "public override X Y()\n"
  238. "{\n"
  239. "}\n",
  240. Style);
  241. verifyFormat("[SuppressMessage]\n"
  242. "public X Y()\n"
  243. "{\n"
  244. "}\n",
  245. Style);
  246. verifyFormat("[SuppressMessage]\n"
  247. "public override X Y()\n"
  248. "{\n"
  249. "}\n",
  250. Style);
  251. verifyFormat("public A(B b) : base(b)\n"
  252. "{\n"
  253. " [SuppressMessage]\n"
  254. " public override X Y()\n"
  255. " {\n"
  256. " }\n"
  257. "}\n",
  258. Style);
  259. }
  260. } // namespace format
  261. } // end namespace clang