FormatTestCSharp.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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 = getGoogleStyle(FormatStyle::LK_CSharp)) {
  31. return format(Code, 0, Code.size(), Style);
  32. }
  33. static FormatStyle getStyleWithColumns(unsigned ColumnLimit) {
  34. FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
  35. Style.ColumnLimit = ColumnLimit;
  36. return Style;
  37. }
  38. static void verifyFormat(
  39. llvm::StringRef Code,
  40. const FormatStyle &Style = getGoogleStyle(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. " void f() {}\n"
  48. " int g() { return 0; }\n"
  49. " void h() {\n"
  50. " while (true) f();\n"
  51. " for (;;) f();\n"
  52. " if (true) f();\n"
  53. " }\n"
  54. "}");
  55. }
  56. TEST_F(FormatTestCSharp, AccessModifiers) {
  57. verifyFormat("public String toString() {}");
  58. verifyFormat("private String toString() {}");
  59. verifyFormat("protected String toString() {}");
  60. verifyFormat("internal String toString() {}");
  61. verifyFormat("public override String toString() {}");
  62. verifyFormat("private override String toString() {}");
  63. verifyFormat("protected override String toString() {}");
  64. verifyFormat("internal override String toString() {}");
  65. verifyFormat("internal static String toString() {}");
  66. }
  67. TEST_F(FormatTestCSharp, NoStringLiteralBreaks) {
  68. verifyFormat("foo("
  69. "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  70. "aaaaaa\");");
  71. }
  72. TEST_F(FormatTestCSharp, CSharpVerbatiumStringLiterals) {
  73. verifyFormat("foo(@\"aaaaaaaa\\abc\\aaaa\");");
  74. // @"ABC\" + ToString("B") - handle embedded \ in literal string at
  75. // the end
  76. //
  77. /*
  78. * After removal of Lexer change we are currently not able
  79. * To handle these cases
  80. verifyFormat("string s = @\"ABC\\\" + ToString(\"B\");");
  81. verifyFormat("string s = @\"ABC\"\"DEF\"\"GHI\"");
  82. verifyFormat("string s = @\"ABC\"\"DEF\"\"\"");
  83. verifyFormat("string s = @\"ABC\"\"DEF\"\"\" + abc");
  84. */
  85. }
  86. TEST_F(FormatTestCSharp, CSharpInterpolatedStringLiterals) {
  87. verifyFormat("foo($\"aaaaaaaa{aaa}aaaa\");");
  88. verifyFormat("foo($\"aaaa{A}\");");
  89. verifyFormat(
  90. "foo($\"aaaa{A}"
  91. "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");");
  92. verifyFormat("Name = $\"{firstName} {lastName}\";");
  93. // $"ABC\" + ToString("B") - handle embedded \ in literal string at
  94. // the end
  95. verifyFormat("string s = $\"A{abc}BC\" + ToString(\"B\");");
  96. verifyFormat("$\"{domain}\\\\{user}\"");
  97. verifyFormat(
  98. "var verbatimInterpolated = $@\"C:\\Users\\{userName}\\Documents\\\";");
  99. }
  100. TEST_F(FormatTestCSharp, CSharpFatArrows) {
  101. verifyFormat("Task serverTask = Task.Run(async() => {");
  102. verifyFormat("public override string ToString() => \"{Name}\\{Age}\";");
  103. }
  104. TEST_F(FormatTestCSharp, CSharpNullConditional) {
  105. verifyFormat(
  106. "public Person(string firstName, string lastName, int? age=null)");
  107. verifyFormat("switch(args?.Length)");
  108. verifyFormat("public static void Main(string[] args) { string dirPath "
  109. "= args?[0]; }");
  110. }
  111. TEST_F(FormatTestCSharp, Attributes) {
  112. verifyFormat("[STAThread]\n"
  113. "static void\n"
  114. "Main(string[] args) {}");
  115. verifyFormat("[TestMethod]\n"
  116. "private class Test {}");
  117. verifyFormat("[TestMethod]\n"
  118. "protected class Test {}");
  119. verifyFormat("[TestMethod]\n"
  120. "internal class Test {}");
  121. verifyFormat("[TestMethod]\n"
  122. "class Test {}");
  123. verifyFormat("[TestMethod]\n"
  124. "[DeploymentItem(\"Test.txt\")]\n"
  125. "public class Test {}");
  126. verifyFormat("[System.AttributeUsage(System.AttributeTargets.Method)]\n"
  127. "[System.Runtime.InteropServices.ComVisible(true)]\n"
  128. "public sealed class STAThreadAttribute : Attribute {}");
  129. verifyFormat("[Verb(\"start\", HelpText = \"Starts the server listening on "
  130. "provided port\")]\n"
  131. "class Test {}");
  132. verifyFormat("[TestMethod]\n"
  133. "public string Host {\n set;\n get;\n}");
  134. verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server "
  135. "listening on provided host\")]\n"
  136. "public string Host {\n set;\n get;\n}");
  137. }
  138. TEST_F(FormatTestCSharp, CSharpUsing) {
  139. FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
  140. Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
  141. verifyFormat("public void foo() {\n"
  142. " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n"
  143. "}",
  144. Style);
  145. Style.SpaceBeforeParens = FormatStyle::SBPO_Never;
  146. verifyFormat("public void foo() {\n"
  147. " using(StreamWriter sw = new StreamWriter(filenameB)) {}\n"
  148. "}",
  149. Style);
  150. }
  151. TEST_F(FormatTestCSharp, CSharpRegions) {
  152. verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa "
  153. "aaaaaaaaaaaaaaa long region");
  154. }
  155. TEST_F(FormatTestCSharp, CSharpKeyWordEscaping) {
  156. verifyFormat("public enum var { none, @string, bool, @enum }");
  157. }
  158. TEST_F(FormatTestCSharp, CSharpNullCoalescing) {
  159. verifyFormat("var test = ABC ?? DEF");
  160. verifyFormat("string myname = name ?? \"ABC\";");
  161. verifyFormat("return _name ?? \"DEF\";");
  162. }
  163. } // namespace format
  164. } // end namespace clang