brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.1 KiB · 278d435 Raw
322 lines · cpp
1#include "ClangTidyOptions.h"2#include "ClangTidyTest.h"3#include "llvm/ADT/ArrayRef.h"4#include "llvm/ADT/StringRef.h"5#include "llvm/HeaderGuardCheck.h"6#include "llvm/IncludeOrderCheck.h"7#include "gtest/gtest.h"8#include <optional>9 10using namespace clang::tidy::llvm_check;11 12namespace clang {13namespace tidy {14namespace test {15 16template <typename T>17static std::string runCheck(StringRef Code, const Twine &Filename,18                            std::optional<StringRef> ExpectedWarning,19                            std::map<StringRef, StringRef> PathsToContent =20                                std::map<StringRef, StringRef>()) {21  std::vector<ClangTidyError> Errors;22  std::string Result = test::runCheckOnCode<T>(23      Code, &Errors, Filename, std::string("-xc++-header"), ClangTidyOptions{},24      std::move(PathsToContent));25  if (Errors.size() != (size_t)ExpectedWarning.has_value())26    return "invalid error count";27  if (ExpectedWarning && *ExpectedWarning != Errors.back().Message.Message)28    return "expected: '" + ExpectedWarning->str() + "', saw: '" +29           Errors.back().Message.Message + "'";30  return Result;31}32 33static std::string34runHeaderGuardCheck(StringRef Code, const Twine &Filename,35                    std::optional<StringRef> ExpectedWarning) {36  return runCheck<LLVMHeaderGuardCheck>(Code, Filename,37                                        std::move(ExpectedWarning));38}39 40static std::string41runIncludeOrderCheck(StringRef Code, const Twine &Filename,42                     std::optional<StringRef> ExpectedWarning,43                     llvm::ArrayRef<llvm::StringLiteral> Includes) {44  std::map<StringRef, StringRef> PathsToContent;45  for (auto Include : Includes)46    PathsToContent.emplace(Include, "");47  return runCheck<IncludeOrderCheck>(Code, Filename, std::move(ExpectedWarning),48                                     PathsToContent);49}50 51namespace {52struct WithEndifComment : public LLVMHeaderGuardCheck {53  WithEndifComment(StringRef Name, ClangTidyContext *Context)54      : LLVMHeaderGuardCheck(Name, Context) {}55  bool shouldSuggestEndifComment(StringRef Filename) override { return true; }56};57 58static std::string59runHeaderGuardCheckWithEndif(StringRef Code, const Twine &Filename,60                             std::optional<StringRef> ExpectedWarning) {61  return runCheck<WithEndifComment>(Code, Filename, std::move(ExpectedWarning));62}63} // namespace64 65TEST(LLVMHeaderGuardCheckTest, FixHeaderGuards) {66  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"67            "#define LLVM_ADT_FOO_H\n"68            "#endif\n",69            runHeaderGuardCheck(70                "#ifndef FOO\n"71                "#define FOO\n"72                "#endif\n",73                "include/llvm/ADT/foo.h",74                StringRef("header guard does not follow preferred style")));75 76  // Allow trailing underscores.77  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H_\n"78            "#define LLVM_ADT_FOO_H_\n"79            "#endif\n",80            runHeaderGuardCheck("#ifndef LLVM_ADT_FOO_H_\n"81                                "#define LLVM_ADT_FOO_H_\n"82                                "#endif\n",83                                "include/llvm/ADT/foo.h", std::nullopt));84 85  EXPECT_EQ("#ifndef LLVM_CLANG_C_BAR_H\n"86            "#define LLVM_CLANG_C_BAR_H\n"87            "\n"88            "\n"89            "#endif\n",90            runHeaderGuardCheck("", "./include/clang-c/bar.h",91                                StringRef("header is missing header guard")));92 93  EXPECT_EQ("#ifndef LLVM_CLANG_LIB_CODEGEN_C_H\n"94            "#define LLVM_CLANG_LIB_CODEGEN_C_H\n"95            "\n"96            "\n"97            "#endif\n",98            runHeaderGuardCheck("", "tools/clang/lib/CodeGen/c.h",99                                StringRef("header is missing header guard")));100 101  EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_X_H\n"102            "#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_X_H\n"103            "\n"104            "\n"105            "#endif\n",106            runHeaderGuardCheck("", "tools/clang/tools/extra/clang-tidy/x.h",107                                StringRef("header is missing header guard")));108 109  EXPECT_EQ(110      "int foo;\n"111      "#ifndef LLVM_CLANG_BAR_H\n"112      "#define LLVM_CLANG_BAR_H\n"113      "#endif\n",114      runHeaderGuardCheck("int foo;\n"115                          "#ifndef LLVM_CLANG_BAR_H\n"116                          "#define LLVM_CLANG_BAR_H\n"117                          "#endif\n",118                          "include/clang/bar.h",119                          StringRef("code/includes outside of area guarded by "120                                    "header guard; consider moving it")));121 122  EXPECT_EQ(123      "#ifndef LLVM_CLANG_BAR_H\n"124      "#define LLVM_CLANG_BAR_H\n"125      "#endif\n"126      "int foo;\n",127      runHeaderGuardCheck("#ifndef LLVM_CLANG_BAR_H\n"128                          "#define LLVM_CLANG_BAR_H\n"129                          "#endif\n"130                          "int foo;\n",131                          "include/clang/bar.h",132                          StringRef("code/includes outside of area guarded by "133                                    "header guard; consider moving it")));134 135  EXPECT_EQ("#ifndef LLVM_CLANG_BAR_H\n"136            "#define LLVM_CLANG_BAR_H\n"137            "\n"138            "int foo;\n"139            "#ifndef FOOLOLO\n"140            "#define FOOLOLO\n"141            "#endif\n"142            "\n"143            "#endif\n",144            runHeaderGuardCheck("int foo;\n"145                                "#ifndef FOOLOLO\n"146                                "#define FOOLOLO\n"147                                "#endif\n",148                                "include/clang/bar.h",149                                StringRef("header is missing header guard")));150 151  // Fix incorrect #endif comments even if we shouldn't add new ones.152  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"153            "#define LLVM_ADT_FOO_H\n"154            "#endif // LLVM_ADT_FOO_H\n",155            runHeaderGuardCheck(156                "#ifndef FOO\n"157                "#define FOO\n"158                "#endif // FOO\n",159                "include/llvm/ADT/foo.h",160                StringRef("header guard does not follow preferred style")));161 162  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"163            "#define LLVM_ADT_FOO_H\n"164            "#endif // LLVM_ADT_FOO_H\n",165            runHeaderGuardCheckWithEndif(166                "#ifndef FOO\n"167                "#define FOO\n"168                "#endif\n",169                "include/llvm/ADT/foo.h",170                StringRef("header guard does not follow preferred style")));171 172  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"173            "#define LLVM_ADT_FOO_H\n"174            "#endif // LLVM_ADT_FOO_H\n",175            runHeaderGuardCheckWithEndif(176                "#ifndef LLVM_ADT_FOO_H\n"177                "#define LLVM_ADT_FOO_H\n"178                "#endif // LLVM_H\n",179                "include/llvm/ADT/foo.h",180                StringRef("#endif for a header guard should reference the "181                          "guard macro in a comment")));182 183  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"184            "#define LLVM_ADT_FOO_H\n"185            "#endif /* LLVM_ADT_FOO_H */\n",186            runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H\n"187                                         "#define LLVM_ADT_FOO_H\n"188                                         "#endif /* LLVM_ADT_FOO_H */\n",189                                         "include/llvm/ADT/foo.h",190                                         std::nullopt));191 192  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H_\n"193            "#define LLVM_ADT_FOO_H_\n"194            "#endif // LLVM_ADT_FOO_H_\n",195            runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H_\n"196                                         "#define LLVM_ADT_FOO_H_\n"197                                         "#endif // LLVM_ADT_FOO_H_\n",198                                         "include/llvm/ADT/foo.h",199                                         std::nullopt));200 201  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"202            "#define LLVM_ADT_FOO_H\n"203            "#endif // LLVM_ADT_FOO_H\n",204            runHeaderGuardCheckWithEndif(205                "#ifndef LLVM_ADT_FOO_H_\n"206                "#define LLVM_ADT_FOO_H_\n"207                "#endif // LLVM\n",208                "include/llvm/ADT/foo.h",209                StringRef("header guard does not follow preferred style")));210 211  // An extra space inside the comment is OK.212  llvm::StringRef WithExtraSpace = "#ifndef LLVM_ADT_FOO_H\n"213                                   "#define LLVM_ADT_FOO_H\n"214                                   "#endif //  LLVM_ADT_FOO_H\n";215  EXPECT_EQ(WithExtraSpace,216            runHeaderGuardCheckWithEndif(217                WithExtraSpace, "include/llvm/ADT/foo.h", std::nullopt));218 219  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"220            "#define LLVM_ADT_FOO_H\n"221            "#endif \\ \n"222            "// LLVM_ADT_FOO_H\n",223            runHeaderGuardCheckWithEndif(224                "#ifndef LLVM_ADT_FOO_H\n"225                "#define LLVM_ADT_FOO_H\n"226                "#endif \\ \n"227                "// LLVM_ADT_FOO_H\n",228                "include/llvm/ADT/foo.h",229                StringRef("backslash and newline separated by space")));230 231  EXPECT_EQ("#ifndef LLVM_ADT_FOO_H\n"232            "#define LLVM_ADT_FOO_H\n"233            "#endif  /* LLVM_ADT_FOO_H\\ \n"234            " FOO */",235            runHeaderGuardCheckWithEndif("#ifndef LLVM_ADT_FOO_H\n"236                                         "#define LLVM_ADT_FOO_H\n"237                                         "#endif  /* LLVM_ADT_FOO_H\\ \n"238                                         " FOO */",239                                         "include/llvm/ADT/foo.h",240                                         std::nullopt));241 242  EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"243            "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"244            "\n"245            "\n"246            "#endif\n",247            runHeaderGuardCheck(248                "", "/llvm-project/clang-tools-extra/clangd/foo.h",249                StringRef("header is missing header guard")));250 251  // Substitution of characters should not result in a header guard starting252  // with "_".253  EXPECT_EQ("#ifndef BAR_H\n"254            "#define BAR_H\n"255            "\n"256            "\n"257            "#endif\n",258            runHeaderGuardCheck("", "include/--bar.h",259                                StringRef("header is missing header guard")));260 261#ifdef WIN32262  // Check interaction with Windows-style path separators (\).263  EXPECT_EQ(264      "#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"265      "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"266      "\n"267      "\n"268      "#endif\n",269      runHeaderGuardCheck("", "llvm-project\\clang-tools-extra\\clangd\\foo.h",270                          StringRef("header is missing header guard")));271 272  EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"273            "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"274            "\n"275            "\n"276            "#endif\n",277            runHeaderGuardCheck(278                "", "C:\\llvm-project\\clang-tools-extra\\clangd\\foo.h",279                StringRef("header is missing header guard")));280 281  EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"282            "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"283            "\n"284            "\n"285            "#endif\n",286            runHeaderGuardCheck(287                "",288                "\\\\SMBShare\\llvm-project\\clang-tools-extra\\clangd\\foo.h",289                StringRef("header is missing header guard")));290 291  EXPECT_EQ("#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"292            "#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FOO_H\n"293            "\n"294            "\n"295            "#endif\n",296            runHeaderGuardCheck(297                "", "\\\\?\\C:\\llvm-project\\clang-tools-extra\\clangd\\foo.h",298                StringRef("header is missing header guard")));299#endif300}301 302TEST(IncludeOrderCheck, GTestHeaders) {303  EXPECT_EQ(304      R"cpp(305  #include "foo.h"306  #include "llvm/foo.h"307  #include "gtest/foo.h"308  #include <algorithm>)cpp",309      runIncludeOrderCheck(310          R"cpp(311  #include "foo.h"312  #include "llvm/foo.h"313  #include <algorithm>314  #include "gtest/foo.h")cpp",315          "foo.cc", StringRef("#includes are not sorted properly"),316          {"foo.h", "algorithm", "gtest/foo.h", "llvm/foo.h"}));317}318 319} // namespace test320} // namespace tidy321} // namespace clang322