From a3580db7bcd12c91721c36d3c500d98a275f784f Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Wed, 18 Nov 2009 16:12:23 +0100 Subject: [PATCH] Split if statements. --- src/plugins/cppeditor/cppquickfix.cpp | 109 ++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 5 deletions(-) diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp index b6a21ed9d2c..622e41962a3 100644 --- a/src/plugins/cppeditor/cppquickfix.cpp +++ b/src/plugins/cppeditor/cppquickfix.cpp @@ -142,6 +142,98 @@ private: BinaryExpressionAST *pattern; }; +/* + Replace + if (something && something_else) { + } + + with + if (something) { + if (something_else) { + } + } +*/ +class SplitIfStatementOp: public QuickFixOperation +{ +public: + SplitIfStatementOp(Document::Ptr doc, const Snapshot &snapshot, CPPEditor *editor) + : QuickFixOperation(doc, snapshot), matcher(doc->translationUnit()), + condition(0), pattern(0), editor(editor) + {} + + virtual QString description() const + { + return QLatin1String("Split if statement"); // ### tr? + } + + bool match(IfStatementAST *statement) + { + condition = mk.BinaryExpression(); + pattern = mk.IfStatement(condition); + + if (statement->match(pattern, &matcher) + && pattern->statement + && pattern->rparen_token + && tokenAt(condition->binary_op_token).is(T_AMPER_AMPER)) + return true; + + return false; + } + + virtual void apply() + { + StatementAST *ifTrueStatement = pattern->statement; + CompoundStatementAST *compoundStatement = ifTrueStatement->asCompoundStatement(); + + QTextCursor completeIfStatement = selectNode(pattern); + { + // ### HACK + const int anchor = completeIfStatement.anchor(); + const int position = completeIfStatement.position(); + completeIfStatement.setPosition(position); + completeIfStatement.setPosition(anchor, QTextCursor::KeepAnchor); + } + + // take the right-expression from the condition. + const QString rightCondition = selectNode(condition->right_expression).selectedText(); + replace(endOf(condition->left_expression), startOf(pattern->rparen_token), QString()); + + int offset = 0; + + if (compoundStatement) + offset = endOf(compoundStatement->lbrace_token); + else + offset = endOf(pattern->rparen_token); + + // create the nested if statement + QString nestedIfStatement; + + if (! compoundStatement) + nestedIfStatement += QLatin1String(" {"); // open a compound statement + + nestedIfStatement += QLatin1String("\nif ("); + nestedIfStatement += rightCondition; + nestedIfStatement += QLatin1String(") {\n}"); + + insert(offset, nestedIfStatement); + + if (! compoundStatement) + insert(endOf(ifTrueStatement), "\n}"); // finish the compound statement + + QTextCursor tc = textCursor(); + tc.beginEditBlock(); + execute(); + editor->indentInsertedText(completeIfStatement); + tc.endEditBlock(); + } + +private: + ASTMatcher matcher; + ASTPatternBuilder mk; + BinaryExpressionAST *condition; + IfStatementAST *pattern; + QPointer<CPPEditor> editor; +}; } // end of anonymous namespace @@ -279,15 +371,22 @@ int CPPQuickFixCollector::startCompletion(TextEditor::ITextEditable *editable) const QList<AST *> path = astPath(_editor->textCursor()); // ### build the list of the quick fix ops by scanning path. - RewriteLogicalAndOp *op = new RewriteLogicalAndOp(info.doc, info.snapshot); - QuickFixOperationPtr quickFix(op); + QSharedPointer<RewriteLogicalAndOp> rewriteLogicalAndOp(new RewriteLogicalAndOp(info.doc, info.snapshot)); + QSharedPointer<SplitIfStatementOp> splitIfStatement(new SplitIfStatementOp(info.doc, info.snapshot, _editor)); for (int i = path.size() - 1; i != -1; --i) { AST *node = path.at(i); + + // ### TODO: generalize + if (BinaryExpressionAST *binary = node->asBinaryExpression()) { - if (op->match(binary)) { - _quickFixes.append(quickFix); - break; + if (! _quickFixes.contains(rewriteLogicalAndOp) && rewriteLogicalAndOp->match(binary)) { + _quickFixes.append(rewriteLogicalAndOp); + } + + } else if (IfStatementAST *ifStatement = node->asIfStatement()) { + if (! _quickFixes.contains(splitIfStatement) && splitIfStatement->match(ifStatement)) { + _quickFixes.append(splitIfStatement); } } } -- GitLab