C ++ / llvm / clang:重构工具方法所需的一般建议

时间:2018-01-04 20:31:37

标签: c++ c++11 clang

我想创建一个工具来检查C ++源文件中方法实现的顺序是否与相应头文件中的方法声明顺序相匹配。

这是我到目前为止的代码的缩短版本:

// #includes and namespace statements snipped
// error handling and log output also snipped

static llvm::cl::OptionCategory ClangOrderCategory("clang-order options");
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
static cl::extrahelp MoreHelp("\nMore help text...");

DeclarationMatcher MethodMatcher = cxxMethodDecl(unless(isImplicit())).bind("methodDeclaration");

class MethodPrinter : public MatchFinder::MatchCallback
{
  public:
    virtual void run(const MatchFinder::MatchResult& result)
    {
        const CXXMethodDecl* decl = result.Nodes.getNodeAs<clang::CXXMethodDecl>("methodDeclaration");

        // get parent declaration, i.e. the method's class
        const CXXRecordDecl* parentDecl = decl->getParent();
        std::string parentName = parentDecl->getNameAsString();

        SourceLocation location = decl->getLocation();
        SourceManager& manager  = result.Context->getSourceManager();

        std::string filename = manager.getFilename(location).str();

        // remove path and leave filename only
        filename = filename.substr(filename.find_last_of("/") + 1, filename.length());

        int lineNumber = manager.getSpellingLineNumber(location);
        DeclarationNameInfo nameInfo = decl->getNameInfo();
        std::string methodName = nameInfo.getName().getAsString();

        // TODO: this relies on class name == filename.[cpp|h], incl. case
        if (filename == parentName + ".h")
        {
            // TODO: store method name and line number in some kind of list
        }
        else
        if (filename == parentName + ".cpp")
        {
            // TODO: store method name and line number in a second list
        }

        // TODO: compare lists to verify method order is identical
    }
};

int main(int argc, const char** argv)
{
    CommonOptionsParser OptionsParser(argc, argv, ClangOrderCategory);
    ClangTool           Tool(OptionsParser.getCompilations(),
                             OptionsParser.getSourcePathList());

    MethodPrinter Printer;
    MatchFinder   Finder;
    Finder.addMatcher(MethodMatcher, &Printer);

    return Tool.run(newFrontendActionFactory(&Finder).get());
}

这显然有很多缺点,但适用于包含其头文件的一个源文件的非常简单的测试集。但是,只要源文件包含更多文件,就会为每个run(...)中遇到的每个方法调用#include

我似乎无法从Tool内找到访问run(...)的方法,因此我无法使用ClangTool::getSourcePaths()来确定我当前处理的文件。我也查看了SourceManager::isInMainFile(...),但这只能让我获得方法实现,而不是声明。

使用clang-formatclang-tidy后,我的印象是clang-*工具使用概念一般是一次处理一个文件并使用shell来处理find ... | xargs左右。

现在我开始认为我的一般方法是错误的。这通常是怎么做的?

对于比我更了解铿锵的人,能否分享他们如何解决这个问题?

0 个答案:

没有答案