基于Clang库获取源文件所有注释

Clang默认只分析以 /**///开头的文档注释,需要通过添加命令行参数-fparse-all-comments分析所有注释。


实现

#include "clang/AST/ASTConsumer.h"#include "clang/AST/RecursiveASTVisitor.h"#include "clang/Frontend/CompilerInstance.h"#include "clang/Frontend/FrontendAction.h"#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"#include "clang/Driver/Options.h"#include "clang/Rewrite/Frontend/FixItRewriter.h"#include "clang/Rewrite/Frontend/FrontendActions.h"#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"#include "clang/Tooling/CommonOptionsParser.h"#include "clang/Tooling/Syntax/BuildTree.h"#include "clang/Tooling/Syntax/Tokens.h"#include "clang/Tooling/Syntax/Tree.h"#include "clang/Tooling/Tooling.h"#include "clang/ASTMatchers/ASTMatchFinder.h"#include "clang/ASTMatchers/ASTMatchers.h"#include "llvm/ADT/STLExtras.h"#include "llvm/Option/OptTable.h"#include "llvm/Support/Path.h"#include "llvm/Support/Signals.h"#include "llvm/Support/TargetSelect.h"using namespace clang;using namespace clang::ast_matchers;using namespace clang::driver;using namespace clang::tooling;using namespace llvm;/// 定义命令行选项static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);static cl::extrahelp MoreHelp(    "	For example, to run comment
"    "
");static cl::OptionCategory ClangCheckCategory("comment options");static const opt::OptTable &Options = getDriverOptTable();static cl::opt    VISITORDump("visitor",            cl::desc(Options.getOptionHelpText(options::OPT_ast_dump)),            cl::cat(ClangCheckCategory));/// 定义Visitorclass CommClassVisitor : public RecursiveASTVisitor {public:  explicit CommClassVisitor(ASTContext *context, SourceManager *sm,                            Rewriter *rw)      : context_(context), sm_(sm), rewriter_(rw) {}    bool VisitStmt(Stmt *s) {        // 当前文件,排除包含文件      if (sm_->isInMainFile(s->getBeginLoc()) && isa(s)) {            /// 插入注释            IfStmt *IfStatement = cast(s);            Stmt *Then = IfStatement->getThen();            rewriter_->InsertText(Then->getBeginLoc(), "// visitor, the 'if' part
", true, true);            Stmt *Else = IfStatement->getElse();            if (Else) {              rewriter_->InsertText(Else->getBeginLoc(), "// visitor, the 'else' part
", true, true);            }        }      return true;    }    bool VisitDecl(Decl *d) {        /// 遍历声明相关的注释        ASTContext &ctx = d->getASTContext();        SourceManager &sm = ctx.getSourceManager();        const RawComment *rc = d->getASTContext().getRawCommentForDeclNoCache(d);        //const RawComment *rc = d->getASTContext().getRawCommentForAnyRedecl(d);               if (rc) {            // Found comment!            SourceRange range = rc->getSourceRange();            PresumedLoc startPos = sm.getPresumedLoc(range.getBegin());            PresumedLoc endPos = sm.getPresumedLoc(range.getEnd());            llvm::StringRef raw = rc->getRawText(sm);            std::string brief = rc->getBriefText(ctx);            llvm::outs() << brief << "
";            llvm::outs() << raw << "
";        }      return true;    }private:  ASTContext *context_;  SourceManager *sm_;  std::string caller_;  Rewriter *rewriter_;};class CommClassConsumer : public clang::ASTConsumer {public:  explicit CommClassConsumer(ASTContext *context, SourceManager *sm,                                  Rewriter *rw)      : visitor_(context, sm, rw), sm_(sm), rewriter_(rw) {}  ~CommClassConsumer() {    llvm::outs() << "I have finished get comments." << "
";  }  virtual void Initialize(ASTContext &Context) override {    context_ = &Context;  }  virtual void HandleTranslationUnit(clang::ASTContext &context) override {    /// 遍历所有注释    bool empty = context.Comments.empty();    if (!empty) {        SourceManager &sm = context.getSourceManager();        const std::map *commentList =            context.Comments.getCommentsInFile(sm.getMainFileID());        for (auto comment : *commentList) {          const char *brief = comment.second->getBriefText(context);          llvm::outs() << brief << "
";          StringRef raw = comment.second->getRawText(sm);          llvm::outs() << raw << "
";        }        llvm::outs() << "------------------------------" << "
";    }    if (VISITORDump) {      // 使用遍历模式      visitor_.TraverseDecl(context.getTranslationUnitDecl());    }   }private:  CommClassVisitor visitor_;  ASTContext *context_;  SourceManager *sm_;  Rewriter *rewriter_;};class CommClassAction : public clang::ASTFrontendAction {public:  void EndSourceFileAction() override {    //rewriter_.getEditBuffer(rewriter_.getSourceMgr().getMainFileID()) .write(llvm::outs());    rewriter_.overwriteChangedFiles();  }  virtual std::unique_ptr  CreateASTConsumer(clang::CompilerInstance &compiler, llvm::StringRef in_file) {    // 屏蔽错误信息输出    compiler.getDiagnostics().setClient(new IgnoringDiagConsumer()); // 相当于-w    rewriter_.setSourceMgr(compiler.getSourceManager(), compiler.getLangOpts());    return std::make_unique(        &compiler.getASTContext(), &compiler.getSourceManager(), &rewriter_);  }private:  Rewriter rewriter_;  };//命令行参数: ast.cpp --  屏蔽编译数据库找不到int main(int argc, const char **argv) {  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);  // Initialize targets for clang module support.  llvm::InitializeAllTargets();  llvm::InitializeAllTargetMCs();  llvm::InitializeAllAsmPrinters();  llvm::InitializeAllAsmParsers();  auto ExpectedParser =      CommonOptionsParser::create(argc, argv, ClangCheckCategory);  if (!ExpectedParser) {    llvm::errs() << ExpectedParser.takeError();    return 1;  }  CommonOptionsParser &OptionsParser = ExpectedParser.get();  ClangTool Tool(OptionsParser.getCompilations(),                 OptionsParser.getSourcePathList());  std::unique_ptr FrontendFactory;  FrontendFactory = newFrontendActionFactory();  return Tool.run(FrontendFactory.get());}

验证

测试文件:

/// for linux,__cdecl// g++ -g ast.cpp -std=c++11 -I../src -o ast#include#include "stub.h"using namespace std;templatevoid swap(T &a, T &b){    T temp = a;    a = b;    b = temp;}// Class Aclass A{    int i;public:    /// function foo for A    int foo(int a){        if(a > 1)            cout<<"I am A_foo:"<< a < 1:"<< a <

执行:

./comm_print --extra-arg=-fparse-all-comments --extra-arg=-Wdocumentation -visitor ast.cpp --

结果:


发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章