//===- unittests/AST/RawCommentForDeclTestTest.cpp //-------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/AST/ASTConsumer.h" #include "clang/AST/DeclGroup.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Tooling/Tooling.h" #include "gmock/gmock-matchers.h" #include "gtest/gtest.h" namespace clang { struct FoundComment { std::string DeclName; bool IsDefinition; std::string Comment; bool operator==(const FoundComment &RHS) const { return DeclName == RHS.DeclName && IsDefinition == RHS.IsDefinition && Comment == RHS.Comment; } friend llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream, const FoundComment &C) { return Stream << "{Name: " << C.DeclName << ", Def: " << C.IsDefinition << ", Comment: " << C.Comment << "}"; } }; class CollectCommentsAction : public ASTFrontendAction { public: CollectCommentsAction(std::vector &Comments) : Comments(Comments) {} std::unique_ptr CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) override { CI.getLangOpts().CommentOpts.ParseAllComments = true; return std::make_unique(*this); } std::vector &Comments; private: class Consumer : public clang::ASTConsumer { private: CollectCommentsAction &Action; public: Consumer(CollectCommentsAction &Action) : Action(Action) {} bool HandleTopLevelDecl(DeclGroupRef DG) override { for (Decl *D : DG) { if (NamedDecl *ND = dyn_cast(D)) { auto &Ctx = D->getASTContext(); const auto *RC = Ctx.getRawCommentForAnyRedecl(D); Action.Comments.push_back(FoundComment{ ND->getNameAsString(), IsDefinition(D), RC ? RC->getRawText(Ctx.getSourceManager()).str() : ""}); } } return true; } static bool IsDefinition(const Decl *D) { if (const FunctionDecl *FD = dyn_cast(D)) { return FD->isThisDeclarationADefinition(); } if (const TagDecl *TD = dyn_cast(D)) { return TD->isThisDeclarationADefinition(); } return false; } }; }; TEST(RawCommentForDecl, DefinitionComment) { std::vector Comments; auto Action = std::make_unique(Comments); ASSERT_TRUE(tooling::runToolOnCode(std::move(Action), R"cpp( void f(); // f is the best void f() {} )cpp")); EXPECT_THAT(Comments, testing::ElementsAre( FoundComment{"f", false, ""}, FoundComment{"f", true, "// f is the best"})); } } // namespace clang