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