Clang Tool: переписать ObjCMessageExpr

Я хочу переписать все сообщения в моем коде, мне нужно заменить только селекторы, но мне нужно иметь возможность заменить вложенные выражения f. е. :

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

Я пытался сделать это сclang::Rewriter replaceText и просто сгенерировать новую строку, но есть проблема: это не будет работать, если я изменю длину селекторов, потому что я заменяю вложенные сообщения этими старыми позициями.

Итак, я предположил, что мне нужно использоватьclang::Rewriter ReplaceStmt(originalStatement, newStatement);

Я используюRecursiveASTVisitor чтобы посетить все сообщения, и я хочу скопировать объекты этих сообщений и заменить селекторы:

Как я могу это сделать?

Я пытался использоватьObjCMessageExpr::Create но там так много споров, я не знаю как получитьASTContext &Context and ArrayRef<SourceLocation> SeLocs а такжеExpr *Receiver параметры из исходного сообщения.

Как правильно заменить селекторы во вложенных сообщениях, используя инструмент clang (интерфейс инструмента clang)?

Обновить:

Должен ли я использоватьReplaceStmtWithStmt обратный вызов иASTMatchFinder ?

Обновить:

Я использую следующую функцию для перезаписи текста в файле:

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

И я хочу заменить все messageExpr в коде новым селектором f.e: как это было:

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

как это должно быть:

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

Я использую ReqoursiveASTVisitor:

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

Я создал метод для генерации новой строки expr сообщения:

string StringFromObjCMessageExpr(ObjCMessageExpr& messageExpression) { 
    std::ostringstream stringStream; 
    const string selectorString = messageExpression.getSelector().getAsString(); 
    cout << selectorString << endl; 
    vector<string> 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<string>::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(); Как я могу это исправить?

Ответы на вопрос(1)

Ваш ответ на вопрос