コード内のすべてのメッセージを書き直したいのですが、セレクターのみを置き換える必要がありますが、ネストされた式 fe を置き換えることができる必要があります。
[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 を新しいセレクター fe: に置き換えたい:
[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();
どうすれば修正できますか?