diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp index ea09db7d8c20116a10a55f68859f460f4eb55819..f5819b74ed7c04c10723c141586167b757d15301 100644 --- a/src/plugins/cppeditor/cppquickfix.cpp +++ b/src/plugins/cppeditor/cppquickfix.cpp @@ -35,6 +35,8 @@ #include <TranslationUnit.h> #include <ASTVisitor.h> #include <AST.h> +#include <ASTPatternBuilder.h> +#include <ASTMatcher.h> #include <Token.h> #include <cpptools/cppmodelmanagerinterface.h> @@ -111,6 +113,66 @@ public: } }; +class RewriteLogicalAndOp: public QuickFixOperation +{ +public: + RewriteLogicalAndOp(Document::Ptr doc, const Snapshot &snapshot) + : QuickFixOperation(doc, snapshot), matcher(doc->translationUnit()), + left(0), right(0), pattern(0) + {} + + virtual QString description() const + { + return QLatin1String("Rewrite condition using ||"); // ### tr? + } + + bool match(BinaryExpressionAST *expression) + { + left = mk.UnaryExpression(); + right = mk.UnaryExpression(); + pattern = mk.BinaryExpression(left, right); + + if (expression->match(pattern, &matcher) && + tokenAt(pattern->binary_op_token).is(T_AMPER_AMPER) && + tokenAt(left->unary_op_token).is(T_EXCLAIM) && + tokenAt(right->unary_op_token).is(T_EXCLAIM)) { + return true; + } + + return false; + } + + virtual void apply() + { + // nothing to do. + + QTextCursor binaryOp = selectToken(pattern->binary_op_token); + QTextCursor firstUnaryOp = selectToken(left->unary_op_token); + QTextCursor secondUnaryOp = selectToken(right->unary_op_token); + + QTextCursor tc = textCursor(); + tc.beginEditBlock(); + firstUnaryOp.removeSelectedText(); + secondUnaryOp.removeSelectedText(); + binaryOp.insertText(QLatin1String("||")); + firstUnaryOp.insertText(QLatin1String("!(")); + + QTextCursor endOfRightUnaryExpression = selectToken(right->lastToken() - 1); + endOfRightUnaryExpression.setPosition(endOfRightUnaryExpression.position()); // ### method + + endOfRightUnaryExpression.insertText(QLatin1String(")")); + tc.endEditBlock(); + } + +private: + ASTMatcher matcher; + ASTPatternBuilder mk; + UnaryExpressionAST *left; + UnaryExpressionAST *right; + BinaryExpressionAST *pattern; +}; + + } // end of anonymous namespace @@ -183,8 +245,6 @@ int CPPQuickFixCollector::startCompletion(TextEditor::ITextEditable *editable) const SemanticInfo info = _editor->semanticInfo(); - QTextCursor textCursor = _editor->textCursor(); - if (info.revision != _editor->document()->revision()) { // outdated qWarning() << "TODO: outdated semantic info, force a reparse."; @@ -197,6 +257,19 @@ 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); + + for (int i = path.size() - 1; i != -1; --i) { + AST *node = path.at(i); + if (BinaryExpressionAST *binary = node->asBinaryExpression()) { + if (op->match(binary)) { + _quickFixes.append(quickFix); + break; + } + } + } + if (! _quickFixes.isEmpty()) return editable->position(); }