1 //===- unittest/Format/SortIncludesTest.cpp - Include sort unit tests -----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "FormatTestUtils.h" 11 #include "clang/Format/Format.h" 12 #include "llvm/Support/Debug.h" 13 #include "gtest/gtest.h" 14 15 #define DEBUG_TYPE "format-test" 16 17 namespace clang { 18 namespace format { 19 namespace { 20 21 class SortIncludesTest : public ::testing::Test { 22 protected: 23 std::vector<tooling::Range> GetCodeRange(StringRef Code) { 24 return std::vector<tooling::Range>(1, tooling::Range(0, Code.size())); 25 } 26 27 std::string sort(StringRef Code, std::vector<tooling::Range> Ranges, 28 StringRef FileName = "input.cc") { 29 auto Replaces = sortIncludes(Style, Code, Ranges, FileName); 30 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); 31 auto Sorted = applyAllReplacements(Code, Replaces); 32 EXPECT_TRUE(static_cast<bool>(Sorted)); 33 auto Result = applyAllReplacements( 34 *Sorted, reformat(Style, *Sorted, Ranges, FileName)); 35 EXPECT_TRUE(static_cast<bool>(Result)); 36 return *Result; 37 } 38 39 std::string sort(StringRef Code, StringRef FileName = "input.cpp") { 40 return sort(Code, GetCodeRange(Code), FileName); 41 } 42 43 unsigned newCursor(llvm::StringRef Code, unsigned Cursor) { 44 sortIncludes(Style, Code, GetCodeRange(Code), "input.cpp", &Cursor); 45 return Cursor; 46 } 47 48 FormatStyle Style = getLLVMStyle(); 49 50 }; 51 52 TEST_F(SortIncludesTest, BasicSorting) { 53 EXPECT_EQ("#include \"a.h\"\n" 54 "#include \"b.h\"\n" 55 "#include \"c.h\"\n", 56 sort("#include \"a.h\"\n" 57 "#include \"c.h\"\n" 58 "#include \"b.h\"\n")); 59 60 EXPECT_EQ("// comment\n" 61 "#include <a>\n" 62 "#include <b>\n", 63 sort("// comment\n" 64 "#include <b>\n" 65 "#include <a>\n", 66 {tooling::Range(25, 1)})); 67 } 68 69 TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) { 70 // Identical #includes have led to a failure with an unstable sort. 71 std::string Code = "#include <a>\n" 72 "#include <b>\n" 73 "#include <c>\n" 74 "#include <d>\n" 75 "#include <e>\n" 76 "#include <f>\n"; 77 EXPECT_TRUE(sortIncludes(Style, Code, GetCodeRange(Code), "a.cc").empty()); 78 } 79 80 TEST_F(SortIncludesTest, SupportClangFormatOff) { 81 EXPECT_EQ("#include <a>\n" 82 "#include <b>\n" 83 "#include <c>\n" 84 "// clang-format off\n" 85 "#include <b>\n" 86 "#include <a>\n" 87 "#include <c>\n" 88 "// clang-format on\n", 89 sort("#include <b>\n" 90 "#include <a>\n" 91 "#include <c>\n" 92 "// clang-format off\n" 93 "#include <b>\n" 94 "#include <a>\n" 95 "#include <c>\n" 96 "// clang-format on\n")); 97 } 98 99 TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) { 100 Style.SortIncludes = false; 101 EXPECT_EQ("#include \"a.h\"\n" 102 "#include \"c.h\"\n" 103 "#include \"b.h\"\n", 104 sort("#include \"a.h\"\n" 105 "#include \"c.h\"\n" 106 "#include \"b.h\"\n")); 107 } 108 109 TEST_F(SortIncludesTest, MixIncludeAndImport) { 110 EXPECT_EQ("#include \"a.h\"\n" 111 "#import \"b.h\"\n" 112 "#include \"c.h\"\n", 113 sort("#include \"a.h\"\n" 114 "#include \"c.h\"\n" 115 "#import \"b.h\"\n")); 116 } 117 118 TEST_F(SortIncludesTest, FixTrailingComments) { 119 EXPECT_EQ("#include \"a.h\" // comment\n" 120 "#include \"bb.h\" // comment\n" 121 "#include \"ccc.h\"\n", 122 sort("#include \"a.h\" // comment\n" 123 "#include \"ccc.h\"\n" 124 "#include \"bb.h\" // comment\n")); 125 } 126 127 TEST_F(SortIncludesTest, LeadingWhitespace) { 128 EXPECT_EQ("#include \"a.h\"\n" 129 "#include \"b.h\"\n" 130 "#include \"c.h\"\n", 131 sort(" #include \"a.h\"\n" 132 " #include \"c.h\"\n" 133 " #include \"b.h\"\n")); 134 EXPECT_EQ("#include \"a.h\"\n" 135 "#include \"b.h\"\n" 136 "#include \"c.h\"\n", 137 sort("# include \"a.h\"\n" 138 "# include \"c.h\"\n" 139 "# include \"b.h\"\n")); 140 } 141 142 TEST_F(SortIncludesTest, GreaterInComment) { 143 EXPECT_EQ("#include \"a.h\"\n" 144 "#include \"b.h\" // >\n" 145 "#include \"c.h\"\n", 146 sort("#include \"a.h\"\n" 147 "#include \"c.h\"\n" 148 "#include \"b.h\" // >\n")); 149 } 150 151 TEST_F(SortIncludesTest, SortsLocallyInEachBlock) { 152 EXPECT_EQ("#include \"a.h\"\n" 153 "#include \"c.h\"\n" 154 "\n" 155 "#include \"b.h\"\n", 156 sort("#include \"a.h\"\n" 157 "#include \"c.h\"\n" 158 "\n" 159 "#include \"b.h\"\n")); 160 } 161 162 TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) { 163 EXPECT_EQ("#include \"a.h\"\n" 164 "#include \"c.h\"\n" 165 "#include <b.h>\n" 166 "#include <d.h>\n", 167 sort("#include <d.h>\n" 168 "#include <b.h>\n" 169 "#include \"c.h\"\n" 170 "#include \"a.h\"\n")); 171 172 Style = getGoogleStyle(FormatStyle::LK_Cpp); 173 EXPECT_EQ("#include <b.h>\n" 174 "#include <d.h>\n" 175 "#include \"a.h\"\n" 176 "#include \"c.h\"\n", 177 sort("#include <d.h>\n" 178 "#include <b.h>\n" 179 "#include \"c.h\"\n" 180 "#include \"a.h\"\n")); 181 } 182 183 TEST_F(SortIncludesTest, HandlesMultilineIncludes) { 184 EXPECT_EQ("#include \"a.h\"\n" 185 "#include \"b.h\"\n" 186 "#include \"c.h\"\n", 187 sort("#include \"a.h\"\n" 188 "#include \\\n" 189 "\"c.h\"\n" 190 "#include \"b.h\"\n")); 191 } 192 193 TEST_F(SortIncludesTest, LeavesMainHeaderFirst) { 194 Style.IncludeIsMainRegex = "([-_](test|unittest))?$"; 195 EXPECT_EQ("#include \"llvm/a.h\"\n" 196 "#include \"b.h\"\n" 197 "#include \"c.h\"\n", 198 sort("#include \"llvm/a.h\"\n" 199 "#include \"c.h\"\n" 200 "#include \"b.h\"\n", 201 "a.cc")); 202 EXPECT_EQ("#include \"llvm/a.h\"\n" 203 "#include \"b.h\"\n" 204 "#include \"c.h\"\n", 205 sort("#include \"llvm/a.h\"\n" 206 "#include \"c.h\"\n" 207 "#include \"b.h\"\n", 208 "a_test.cc")); 209 EXPECT_EQ("#include \"llvm/input.h\"\n" 210 "#include \"b.h\"\n" 211 "#include \"c.h\"\n", 212 sort("#include \"llvm/input.h\"\n" 213 "#include \"c.h\"\n" 214 "#include \"b.h\"\n", 215 "input.mm")); 216 217 // Don't allow prefixes. 218 EXPECT_EQ("#include \"b.h\"\n" 219 "#include \"c.h\"\n" 220 "#include \"llvm/not_a.h\"\n", 221 sort("#include \"llvm/not_a.h\"\n" 222 "#include \"c.h\"\n" 223 "#include \"b.h\"\n", 224 "a.cc")); 225 226 // Don't do this for _main and other suffixes. 227 EXPECT_EQ("#include \"b.h\"\n" 228 "#include \"c.h\"\n" 229 "#include \"llvm/a.h\"\n", 230 sort("#include \"llvm/a.h\"\n" 231 "#include \"c.h\"\n" 232 "#include \"b.h\"\n", 233 "a_main.cc")); 234 235 // Don't do this in headers. 236 EXPECT_EQ("#include \"b.h\"\n" 237 "#include \"c.h\"\n" 238 "#include \"llvm/a.h\"\n", 239 sort("#include \"llvm/a.h\"\n" 240 "#include \"c.h\"\n" 241 "#include \"b.h\"\n", 242 "a.h")); 243 244 // Only do this in the first #include block. 245 EXPECT_EQ("#include <a>\n" 246 "\n" 247 "#include \"b.h\"\n" 248 "#include \"c.h\"\n" 249 "#include \"llvm/a.h\"\n", 250 sort("#include <a>\n" 251 "\n" 252 "#include \"llvm/a.h\"\n" 253 "#include \"c.h\"\n" 254 "#include \"b.h\"\n", 255 "a.cc")); 256 257 // Only recognize the first #include with a matching basename as main include. 258 EXPECT_EQ("#include \"a.h\"\n" 259 "#include \"b.h\"\n" 260 "#include \"c.h\"\n" 261 "#include \"llvm/a.h\"\n", 262 sort("#include \"b.h\"\n" 263 "#include \"a.h\"\n" 264 "#include \"c.h\"\n" 265 "#include \"llvm/a.h\"\n", 266 "a.cc")); 267 } 268 269 TEST_F(SortIncludesTest, NegativePriorities) { 270 Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}}; 271 EXPECT_EQ("#include \"important_os_header.h\"\n" 272 "#include \"c_main.h\"\n" 273 "#include \"a_other.h\"\n", 274 sort("#include \"c_main.h\"\n" 275 "#include \"a_other.h\"\n" 276 "#include \"important_os_header.h\"\n", 277 "c_main.cc")); 278 279 // check stable when re-run 280 EXPECT_EQ("#include \"important_os_header.h\"\n" 281 "#include \"c_main.h\"\n" 282 "#include \"a_other.h\"\n", 283 sort("#include \"important_os_header.h\"\n" 284 "#include \"c_main.h\"\n" 285 "#include \"a_other.h\"\n", 286 "c_main.cc")); 287 } 288 289 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { 290 std::string Code = "#include <ccc>\n" // Start of line: 0 291 "#include <bbbbbb>\n" // Start of line: 15 292 "#include <a>\n"; // Start of line: 33 293 EXPECT_EQ(31u, newCursor(Code, 0)); 294 EXPECT_EQ(13u, newCursor(Code, 15)); 295 EXPECT_EQ(0u, newCursor(Code, 33)); 296 297 EXPECT_EQ(41u, newCursor(Code, 10)); 298 EXPECT_EQ(23u, newCursor(Code, 25)); 299 EXPECT_EQ(10u, newCursor(Code, 43)); 300 } 301 302 TEST_F(SortIncludesTest, DeduplicateIncludes) { 303 EXPECT_EQ("#include <a>\n" 304 "#include <b>\n" 305 "#include <c>\n", 306 sort("#include <a>\n" 307 "#include <b>\n" 308 "#include <b>\n" 309 "#include <b>\n" 310 "#include <b>\n" 311 "#include <c>\n")); 312 } 313 314 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { 315 EXPECT_EQ("#include <a>\n" 316 "#include <b>\n" 317 "#include <c>\n", 318 sort("#include <b>\n" 319 "#include <a>\n" 320 "#include <b>\n" 321 "#include <b>\n" 322 "#include <c>\n" 323 "#include <b>\n")); 324 } 325 326 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) { 327 std::string Code = "#include <b>\n" // Start of line: 0 328 "#include <a>\n" // Start of line: 13 329 "#include <b>\n" // Start of line: 26 330 "#include <b>\n" // Start of line: 39 331 "#include <c>\n" // Start of line: 52 332 "#include <b>\n"; // Start of line: 65 333 std::string Expected = "#include <a>\n" // Start of line: 0 334 "#include <b>\n" // Start of line: 13 335 "#include <c>\n"; // Start of line: 26 336 EXPECT_EQ(Expected, sort(Code)); 337 // Cursor on 'i' in "#include <a>". 338 EXPECT_EQ(1u, newCursor(Code, 14)); 339 // Cursor on 'b' in "#include <b>". 340 EXPECT_EQ(23u, newCursor(Code, 10)); 341 EXPECT_EQ(23u, newCursor(Code, 36)); 342 EXPECT_EQ(23u, newCursor(Code, 49)); 343 EXPECT_EQ(23u, newCursor(Code, 36)); 344 EXPECT_EQ(23u, newCursor(Code, 75)); 345 // Cursor on '#' in "#include <c>". 346 EXPECT_EQ(26u, newCursor(Code, 52)); 347 } 348 349 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) { 350 EXPECT_EQ("#include <a>\n" 351 "#include <b>\n" 352 "\n" 353 "#include <b>\n" 354 "#include <c>\n", 355 sort("#include <a>\n" 356 "#include <b>\n" 357 "\n" 358 "#include <c>\n" 359 "#include <b>\n" 360 "#include <b>\n")); 361 } 362 363 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { 364 std::string Code = "#include <a>\n" 365 "#include <b>\n" 366 "#include <a>\n" 367 "#include <a>\n" 368 "\n" 369 " int x ;"; 370 std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)}; 371 auto Replaces = sortIncludes(Style, Code, Ranges, "input.cpp"); 372 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); 373 EXPECT_EQ(1u, Ranges.size()); 374 EXPECT_EQ(0u, Ranges[0].getOffset()); 375 EXPECT_EQ(26u, Ranges[0].getLength()); 376 } 377 378 } // end namespace 379 } // end namespace format 380 } // end namespace clang 381