CppEditor: Consider all "else" branches

... in "Add braces to control statement" quickfix.

Change-Id: Ie9dde7692e72300d350029cac01b712795c6e200
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Christian Kandeler
2024-03-07 11:10:31 +01:00
parent c19f97bd23
commit 71ada2b478
2 changed files with 331 additions and 3 deletions

View File

@@ -8243,6 +8243,298 @@ void MyObject::f()
original = R"delim( original = R"delim(
void MyObject::f() void MyObject::f()
{
@if (true)
emit mySig();
else
emit otherSig();
})delim";
expected = R"delim(
void MyObject::f()
{
@if (true) {
emit mySig();
} else {
emit otherSig();
}
})delim";
QTest::newRow("if with one else, unbraced") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (true) {
emit mySig();
} else
emit otherSig();
})delim";
expected = R"delim(
void MyObject::f()
{
@if (true) {
emit mySig();
} else {
emit otherSig();
}
})delim";
QTest::newRow("if with one else, if braced") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (true)
emit mySig();
else {
emit otherSig();
}
})delim";
expected = R"delim(
void MyObject::f()
{
@if (true) {
emit mySig();
} else {
emit otherSig();
}
})delim";
QTest::newRow("if with one else, else braced") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (true) {
emit mySig();
} else {
emit otherSig();
}
})delim";
expected.clear();
QTest::newRow("if with one else, both braced") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (x == 1)
emit sig1();
else if (x == 2)
emit sig2();
})delim";
expected = R"delim(
void MyObject::f()
{
if (x == 1) {
emit sig1();
} else if (x == 2) {
emit sig2();
}
})delim";
QTest::newRow("if-else chain without final else, unbraced") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (x == 1) {
emit sig1();
} else if (x == 2)
emit sig2();
})delim";
expected = R"delim(
void MyObject::f()
{
if (x == 1) {
emit sig1();
} else if (x == 2) {
emit sig2();
}
})delim";
QTest::newRow("if-else chain without final else, partially braced 1") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (x == 1)
emit sig1();
else if (x == 2) {
emit sig2();
}
})delim";
expected = R"delim(
void MyObject::f()
{
if (x == 1) {
emit sig1();
} else if (x == 2) {
emit sig2();
}
})delim";
QTest::newRow("if-else chain without final else, partially braced 2") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (x == 1) {
emit sig1();
} else if (x == 2) {
emit sig2();
}
})delim";
expected.clear();
QTest::newRow("if-else chain without final else, fully braced") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (x == 1)
emit sig1();
else if (x == 2)
emit sig2();
else if (x == 3)
emit sig3();
else
emit otherSig();
})delim";
expected = R"delim(
void MyObject::f()
{
if (x == 1) {
emit sig1();
} else if (x == 2) {
emit sig2();
} else if (x == 3) {
emit sig3();
} else {
emit otherSig();
}
})delim";
QTest::newRow("if-else chain, unbraced") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (x == 1) {
emit sig1();
} else if (x == 2)
emit sig2();
else if (x == 3)
emit sig3();
else
emit otherSig();
})delim";
expected = R"delim(
void MyObject::f()
{
if (x == 1) {
emit sig1();
} else if (x == 2) {
emit sig2();
} else if (x == 3) {
emit sig3();
} else {
emit otherSig();
}
})delim";
QTest::newRow("if-else chain, partially braced 1") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (x == 1)
emit sig1();
else if (x == 2) {
emit sig2();
} else if (x == 3)
emit sig3();
else
emit otherSig();
})delim";
expected = R"delim(
void MyObject::f()
{
if (x == 1) {
emit sig1();
} else if (x == 2) {
emit sig2();
} else if (x == 3) {
emit sig3();
} else {
emit otherSig();
}
})delim";
QTest::newRow("if-else chain, partially braced 2") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (x == 1)
emit sig1();
else if (x == 2)
emit sig2();
else if (x == 3) {
emit sig3();
} else
emit otherSig();
})delim";
expected = R"delim(
void MyObject::f()
{
if (x == 1) {
emit sig1();
} else if (x == 2) {
emit sig2();
} else if (x == 3) {
emit sig3();
} else {
emit otherSig();
}
})delim";
QTest::newRow("if-else chain, partially braced 3") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (x == 1)
emit sig1();
else if (x == 2)
emit sig2();
else if (x == 3)
emit sig3();
else {
emit otherSig();
}
})delim";
expected = R"delim(
void MyObject::f()
{
if (x == 1) {
emit sig1();
} else if (x == 2) {
emit sig2();
} else if (x == 3) {
emit sig3();
} else {
emit otherSig();
}
})delim";
QTest::newRow("if-else chain, partially braced 4") << original << expected;
original = R"delim(
void MyObject::f()
{
@if (x == 1) {
emit sig1();
} else if (x == 2) {
emit sig2();
} else if (x == 3) {
emit sig3();
} else {
emit otherSig();
}
})delim";
expected.clear();
QTest::newRow("if-else chain, fully braced") << original << expected;
original = R"delim(
void MyObject::f()
{ {
@while (true) @while (true)
emit mySig(); emit mySig();

View File

@@ -809,9 +809,11 @@ template<typename Statement> class AddBracesToControlStatementOp : public CppQui
{ {
public: public:
AddBracesToControlStatementOp(const CppQuickFixInterface &interface, AddBracesToControlStatementOp(const CppQuickFixInterface &interface,
const QList<Statement *> &statements) const QList<Statement *> &statements,
StatementAST *elseStatement,
int elseToken)
: CppQuickFixOperation(interface, 0) : CppQuickFixOperation(interface, 0)
, m_statements(statements) , m_statements(statements), m_elseStatement(elseStatement), m_elseToken(elseToken)
{ {
setDescription(Tr::tr("Add Curly Braces")); setDescription(Tr::tr("Add Curly Braces"));
} }
@@ -828,11 +830,23 @@ public:
if constexpr (std::is_same_v<Statement, DoStatementAST>) { if constexpr (std::is_same_v<Statement, DoStatementAST>) {
const int end = currentFile->startOf(statement->while_token); const int end = currentFile->startOf(statement->while_token);
changes.insert(end, QLatin1String("} ")); changes.insert(end, QLatin1String("} "));
} else if constexpr (std::is_same_v<Statement, IfStatementAST>) {
if (statement->else_statement) {
changes.insert(currentFile->startOf(statement->else_token), "} ");
} else {
changes.insert(currentFile->endOf(statement->statement->lastToken() - 1),
"\n}");
}
} else { } else {
const int end = currentFile->endOf(statement->statement->lastToken() - 1); const int end = currentFile->endOf(statement->statement->lastToken() - 1);
changes.insert(end, QLatin1String("\n}")); changes.insert(end, QLatin1String("\n}"));
} }
} }
if (m_elseStatement) {
changes.insert(currentFile->endOf(m_elseToken), " {");
changes.insert(currentFile->endOf(m_elseStatement->lastToken() - 1), "\n}");
}
currentFile->setChangeSet(changes); currentFile->setChangeSet(changes);
currentFile->apply(); currentFile->apply();
@@ -840,6 +854,8 @@ public:
private: private:
const QList<Statement *> m_statements; const QList<Statement *> m_statements;
StatementAST * const m_elseStatement;
const int m_elseToken;
}; };
} // anonymous namespace } // anonymous namespace
@@ -851,10 +867,30 @@ bool checkControlStatementsHelper(const CppQuickFixInterface &interface, QuickFi
if (!statement) if (!statement)
return false; return false;
QList<Statement *> statements;
if (interface.isCursorOn(triggerToken(statement)) && statement->statement if (interface.isCursorOn(triggerToken(statement)) && statement->statement
&& !statement->statement->asCompoundStatement()) { && !statement->statement->asCompoundStatement()) {
result << new AddBracesToControlStatementOp(interface, QList{statement}); statements << statement;
} }
StatementAST *elseStmt = nullptr;
int elseToken = 0;
if constexpr (std::is_same_v<Statement, IfStatementAST>) {
IfStatementAST *currentIfStmt = statement;
for (elseStmt = currentIfStmt->else_statement, elseToken = currentIfStmt->else_token;
elseStmt && (currentIfStmt = elseStmt->asIfStatement());
elseStmt = currentIfStmt->else_statement, elseToken = currentIfStmt->else_token) {
if (currentIfStmt->statement && !currentIfStmt->statement->asCompoundStatement())
statements << currentIfStmt;
}
if (elseStmt && (elseStmt->asIfStatement() || elseStmt->asCompoundStatement())) {
elseStmt = nullptr;
elseToken = 0;
}
}
if (!statements.isEmpty() || elseStmt)
result << new AddBracesToControlStatementOp(interface, statements, elseStmt, elseToken);
return true; return true;
} }