Clang工具:重写ObjCMessageExpr

 风行天下的石头_467 发布于 2023-02-12 15:11

我想重写我的代码中的所有消息,我只需要替换选择器,但我需要能够替换嵌套的表达式fe:

[super foo:[someInstance someMessage:@""] foo2:[someInstance someMessage2]];

我尝试使用clang::Rewriter replaceText并生成新的字符串,但是有一个问题:如果我更改选择器长度,它将无法工作,因为我用那些旧位置替换嵌套消息.

所以,我认为我需要使用 clang::Rewriter ReplaceStmt(originalStatement, newStatement);

RecursiveASTVisitor用来访问所有消息,我想复制这些消息对象,并替换选择器:

我怎样才能做到这一点?

我试过使用ObjCMessageExpr::Create但是有如此经典的args,我不知道如何从原始消息中获取ASTContext &Context and ArrayRef SeLocsExpr *Receiver参数.

使用clang工具(clang工具界面)替换嵌套消息中选择器的正确方法是什么?

更新:

我应该使用ReplaceStmtWithStmt回调ASTMatchFinder吗?

更新:

我正在使用以下函数来重写文件中的文本:

void ReplaceText(SourceLocation start, unsigned originalLength, StringRef string) { 
    m_rewriter.ReplaceText(start, originalLength, string); 
    m_rewriter.overwriteChangedFiles(); 
} 

我想用新的选择器替换代码中的所有messageExpr:它是怎么回事:

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

怎么样:

[object newSelector:[object2 newSelector:obj3 newSelector:obj4]]; 

我正在使用ReqoursiveASTVisitor:

bool VisitStmt(Stmt *statement) { 
    if (ObjCMessageExpr *messageExpr = dyn_cast(statement)) { 
         ReplaceMessage(*messageExpr) 
    } 
    return true; 
} 

我创建了生成新消息expr字符串的方法:

string StringFromObjCMessageExpr(ObjCMessageExpr& messageExpression) { 
    std::ostringstream stringStream; 
    const string selectorString = messageExpression.getSelector().getAsString(); 
    cout << selectorString << endl; 
    vector methodParts; 
    split(selectorString, ParametersDelimiter, methodParts); 
    stringStream << "[" ; 
    const string receiver = GetStringFromLocations(m_compiler, messageExpression.getReceiverRange().getBegin(), messageExpression.getSelectorStartLoc()); 
    stringStream << receiver; 
    clang::ObjCMessageExpr::arg_iterator argIterator = messageExpression.arg_begin(); 
    for (vector::const_iterator partsIterator = methodParts.begin(); 
         partsIterator != methodParts.end(); 
         ++partsIterator) { 
        stringStream << "newSelector"; 
        if (messageExpression.getNumArgs() != 0) { 
            const clang::Stmt *argument = *argIterator; 
            stringStream << ":" << GetStatementString(*argument) << " "; 
            ++argIterator; 
        } 
    } 
    stringStream << "]"; 
    return stringStream.str(); 
} 

void ReplaceMessage(ObjCMessageExpr& messageExpression) { 
    SourceLocation locStart = messageExpression.getLocStart(); 
    SourceLocation locEnd = messageExpression.getLocEnd(); 
    string newExpr = StringFromObjCMessageExpr(messageExpression); 
    const int exprStringLegth = m_rewriter.getRangeSize(SourceRange(locStart, locEnd)); 
    ReplaceText(locStart, exprStringLegth, newExpr); 
} 

当我尝试替换嵌套消息时会出现问题,例如:

[simpleClass doSomeActionWithString:string3 andAnotherString:string4]; 
[simpleClass doSomeActionWithString:str andAnotherString:str2]; 
[simpleClass doSomeActionWithString:@"" andAnotherString:@"asdasdsad"]; 
[simpleClass setSimpleClassZAZAZAZAZAZAZAZA:[simpleClass getSimpleClassZAZAZAZAZAZAZAZA]];

结果是:

[simpleClass newSelector:string3 newSelector:string4 ]; 
[simpleClass newSelector:str newSelector:str2 ]; 
[simpleClass newSelector:@"" newSelector:@"asdasdsad" ]; 
[simpleClass newSelector:[simpleClass getSimp[simpleClass newSelector]]; 

因为messageExpression有"老"的价值getLocStart();getLocEnd();如何解决呢?

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有