[cfe-dev] Clang Tool: rewrite ObjCMessageExpr

PavelKatunin wk.katunin at gmail.com
Sun Dec 8 22:52:57 PST 2013


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?





--
View this message in context: http://clang-developers.42468.n3.nabble.com/Clang-Tool-rewrite-ObjCMessageExpr-tp4036492p4036524.html
Sent from the Clang Developers mailing list archive at Nabble.com.



More information about the cfe-dev mailing list