Clang Tool: rewrite ObjCMessageExpr

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 someMessage:@""] foo2:[someInstance someMessage2]];
I tried do it with clang::Rewriter replaceText and just generate new string,
but there is a problem: It would not be work if I change selectors length,
because I replace nested messages with those old positions.

So, I assumed that I need to use clang::Rewriter
ReplaceStmt(originalStatement, newStatement);

I am using RecursiveASTVisitor to visit all messages, and I want to copy
those messages objects, and replace selectors:

How can I do that?

I tried use ObjCMessageExpr::Create but there is so meny args, I don't know
how to get ASTContext &Context and ArrayRef<SourceLocation> SeLocs and Expr
*Receiver parameters from the original message.

What is the proper way to replace selectors in nested messages using clang
tool (clang tooling interface)?

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 someMessage:@""] foo2:[someInstance
someMessage2]];
I tried do it with clang::Rewriter replaceText and just generate new
string,
but there is a problem: It would not be work if I change selectors length,
because I replace nested messages with those old positions.

I don't fully understand what the problem is - can you give an example of
what would happen?

So, I assumed that I need to use clang::Rewriter
ReplaceStmt(originalStatement, newStatement);

I am using RecursiveASTVisitor to visit all messages, and I want to copy
those messages objects, and replace selectors:

How can I do that?

I tried use ObjCMessageExpr::Create but there is so meny args, I don't know
how to get ASTContext &Context and ArrayRef<SourceLocation> SeLocs and Expr
*Receiver parameters from the original message.

What is the proper way to replace selectors in nested messages using clang
tool (clang tooling interface)?

I'd usually suggest the AST matchers, but you can also use the RAV - the
AST matchers make it a little easier to get all information you need
together...

Cheers,
/Manuel

I am using following function to rewrite text in file:

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

And I want to replace all messageExpr in code with new selector f.e:
how it was:
[object someMessage:[object2 someMessage:obj3 calculate:obj4]];
how it should be:
[object newSelector:[object2 newSelector:obj3 newSelector:obj4]];

I am using ReqoursiveASTVisitor:

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

I created method for generating new message expr string:

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);
}

The problem occurs when I try to replace nested messages, like that:
    [simpleClass doSomeActionWithString:string3 andAnotherString:string4];
    [simpleClass doSomeActionWithString:str andAnotherString:str2];
    [simpleClass doSomeActionWithString:@"" andAnotherString:@"asdasdsad"];
    [simpleClass setSimpleClassZAZAZAZAZAZAZAZA:[simpleClass
getSimpleClassZAZAZAZAZAZAZAZA]];

the result is:

    [simpleClass newSelector:string3 newSelector:string4 ];
    [simpleClass newSelector:str newSelector:str2 ];
    [simpleClass newSelector:@"" newSelector:@"asdasdsad" ];
    [simpleClass newSelector:[simpleClass getSimp[simpleClass newSelector]];
                                                                   ^
                                                                   ^
                                                                   ^
                                                                   ^
because messageExpression has "old" value of getLocStart(); and
getLocEnd(); How can I fix it?