1 //===- unittests/AST/RawCommentForDeclTestTest.cpp 2 //-------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "clang/AST/ASTConsumer.h" 11 #include "clang/AST/DeclGroup.h" 12 #include "clang/Frontend/CompilerInstance.h" 13 #include "clang/Frontend/FrontendAction.h" 14 #include "clang/Tooling/Tooling.h" 15 16 #include "gmock/gmock-matchers.h" 17 #include "gtest/gtest.h" 18 19 namespace clang { 20 21 struct FoundComment { 22 std::string DeclName; 23 bool IsDefinition; 24 std::string Comment; 25 26 bool operator==(const FoundComment &RHS) const { 27 return DeclName == RHS.DeclName && IsDefinition == RHS.IsDefinition && 28 Comment == RHS.Comment; 29 } 30 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream, 31 const FoundComment &C) { 32 return Stream << "{Name: " << C.DeclName << ", Def: " << C.IsDefinition 33 << ", Comment: " << C.Comment << "}"; 34 } 35 }; 36 37 class CollectCommentsAction : public ASTFrontendAction { 38 public: 39 CollectCommentsAction(std::vector<FoundComment> &Comments) 40 : Comments(Comments) {} 41 42 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 43 llvm::StringRef) override { 44 CI.getLangOpts().CommentOpts.ParseAllComments = true; 45 return std::make_unique<Consumer>(*this); 46 } 47 48 std::vector<FoundComment> &Comments; 49 50 private: 51 class Consumer : public clang::ASTConsumer { 52 private: 53 CollectCommentsAction &Action; 54 55 public: 56 Consumer(CollectCommentsAction &Action) : Action(Action) {} 57 58 bool HandleTopLevelDecl(DeclGroupRef DG) override { 59 for (Decl *D : DG) { 60 if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) { 61 auto &Ctx = D->getASTContext(); 62 const auto *RC = Ctx.getRawCommentForAnyRedecl(D); 63 Action.Comments.push_back(FoundComment{ 64 ND->getNameAsString(), IsDefinition(D), 65 RC ? RC->getRawText(Ctx.getSourceManager()).str() : ""}); 66 } 67 } 68 69 return true; 70 } 71 72 static bool IsDefinition(const Decl *D) { 73 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 74 return FD->isThisDeclarationADefinition(); 75 } 76 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { 77 return TD->isThisDeclarationADefinition(); 78 } 79 return false; 80 } 81 }; 82 }; 83 84 TEST(RawCommentForDecl, DefinitionComment) { 85 std::vector<FoundComment> Comments; 86 auto Action = std::make_unique<CollectCommentsAction>(Comments); 87 ASSERT_TRUE(tooling::runToolOnCode(std::move(Action), R"cpp( 88 void f(); 89 90 // f is the best 91 void f() {} 92 )cpp")); 93 EXPECT_THAT(Comments, testing::ElementsAre( 94 FoundComment{"f", false, ""}, 95 FoundComment{"f", true, "// f is the best"})); 96 } 97 98 } // namespace clang 99