xref: /llvm-project/clang-tools-extra/unittests/clang-tidy/NamespaceAliaserTest.cpp (revision bd31488083f3d3db2603464026853d528cfdc07e)
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 CallExpr *Call =
35         Result.Nodes.getNodeAs<CallExpr>("foo");
36     assert(Call != nullptr && "Did not find node \"foo\"");
37     auto Hint = Aliaser->createAlias(*Result.Context, *Call, "::foo::bar",
38                                      {"b", "some_alias"});
39     if (Hint.hasValue())
40       diag(Call->getLocStart(), "Fix for testing") << Hint.getValue();
41 
42     diag(Call->getLocStart(), "insert call")
43         << FixItHint::CreateInsertion(
44                Call->getLocStart(),
45                Aliaser->getNamespaceName(*Result.Context, *Call, "::foo::bar") +
46                    "::");
47   }
48 
49 private:
50   std::unique_ptr<NamespaceAliaser> Aliaser;
51 };
52 
53 template <typename Check>
54 std::string runChecker(StringRef Code, int ExpectedWarningCount) {
55   std::map<StringRef, StringRef> AdditionalFileContents = {{"foo.h",
56                                                             "namespace foo {\n"
57                                                             "namespace bar {\n"
58                                                             "}\n"
59                                                             "void func() { }\n"
60                                                             "}"}};
61   std::vector<ClangTidyError> errors;
62 
63   std::string result =
64       test::runCheckOnCode<Check>(Code, &errors, "foo.cc", None,
65                                   ClangTidyOptions(), AdditionalFileContents);
66 
67   EXPECT_EQ(ExpectedWarningCount, errors.size());
68   return result;
69 }
70 
71 TEST(NamespaceAliaserTest, AddNewAlias) {
72   EXPECT_EQ("#include \"foo.h\"\n"
73             "void f() {\n"
74             "namespace b = ::foo::bar;"
75             " b::f(); }",
76             runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
77                                          "void f() { f(); }",
78                                          2));
79 }
80 
81 TEST(NamespaceAliaserTest, ReuseAlias) {
82   EXPECT_EQ(
83       "#include \"foo.h\"\n"
84       "void f() { namespace x = foo::bar; x::f(); }",
85       runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
86                                    "void f() { namespace x = foo::bar; f(); }",
87                                    1));
88 }
89 
90 TEST(NamespaceAliaserTest, AddsOnlyOneAlias) {
91   EXPECT_EQ("#include \"foo.h\"\n"
92             "void f() {\n"
93             "namespace b = ::foo::bar;"
94             " b::f(); b::f(); }",
95             runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
96                                          "void f() { f(); f(); }",
97                                          3));
98 }
99 
100 TEST(NamespaceAliaserTest, LocalConflict) {
101   EXPECT_EQ("#include \"foo.h\"\n"
102             "void f() {\n"
103             "namespace some_alias = ::foo::bar;"
104             " namespace b = foo; some_alias::f(); }",
105             runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
106                                          "void f() { namespace b = foo; f(); }",
107                                          2));
108 }
109 
110 TEST(NamespaceAliaserTest, GlobalConflict) {
111   EXPECT_EQ("#include \"foo.h\"\n"
112             "namespace b = foo;\n"
113             "void f() {\n"
114             "namespace some_alias = ::foo::bar;"
115             " some_alias::f(); }",
116             runChecker<InsertAliasCheck>("#include \"foo.h\"\n"
117                                          "namespace b = foo;\n"
118                                          "void f() { f(); }",
119                                          2));
120 }
121 
122 } // namespace utils
123 } // namespace tidy
124 } // namespace clang
125