Мне нужно написать утилиту для рефакторинга исходного кода на C / C ++. Для этого я использую Clang. Clang построен на Windows 7 x64 с Visual Studio 2012.
Ниже приведен код, который необходимо инвертировать условия IF
и поменять блоки кода THEN
а также ELSE
,
void foo(int* a, int *b)
{
if (a[0] > 1)
{
b[0] = 2;
}
else
{
b[0] = 3;
}
}
Для базы я использую пример https://github.com/eliben/llvm-clang-samples/blob/master/src_clang/tooling_sample.cpp
Для этого я обхожу все условия и меняю каждое из них.
class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor> {
public:
MyASTVisitor(Rewriter &R) : TheRewriter(R) {}
bool VisitStmt(Stmt *s)
{
if (isa<IfStmt>(s))
{
IfStmt * IfStatement = cast<IfStmt>(s);
Stmt * Then = IfStatement->getThen();
Stmt * Else = IfStatement->getElse();
Expr * ifCondition = IfStatement->getCond();
SourceRange conditionRange = IfStatement->getCond()->getSourceRange();
stringstream invertConditionStream;
invertConditionStream << " !( " << TheRewriter.ConvertToString(ifCondition) << " ) ";
TheRewriter.ReplaceText(conditionRange, invertConditionStream.str());
TheRewriter.ReplaceStmt(Then, Else);
TheRewriter.ReplaceStmt(Else, Then);
}
return true;
}
Результат рефакторинга показан ниже:
void foo(int* a, int *b)
{
if ( !( a[0] > 1 ) )
{
b[0] = 3;
}
else
{
b[0] = 2;
}
}
Не так хорошо, как мне нравится, но работает.
Но если вы занимаетесь рефакторингом, нижеприведенная программа получается на выходе из приложения каши.
void foo(int* a, int *b)
{
if (a[0] > 1)
{
b[0] = 2;
if (a[0] > 1)
{
b[0] = 2;
}
else
{
b[0] = 3;
}
}
else
{
b[0] = 3;
}
}
Результат моих утилит:
vo !( a[0] > 1 ) nt* a{
b[0] = 3;
}
!( a[0] > 1 {
b[0] = 2;
}
;
}else
{
b[0] = 2;
if (a[0] > 1) {
b[0] = 2;
} else {
b[0] = 3;
}
}}
Скажите, что я делаю не так? Есть ли в Clang какие-то другие функции для рефакторинга, такие как переименование переменных и меток перехода?
Заранее спасибо.
Задача ещё не решена.