Clang Tool: rewrite ObjCMessageExpr

前端 未结 1 1404
猫巷女王i
猫巷女王i 2021-02-07 07:10

I want to rewrite all messages in my code, I need replace only selectors, but I need be able to replace nested expressions f. e. :

[super foo:[someInstance some         


        
1条回答
  •  暖寄归人
    2021-02-07 07:33

    You can rewrite selector name by replacing only continuous parts of selector name. For example, replace only underlined parts

    [object someMessage:[object2 someMessage:obj3 calculate:obj4]];
            ^~~~~~~~~~~          ^~~~~~~~~~~      ^~~~~~~~~
    

    To achieve this you require only

    • number of selector parts - ObjCMessageExpr::getNumSelectorLocs()
    • their locations - ObjCMessageExpr::getSelectorLoc(index)
    • their lengths - ObjCMessageExpr::getSelector().getNameForSlot(index).size().

    Overall, you can rewrite ObjCMessageExpr with the following RecursiveASTVisitor:

    #include "clang/AST/ASTConsumer.h"
    #include "clang/AST/ASTContext.h"
    #include "clang/AST/RecursiveASTVisitor.h"
    #include "clang/Rewrite/Core/Rewriter.h"
    
    namespace clang_tooling
    {
    
    using clang::SourceLocation;
    
    class RewritingVisitor : public clang::ASTConsumer,
                             public clang::RecursiveASTVisitor
    {
    public:
        // You can obtain SourceManager and LangOptions from CompilerInstance when
        // you are creating visitor (which is also ASTConsumer) in
        // clang::ASTFrontendAction::CreateASTConsumer.
        RewritingVisitor(clang::SourceManager &sourceManager,
                         const clang::LangOptions &langOptions)
            : _sourceManager(sourceManager), _rewriter(sourceManager, langOptions)
        {}
    
        virtual void HandleTranslationUnit(clang::ASTContext &context)
        {
            TraverseDecl(context.getTranslationUnitDecl());
            _rewriter.overwriteChangedFiles();
        }
    
        bool VisitObjCMessageExpr(clang::ObjCMessageExpr *messageExpr)
        {
            if (_sourceManager.isInMainFile(messageExpr->getLocStart()))
            {
                clang::Selector selector = messageExpr->getSelector();
                for (unsigned i = 0, end = messageExpr->getNumSelectorLocs();
                     i < end; ++i)
                {
                    SourceLocation selectorLoc = messageExpr->getSelectorLoc(i);
                    _rewriter.ReplaceText(selectorLoc,
                                          selector.getNameForSlot(i).size(),
                                          "newSelector");
                }
            }
            return Base::VisitObjCMessageExpr(messageExpr);
        }
    
    private:
        typedef clang::RecursiveASTVisitor Base;
    
        clang::SourceManager &_sourceManager;
        clang::Rewriter _rewriter;
    };
    
    } // end namespace clang_tooling
    

    0 讨论(0)
提交回复
热议问题