xref: /llvm-project/clang-tools-extra/unittests/clang-tidy/NamespaceAliaserTest.cpp (revision 43465bf3fd6cca715187ee7286c881cb210fc3c4)
1 //===---- NamespaceAliaserTest.cpp - clang-tidy
2 //----------------------------===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 
11 #include "../clang-tidy/utils/NamespaceAliaser.h"
12 
13 #include "ClangTidyTest.h"
14 #include "clang/ASTMatchers/ASTMatchFinder.h"
15 #include "clang/ASTMatchers/ASTMatchers.h"
16 #include "gtest/gtest.h"
17 
18 namespace clang {
19 namespace tidy {
20 namespace utils {
21 // This checker is for testing only. It can only run on one test case
22 // (e.g. with one SourceManager).
23 class InsertAliasCheck : public ClangTidyCheck {
24 public:
25   InsertAliasCheck(StringRef Name, ClangTidyContext *Context)
26       :ClangTidyCheck(Name, Context) {}
27   void registerMatchers(ast_matchers::MatchFinder *Finder) override {
28     Finder->addMatcher(ast_matchers::callExpr().bind("foo"), this);
29   }
30   void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
31     if (!Aliaser)
32       Aliaser.reset(new NamespaceAliaser(*Result.SourceManager));
33 
34     const auto *Call = Result.Nodes.getNodeAs<CallExpr>("foo");
35     assert(Call != nullptr && "Did not find node \"foo\"");
36     auto Hint = Aliaser->createAlias(*Result.Context, *Call, "::foo::bar",
37                                      {"b", "some_alias"});
38     if (Hint.hasValue())
39       diag(Call->getBeginLoc(), "Fix for testing") << Hint.getValue();
40 
41     diag(Call->getBeginLoc(), "insert call") << FixItHint::CreateInsertion(
42         Call->getBeginLoc(),
43         Aliaser->getNamespaceName(*Result.Context, *Call, "::foo::bar") + "::");
44   }
45 
46 private:
47   std::unique_ptr<NamespaceAliaser> Aliaser;
48 };
49 
50 template <typename Check>
51 std::string runChecker(StringRef Code, unsigned ExpectedWarningCount) {
52   std::map<StringRef, StringRef> AdditionalFileContents = {{"foo.h",
53                                                             "namespace foo {\n"
54                                                             "namespace bar {\n"
55                                                             "}\n"
56                                                             "void func() { }\n"
57                                                             "}"}};
58   std::vector<ClangTidyError> errors;
59 
60   std::string result =
61       test::runCheckOnCode<Check>(Code, &errors, "foo.cc", None,
62                                   ClangTidyOptions(), AdditionalFileContents);
63 
64   EXPECT_EQ(ExpectedWarningCount, errors.size());
65   return result;
66 }
67 
68 TEST(NamespaceAliaserTest, AddNewAlias) {
69   EXPECT_EQ("#include \"foo.h\"\n"
70             "void f() {\n"
71             "namespace b = ::foo::bar;"
72             " b::f(); }",
73             runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
74                                          "void f() { f(); }",
75                                          2));
76 }
77 
78 TEST(NamespaceAliaserTest, ReuseAlias) {
79   EXPECT_EQ(
80       "#include \"foo.h\"\n"
81       "void f() { namespace x = foo::bar; x::f(); }",
82       runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
83                                    "void f() { namespace x = foo::bar; f(); }",
84                                    1));
85 }
86 
87 TEST(NamespaceAliaserTest, AddsOnlyOneAlias) {
88   EXPECT_EQ("#include \"foo.h\"\n"
89             "void f() {\n"
90             "namespace b = ::foo::bar;"
91             " b::f(); b::f(); }",
92             runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
93                                          "void f() { f(); f(); }",
94                                          3));
95 }
96 
97 TEST(NamespaceAliaserTest, LocalConflict) {
98   EXPECT_EQ("#include \"foo.h\"\n"
99             "void f() {\n"
100             "namespace some_alias = ::foo::bar;"
101             " namespace b = foo; some_alias::f(); }",
102             runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
103                                          "void f() { namespace b = foo; f(); }",
104                                          2));
105 }
106 
107 TEST(NamespaceAliaserTest, GlobalConflict) {
108   EXPECT_EQ("#include \"foo.h\"\n"
109             "namespace b = foo;\n"
110             "void f() {\n"
111             "namespace some_alias = ::foo::bar;"
112             " some_alias::f(); }",
113             runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
114                                          "namespace b = foo;\n"
115                                          "void f() { f(); }",
116                                          2));
117 }
118 
119 } // namespace utils
120 } // namespace tidy
121 } // namespace clang
122