//===---- NamespaceAliaserTest.cpp - clang-tidy //----------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../clang-tidy/utils/NamespaceAliaser.h" #include "ClangTidyTest.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "gtest/gtest.h" namespace clang { namespace tidy { namespace utils { // This checker is for testing only. It can only run on one test case // (e.g. with one SourceManager). class InsertAliasCheck : public ClangTidyCheck { public: InsertAliasCheck(StringRef Name, ClangTidyContext *Context) :ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override { Finder->addMatcher(ast_matchers::callExpr().bind("foo"), this); } void check(const ast_matchers::MatchFinder::MatchResult &Result) override { if (!Aliaser) Aliaser.reset(new NamespaceAliaser(*Result.SourceManager)); const auto *Call = Result.Nodes.getNodeAs("foo"); assert(Call != nullptr && "Did not find node \"foo\""); auto Hint = Aliaser->createAlias(*Result.Context, *Call, "::foo::bar", {"b", "some_alias"}); if (Hint.hasValue()) diag(Call->getLocStart(), "Fix for testing") << Hint.getValue(); diag(Call->getLocStart(), "insert call") << FixItHint::CreateInsertion( Call->getLocStart(), Aliaser->getNamespaceName(*Result.Context, *Call, "::foo::bar") + "::"); } private: std::unique_ptr Aliaser; }; template std::string runChecker(StringRef Code, unsigned ExpectedWarningCount) { std::map AdditionalFileContents = {{"foo.h", "namespace foo {\n" "namespace bar {\n" "}\n" "void func() { }\n" "}"}}; std::vector errors; std::string result = test::runCheckOnCode(Code, &errors, "foo.cc", None, ClangTidyOptions(), AdditionalFileContents); EXPECT_EQ(ExpectedWarningCount, errors.size()); return result; } TEST(NamespaceAliaserTest, AddNewAlias) { EXPECT_EQ("#include \"foo.h\"\n" "void f() {\n" "namespace b = ::foo::bar;" " b::f(); }", runChecker("#include \"foo.h\"\n" "void f() { f(); }", 2)); } TEST(NamespaceAliaserTest, ReuseAlias) { EXPECT_EQ( "#include \"foo.h\"\n" "void f() { namespace x = foo::bar; x::f(); }", runChecker("#include \"foo.h\"\n" "void f() { namespace x = foo::bar; f(); }", 1)); } TEST(NamespaceAliaserTest, AddsOnlyOneAlias) { EXPECT_EQ("#include \"foo.h\"\n" "void f() {\n" "namespace b = ::foo::bar;" " b::f(); b::f(); }", runChecker("#include \"foo.h\"\n" "void f() { f(); f(); }", 3)); } TEST(NamespaceAliaserTest, LocalConflict) { EXPECT_EQ("#include \"foo.h\"\n" "void f() {\n" "namespace some_alias = ::foo::bar;" " namespace b = foo; some_alias::f(); }", runChecker("#include \"foo.h\"\n" "void f() { namespace b = foo; f(); }", 2)); } TEST(NamespaceAliaserTest, GlobalConflict) { EXPECT_EQ("#include \"foo.h\"\n" "namespace b = foo;\n" "void f() {\n" "namespace some_alias = ::foo::bar;" " some_alias::f(); }", runChecker("#include \"foo.h\"\n" "namespace b = foo;\n" "void f() { f(); }", 2)); } } // namespace utils } // namespace tidy } // namespace clang