diff --git a/src/plugins/cppeditor/cppdeclfromdef.cpp b/src/plugins/cppeditor/cppdeclfromdef.cpp
index 23a11d7a500d090c395670dbfadc34f5d1984c46..d874a474096fea8a2f1a3edb44a4c78cb126371e 100644
--- a/src/plugins/cppeditor/cppdeclfromdef.cpp
+++ b/src/plugins/cppeditor/cppdeclfromdef.cpp
@@ -45,6 +45,7 @@
 #include <QtCore/QCoreApplication>
 
 using namespace CPlusPlus;
+using namespace CppEditor;
 using namespace CppEditor::Internal;
 using namespace CppTools;
 
@@ -146,22 +147,54 @@ QString prettyMinimalType(const FullySpecifiedType &ty,
         return oo(ty);
 }
 
-} // anonymous namespace
+class Operation: public CppQuickFixOperation
+{
+public:
+    Operation(const CppQuickFixState &state, int priority,
+              const QString &targetFileName, const QString &targetSymbolName,
+              const QString &decl)
+        : CppQuickFixOperation(state, priority)
+        , m_targetFileName(targetFileName)
+        , m_targetSymbolName(targetSymbolName)
+        , m_decl(decl)
+    {
+        setDescription(QCoreApplication::tr("Create Declaration from Definition",
+                                            "CppEditor::DeclFromDef"));
+    }
 
-DeclFromDef::DeclFromDef(TextEditor::BaseTextEditor *editor)
-    : CppQuickFixOperation(editor)
-{}
+    void createChanges()
+    {
+        CppRefactoringChanges *changes = refactoringChanges();
 
-QString DeclFromDef::description() const
-{
-    return QCoreApplication::tr("Create Declaration from Definition", "DeclFromDef");
-}
+        Document::Ptr targetDoc = changes->document(m_targetFileName);
+        InsertionPointFinder findInsertionPoint(targetDoc, m_targetSymbolName);
+        int line = 0, column = 0;
+        findInsertionPoint(&line, &column);
+
+        int targetPosition1 = changes->positionInFile(m_targetFileName, line, column);
+        int targetPosition2 = changes->positionInFile(m_targetFileName, line + 1, 0) - 1;
+
+        Utils::ChangeSet target;
+        target.insert(targetPosition1, m_decl);
+        changes->changeFile(m_targetFileName, target);
+
+        changes->reindent(m_targetFileName,
+                          Utils::ChangeSet::Range(targetPosition1, targetPosition2));
+
+        changes->openEditor(m_targetFileName, line, column);
+    }
+
+private:
+    QString m_targetFileName;
+    QString m_targetSymbolName;
+    QString m_decl;
+};
+
+} // anonymous namespace
 
-int DeclFromDef::match(const QList<CPlusPlus::AST *> &path)
+QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &state)
 {
-    m_targetFileName.clear();
-    m_targetSymbolName.clear();
-    m_decl.clear();
+    const QList<AST *> &path = state.path();
 
     FunctionDefinitionAST *funDef = 0;
     int idx = 0;
@@ -171,62 +204,40 @@ int DeclFromDef::match(const QList<CPlusPlus::AST *> &path)
             if (!funDef)
                 funDef = candidate;
         } else if (node->asClassSpecifier()) {
-            return -1;
+            return noResult();
         }
     }
 
     if (!funDef || !funDef->symbol)
-        return -1;
+        return noResult();
 
     Function *method = funDef->symbol;
-    LookupContext context(document(), snapshot());
 
-    if (ClassOrNamespace *targetBinding = context.lookupParent(method)) {
+    if (ClassOrNamespace *targetBinding = state.context().lookupParent(method)) {
         foreach (Symbol *s, targetBinding->symbols()) {
             if (Class *clazz = s->asClass()) {
-                m_targetFileName = QLatin1String(clazz->fileName());
-                m_targetSymbolName = QLatin1String(clazz->identifier()->chars());
-
-                m_decl = generateDeclaration(method, targetBinding);
-
-                return idx;
+                return singleResult(new Operation(state, idx,
+                                                  QLatin1String(clazz->fileName()),
+                                                  QLatin1String(clazz->identifier()->chars()),
+                                                  generateDeclaration(state,
+                                                                      method,
+                                                                      targetBinding)));
             } // ### TODO: support insertion into namespaces
         }
     }
 
-    return -1;
-}
-
-void DeclFromDef::createChanges()
-{
-    CppRefactoringChanges *changes = refactoringChanges();
-
-    Document::Ptr targetDoc = changes->document(m_targetFileName);
-    InsertionPointFinder findInsertionPoint(targetDoc, m_targetSymbolName);
-    int line = 0, column = 0;
-    findInsertionPoint(&line, &column);
-
-    int targetPosition1 = changes->positionInFile(m_targetFileName, line, column);
-    int targetPosition2 = changes->positionInFile(m_targetFileName, line + 1, 0) - 1;
-
-    Utils::ChangeSet target;
-    target.insert(targetPosition1, m_decl);
-    changes->changeFile(m_targetFileName, target);
-
-    changes->reindent(m_targetFileName,
-                      Utils::ChangeSet::Range(targetPosition1, targetPosition2));
-
-    changes->openEditor(m_targetFileName, line, column);
+    return noResult();
 }
 
-QString DeclFromDef::generateDeclaration(Function *method, ClassOrNamespace *targetBinding)
+QString DeclFromDef::generateDeclaration(const CppQuickFixState &state,
+                                         Function *method,
+                                         ClassOrNamespace *targetBinding)
 {
-    LookupContext context(document(), snapshot());
     Overview oo;
     QString decl;
 
     decl.append(prettyMinimalType(method->returnType(),
-                                  context,
+                                  state.context(),
                                   method->scope(),
                                   targetBinding));
 
@@ -238,7 +249,7 @@ QString DeclFromDef::generateDeclaration(Function *method, ClassOrNamespace *tar
             decl.append(QLatin1String(", "));
         Argument *arg = method->argumentAt(argIdx)->asArgument();
         decl.append(prettyMinimalType(arg->type(),
-                                      context,
+                                      state.context(),
                                       method->members(),
                                       targetBinding));
         decl.append(QLatin1Char(' '));
diff --git a/src/plugins/cppeditor/cppdeclfromdef.h b/src/plugins/cppeditor/cppdeclfromdef.h
index 8cbebc9271b3cd77777601e4da3254ac92cb4eff..8b71ef78c046b5c76c2385f3407307f34530d099 100644
--- a/src/plugins/cppeditor/cppdeclfromdef.h
+++ b/src/plugins/cppeditor/cppdeclfromdef.h
@@ -41,23 +41,15 @@ class ClassOrNamespace;
 namespace CppEditor {
 namespace Internal {
 
-class DeclFromDef: public CppQuickFixOperation
+class DeclFromDef: public CppQuickFixFactory
 {
 public:
-    DeclFromDef(TextEditor::BaseTextEditor *editor);
-
-    virtual int match(const QList<CPlusPlus::AST *> &path);
-    virtual QString description() const;
-    virtual void createChanges();
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state);
 
 protected:
-    virtual QString generateDeclaration(CPlusPlus::Function *method,
-                                        CPlusPlus::ClassOrNamespace *targetBinding);
-
-private:
-    QString m_targetFileName;
-    QString m_targetSymbolName;
-    QString m_decl;
+    static QString generateDeclaration(const CppQuickFixState &state,
+                                       CPlusPlus::Function *method,
+                                       CPlusPlus::ClassOrNamespace *targetBinding);
 };
 
 
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index 274639f4141756b2bc76a6c263f93b6a736f0079..6707b2d3e6a9fbbf580609cc85a82350214f7130 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -30,6 +30,7 @@ SOURCES += cppplugin.cpp \
     cppfilewizard.cpp \
     cppclasswizard.cpp \
     cppquickfix.cpp \
+    cppquickfixes.cpp \
     cpprefactoringchanges.cpp \
     cppchecksymbols.cpp \
     cppsemanticinfo.cpp \
diff --git a/src/plugins/cppeditor/cppplugin.cpp b/src/plugins/cppeditor/cppplugin.cpp
index 2b9e980f827da7a19fd53b993eab8e154a5bb937..9d269b536efc4199005005d4178fc296c650f03f 100644
--- a/src/plugins/cppeditor/cppplugin.cpp
+++ b/src/plugins/cppeditor/cppplugin.cpp
@@ -63,6 +63,7 @@
 
 #include <QtGui/QMenu>
 
+using namespace CppEditor;
 using namespace CppEditor::Internal;
 
 enum { QUICKFIX_INTERVAL = 20 };
@@ -208,8 +209,7 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess
 
     m_quickFixCollector = new CppQuickFixCollector;
     addAutoReleasedObject(m_quickFixCollector);
-
-    addAutoReleasedObject(new CppQuickFixFactory);
+    CppQuickFixCollector::registerQuickFixes(this);
 
     CppFileWizard::BaseFileWizardParameters wizardParameters(Core::IWizard::FileWizard);
 
diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp
index fdc9d676ebcada2a5db19b501c5fd8da1e25aa19..eb452c598b9971f341a670394d41aeb1885f36f0 100644
--- a/src/plugins/cppeditor/cppquickfix.cpp
+++ b/src/plugins/cppeditor/cppquickfix.cpp
@@ -31,6 +31,10 @@
 #include "cppeditor.h"
 #include "cppdeclfromdef.h"
 
+#include <AST.h>
+#include <TranslationUnit.h>
+#include <Token.h>
+
 #include <cplusplus/ASTPath.h>
 #include <cplusplus/CppDocument.h>
 #include <cplusplus/ResolveExpression.h>
@@ -39,1702 +43,118 @@
 #include <cplusplus/DependencyTable.h>
 #include <cplusplus/CppRewriter.h>
 
-#include <TranslationUnit.h>
-#include <ASTVisitor.h>
-#include <AST.h>
-#include <ASTPatternBuilder.h>
-#include <ASTMatcher.h>
-#include <Token.h>
-#include <Type.h>
-#include <CoreTypes.h>
-#include <Symbol.h>
-#include <Symbols.h>
-#include <Name.h>
-#include <Names.h>
-#include <Literals.h>
-
 #include <cppeditor/cppeditor.h>
 #include <cppeditor/cpprefactoringchanges.h>
 #include <cpptools/cpptoolsconstants.h>
 #include <cpptools/cppmodelmanagerinterface.h>
 #include <extensionsystem/pluginmanager.h>
 
-#include <QtGui/QApplication>
 #include <QtGui/QTextBlock>
 
+using namespace CppEditor;
 using namespace CppEditor::Internal;
+using namespace TextEditor;
 using namespace CPlusPlus;
 using namespace Utils;
 
-namespace {
-
-class CppQuickFixState: public TextEditor::QuickFixState
-{
-public:
-    QList<CPlusPlus::AST *> path;
-    Snapshot snapshot;
-    SemanticInfo info;
-};
-
-/*
-    Rewrite
-    a op b -> !(a invop b)
-    (a op b) -> !(a invop b)
-    !(a op b) -> (a invob b)
-*/
-class UseInverseOp: public CppQuickFixOperation
-{
-public:
-    UseInverseOp(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), binary(0), nested(0), negation(0)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Rewrite Using %1").arg(replacement);
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        int index = path.size() - 1;
-        binary = path.at(index)->asBinaryExpression();
-        if (! binary)
-            return -1;
-        if (! isCursorOn(binary->binary_op_token))
-            return -1;
-
-        CPlusPlus::Kind invertToken;
-        switch (tokenAt(binary->binary_op_token).kind()) {
-        case T_LESS_EQUAL:
-            invertToken = T_GREATER;
-            break;
-        case T_LESS:
-            invertToken = T_GREATER_EQUAL;
-            break;
-        case T_GREATER:
-            invertToken = T_LESS_EQUAL;
-            break;
-        case T_GREATER_EQUAL:
-            invertToken = T_LESS;
-            break;
-        case T_EQUAL_EQUAL:
-            invertToken = T_EXCLAIM_EQUAL;
-            break;
-        case T_EXCLAIM_EQUAL:
-            invertToken = T_EQUAL_EQUAL;
-            break;
-        default:
-            return -1;
-        }
-
-        CPlusPlus::Token tok;
-        tok.f.kind = invertToken;
-        replacement = QLatin1String(tok.spell());
-
-        // check for enclosing nested expression
-        if (index - 1 >= 0)
-            nested = path[index - 1]->asNestedExpression();
-
-        // check for ! before parentheses
-        if (nested && index - 2 >= 0) {
-            negation = path[index - 2]->asUnaryExpression();
-            if (negation && ! tokenAt(negation->unary_op_token).is(T_EXCLAIM))
-                negation = 0;
-        }
-
-        return index;
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-        if (negation) {
-            // can't remove parentheses since that might break precedence
-            changes.remove(range(negation->unary_op_token));
-        } else if (nested) {
-            changes.insert(startOf(nested), "!");
-        } else {
-            changes.insert(startOf(binary), "!(");
-            changes.insert(endOf(binary), ")");
-        }
-        changes.replace(range(binary->binary_op_token), replacement);
-        refactoringChanges()->changeFile(fileName(), changes);
-    }
-
-private:
-    BinaryExpressionAST *binary;
-    NestedExpressionAST *nested;
-    UnaryExpressionAST *negation;
-
-    QString replacement;
-};
-
-/*
-    Rewrite
-    a op b
-
-    As
-    b flipop a
-*/
-class FlipBinaryOp: public CppQuickFixOperation
-{
-public:
-    FlipBinaryOp(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), binary(0)
-    {}
-
-
-    virtual QString description() const
-    {
-        if (replacement.isEmpty())
-            return QApplication::translate("CppTools::QuickFix", "Swap Operands");
-        else
-            return QApplication::translate("CppTools::QuickFix", "Rewrite Using %1").arg(replacement);
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        int index = path.size() - 1;
-        binary = path.at(index)->asBinaryExpression();
-        if (! binary)
-            return -1;
-        if (! isCursorOn(binary->binary_op_token))
-            return -1;
-
-        CPlusPlus::Kind flipToken;
-        switch (tokenAt(binary->binary_op_token).kind()) {
-        case T_LESS_EQUAL:
-            flipToken = T_GREATER_EQUAL;
-            break;
-        case T_LESS:
-            flipToken = T_GREATER;
-            break;
-        case T_GREATER:
-            flipToken = T_LESS;
-            break;
-        case T_GREATER_EQUAL:
-            flipToken = T_LESS_EQUAL;
-            break;
-        case T_EQUAL_EQUAL:
-        case T_EXCLAIM_EQUAL:
-        case T_AMPER_AMPER:
-        case T_PIPE_PIPE:
-            flipToken = T_EOF_SYMBOL;
-            break;
-        default:
-            return -1;
-        }
-
-        if (flipToken != T_EOF_SYMBOL) {
-            CPlusPlus::Token tok;
-            tok.f.kind = flipToken;
-            replacement = QLatin1String(tok.spell());
-        }
-        return index;
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-
-        changes.flip(range(binary->left_expression), range(binary->right_expression));
-        if (! replacement.isEmpty())
-            changes.replace(range(binary->binary_op_token), replacement);
-
-        refactoringChanges()->changeFile(fileName(), changes);
-    }
-
-private:
-    BinaryExpressionAST *binary;
-    QString replacement;
-};
-
-/*
-    Rewrite
-    !a && !b
-
-    As
-    !(a || b)
-*/
-class RewriteLogicalAndOp: public CppQuickFixOperation
-{
-public:
-    RewriteLogicalAndOp(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), left(0), right(0), pattern(0)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Rewrite Condition Using ||");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        BinaryExpressionAST *expression = 0;
-
-        int index = path.size() - 1;
-        for (; index != -1; --index) {
-            expression = path.at(index)->asBinaryExpression();
-            if (expression)
-                break;
-        }
-
-        if (! expression)
-            return -1;
-
-        if (! isCursorOn(expression->binary_op_token))
-            return -1;
-
-        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 index;
-        }
-
-        return -1;
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-        changes.replace(range(pattern->binary_op_token), QLatin1String("||"));
-        changes.remove(range(left->unary_op_token));
-        changes.remove(range(right->unary_op_token));
-        const int start = startOf(pattern);
-        const int end = endOf(pattern);
-        changes.insert(start, QLatin1String("!("));
-        changes.insert(end, QLatin1String(")"));
-
-        refactoringChanges()->changeFile(fileName(), changes);
-        refactoringChanges()->reindent(fileName(), range(pattern));
-    }
-
-private:
-    ASTMatcher matcher;
-    ASTPatternBuilder mk;
-    UnaryExpressionAST *left;
-    UnaryExpressionAST *right;
-    BinaryExpressionAST *pattern;
-};
-
-class SplitSimpleDeclarationOp: public CppQuickFixOperation
-{
-public:
-    SplitSimpleDeclarationOp(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), declaration(0)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Split Declaration");
-    }
-
-    bool checkDeclaration(SimpleDeclarationAST *declaration) const
-    {
-        if (! declaration->semicolon_token)
-            return false;
-
-        if (! declaration->decl_specifier_list)
-            return false;
-
-        for (SpecifierListAST *it = declaration->decl_specifier_list; it; it = it->next) {
-            SpecifierAST *specifier = it->value;
-
-            if (specifier->asEnumSpecifier() != 0)
-                return false;
-
-            else if (specifier->asClassSpecifier() != 0)
-                return false;
-        }
-
-        if (! declaration->declarator_list)
-            return false;
-
-        else if (! declaration->declarator_list->next)
-            return false;
-
-        return true;
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        CoreDeclaratorAST *core_declarator = 0;
-
-        int index = path.size() - 1;
-        for (; index != -1; --index) {
-            AST *node = path.at(index);
-
-            if (CoreDeclaratorAST *coreDecl = node->asCoreDeclarator())
-                core_declarator = coreDecl;
-
-            else if (SimpleDeclarationAST *simpleDecl = node->asSimpleDeclaration()) {
-                if (checkDeclaration(simpleDecl)) {
-                    declaration = simpleDecl;
-
-                    const int cursorPosition = selectionStart();
-
-                    const int startOfDeclSpecifier = startOf(declaration->decl_specifier_list->firstToken());
-                    const int endOfDeclSpecifier = endOf(declaration->decl_specifier_list->lastToken() - 1);
-
-                    if (cursorPosition >= startOfDeclSpecifier && cursorPosition <= endOfDeclSpecifier)
-                        return index; // the AST node under cursor is a specifier.
-
-                    if (core_declarator && isCursorOn(core_declarator))
-                        return index; // got a core-declarator under the text cursor.
-                }
-
-                break;
-            }
-        }
-
-        return -1;
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-
-        SpecifierListAST *specifiers = declaration->decl_specifier_list;
-        int declSpecifiersStart = startOf(specifiers->firstToken());
-        int declSpecifiersEnd = endOf(specifiers->lastToken() - 1);
-        int insertPos = endOf(declaration->semicolon_token);
-
-        DeclaratorAST *prevDeclarator = declaration->declarator_list->value;
-
-        for (DeclaratorListAST *it = declaration->declarator_list->next; it; it = it->next) {
-            DeclaratorAST *declarator = it->value;
-
-            changes.insert(insertPos, QLatin1String("\n"));
-            changes.copy(declSpecifiersStart, declSpecifiersEnd, insertPos);
-            changes.insert(insertPos, QLatin1String(" "));
-            changes.move(range(declarator), insertPos);
-            changes.insert(insertPos, QLatin1String(";"));
-
-            const int prevDeclEnd = endOf(prevDeclarator);
-            changes.remove(prevDeclEnd, startOf(declarator));
-
-            prevDeclarator = declarator;
-        }
-
-        refactoringChanges()->changeFile(fileName(), changes);
-        refactoringChanges()->reindent(fileName(), range(declaration));
-    }
-
-private:
-    SimpleDeclarationAST *declaration;
-};
-
-/*
-    Add curly braces to a if statement that doesn't already contain a
-    compound statement.
-*/
-class AddBracesToIfOp: public CppQuickFixOperation
-{
-public:
-    AddBracesToIfOp(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), _statement(0)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Add Curly Braces");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        // show when we're on the 'if' of an if statement
-        int index = path.size() - 1;
-        IfStatementAST *ifStatement = path.at(index)->asIfStatement();
-        if (ifStatement && isCursorOn(ifStatement->if_token) && ifStatement->statement
-            && ! ifStatement->statement->asCompoundStatement()) {
-            _statement = ifStatement->statement;
-            return index;
-        }
-
-        // or if we're on the statement contained in the if
-        // ### This may not be such a good idea, consider nested ifs...
-        for (; index != -1; --index) {
-            IfStatementAST *ifStatement = path.at(index)->asIfStatement();
-            if (ifStatement && ifStatement->statement
-                && isCursorOn(ifStatement->statement)
-                && ! ifStatement->statement->asCompoundStatement()) {
-                _statement = ifStatement->statement;
-                return index;
-            }
-        }
-
-        // ### This could very well be extended to the else branch
-        // and other nodes entirely.
-
-        return -1;
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-
-        const int start = endOf(_statement->firstToken() - 1);
-        changes.insert(start, QLatin1String(" {"));
-
-        const int end = endOf(_statement->lastToken() - 1);
-        changes.insert(end, "\n}");
-
-        refactoringChanges()->changeFile(fileName(), changes);
-        refactoringChanges()->reindent(fileName(), range(start, end));
-    }
-
-private:
-    StatementAST *_statement;
-};
+CppQuickFixState::CppQuickFixState(TextEditor::BaseTextEditor *editor)
+    : QuickFixState(editor)
+{}
 
-/*
-    Replace
-    if (Type name = foo()) {...}
-
-    With
-    Type name = foo;
-    if (name) {...}
-*/
-class MoveDeclarationOutOfIfOp: public CppQuickFixOperation
+const QList<AST *> &CppQuickFixState::path() const
 {
-public:
-    MoveDeclarationOutOfIfOp(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), condition(0), pattern(0), core(0)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Move Declaration out of Condition");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        condition = mk.Condition();
-        pattern = mk.IfStatement(condition);
-
-        int index = path.size() - 1;
-        for (; index != -1; --index) {
-            if (IfStatementAST *statement = path.at(index)->asIfStatement()) {
-                if (statement->match(pattern, &matcher) && condition->declarator) {
-                    DeclaratorAST *declarator = condition->declarator;
-                    core = declarator->core_declarator;
-                    if (! core)
-                        return -1;
-
-                    if (isCursorOn(core))
-                        return index;
-                }
-            }
-        }
-
-        return -1;
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-
-        changes.copy(range(core), startOf(condition));
-
-        int insertPos = startOf(pattern);
-        changes.move(range(condition), insertPos);
-        changes.insert(insertPos, QLatin1String(";\n"));
-
-        refactoringChanges()->changeFile(fileName(), changes);
-        refactoringChanges()->reindent(fileName(), range(pattern));
-    }
-
-private:
-    ASTMatcher matcher;
-    ASTPatternBuilder mk;
-    CPPEditor *editor;
-    ConditionAST *condition;
-    IfStatementAST *pattern;
-    CoreDeclaratorAST *core;
-};
-
-/*
-    Replace
-    while (Type name = foo()) {...}
-
-    With
-    Type name;
-    while ((name = foo()) != 0) {...}
-*/
-class MoveDeclarationOutOfWhileOp: public CppQuickFixOperation
-{
-public:
-    MoveDeclarationOutOfWhileOp(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), condition(0), pattern(0), core(0)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Move Declaration out of Condition");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        condition = mk.Condition();
-        pattern = mk.WhileStatement(condition);
-
-        int index = path.size() - 1;
-        for (; index != -1; --index) {
-            if (WhileStatementAST *statement = path.at(index)->asWhileStatement()) {
-                if (statement->match(pattern, &matcher) && condition->declarator) {
-                    DeclaratorAST *declarator = condition->declarator;
-                    core = declarator->core_declarator;
-
-                    if (! core)
-                        return -1;
-
-                    else if (! declarator->equals_token)
-                        return -1;
-
-                    else if (! declarator->initializer)
-                        return -1;
-
-                    if (isCursorOn(core))
-                        return index;
-                }
-            }
-        }
-
-        return -1;
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-
-        changes.insert(startOf(condition), QLatin1String("("));
-        changes.insert(endOf(condition), QLatin1String(") != 0"));
-
-        int insertPos = startOf(pattern);
-        const int conditionStart = startOf(condition);
-        changes.move(conditionStart, startOf(core), insertPos);
-        changes.copy(range(core), insertPos);
-        changes.insert(insertPos, QLatin1String(";\n"));
-
-        refactoringChanges()->changeFile(fileName(), changes);
-        refactoringChanges()->reindent(fileName(), range(pattern));
-    }
-
-private:
-    ASTMatcher matcher;
-    ASTPatternBuilder mk;
-    CPPEditor *editor;
-    ConditionAST *condition;
-    WhileStatementAST *pattern;
-    CoreDeclaratorAST *core;
-};
-
-/*
-  Replace
-     if (something && something_else) {
-     }
-
-  with
-     if (something) {
-        if (something_else) {
-        }
-     }
-
-  and
-    if (something || something_else)
-      x;
-
-  with
-    if (something)
-      x;
-    else if (something_else)
-      x;
-*/
-class SplitIfStatementOp: public CppQuickFixOperation
-{
-public:
-    SplitIfStatementOp(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), condition(0), pattern(0)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Split if Statement");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        pattern = 0;
-
-        int index = path.size() - 1;
-        for (; index != -1; --index) {
-            AST *node = path.at(index);
-            if (IfStatementAST *stmt = node->asIfStatement()) {
-                pattern = stmt;
-                break;
-            }
-        }
-
-        if (! pattern || ! pattern->statement)
-            return -1;
-
-        unsigned splitKind = 0;
-        for (++index; index < path.size(); ++index) {
-            AST *node = path.at(index);
-            condition = node->asBinaryExpression();
-            if (! condition)
-                return -1;
-
-            Token binaryToken = tokenAt(condition->binary_op_token);
-
-            // only accept a chain of ||s or &&s - no mixing
-            if (! splitKind) {
-                splitKind = binaryToken.kind();
-                if (splitKind != T_AMPER_AMPER && splitKind != T_PIPE_PIPE)
-                    return -1;
-                // we can't reliably split &&s in ifs with an else branch
-                if (splitKind == T_AMPER_AMPER && pattern->else_statement)
-                    return -1;
-            } else if (splitKind != binaryToken.kind()) {
-                return -1;
-            }
-
-            if (isCursorOn(condition->binary_op_token))
-                return index;
-        }
-
-        return -1;
-    }
-
-    virtual void createChanges()
-    {
-        Token binaryToken = tokenAt(condition->binary_op_token);
-
-        if (binaryToken.is(T_AMPER_AMPER))
-            splitAndCondition();
-        else
-            splitOrCondition();
-    }
-
-    void splitAndCondition()
-    {
-        ChangeSet changes;
-
-        int startPos = startOf(pattern);
-        changes.insert(startPos, QLatin1String("if ("));
-        changes.move(range(condition->left_expression), startPos);
-        changes.insert(startPos, QLatin1String(") {\n"));
-
-        const int lExprEnd = endOf(condition->left_expression);
-        changes.remove(lExprEnd, startOf(condition->right_expression));
-        changes.insert(endOf(pattern), QLatin1String("\n}"));
-
-        refactoringChanges()->changeFile(fileName(), changes);
-        refactoringChanges()->reindent(fileName(), range(pattern));
-    }
-
-    void splitOrCondition()
-    {
-        ChangeSet changes;
-
-        StatementAST *ifTrueStatement = pattern->statement;
-        CompoundStatementAST *compoundStatement = ifTrueStatement->asCompoundStatement();
-
-        int insertPos = endOf(ifTrueStatement);
-        if (compoundStatement)
-            changes.insert(insertPos, QLatin1String(" "));
-        else
-            changes.insert(insertPos, QLatin1String("\n"));
-        changes.insert(insertPos, QLatin1String("else if ("));
-
-        const int rExprStart = startOf(condition->right_expression);
-        changes.move(rExprStart, startOf(pattern->rparen_token), insertPos);
-        changes.insert(insertPos, QLatin1String(")"));
-
-        const int rParenEnd = endOf(pattern->rparen_token);
-        changes.copy(rParenEnd, endOf(pattern->statement), insertPos);
-
-        const int lExprEnd = endOf(condition->left_expression);
-        changes.remove(lExprEnd, startOf(condition->right_expression));
-
-        refactoringChanges()->changeFile(fileName(), changes);
-        refactoringChanges()->reindent(fileName(), range(pattern));
-    }
-
-private:
-    BinaryExpressionAST *condition;
-    IfStatementAST *pattern;
-};
-
-/*
-  Replace
-    "abcd"
-  With
-    QLatin1String("abcd")
-*/
-class WrapStringLiteral: public CppQuickFixOperation
-{
-public:
-    WrapStringLiteral(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), literal(0), type(TypeNone)
-    {}
-
-    enum Type { TypeString, TypeObjCString, TypeChar, TypeNone };
-
-    virtual QString description() const
-    {
-        if (type == TypeChar)
-            return QApplication::translate("CppTools::QuickFix", "Enclose in QLatin1Char(...)");
-        return QApplication::translate("CppTools::QuickFix", "Enclose in QLatin1String(...)");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        literal = 0;
-        type = TypeNone;
-
-        if (path.isEmpty())
-            return -1; // nothing to do
-
-        literal = path.last()->asStringLiteral();
-
-        if (! literal) {
-            literal = path.last()->asNumericLiteral();
-            if (!literal || !tokenAt(literal->asNumericLiteral()->literal_token).is(T_CHAR_LITERAL))
-                return -1;
-            else
-                type = TypeChar;
-        } else {
-            type = TypeString;
-        }
-
-        if (path.size() > 1) {
-            if (CallAST *call = path.at(path.size() - 2)->asCall()) {
-                if (call->base_expression) {
-                    if (SimpleNameAST *functionName = call->base_expression->asSimpleName()) {
-                        const QByteArray id(tokenAt(functionName->identifier_token).identifier->chars());
-
-                        if (id == "QT_TRANSLATE_NOOP" || id == "tr" || id == "trUtf8"
-                                || (type == TypeString && (id == "QLatin1String" || id == "QLatin1Literal"))
-                                || (type == TypeChar && id == "QLatin1Char"))
-                            return -1; // skip it
-                    }
-                }
-            }
-        }
-
-        if (type == TypeString) {
-            if (charAt(startOf(literal)) == QLatin1Char('@'))
-                type = TypeObjCString;
-        }
-        return path.size() - 1; // very high priority
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-
-        const int startPos = startOf(literal);
-        QLatin1String replacement = (type == TypeChar ? QLatin1String("QLatin1Char(")
-            : QLatin1String("QLatin1String("));
-
-        if (type == TypeObjCString)
-            changes.replace(startPos, startPos + 1, replacement);
-        else
-            changes.insert(startPos, replacement);
-
-        changes.insert(endOf(literal), ")");
-
-        refactoringChanges()->changeFile(fileName(), changes);
-    }
-
-private:
-    ExpressionAST *literal;
-    Type type;
-};
-
-/*
-  Replace
-    "abcd"
-  With
-    tr("abcd") or
-    QCoreApplication::translate("CONTEXT", "abcd") or
-    QT_TRANSLATE_NOOP("GLOBAL", "abcd")
-*/
-class TranslateStringLiteral: public CppQuickFixOperation
-{
-public:
-    TranslateStringLiteral(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), m_literal(0)
-    { }
-
-    enum TranslationOption { unknown, useTr, useQCoreApplicationTranslate, useMacro };
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Mark as translateable");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        // Initialize
-        m_literal = 0;
-        m_option = unknown;
-        m_context.clear();
-
-        if (path.isEmpty())
-            return -1;
-
-        m_literal = path.last()->asStringLiteral();
-        if (!m_literal)
-            return -1; // No string, nothing to do
-
-        // Do we already have a translation markup?
-        if (path.size() >= 2) {
-            if (CallAST *call = path.at(path.size() - 2)->asCall()) {
-                if (call->base_expression) {
-                    if (SimpleNameAST *functionName = call->base_expression->asSimpleName()) {
-                        const QByteArray id(tokenAt(functionName->identifier_token).identifier->chars());
-
-                        if (id == "tr" || id == "trUtf8"
-                                || id == "translate"
-                                || id == "QT_TRANSLATE_NOOP"
-                                || id == "QLatin1String" || id == "QLatin1Literal")
-                            return -1; // skip it
-                    }
-                }
-            }
-        }
-
-        QSharedPointer<Control> control = context().control();
-        const Name *trName = control->nameId(control->findOrInsertIdentifier("tr"));
-
-        // Check whether we are in a method:
-        for (int i = path.size() - 1; i >= 0; --i)
-        {
-            if (FunctionDefinitionAST *definition = path.at(i)->asFunctionDefinition()) {
-                Function *function = definition->symbol;
-                ClassOrNamespace *b = context().lookupType(function);
-                if (b) {
-                    // Do we have a tr method?
-                    foreach(const LookupItem &r, b->find(trName)) {
-                        Symbol *s = r.declaration();
-                        if (s->type()->isFunctionType()) {
-                            m_option = useTr;
-                            // no context required for tr
-                            return path.size() - 1;
-                        }
-                    }
-                }
-                // We need to do a QCA::translate, so we need a context.
-                // Use fully qualified class name:
-                Overview oo;
-                foreach (const Name *n, LookupContext::path(function)) {
-                    if (!m_context.isEmpty())
-                        m_context.append(QLatin1String("::"));
-                    m_context.append(oo.prettyName(n));
-                }
-                // ... or global if none available!
-                if (m_context.isEmpty())
-                    m_context = QLatin1String("GLOBAL");
-                m_option = useQCoreApplicationTranslate;
-                return path.size() - 1;
-            }
-        }
-
-        // We need to use Q_TRANSLATE_NOOP
-        m_context = QLatin1String("GLOBAL");
-        m_option = useMacro;
-        return path.size() - 1;
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-
-        const int startPos = startOf(m_literal);
-        QString replacement(QLatin1String("tr("));
-        if (m_option == useQCoreApplicationTranslate) {
-            replacement = QLatin1String("QCoreApplication::translate(\"")
-                          + m_context + QLatin1String("\", ");
-        } else if (m_option == useMacro) {
-            replacement = QLatin1String("QT_TRANSLATE_NOOP(\"")
-                    + m_context + QLatin1String("\", ");
-        }
-
-        changes.insert(startPos, replacement);
-        changes.insert(endOf(m_literal), QLatin1String(")"));
-
-        refactoringChanges()->changeFile(fileName(), changes);
-    }
-
-private:
-    ExpressionAST *m_literal;
-    TranslationOption m_option;
-    QString m_context;
-};
-
-class CStringToNSString: public CppQuickFixOperation
-{
-public:
-    CStringToNSString(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor)
-        , stringLiteral(0)
-        , qlatin1Call(0)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Convert to Objective-C String Literal");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        stringLiteral = 0;
-        qlatin1Call = 0;
-
-        if (path.isEmpty())
-            return -1; // nothing to do
-
-        stringLiteral = path.last()->asStringLiteral();
-
-        if (! stringLiteral)
-            return -1;
-
-        else if (charAt(startOf(stringLiteral)) == QLatin1Char('@'))
-            return -1; // it's already an objc string literal.
-
-        else if (path.size() > 1) {
-            if (CallAST *call = path.at(path.size() - 2)->asCall()) {
-                if (call->base_expression) {
-                    if (SimpleNameAST *functionName = call->base_expression->asSimpleName()) {
-                        const QByteArray id(tokenAt(functionName->identifier_token).identifier->chars());
-
-                        if (id == "QLatin1String" || id == "QLatin1Literal")
-                            qlatin1Call = call;
-                    }
-                }
-            }
-        }
-
-        return path.size() - 1; // very high priority
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-
-        if (qlatin1Call) {
-            changes.replace(startOf(qlatin1Call), startOf(stringLiteral), QLatin1String("@"));
-            changes.remove(endOf(stringLiteral), endOf(qlatin1Call));
-        } else {
-            changes.insert(startOf(stringLiteral), "@");
-        }
-
-        refactoringChanges()->changeFile(fileName(), changes);
-    }
-
-private:
-    StringLiteralAST *stringLiteral;
-    CallAST *qlatin1Call;
-};
-
-/*
-  Base class for converting numeric literals between decimal, octal and hex.
-  Does the base check for the specific ones and parses the number.
-  Test cases:
-    0xFA0Bu;
-    0X856A;
-    298.3;
-    199;
-    074;
-    199L;
-    074L;
-    -199;
-    -017;
-    0783; // invalid octal
-    0; // border case, allow only hex<->decimal
-*/
-class ConvertNumericLiteral: public CppQuickFixOperation
-{
-public:
-    ConvertNumericLiteral(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor)
-    {}
-
-    virtual int match(const QList<AST *> &path)
-    {
-        literal = 0;
-
-        if (path.isEmpty())
-            return -1; // nothing to do
-
-        literal = path.last()->asNumericLiteral();
-
-        if (! literal)
-            return -1;
-
-        Token token = tokenAt(literal->asNumericLiteral()->literal_token);
-        if (!token.is(T_NUMERIC_LITERAL))
-            return -1;
-        numeric = token.number;
-        if (numeric->isDouble() || numeric->isFloat())
-            return -1;
-
-        // remove trailing L or U and stuff
-        const char * const spell = numeric->chars();
-        numberLength = numeric->size();
-        while (numberLength > 0 && (spell[numberLength-1] < '0' || spell[numberLength-1] > 'F'))
-            --numberLength;
-        if (numberLength < 1)
-            return -1;
-
-        // convert to number
-        bool valid;
-        value = QString::fromUtf8(spell).left(numberLength).toULong(&valid, 0);
-        if (!valid) // e.g. octal with digit > 7
-            return -1;
-
-        return path.size() - 1; // very high priority
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-        int start = startOf(literal);
-        changes.replace(start, start + numberLength, replacement);
-        refactoringChanges()->changeFile(fileName(), changes);
-    }
-
-protected:
-    NumericLiteralAST *literal;
-    const NumericLiteral *numeric;
-    ulong value;
-    int numberLength;
-    QString replacement;
-};
-
-/*
-  Convert integer literal to hex representation.
-  Replace
-    32
-    040
-  With
-    0x20
+    return _path;
+}
 
-*/
-class ConvertNumericToHex: public ConvertNumericLiteral
+Snapshot CppQuickFixState::snapshot() const
 {
-public:
-    ConvertNumericToHex(TextEditor::BaseTextEditor *editor)
-        : ConvertNumericLiteral(editor)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Convert to Hexadecimal");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        int ret = ConvertNumericLiteral::match(path);
-        if (ret != -1 && !numeric->isHex()) {
-            replacement.sprintf("0x%lX", value);
-            return ret;
-        }
-        return -1;
-    }
-
-};
+    return _snapshot;
+}
 
-/*
-  Convert integer literal to octal representation.
-  Replace
-    32
-    0x20
-  With
-    040
-*/
-class ConvertNumericToOctal: public ConvertNumericLiteral
+Document::Ptr CppQuickFixState::document() const
 {
-public:
-    ConvertNumericToOctal(TextEditor::BaseTextEditor *editor)
-        : ConvertNumericLiteral(editor)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Convert to Octal");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        int ret = ConvertNumericLiteral::match(path);
-        if (ret != -1 && value != 0) {
-            const char * const str = numeric->chars();
-            if (numberLength > 1 && str[0] == '0' && str[1] != 'x' && str[1] != 'X')
-                return -1;
-            replacement.sprintf("0%lo", value);
-            return ret;
-        }
-        return -1;
-    }
-
-};
+    return _semanticInfo.doc;
+}
 
-/*
-  Convert integer literal to decimal representation.
-  Replace
-    0x20
-    040
-  With
-    32
-*/
-class ConvertNumericToDecimal: public ConvertNumericLiteral
+SemanticInfo CppQuickFixState::semanticInfo() const
 {
-public:
-    ConvertNumericToDecimal(TextEditor::BaseTextEditor *editor)
-        : ConvertNumericLiteral(editor)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Convert to Decimal");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        int ret = ConvertNumericLiteral::match(path);
-        if (ret != -1 && (value != 0 || numeric->isHex())) {
-            const char * const str = numeric->chars();
-            if (numberLength > 1 && str[0] != '0')
-                return -1;
-            replacement.sprintf("%lu", value);
-            return ret;
-        }
-        return -1;
-    }
-
-};
+    return _semanticInfo;
+}
 
-/*
-  Adds missing case statements for "switch (enumVariable)"
-*/
-class CompleteSwitchCaseStatement: public CppQuickFixOperation
+LookupContext CppQuickFixState::context() const
 {
-public:
-    CompleteSwitchCaseStatement(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Complete Switch Statement");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        if (path.isEmpty())
-            return -1; // nothing to do
-
-        // look for switch statement
-        for (int depth = path.size()-1; depth >= 0; --depth) {
-            AST *ast = path.at(depth);
-            SwitchStatementAST *switchStatement = ast->asSwitchStatement();
-            if (switchStatement) {
-                if (!isCursorOn(switchStatement->switch_token) || !switchStatement->statement)
-                    return -1;
-                compoundStatement = switchStatement->statement->asCompoundStatement();
-                if (!compoundStatement) // we ignore pathologic case "switch (t) case A: ;"
-                    return -1;
-                // look if the condition's type is an enum
-                if (Enum *e = conditionEnum(switchStatement)) {
-                    // check the possible enum values
-                    values.clear();
-                    Overview prettyPrint;
-                    for (unsigned i = 0; i < e->memberCount(); ++i) {
-                        if (Declaration *decl = e->memberAt(i)->asDeclaration()) {
-                            values << prettyPrint(LookupContext::fullyQualifiedName(decl));
-                        }
-                    }
-                    // Get the used values
-                    Block *block = switchStatement->symbol;
-                    CaseStatementCollector caseValues(document(), snapshot(),
-                        document()->scopeAt(block->line(), block->column()));
-                    QStringList usedValues = caseValues(switchStatement);
-                    // save the values that would be added
-                    foreach (const QString &usedValue, usedValues)
-                        values.removeAll(usedValue);
-                    if (values.isEmpty())
-                        return -1;
-                    return depth;
-                }
-                return -1;
-            }
-        }
-
-        return -1;
-    }
-
-    virtual void createChanges()
-    {
-        ChangeSet changes;
-        int start = endOf(compoundStatement->lbrace_token);
-        changes.insert(start, QLatin1String("\ncase ")
-                       + values.join(QLatin1String(":\nbreak;\ncase "))
-                       + QLatin1String(":\nbreak;"));
-        refactoringChanges()->changeFile(fileName(), changes);
-        refactoringChanges()->reindent(fileName(), range(compoundStatement));
-    }
-
-protected:
-    Enum *conditionEnum(SwitchStatementAST *statement)
-    {
-        Block *block = statement->symbol;
-        Scope *scope = document()->scopeAt(block->line(), block->column());
-        TypeOfExpression typeOfExpression;
-        typeOfExpression.init(document(), snapshot());
-        const QList<LookupItem> results = typeOfExpression(statement->condition,
-                                                           document(),
-                                                           scope);
-        foreach (LookupItem result, results) {
-            FullySpecifiedType fst = result.type();
-            if (Enum *e = result.declaration()->type()->asEnumType())
-                return e;
-            if (NamedType *namedType = fst->asNamedType()) {
-                QList<LookupItem> candidates =
-                        typeOfExpression.context().lookup(namedType->name(), scope);
-                foreach (const LookupItem &r, candidates) {
-                    Symbol *candidate = r.declaration();
-                    if (Enum *e = candidate->asEnum()) {
-                        return e;
-                    }
-                }
-            }
-        }
-        return 0;
-    }
-    class CaseStatementCollector : public ASTVisitor
-    {
-    public:
-        CaseStatementCollector(Document::Ptr document, const Snapshot &snapshot,
-                               Scope *scope)
-            : ASTVisitor(document->translationUnit()),
-            document(document),
-            scope(scope)
-        {
-            typeOfExpression.init(document, snapshot);
-        }
-
-        QStringList operator ()(AST *ast)
-        {
-            values.clear();
-            foundCaseStatementLevel = false;
-            accept(ast);
-            return values;
-        }
-
-        bool preVisit(AST *ast) {
-            if (CaseStatementAST *cs = ast->asCaseStatement()) {
-                foundCaseStatementLevel = true;
-                ExpressionAST *expression = cs->expression->asSimpleName();
-                if (!expression)
-                    expression = cs->expression->asQualifiedName();
-                if (expression) {
-                    LookupItem item = typeOfExpression(expression,
-                                                       document,
-                                                       scope).first();
-                    values << prettyPrint(LookupContext::fullyQualifiedName(item.declaration()));
-                }
-                return true;
-            } else if (foundCaseStatementLevel) {
-                return false;
-            }
-            return true;
-        }
-
-        Overview prettyPrint;
-        bool foundCaseStatementLevel;
-        QStringList values;
-        TypeOfExpression typeOfExpression;
-        Document::Ptr document;
-        Scope *scope;
-    };
-
-protected:
-    CompoundStatementAST *compoundStatement;
-    QStringList values;
-};
-
+    return _context;
+}
 
-class FixForwardDeclarationOp: public CppQuickFixOperation
+Scope *CppQuickFixState::scopeAt(unsigned index) const
 {
-public:
-    FixForwardDeclarationOp(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), fwdClass(0)
-    {
-    }
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "#include header file");
-    }
-
-    bool checkName(NameAST *ast)
-    {
-        if (ast && isCursorOn(ast)) {
-            if (const Name *name = ast->name) {
-                unsigned line, column;
-                document()->translationUnit()->getTokenStartPosition(ast->firstToken(), &line, &column);
-
-                fwdClass = 0;
-
-                foreach (const LookupItem &r, context().lookup(name, document()->scopeAt(line, column))) {
-                    if (! r.declaration())
-                        continue;
-                    else if (ForwardClassDeclaration *fwd = r.declaration()->asForwardClassDeclaration())
-                        fwdClass = fwd;
-                    else if (r.declaration()->isClass())
-                        return false; // nothing to do.
-                }
-
-                if (fwdClass)
-                    return true;
-            }
-        }
-
-        return false;
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        fwdClass = 0;
-
-        for (int index = path.size() - 1; index != -1; --index) {
-            AST *ast = path.at(index);
-            if (NamedTypeSpecifierAST *namedTy = ast->asNamedTypeSpecifier()) {
-                if (checkName(namedTy->name))
-                    return index;
-            } else if (ElaboratedTypeSpecifierAST *eTy = ast->asElaboratedTypeSpecifier()) {
-                if (checkName(eTy->name))
-                    return index;
-            }
-        }
-
-        return -1;
-    }
-
-    virtual void createChanges()
-    {
-        Q_ASSERT(fwdClass != 0);
-
-        if (Class *k = snapshot().findMatchingClassDeclaration(fwdClass)) {
-            const QString headerFile = QString::fromUtf8(k->fileName(), k->fileNameLength());
-
-            // collect the fwd headers
-            Snapshot fwdHeaders;
-            fwdHeaders.insert(snapshot().document(headerFile));
-            foreach (Document::Ptr doc, snapshot()) {
-                QFileInfo headerFileInfo(doc->fileName());
-                if (doc->globalSymbolCount() == 0 && doc->includes().size() == 1)
-                    fwdHeaders.insert(doc);
-                else if (headerFileInfo.suffix().isEmpty())
-                    fwdHeaders.insert(doc);
-            }
-
-
-            DependencyTable dep;
-            dep.build(fwdHeaders);
-            QStringList candidates = dep.dependencyTable().value(headerFile);
-
-            const QString className = QString::fromUtf8(k->identifier()->chars());
-
-            QString best;
-            foreach (const QString &c, candidates) {
-                QFileInfo headerFileInfo(c);
-                if (headerFileInfo.fileName() == className) {
-                    best = c;
-                    break;
-                } else if (headerFileInfo.fileName().at(0).isUpper()) {
-                    best = c;
-                    // and continue
-                } else if (! best.isEmpty()) {
-                    if (c.count(QLatin1Char('/')) < best.count(QLatin1Char('/')))
-                        best = c;
-                }
-            }
-
-            if (best.isEmpty())
-                best = headerFile;
-
-            int pos = startOf(1);
-
-            unsigned currentLine = textCursor().blockNumber() + 1;
-            unsigned bestLine = 0;
-            foreach (const Document::Include &incl, document()->includes()) {
-                if (incl.line() < currentLine)
-                    bestLine = incl.line();
-            }
-
-            if (bestLine)
-                pos = editor()->document()->findBlockByNumber(bestLine).position();
-
-            Utils::ChangeSet changes;
-            changes.insert(pos, QString("#include <%1>\n").arg(QFileInfo(best).fileName()));
-            refactoringChanges()->changeFile(fileName(), changes);
-        }
-    }
-
-private:
-    Symbol *fwdClass;
-};
+    unsigned line, column;
+    document()->translationUnit()->getTokenStartPosition(index, &line, &column);
+    return document()->scopeAt(line, column);
+}
 
-class AddLocalDeclarationOp: public CppQuickFixOperation
+bool CppQuickFixState::isCursorOn(unsigned tokenIndex) const
 {
-public:
-    AddLocalDeclarationOp(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor), binaryAST(0)
-    {
-    }
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Add local declaration");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        for (int index = path.size() - 1; index != -1; --index) {
-            if (BinaryExpressionAST *binary = path.at(index)->asBinaryExpression()) {
-                if (binary->left_expression && binary->right_expression && tokenAt(binary->binary_op_token).is(T_EQUAL)) {
-                    if (isCursorOn(binary->left_expression) && binary->left_expression->asSimpleName() != 0) {
-                        SimpleNameAST *nameAST = binary->left_expression->asSimpleName();
-                        const QList<LookupItem> results = context().lookup(nameAST->name, scopeAt(nameAST->firstToken()));
-                        Declaration *decl = 0;
-                        foreach (const LookupItem &r, results) {
-                            if (! r.declaration())
-                                continue;
-                            else if (Declaration *d = r.declaration()->asDeclaration()) {
-                                if (! d->type()->isFunctionType()) {
-                                    decl = d;
-                                    break;
-                                }
-                            }
-                        }
-
-                        if (! decl) {
-                            binaryAST = binary;
-                            typeOfExpression.init(document(), snapshot(), context().bindings());
-                            return index;
-                        }
-                    }
-                }
-            }
-        }
-
-        return -1;
-    }
-
-    virtual void createChanges()
-    {
-        const QList<LookupItem> result = typeOfExpression(textOf(binaryAST->right_expression),
-                                                          scopeAt(binaryAST->firstToken()),
-                                                          TypeOfExpression::Preprocess);
-
-        if (! result.isEmpty()) {
-
-            SubstitutionEnvironment env;
-            env.setContext(context());
-            env.switchScope(result.first().scope());
-            UseQualifiedNames q;
-            env.enter(&q);
-
-            Control *control = context().control().data();
-            FullySpecifiedType tn = rewriteType(result.first().type(), &env, control);
-
-            Overview oo;
-            QString ty = oo(tn);
-            if (! ty.isEmpty()) {
-                const QChar ch = ty.at(ty.size() - 1);
+    QTextCursor tc = textCursor();
+    int cursorBegin = tc.selectionStart();
 
-                if (ch.isLetterOrNumber() || ch == QLatin1Char(' ') || ch == QLatin1Char('>'))
-                    ty += QLatin1Char(' ');
+    int start = startOf(tokenIndex);
+    int end = endOf(tokenIndex);
 
-                Utils::ChangeSet changes;
-                changes.insert(startOf(binaryAST), ty);
-                refactoringChanges()->changeFile(fileName(), changes);
-            }
-        }
-    }
+    if (cursorBegin >= start && cursorBegin <= end)
+        return true;
 
-private:
-    TypeOfExpression typeOfExpression;
-    BinaryExpressionAST *binaryAST;
-};
+    return false;
+}
 
-/*
- * Turns "an_example_symbol" into "anExampleSymbol" and
- * "AN_EXAMPLE_SYMBOL" into "AnExampleSymbol".
- */
-class ToCamelCaseConverter : public CppQuickFixOperation
+bool CppQuickFixState::isCursorOn(const AST *ast) const
 {
-public:
-    ToCamelCaseConverter(TextEditor::BaseTextEditor *editor)
-        : CppQuickFixOperation(editor)
-    {}
-
-    virtual QString description() const
-    {
-        return QApplication::translate("CppTools::QuickFix", "Convert to Camel Case ...");
-    }
-
-    virtual int match(const QList<AST *> &path)
-    {
-        if (path.isEmpty())
-            return -1;
-
-        AST * const ast = path.last();
-        const Name *name = 0;
-        if (const NameAST * const nameAst = ast->asName()) {
-            if (nameAst->name && nameAst->name->asNameId())
-                name = nameAst->name;
-        } else if (const NamespaceAST * const namespaceAst = ast->asNamespace()) {
-            name = namespaceAst->symbol->name();
-        }
-
-        if (!name)
-            return -1;
-
-        m_name = QString::fromUtf8(name->identifier()->chars());
-        if (m_name.length() < 3)
-            return -1;
-        for (int i = 1; i < m_name.length() - 1; ++i) {
-            if (isConvertibleUnderscore(i))
-                return path.size() - 1;
-        }
-
-        return -1;
-    }
-
-    virtual void createChanges()
-    {
-        for (int i = 1; i < m_name.length(); ++i) {
-            QCharRef c = m_name[i];
-            if (c.isUpper()) {
-                c = c.toLower();
-            } else if (i < m_name.length() - 1
-                && isConvertibleUnderscore(i)) {
-                m_name.remove(i, 1);
-                m_name[i] = m_name.at(i).toUpper();
-            }
-        }
-        static_cast<CppEditor::Internal::CPPEditor*>(editor())->renameUsagesNow(m_name);
-    }
-
-private:
-    bool isConvertibleUnderscore(int pos) const
-    {
-        return m_name.at(pos) == QLatin1Char('_') && m_name.at(pos+1).isLetter()
-            && !(pos == 1 && m_name.at(0) == QLatin1Char('m'));
-    }
-
-    QString m_name;
-};
-
-} // end of anonymous namespace
-
+    QTextCursor tc = textCursor();
+    int cursorBegin = tc.selectionStart();
 
-CppQuickFixOperation::CppQuickFixOperation(TextEditor::BaseTextEditor *editor)
-    : TextEditor::QuickFixOperation(editor)
-    , _refactoringChanges(0)
-    , _topLevelNode(0)
-{ }
+    int start = startOf(ast);
+    int end = endOf(ast);
 
-CppQuickFixOperation::~CppQuickFixOperation()
-{
-    if (_refactoringChanges)
-        delete _refactoringChanges;
-}
+    if (cursorBegin >= start && cursorBegin <= end)
+        return true;
 
-int CppQuickFixOperation::match(TextEditor::QuickFixState *state)
-{
-    CppQuickFixState *s = static_cast<CppQuickFixState *>(state);
-    _document = s->info.doc;
-    if (_refactoringChanges)
-        delete _refactoringChanges;
-    _refactoringChanges = new CppRefactoringChanges(_document, s->snapshot);
-    return match(s->path);
+    return false;
 }
 
-Utils::ChangeSet::Range CppQuickFixOperation::range(unsigned tokenIndex) const
+ChangeSet::Range CppQuickFixState::range(unsigned tokenIndex) const
 {
-    const CPlusPlus::Token &token = tokenAt(tokenIndex);
+    const Token &token = tokenAt(tokenIndex);
     unsigned line, column;
-    _document->translationUnit()->getPosition(token.begin(), &line, &column);
+    document()->translationUnit()->getPosition(token.begin(), &line, &column);
     const int start = editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
-    return Utils::ChangeSet::Range(start, start + token.length());
-}
-
-Utils::ChangeSet::Range CppQuickFixOperation::range(CPlusPlus::AST *ast) const
-{
-    return Utils::ChangeSet::Range(startOf(ast), endOf(ast));
+    return ChangeSet::Range(start, start + token.length());
 }
 
-QString CppQuickFixOperation::fileName() const
-{ return document()->fileName(); }
-
-void CppQuickFixOperation::apply()
+ChangeSet::Range CppQuickFixState::range(AST *ast) const
 {
-    refactoringChanges()->apply();
+    return ChangeSet::Range(startOf(ast), endOf(ast));
 }
 
-CppEditor::CppRefactoringChanges *CppQuickFixOperation::refactoringChanges() const
-{ return _refactoringChanges; }
-
-Document::Ptr CppQuickFixOperation::document() const
-{ return _document; }
-
-const Snapshot &CppQuickFixOperation::snapshot() const
-{ return _refactoringChanges->snapshot(); }
-
-const CPlusPlus::LookupContext &CppQuickFixOperation::context() const
-{ return _refactoringChanges->context(); }
-
-CPlusPlus::Scope *CppQuickFixOperation::scopeAt(unsigned index) const
-{
-    unsigned line, column;
-    document()->translationUnit()->getTokenStartPosition(index, &line, &column);
-    return document()->scopeAt(line, column);
-}
-
-const CPlusPlus::Token &CppQuickFixOperation::tokenAt(unsigned index) const
-{ return _document->translationUnit()->tokenAt(index); }
-
-int CppQuickFixOperation::startOf(unsigned index) const
+int CppQuickFixState::startOf(unsigned index) const
 {
     unsigned line, column;
-    _document->translationUnit()->getPosition(tokenAt(index).begin(), &line, &column);
+    document()->translationUnit()->getPosition(tokenAt(index).begin(), &line, &column);
     return editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
 }
 
-int CppQuickFixOperation::startOf(const CPlusPlus::AST *ast) const
+int CppQuickFixState::startOf(const AST *ast) const
 {
     return startOf(ast->firstToken());
 }
 
-int CppQuickFixOperation::endOf(unsigned index) const
+int CppQuickFixState::endOf(unsigned index) const
 {
     unsigned line, column;
-    _document->translationUnit()->getPosition(tokenAt(index).end(), &line, &column);
+    document()->translationUnit()->getPosition(tokenAt(index).end(), &line, &column);
     return editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
 }
 
-int CppQuickFixOperation::endOf(const CPlusPlus::AST *ast) const
+int CppQuickFixState::endOf(const AST *ast) const
 {
     if (unsigned end = ast->lastToken())
         return endOf(end - 1);
@@ -1742,46 +162,71 @@ int CppQuickFixOperation::endOf(const CPlusPlus::AST *ast) const
         return 0;
 }
 
-void CppQuickFixOperation::startAndEndOf(unsigned index, int *start, int *end) const
+void CppQuickFixState::startAndEndOf(unsigned index, int *start, int *end) const
 {
     unsigned line, column;
-    CPlusPlus::Token token(tokenAt(index));
-    _document->translationUnit()->getPosition(token.begin(), &line, &column);
+    Token token(tokenAt(index));
+    document()->translationUnit()->getPosition(token.begin(), &line, &column);
     *start = editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
     *end = *start + token.length();
 }
 
-bool CppQuickFixOperation::isCursorOn(unsigned tokenIndex) const
+QString CppQuickFixState::textOf(const AST *ast) const
 {
-    QTextCursor tc = textCursor();
-    int cursorBegin = tc.selectionStart();
+    return textOf(startOf(ast), endOf(ast));
+}
 
-    int start = startOf(tokenIndex);
-    int end = endOf(tokenIndex);
+const Token &CppQuickFixState::tokenAt(unsigned index) const
+{
+    return document()->translationUnit()->tokenAt(index);
+}
 
-    if (cursorBegin >= start && cursorBegin <= end)
-        return true;
+CppQuickFixOperation::CppQuickFixOperation(const CppQuickFixState &state, int priority)
+    : QuickFixOperation(priority)
+    , _state(state)
+    , _refactoringChanges(new CppRefactoringChanges(state.document(), state.snapshot()))
+{}
 
-    return false;
+CppQuickFixOperation::~CppQuickFixOperation()
+{}
+
+const CppQuickFixState &CppQuickFixOperation::state() const
+{
+    return _state;
 }
 
-bool CppQuickFixOperation::isCursorOn(const CPlusPlus::AST *ast) const
+QString CppQuickFixOperation::fileName() const
+{ return state().document()->fileName(); }
+
+CppRefactoringChanges *CppQuickFixOperation::refactoringChanges() const
+{ return _refactoringChanges.data(); }
+
+CppQuickFixFactory::CppQuickFixFactory()
 {
-    QTextCursor tc = textCursor();
-    int cursorBegin = tc.selectionStart();
+}
 
-    int start = startOf(ast);
-    int end = endOf(ast);
+CppQuickFixFactory::~CppQuickFixFactory()
+{
+}
 
-    if (cursorBegin >= start && cursorBegin <= end)
-        return true;
+QList<QuickFixOperation::Ptr> CppQuickFixFactory::matchingOperations(QuickFixState *state)
+{
+    if (CppQuickFixState *cppState = static_cast<CppQuickFixState *>(state))
+        return match(*cppState);
+    else
+        return QList<TextEditor::QuickFixOperation::Ptr>();
+}
 
-    return false;
+QList<CppQuickFixOperation::Ptr> CppQuickFixFactory::singleResult(CppQuickFixOperation *operation)
+{
+    QList<CppQuickFixOperation::Ptr> result;
+    result.append(CppQuickFixOperation::Ptr(operation));
+    return result;
 }
 
-QString CppQuickFixOperation::textOf(const AST *ast) const
+QList<CppQuickFixOperation::Ptr> CppQuickFixFactory::noResult()
 {
-    return textOf(startOf(ast), endOf(ast));
+    return QList<CppQuickFixOperation::Ptr>();
 }
 
 CppQuickFixCollector::CppQuickFixCollector()
@@ -1797,12 +242,12 @@ bool CppQuickFixCollector::supportsEditor(TextEditor::ITextEditable *editor)
     return CppTools::CppModelManagerInterface::instance()->isCppEditor(editor);
 }
 
-TextEditor::QuickFixState *CppQuickFixCollector::initializeCompletion(TextEditor::ITextEditable *editable)
+TextEditor::QuickFixState *CppQuickFixCollector::initializeCompletion(TextEditor::BaseTextEditor *editor)
 {
-    if (CPPEditor *editor = qobject_cast<CPPEditor *>(editable->widget())) {
-        const SemanticInfo info = editor->semanticInfo();
+    if (CPPEditor *cppEditor = qobject_cast<CPPEditor *>(editor)) {
+        const SemanticInfo info = cppEditor->semanticInfo();
 
-        if (info.revision != editor->editorRevision()) {
+        if (info.revision != cppEditor->editorRevision()) {
             // outdated
             qWarning() << "TODO: outdated semantic info, force a reparse.";
             return 0;
@@ -1811,12 +256,13 @@ TextEditor::QuickFixState *CppQuickFixCollector::initializeCompletion(TextEditor
         if (info.doc) {
             ASTPath astPath(info.doc);
 
-            const QList<AST *> path = astPath(editor->textCursor());
+            const QList<AST *> path = astPath(cppEditor->textCursor());
             if (! path.isEmpty()) {
-                CppQuickFixState *state = new CppQuickFixState;
-                state->path = path;
-                state->info = info;
-                state->snapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
+                CppQuickFixState *state = new CppQuickFixState(editor);
+                state->_path = path;
+                state->_semanticInfo = info;
+                state->_snapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
+                state->_context = LookupContext(info.doc, state->snapshot());
                 return state;
             }
         }
@@ -1825,63 +271,11 @@ TextEditor::QuickFixState *CppQuickFixCollector::initializeCompletion(TextEditor
     return 0;
 }
 
-CppQuickFixFactory::CppQuickFixFactory(QObject *parent)
-    : TextEditor::IQuickFixFactory(parent)
-{
-}
-
-CppQuickFixFactory::~CppQuickFixFactory()
+QList<TextEditor::QuickFixFactory *> CppQuickFixCollector::quickFixFactories() const
 {
-}
-
-QList<TextEditor::QuickFixOperation::Ptr> CppQuickFixFactory::quickFixOperations(TextEditor::BaseTextEditor *editor)
-{
-    QList<TextEditor::QuickFixOperation::Ptr> quickFixOperations;
-
-    QSharedPointer<RewriteLogicalAndOp> rewriteLogicalAndOp(new RewriteLogicalAndOp(editor));
-    QSharedPointer<SplitIfStatementOp> splitIfStatementOp(new SplitIfStatementOp(editor));
-    QSharedPointer<MoveDeclarationOutOfIfOp> moveDeclarationOutOfIfOp(new MoveDeclarationOutOfIfOp(editor));
-    QSharedPointer<MoveDeclarationOutOfWhileOp> moveDeclarationOutOfWhileOp(new MoveDeclarationOutOfWhileOp(editor));
-    QSharedPointer<SplitSimpleDeclarationOp> splitSimpleDeclarationOp(new SplitSimpleDeclarationOp(editor));
-    QSharedPointer<AddBracesToIfOp> addBracesToIfOp(new AddBracesToIfOp(editor));
-    QSharedPointer<UseInverseOp> useInverseOp(new UseInverseOp(editor));
-    QSharedPointer<FlipBinaryOp> flipBinaryOp(new FlipBinaryOp(editor));
-    QSharedPointer<WrapStringLiteral> wrapStringLiteral(new WrapStringLiteral(editor));
-    QSharedPointer<CStringToNSString> wrapCString(new CStringToNSString(editor));
-    QSharedPointer<TranslateStringLiteral> translateCString(new TranslateStringLiteral(editor));
-    QSharedPointer<ConvertNumericToHex> convertNumericToHex(new ConvertNumericToHex(editor));
-    QSharedPointer<ConvertNumericToOctal> convertNumericToOctal(new ConvertNumericToOctal(editor));
-    QSharedPointer<ConvertNumericToDecimal> convertNumericToDecimal(new ConvertNumericToDecimal(editor));
-    QSharedPointer<CompleteSwitchCaseStatement> completeSwitchCaseStatement(new CompleteSwitchCaseStatement(editor));
-    QSharedPointer<FixForwardDeclarationOp> fixForwardDeclarationOp(new FixForwardDeclarationOp(editor));
-    QSharedPointer<AddLocalDeclarationOp> addLocalDeclarationOp(new AddLocalDeclarationOp(editor));
-    QSharedPointer<ToCamelCaseConverter> toCamelCase(new ToCamelCaseConverter(editor));
-    QSharedPointer<DeclFromDef> declFromDef(new DeclFromDef(editor));
-
-    quickFixOperations.append(rewriteLogicalAndOp);
-    quickFixOperations.append(splitIfStatementOp);
-    quickFixOperations.append(moveDeclarationOutOfIfOp);
-    quickFixOperations.append(moveDeclarationOutOfWhileOp);
-    quickFixOperations.append(splitSimpleDeclarationOp);
-    quickFixOperations.append(addBracesToIfOp);
-    quickFixOperations.append(useInverseOp);
-    quickFixOperations.append(flipBinaryOp);
-    quickFixOperations.append(wrapStringLiteral);
-    quickFixOperations.append(translateCString);
-    quickFixOperations.append(convertNumericToHex);
-    quickFixOperations.append(convertNumericToOctal);
-    quickFixOperations.append(convertNumericToDecimal);
-    quickFixOperations.append(completeSwitchCaseStatement);
-    quickFixOperations.append(fixForwardDeclarationOp);
-    quickFixOperations.append(addLocalDeclarationOp);
-    quickFixOperations.append(toCamelCase);
-
-#if 0
-    quickFixOperations.append(declFromDef);
-#endif
-
-    if (editor->mimeType() == CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE)
-        quickFixOperations.append(wrapCString);
-
-    return quickFixOperations;
+    QList<TextEditor::QuickFixFactory *> results;
+    ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
+    foreach (CppQuickFixFactory *f, pm->getObjects<CppEditor::CppQuickFixFactory>())
+        results.append(f);
+    return results;
 }
diff --git a/src/plugins/cppeditor/cppquickfix.h b/src/plugins/cppeditor/cppquickfix.h
index 60c990fda0c5164bce9c4f135492b9236b34f199..4b5bfe50e508871397d22f090e228e6f69833ffa 100644
--- a/src/plugins/cppeditor/cppquickfix.h
+++ b/src/plugins/cppeditor/cppquickfix.h
@@ -30,100 +30,142 @@
 #ifndef CPPQUICKFIX_H
 #define CPPQUICKFIX_H
 
-#include <texteditor/icompletioncollector.h>
-#include <texteditor/quickfix.h>
+#include "cpprefactoringchanges.h"
+#include "cppsemanticinfo.h"
 
-#include <cplusplus/CppDocument.h>
 #include <ASTfwd.h>
-
+#include <cplusplus/CppDocument.h>
+#include <texteditor/icompletioncollector.h>
+#include <texteditor/quickfix.h>
 #include <utils/changeset.h>
 
 #include <QtCore/QSharedPointer>
 #include <QtGui/QTextCursor>
 
-#include "cpprefactoringchanges.h"
-
 namespace CppTools {
     class CppModelManagerInterface;
 } // end of namespace CppTools
 
+namespace ExtensionSystem {
+class IPlugin;
+}
+
 namespace CppEditor {
+
 namespace Internal {
+class CppQuickFixCollector;
+} // end of namespace Internal
 
-class CppQuickFixOperation: public TextEditor::QuickFixOperation
+class CPPEDITOR_EXPORT CppQuickFixState: public TextEditor::QuickFixState
 {
-    Q_DISABLE_COPY(CppQuickFixOperation)
+    friend class Internal::CppQuickFixCollector;
 
 public:
-    CppQuickFixOperation(TextEditor::BaseTextEditor *editor);
-    virtual ~CppQuickFixOperation();
-
-    virtual int match(const QList<CPlusPlus::AST *> &path) = 0;
+    CppQuickFixState(TextEditor::BaseTextEditor *editor);
+    typedef Utils::ChangeSet::Range Range;
 
+    const QList<CPlusPlus::AST *> &path() const;
+    CPlusPlus::Snapshot snapshot() const;
     CPlusPlus::Document::Ptr document() const;
-    const CPlusPlus::Snapshot &snapshot() const;
-    const CPlusPlus::LookupContext &context() const;
+    CppEditor::Internal::SemanticInfo semanticInfo() const;
+    CPlusPlus::LookupContext context() const;
 
-    virtual int match(TextEditor::QuickFixState *state);
+    using TextEditor::QuickFixState::range;
+    using TextEditor::QuickFixState::textOf;
+    using TextEditor::QuickFixState::charAt;
 
-protected:
-    using TextEditor::QuickFixOperation::range;
-    using TextEditor::QuickFixOperation::textOf;
-    using TextEditor::QuickFixOperation::charAt;
-
-    Utils::ChangeSet::Range range(unsigned tokenIndex) const;
-    Utils::ChangeSet::Range range(CPlusPlus::AST *ast) const;
+    CPlusPlus::Scope *scopeAt(unsigned index) const;
 
-    QString fileName() const;
+    bool isCursorOn(unsigned tokenIndex) const;
+    bool isCursorOn(const CPlusPlus::AST *ast) const;
 
-    virtual void apply();
-    virtual CppRefactoringChanges *refactoringChanges() const;
+    Range range(unsigned tokenIndex) const;
+    Range range(CPlusPlus::AST *ast) const;
 
     const CPlusPlus::Token &tokenAt(unsigned index) const;
 
-    CPlusPlus::Scope *scopeAt(unsigned index) const;
-
     int startOf(unsigned index) const;
     int startOf(const CPlusPlus::AST *ast) const;
     int endOf(unsigned index) const;
     int endOf(const CPlusPlus::AST *ast) const;
     void startAndEndOf(unsigned index, int *start, int *end) const;
 
-    bool isCursorOn(unsigned tokenIndex) const;
-    bool isCursorOn(const CPlusPlus::AST *ast) const;
-
     QString textOf(const CPlusPlus::AST *ast) const;
 
 private:
-    CppRefactoringChanges *_refactoringChanges;
-    CPlusPlus::Document::Ptr _document;
-    CPlusPlus::AST *_topLevelNode;
+    QList<CPlusPlus::AST *> _path;
+    CPlusPlus::Snapshot _snapshot;
+    CppEditor::Internal::SemanticInfo _semanticInfo;
+    CPlusPlus::LookupContext _context;
 };
 
-class CppQuickFixCollector: public TextEditor::QuickFixCollector
+class CPPEDITOR_EXPORT CppQuickFixOperation: public TextEditor::QuickFixOperation
 {
-    Q_OBJECT
+    Q_DISABLE_COPY(CppQuickFixOperation)
 
 public:
-    CppQuickFixCollector();
-    virtual ~CppQuickFixCollector();
+    CppQuickFixOperation(const CppQuickFixState &state, int priority = -1);
+    virtual ~CppQuickFixOperation();
 
-    virtual bool supportsEditor(TextEditor::ITextEditable *editor);
-    virtual TextEditor::QuickFixState *initializeCompletion(TextEditor::ITextEditable *editable);
+protected:
+    QString fileName() const;
+
+    CppRefactoringChanges *refactoringChanges() const;
+
+    const CppQuickFixState &state() const;
+
+protected: // Utility functions forwarding to CppQuickFixState
+    typedef Utils::ChangeSet::Range Range;
+
+    bool isCursorOn(unsigned tokenIndex) const { return state().isCursorOn(tokenIndex); }
+    bool isCursorOn(const CPlusPlus::AST *ast) const { return state().isCursorOn(ast); }
+
+    Range range(int start, int end) const { return CppQuickFixState::range(start, end); }
+    Range range(unsigned tokenIndex) const { return state().range(tokenIndex); }
+    Range range(CPlusPlus::AST *ast) const { return state().range(ast); }
+
+    int startOf(unsigned index) const { return state().startOf(index); }
+    int startOf(const CPlusPlus::AST *ast) const { return state().startOf(ast); }
+    int endOf(unsigned index) const { return state().endOf(index); }
+    int endOf(const CPlusPlus::AST *ast) const { return state().endOf(ast); }
+
+private:
+    CppQuickFixState _state;
+    QScopedPointer<CppRefactoringChanges> _refactoringChanges;
 };
 
-class CppQuickFixFactory: public TextEditor::IQuickFixFactory
+class CPPEDITOR_EXPORT CppQuickFixFactory: public TextEditor::QuickFixFactory
 {
     Q_OBJECT
 
 public:
-    CppQuickFixFactory(QObject *parent = 0);
+    CppQuickFixFactory();
     virtual ~CppQuickFixFactory();
 
-    /*
-     * Returns true if this IQuickFixFactory can be used with the given editor.
-     */
-    virtual QList<TextEditor::QuickFixOperation::Ptr> quickFixOperations(TextEditor::BaseTextEditor *editor);
+    virtual QList<TextEditor::QuickFixOperation::Ptr> matchingOperations(TextEditor::QuickFixState *state);
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state) = 0;
+
+protected:
+    static QList<CppQuickFixOperation::Ptr> singleResult(CppQuickFixOperation *operation);
+    static QList<CppQuickFixOperation::Ptr> noResult();
+};
+
+namespace Internal {
+
+class CppQuickFixCollector: public TextEditor::QuickFixCollector
+{
+    Q_OBJECT
+
+public:
+    CppQuickFixCollector();
+    virtual ~CppQuickFixCollector();
+
+    virtual bool supportsEditor(TextEditor::ITextEditable *editor);
+    virtual TextEditor::QuickFixState *initializeCompletion(TextEditor::BaseTextEditor *editor);
+
+    virtual QList<TextEditor::QuickFixFactory *> quickFixFactories() const;
+
+    static void registerQuickFixes(ExtensionSystem::IPlugin *plugIn);
 };
 
 } // end of namespace Internal
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d5eec24b630e8d8bfd54677125e3a358797735b4
--- /dev/null
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -0,0 +1,1733 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "cppeditor.h"
+#include "cppquickfix.h"
+#include "cppdeclfromdef.h"
+
+#include <ASTVisitor.h>
+#include <AST.h>
+#include <ASTMatcher.h>
+#include <ASTPatternBuilder.h>
+#include <CoreTypes.h>
+#include <Literals.h>
+#include <Name.h>
+#include <Names.h>
+#include <Symbol.h>
+#include <Symbols.h>
+#include <Token.h>
+#include <TranslationUnit.h>
+#include <Type.h>
+
+#include <cplusplus/DependencyTable.h>
+#include <cplusplus/Overview.h>
+#include <cplusplus/TypeOfExpression.h>
+#include <cplusplus/CppRewriter.h>
+#include <cpptools/cpptoolsconstants.h>
+#include <extensionsystem/iplugin.h>
+
+#include <QtGui/QApplication>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextCursor>
+
+using namespace CppEditor;
+using namespace CppEditor::Internal;
+using namespace TextEditor;
+using namespace CPlusPlus;
+using namespace Utils;
+
+namespace {
+
+/*
+    Rewrite
+    a op b -> !(a invop b)
+    (a op b) -> !(a invop b)
+    !(a op b) -> (a invob b)
+*/
+class UseInverseOp: public CppQuickFixFactory
+{
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        QList<CppQuickFixOperation::Ptr> result;
+
+        const QList<AST *> &path = state.path();
+        int index = path.size() - 1;
+        BinaryExpressionAST *binary = path.at(index)->asBinaryExpression();
+        if (! binary)
+            return result;
+        if (! state.isCursorOn(binary->binary_op_token))
+            return result;
+
+        Kind invertToken;
+        switch (state.tokenAt(binary->binary_op_token).kind()) {
+        case T_LESS_EQUAL:
+            invertToken = T_GREATER;
+            break;
+        case T_LESS:
+            invertToken = T_GREATER_EQUAL;
+            break;
+        case T_GREATER:
+            invertToken = T_LESS_EQUAL;
+            break;
+        case T_GREATER_EQUAL:
+            invertToken = T_LESS;
+            break;
+        case T_EQUAL_EQUAL:
+            invertToken = T_EXCLAIM_EQUAL;
+            break;
+        case T_EXCLAIM_EQUAL:
+            invertToken = T_EQUAL_EQUAL;
+            break;
+        default:
+            return result;
+        }
+
+        result.append(CppQuickFixOperation::Ptr(new Operation(state, index, binary, invertToken)));
+        return result;
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+        BinaryExpressionAST *binary;
+        NestedExpressionAST *nested;
+        UnaryExpressionAST *negation;
+
+        QString replacement;
+
+    public:
+        Operation(const CppQuickFixState &state, int priority, BinaryExpressionAST *binary, Kind invertToken)
+            : CppQuickFixOperation(state, priority)
+            , binary(binary)
+        {
+            Token tok;
+            tok.f.kind = invertToken;
+            replacement = QLatin1String(tok.spell());
+
+            // check for enclosing nested expression
+            if (priority - 1 >= 0)
+                nested = state.path()[priority - 1]->asNestedExpression();
+
+            // check for ! before parentheses
+            if (nested && priority - 2 >= 0) {
+                negation = state.path()[priority - 2]->asUnaryExpression();
+                if (negation && ! state.tokenAt(negation->unary_op_token).is(T_EXCLAIM))
+                    negation = 0;
+            }
+        }
+
+        virtual QString description() const
+        {
+            return QApplication::translate("CppTools::QuickFix", "Rewrite Using %1").arg(replacement);
+        }
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+            if (negation) {
+                // can't remove parentheses since that might break precedence
+                changes.remove(range(negation->unary_op_token));
+            } else if (nested) {
+                changes.insert(state().startOf(nested), "!");
+            } else {
+                changes.insert(state().startOf(binary), "!(");
+                changes.insert(state().endOf(binary), ")");
+            }
+            changes.replace(range(binary->binary_op_token), replacement);
+            refactoringChanges()->changeFile(fileName(), changes);
+        }
+    };
+};
+
+/*
+    Rewrite
+    a op b
+
+    As
+    b flipop a
+*/
+class FlipBinaryOp: public CppQuickFixFactory
+{
+public:
+    virtual QList<QuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        QList<QuickFixOperation::Ptr> result;
+        const QList<AST *> &path = state.path();
+
+        int index = path.size() - 1;
+        BinaryExpressionAST *binary = path.at(index)->asBinaryExpression();
+        if (! binary)
+            return result;
+        if (! state.isCursorOn(binary->binary_op_token))
+            return result;
+
+        Kind flipToken;
+        switch (state.tokenAt(binary->binary_op_token).kind()) {
+        case T_LESS_EQUAL:
+            flipToken = T_GREATER_EQUAL;
+            break;
+        case T_LESS:
+            flipToken = T_GREATER;
+            break;
+        case T_GREATER:
+            flipToken = T_LESS;
+            break;
+        case T_GREATER_EQUAL:
+            flipToken = T_LESS_EQUAL;
+            break;
+        case T_EQUAL_EQUAL:
+        case T_EXCLAIM_EQUAL:
+        case T_AMPER_AMPER:
+        case T_PIPE_PIPE:
+            flipToken = T_EOF_SYMBOL;
+            break;
+        default:
+            return result;
+        }
+
+        QString replacement;
+        if (flipToken != T_EOF_SYMBOL) {
+            Token tok;
+            tok.f.kind = flipToken;
+            replacement = QLatin1String(tok.spell());
+        }
+
+        result.append(QuickFixOperation::Ptr(new Operation(state, index, binary, replacement)));
+        return result;
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority, BinaryExpressionAST *binary, QString replacement)
+            : CppQuickFixOperation(state)
+            , binary(binary)
+            , replacement(replacement)
+        {
+            setPriority(priority);
+        }
+
+        virtual QString description() const
+        {
+            if (replacement.isEmpty())
+                return QApplication::translate("CppTools::QuickFix", "Swap Operands");
+            else
+                return QApplication::translate("CppTools::QuickFix", "Rewrite Using %1").arg(replacement);
+        }
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+
+            changes.flip(range(binary->left_expression), range(binary->right_expression));
+            if (! replacement.isEmpty())
+                changes.replace(range(binary->binary_op_token), replacement);
+
+            refactoringChanges()->changeFile(fileName(), changes);
+        }
+
+    private:
+        BinaryExpressionAST *binary;
+        QString replacement;
+    };
+};
+
+/*
+    Rewrite
+    !a && !b
+
+    As
+    !(a || b)
+*/
+class RewriteLogicalAndOp: public CppQuickFixFactory
+{
+public:
+    virtual QList<QuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        QList<QuickFixOperation::Ptr> result;
+        BinaryExpressionAST *expression = 0;
+        const QList<AST *> &path = state.path();
+
+        int index = path.size() - 1;
+        for (; index != -1; --index) {
+            expression = path.at(index)->asBinaryExpression();
+            if (expression)
+                break;
+        }
+
+        if (! expression)
+            return result;
+
+        if (! state.isCursorOn(expression->binary_op_token))
+            return result;
+
+        QSharedPointer<Operation> op(new Operation(state));
+
+        if (expression->match(op->pattern, &matcher) &&
+                state.tokenAt(op->pattern->binary_op_token).is(T_AMPER_AMPER) &&
+                state.tokenAt(op->left->unary_op_token).is(T_EXCLAIM) &&
+                state.tokenAt(op->right->unary_op_token).is(T_EXCLAIM)) {
+            op->setDescription(QApplication::translate("CppTools::QuickFix", "Rewrite Condition Using ||"));
+            op->setPriority(index);
+            result.append(op);
+        }
+
+        return result;
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        QSharedPointer<ASTPatternBuilder> mk;
+        UnaryExpressionAST *left;
+        UnaryExpressionAST *right;
+        BinaryExpressionAST *pattern;
+
+        Operation(const CppQuickFixState &state)
+            : CppQuickFixOperation(state)
+            , mk(new ASTPatternBuilder)
+        {
+            left = mk->UnaryExpression();
+            right = mk->UnaryExpression();
+            pattern = mk->BinaryExpression(left, right);
+        }
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+            changes.replace(range(pattern->binary_op_token), QLatin1String("||"));
+            changes.remove(range(left->unary_op_token));
+            changes.remove(range(right->unary_op_token));
+            const int start = state().startOf(pattern);
+            const int end = state().endOf(pattern);
+            changes.insert(start, QLatin1String("!("));
+            changes.insert(end, QLatin1String(")"));
+
+            refactoringChanges()->changeFile(fileName(), changes);
+            refactoringChanges()->reindent(fileName(), range(pattern));
+        }
+    };
+
+private:
+    ASTMatcher matcher;
+};
+
+class SplitSimpleDeclarationOp: public CppQuickFixFactory
+{
+    static bool checkDeclaration(SimpleDeclarationAST *declaration)
+    {
+        if (! declaration->semicolon_token)
+            return false;
+
+        if (! declaration->decl_specifier_list)
+            return false;
+
+        for (SpecifierListAST *it = declaration->decl_specifier_list; it; it = it->next) {
+            SpecifierAST *specifier = it->value;
+
+            if (specifier->asEnumSpecifier() != 0)
+                return false;
+
+            else if (specifier->asClassSpecifier() != 0)
+                return false;
+        }
+
+        if (! declaration->declarator_list)
+            return false;
+
+        else if (! declaration->declarator_list->next)
+            return false;
+
+        return true;
+    }
+
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        QList<CppQuickFixOperation::Ptr> result;
+        CoreDeclaratorAST *core_declarator = 0;
+        const QList<AST *> &path = state.path();
+
+        for (int index = path.size() - 1; index != -1; --index) {
+            AST *node = path.at(index);
+
+            if (CoreDeclaratorAST *coreDecl = node->asCoreDeclarator())
+                core_declarator = coreDecl;
+
+            else if (SimpleDeclarationAST *simpleDecl = node->asSimpleDeclaration()) {
+                if (checkDeclaration(simpleDecl)) {
+                    SimpleDeclarationAST *declaration = simpleDecl;
+
+                    const int cursorPosition = state.selectionStart();
+
+                    const int startOfDeclSpecifier = state.startOf(declaration->decl_specifier_list->firstToken());
+                    const int endOfDeclSpecifier = state.endOf(declaration->decl_specifier_list->lastToken() - 1);
+
+                    if (cursorPosition >= startOfDeclSpecifier && cursorPosition <= endOfDeclSpecifier) {
+                        // the AST node under cursor is a specifier.
+                        return singleResult(new Operation(state, index, declaration));
+                    }
+
+                    if (core_declarator && state.isCursorOn(core_declarator)) {
+                        // got a core-declarator under the text cursor.
+                        return singleResult(new Operation(state, index, declaration));
+                    }
+                }
+
+                break;
+            }
+        }
+
+        return result;
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority, SimpleDeclarationAST *decl)
+            : CppQuickFixOperation(state, priority)
+            , declaration(decl)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix",
+                                                   "Split Declaration"));
+        }
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+
+            SpecifierListAST *specifiers = declaration->decl_specifier_list;
+            int declSpecifiersStart = state().startOf(specifiers->firstToken());
+            int declSpecifiersEnd = state().endOf(specifiers->lastToken() - 1);
+            int insertPos = state().endOf(declaration->semicolon_token);
+
+            DeclaratorAST *prevDeclarator = declaration->declarator_list->value;
+
+            for (DeclaratorListAST *it = declaration->declarator_list->next; it; it = it->next) {
+                DeclaratorAST *declarator = it->value;
+
+                changes.insert(insertPos, QLatin1String("\n"));
+                changes.copy(declSpecifiersStart, declSpecifiersEnd, insertPos);
+                changes.insert(insertPos, QLatin1String(" "));
+                changes.move(range(declarator), insertPos);
+                changes.insert(insertPos, QLatin1String(";"));
+
+                const int prevDeclEnd = state().endOf(prevDeclarator);
+                changes.remove(prevDeclEnd, state().startOf(declarator));
+
+                prevDeclarator = declarator;
+            }
+
+            refactoringChanges()->changeFile(fileName(), changes);
+            refactoringChanges()->reindent(fileName(), range(declaration));
+        }
+
+    private:
+        SimpleDeclarationAST *declaration;
+    };
+};
+
+/*
+    Add curly braces to a if statement that doesn't already contain a
+    compound statement.
+*/
+class AddBracesToIfOp: public CppQuickFixFactory
+{
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        const QList<AST *> &path = state.path();
+
+        // show when we're on the 'if' of an if statement
+        int index = path.size() - 1;
+        IfStatementAST *ifStatement = path.at(index)->asIfStatement();
+        if (ifStatement && state.isCursorOn(ifStatement->if_token) && ifStatement->statement
+            && ! ifStatement->statement->asCompoundStatement()) {
+            return singleResult(new Operation(state, index, ifStatement->statement));
+        }
+
+        // or if we're on the statement contained in the if
+        // ### This may not be such a good idea, consider nested ifs...
+        for (; index != -1; --index) {
+            IfStatementAST *ifStatement = path.at(index)->asIfStatement();
+            if (ifStatement && ifStatement->statement
+                && state.isCursorOn(ifStatement->statement)
+                && ! ifStatement->statement->asCompoundStatement()) {
+                return singleResult(new Operation(state, index, ifStatement->statement));
+            }
+        }
+
+        // ### This could very well be extended to the else branch
+        // and other nodes entirely.
+
+        return noResult();
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority, StatementAST *statement)
+            : CppQuickFixOperation(state, priority)
+            , _statement(statement)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix",
+                                                   "Add Curly Braces"));
+        }
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+
+            const int start = endOf(_statement->firstToken() - 1);
+            changes.insert(start, QLatin1String(" {"));
+
+            const int end = endOf(_statement->lastToken() - 1);
+            changes.insert(end, "\n}");
+
+            refactoringChanges()->changeFile(fileName(), changes);
+            refactoringChanges()->reindent(fileName(), range(start, end));
+        }
+
+    private:
+        StatementAST *_statement;
+    };
+};
+
+/*
+    Replace
+    if (Type name = foo()) {...}
+
+    With
+    Type name = foo;
+    if (name) {...}
+*/
+class MoveDeclarationOutOfIfOp: public CppQuickFixFactory
+{
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        const QList<AST *> &path = state.path();
+        QSharedPointer<Operation> op(new Operation(state));
+
+        int index = path.size() - 1;
+        for (; index != -1; --index) {
+            if (IfStatementAST *statement = path.at(index)->asIfStatement()) {
+                if (statement->match(op->pattern, &op->matcher) && op->condition->declarator) {
+                    DeclaratorAST *declarator = op->condition->declarator;
+                    op->core = declarator->core_declarator;
+                    if (! op->core)
+                        return noResult();
+
+                    if (state.isCursorOn(op->core)) {
+                        QList<CppQuickFixOperation::Ptr> result;
+                        op->setPriority(index);
+                        result.append(op);
+                        return result;
+                    }
+                }
+            }
+        }
+
+        return noResult();
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state)
+            : CppQuickFixOperation(state)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix",
+                                                   "Move Declaration out of Condition"));
+
+            condition = mk.Condition();
+            pattern = mk.IfStatement(condition);
+        }
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+
+            changes.copy(range(core), startOf(condition));
+
+            int insertPos = startOf(pattern);
+            changes.move(range(condition), insertPos);
+            changes.insert(insertPos, QLatin1String(";\n"));
+
+            refactoringChanges()->changeFile(fileName(), changes);
+            refactoringChanges()->reindent(fileName(), range(pattern));
+        }
+
+        ASTMatcher matcher;
+        ASTPatternBuilder mk;
+        CPPEditor *editor;
+        ConditionAST *condition;
+        IfStatementAST *pattern;
+        CoreDeclaratorAST *core;
+    };
+};
+
+/*
+    Replace
+    while (Type name = foo()) {...}
+
+    With
+    Type name;
+    while ((name = foo()) != 0) {...}
+*/
+class MoveDeclarationOutOfWhileOp: public CppQuickFixFactory
+{
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        const QList<AST *> &path = state.path();
+        QSharedPointer<Operation> op(new Operation(state));
+
+        int index = path.size() - 1;
+        for (; index != -1; --index) {
+            if (WhileStatementAST *statement = path.at(index)->asWhileStatement()) {
+                if (statement->match(op->pattern, &op->matcher) && op->condition->declarator) {
+                    DeclaratorAST *declarator = op->condition->declarator;
+                    op->core = declarator->core_declarator;
+
+                    if (! op->core)
+                        return noResult();
+
+                    else if (! declarator->equals_token)
+                        return noResult();
+
+                    else if (! declarator->initializer)
+                        return noResult();
+
+                    if (state.isCursorOn(op->core)) {
+                        QList<CppQuickFixOperation::Ptr> result;
+                        op->setPriority(index);
+                        result.append(op);
+                        return result;
+                    }
+                }
+            }
+        }
+
+        return noResult();
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state)
+            : CppQuickFixOperation(state)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix",
+                                                   "Move Declaration out of Condition"));
+
+            condition = mk.Condition();
+            pattern = mk.WhileStatement(condition);
+        }
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+
+            changes.insert(startOf(condition), QLatin1String("("));
+            changes.insert(endOf(condition), QLatin1String(") != 0"));
+
+            int insertPos = startOf(pattern);
+            const int conditionStart = startOf(condition);
+            changes.move(conditionStart, startOf(core), insertPos);
+            changes.copy(range(core), insertPos);
+            changes.insert(insertPos, QLatin1String(";\n"));
+
+            refactoringChanges()->changeFile(fileName(), changes);
+            refactoringChanges()->reindent(fileName(), range(pattern));
+        }
+
+        ASTMatcher matcher;
+        ASTPatternBuilder mk;
+        CPPEditor *editor;
+        ConditionAST *condition;
+        WhileStatementAST *pattern;
+        CoreDeclaratorAST *core;
+    };
+};
+
+/*
+  Replace
+     if (something && something_else) {
+     }
+
+  with
+     if (something) {
+        if (something_else) {
+        }
+     }
+
+  and
+    if (something || something_else)
+      x;
+
+  with
+    if (something)
+      x;
+    else if (something_else)
+      x;
+*/
+class SplitIfStatementOp: public CppQuickFixFactory
+{
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        IfStatementAST *pattern = 0;
+        const QList<AST *> &path = state.path();
+
+        int index = path.size() - 1;
+        for (; index != -1; --index) {
+            AST *node = path.at(index);
+            if (IfStatementAST *stmt = node->asIfStatement()) {
+                pattern = stmt;
+                break;
+            }
+        }
+
+        if (! pattern || ! pattern->statement)
+            return noResult();
+
+        unsigned splitKind = 0;
+        for (++index; index < path.size(); ++index) {
+            AST *node = path.at(index);
+            BinaryExpressionAST *condition = node->asBinaryExpression();
+            if (! condition)
+                return noResult();
+
+            Token binaryToken = state.tokenAt(condition->binary_op_token);
+
+            // only accept a chain of ||s or &&s - no mixing
+            if (! splitKind) {
+                splitKind = binaryToken.kind();
+                if (splitKind != T_AMPER_AMPER && splitKind != T_PIPE_PIPE)
+                    return noResult();
+                // we can't reliably split &&s in ifs with an else branch
+                if (splitKind == T_AMPER_AMPER && pattern->else_statement)
+                    return noResult();
+            } else if (splitKind != binaryToken.kind()) {
+                return noResult();
+            }
+
+            if (state.isCursorOn(condition->binary_op_token))
+                return singleResult(new Operation(state, index, pattern, condition));
+        }
+
+        return noResult();
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority,
+                  IfStatementAST *pattern, BinaryExpressionAST *condition)
+            : CppQuickFixOperation(state, priority)
+            , pattern(pattern)
+            , condition(condition)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix",
+                                                   "Split if Statement"));
+        }
+
+        virtual void createChanges()
+        {
+            const Token binaryToken = state().tokenAt(condition->binary_op_token);
+
+            if (binaryToken.is(T_AMPER_AMPER))
+                splitAndCondition();
+            else
+                splitOrCondition();
+        }
+
+        void splitAndCondition()
+        {
+            ChangeSet changes;
+
+            int startPos = startOf(pattern);
+            changes.insert(startPos, QLatin1String("if ("));
+            changes.move(range(condition->left_expression), startPos);
+            changes.insert(startPos, QLatin1String(") {\n"));
+
+            const int lExprEnd = endOf(condition->left_expression);
+            changes.remove(lExprEnd, startOf(condition->right_expression));
+            changes.insert(endOf(pattern), QLatin1String("\n}"));
+
+            refactoringChanges()->changeFile(fileName(), changes);
+            refactoringChanges()->reindent(fileName(), range(pattern));
+        }
+
+        void splitOrCondition()
+        {
+            ChangeSet changes;
+
+            StatementAST *ifTrueStatement = pattern->statement;
+            CompoundStatementAST *compoundStatement = ifTrueStatement->asCompoundStatement();
+
+            int insertPos = endOf(ifTrueStatement);
+            if (compoundStatement)
+                changes.insert(insertPos, QLatin1String(" "));
+            else
+                changes.insert(insertPos, QLatin1String("\n"));
+            changes.insert(insertPos, QLatin1String("else if ("));
+
+            const int rExprStart = startOf(condition->right_expression);
+            changes.move(rExprStart, startOf(pattern->rparen_token), insertPos);
+            changes.insert(insertPos, QLatin1String(")"));
+
+            const int rParenEnd = endOf(pattern->rparen_token);
+            changes.copy(rParenEnd, endOf(pattern->statement), insertPos);
+
+            const int lExprEnd = endOf(condition->left_expression);
+            changes.remove(lExprEnd, startOf(condition->right_expression));
+
+            refactoringChanges()->changeFile(fileName(), changes);
+            refactoringChanges()->reindent(fileName(), range(pattern));
+        }
+
+    private:
+        IfStatementAST *pattern;
+        BinaryExpressionAST *condition;
+    };
+};
+
+/*
+  Replace
+    "abcd"
+  With
+    QLatin1String("abcd")
+*/
+class WrapStringLiteral: public CppQuickFixFactory
+{
+public:
+    enum Type { TypeString, TypeObjCString, TypeChar, TypeNone };
+
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        ExpressionAST *literal = 0;
+        Type type = TypeNone;
+        const QList<AST *> &path = state.path();
+
+        if (path.isEmpty())
+            return noResult(); // nothing to do
+
+        literal = path.last()->asStringLiteral();
+
+        if (! literal) {
+            literal = path.last()->asNumericLiteral();
+            if (!literal || !state.tokenAt(literal->asNumericLiteral()->literal_token).is(T_CHAR_LITERAL))
+                return noResult();
+            else
+                type = TypeChar;
+        } else {
+            type = TypeString;
+        }
+
+        if (path.size() > 1) {
+            if (CallAST *call = path.at(path.size() - 2)->asCall()) {
+                if (call->base_expression) {
+                    if (SimpleNameAST *functionName = call->base_expression->asSimpleName()) {
+                        const QByteArray id(state.tokenAt(functionName->identifier_token).identifier->chars());
+
+                        if (id == "QT_TRANSLATE_NOOP" || id == "tr" || id == "trUtf8"
+                                || (type == TypeString && (id == "QLatin1String" || id == "QLatin1Literal"))
+                                || (type == TypeChar && id == "QLatin1Char"))
+                            return noResult(); // skip it
+                    }
+                }
+            }
+        }
+
+        if (type == TypeString) {
+            if (state.charAt(state.startOf(literal)) == QLatin1Char('@'))
+                type = TypeObjCString;
+        }
+        return singleResult(new Operation(state,
+                                          path.size() - 1, // very high priority
+                                          type,
+                                          literal));
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority, Type type,
+                  ExpressionAST *literal)
+            : CppQuickFixOperation(state, priority)
+            , type(type)
+            , literal(literal)
+        {
+            if (type == TypeChar)
+                setDescription(QApplication::translate("CppTools::QuickFix",
+                                                       "Enclose in QLatin1Char(...)"));
+            else
+                setDescription(QApplication::translate("CppTools::QuickFix",
+                                                       "Enclose in QLatin1String(...)"));
+        }
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+
+            const int startPos = startOf(literal);
+            QLatin1String replacement = (type == TypeChar ? QLatin1String("QLatin1Char(")
+                                                          : QLatin1String("QLatin1String("));
+
+            if (type == TypeObjCString)
+                changes.replace(startPos, startPos + 1, replacement);
+            else
+                changes.insert(startPos, replacement);
+
+            changes.insert(endOf(literal), ")");
+
+            refactoringChanges()->changeFile(fileName(), changes);
+        }
+
+    private:
+        Type type;
+        ExpressionAST *literal;
+    };
+};
+
+/*
+  Replace
+    "abcd"
+  With
+    tr("abcd") or
+    QCoreApplication::translate("CONTEXT", "abcd") or
+    QT_TRANSLATE_NOOP("GLOBAL", "abcd")
+*/
+class TranslateStringLiteral: public CppQuickFixFactory
+{
+public:
+    enum TranslationOption { unknown, useTr, useQCoreApplicationTranslate, useMacro };
+
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        const QList<AST *> &path = state.path();
+        // Initialize
+        ExpressionAST *literal = 0;
+        QString trContext;
+
+        if (path.isEmpty())
+            return noResult();
+
+        literal = path.last()->asStringLiteral();
+        if (!literal)
+            return noResult(); // No string, nothing to do
+
+        // Do we already have a translation markup?
+        if (path.size() >= 2) {
+            if (CallAST *call = path.at(path.size() - 2)->asCall()) {
+                if (call->base_expression) {
+                    if (SimpleNameAST *functionName = call->base_expression->asSimpleName()) {
+                        const QByteArray id(state.tokenAt(functionName->identifier_token).identifier->chars());
+
+                        if (id == "tr" || id == "trUtf8"
+                                || id == "translate"
+                                || id == "QT_TRANSLATE_NOOP"
+                                || id == "QLatin1String" || id == "QLatin1Literal")
+                            return noResult(); // skip it
+                    }
+                }
+            }
+        }
+
+        QSharedPointer<Control> control = state.context().control();
+        const Name *trName = control->nameId(control->findOrInsertIdentifier("tr"));
+
+        // Check whether we are in a method:
+        for (int i = path.size() - 1; i >= 0; --i)
+        {
+            if (FunctionDefinitionAST *definition = path.at(i)->asFunctionDefinition()) {
+                Function *function = definition->symbol;
+                ClassOrNamespace *b = state.context().lookupType(function);
+                if (b) {
+                    // Do we have a tr method?
+                    foreach(const LookupItem &r, b->find(trName)) {
+                        Symbol *s = r.declaration();
+                        if (s->type()->isFunctionType()) {
+                            // no context required for tr
+                            return singleResult(new Operation(state, path.size() - 1, literal, useTr, trContext));
+                        }
+                    }
+                }
+                // We need to do a QCA::translate, so we need a context.
+                // Use fully qualified class name:
+                Overview oo;
+                foreach (const Name *n, LookupContext::path(function)) {
+                    if (!trContext.isEmpty())
+                        trContext.append(QLatin1String("::"));
+                    trContext.append(oo.prettyName(n));
+                }
+                // ... or global if none available!
+                if (trContext.isEmpty())
+                    trContext = QLatin1String("GLOBAL");
+                return singleResult(new Operation(state, path.size() - 1, literal, useQCoreApplicationTranslate, trContext));
+            }
+        }
+
+        // We need to use Q_TRANSLATE_NOOP
+        return singleResult(new Operation(state, path.size() - 1, literal, useMacro, QLatin1String("GLOBAL")));
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority, ExpressionAST *literal, TranslationOption option, const QString &context)
+            : CppQuickFixOperation(state, priority)
+            , m_literal(literal)
+            , m_option(option)
+            , m_context(context)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix", "Mark as translateable"));
+        }
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+
+            const int startPos = startOf(m_literal);
+            QString replacement(QLatin1String("tr("));
+            if (m_option == useQCoreApplicationTranslate) {
+                replacement = QLatin1String("QCoreApplication::translate(\"")
+                        + m_context + QLatin1String("\", ");
+            } else if (m_option == useMacro) {
+                replacement = QLatin1String("QT_TRANSLATE_NOOP(\"")
+                        + m_context + QLatin1String("\", ");
+            }
+
+            changes.insert(startPos, replacement);
+            changes.insert(endOf(m_literal), QLatin1String(")"));
+
+            refactoringChanges()->changeFile(fileName(), changes);
+        }
+
+    private:
+        ExpressionAST *m_literal;
+        TranslationOption m_option;
+        QString m_context;
+    };
+};
+
+class CStringToNSString: public CppQuickFixFactory
+{
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        if (state.editor()->mimeType() != CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE)
+            return noResult();
+
+        StringLiteralAST *stringLiteral = 0;
+        CallAST *qlatin1Call = 0;
+        const QList<AST *> &path = state.path();
+
+        if (path.isEmpty())
+            return noResult(); // nothing to do
+
+        stringLiteral = path.last()->asStringLiteral();
+
+        if (! stringLiteral)
+            return noResult();
+
+        else if (state.charAt(state.startOf(stringLiteral)) == QLatin1Char('@'))
+            return noResult(); // it's already an objc string literal.
+
+        else if (path.size() > 1) {
+            if (CallAST *call = path.at(path.size() - 2)->asCall()) {
+                if (call->base_expression) {
+                    if (SimpleNameAST *functionName = call->base_expression->asSimpleName()) {
+                        const QByteArray id(state.tokenAt(functionName->identifier_token).identifier->chars());
+
+                        if (id == "QLatin1String" || id == "QLatin1Literal")
+                            qlatin1Call = call;
+                    }
+                }
+            }
+        }
+
+        return singleResult(new Operation(state, path.size() - 1, stringLiteral, qlatin1Call));
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority, StringLiteralAST *stringLiteral, CallAST *qlatin1Call)
+            : CppQuickFixOperation(state, priority)
+            , stringLiteral(stringLiteral)
+            , qlatin1Call(qlatin1Call)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix",
+                                                   "Convert to Objective-C String Literal"));
+        }
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+
+            if (qlatin1Call) {
+                changes.replace(startOf(qlatin1Call), startOf(stringLiteral), QLatin1String("@"));
+                changes.remove(endOf(stringLiteral), endOf(qlatin1Call));
+            } else {
+                changes.insert(startOf(stringLiteral), "@");
+            }
+
+            refactoringChanges()->changeFile(fileName(), changes);
+        }
+
+    private:
+        StringLiteralAST *stringLiteral;
+        CallAST *qlatin1Call;
+    };
+};
+
+/*
+  Base class for converting numeric literals between decimal, octal and hex.
+  Does the base check for the specific ones and parses the number.
+  Test cases:
+    0xFA0Bu;
+    0X856A;
+    298.3;
+    199;
+    074;
+    199L;
+    074L;
+    -199;
+    -017;
+    0783; // invalid octal
+    0; // border case, allow only hex<->decimal
+*/
+class ConvertNumericLiteral: public CppQuickFixFactory
+{
+public:
+    virtual QList<QuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        QList<QuickFixOperation::Ptr> result;
+
+        const QList<AST *> &path = state.path();
+
+        if (path.isEmpty())
+            return result; // nothing to do
+
+        NumericLiteralAST *literal = path.last()->asNumericLiteral();
+
+        if (! literal)
+            return result;
+
+        Token token = state.tokenAt(literal->asNumericLiteral()->literal_token);
+        if (!token.is(T_NUMERIC_LITERAL))
+            return result;
+        const NumericLiteral *numeric = token.number;
+        if (numeric->isDouble() || numeric->isFloat())
+            return result;
+
+        // remove trailing L or U and stuff
+        const char * const spell = numeric->chars();
+        int numberLength = numeric->size();
+        while (numberLength > 0 && (spell[numberLength-1] < '0' || spell[numberLength-1] > 'F'))
+            --numberLength;
+        if (numberLength < 1)
+            return result;
+
+        // convert to number
+        bool valid;
+        ulong value = QString::fromUtf8(spell).left(numberLength).toULong(&valid, 0);
+        if (!valid) // e.g. octal with digit > 7
+            return result;
+
+        const int priority = path.size() - 1; // very high priority
+        const int start = state.startOf(literal);
+        const char * const str = numeric->chars();
+
+        if (!numeric->isHex()) {
+            /*
+              Convert integer literal to hex representation.
+              Replace
+                32
+                040
+              With
+                0x20
+
+            */
+            QString replacement;
+            replacement.sprintf("0x%lX", value);
+            QuickFixOperation::Ptr op(new ConvertNumeric(state, start, start + numberLength, replacement));
+            op->setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Hexadecimal"));
+            op->setPriority(priority);
+            result.append(op);
+        }
+
+        if (value != 0) {
+            if (!(numberLength > 1 && str[0] == '0' && str[1] != 'x' && str[1] != 'X')) {
+                /*
+                  Convert integer literal to octal representation.
+                  Replace
+                    32
+                    0x20
+                  With
+                    040
+                */
+                QString replacement;
+                replacement.sprintf("0%lo", value);
+                QuickFixOperation::Ptr op(new ConvertNumeric(state, start, start + numberLength, replacement));
+                op->setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Octal"));
+                op->setPriority(priority);
+                result.append(op);
+            }
+        }
+
+        if (value != 0 || numeric->isHex()) {
+            if (!(numberLength > 1 && str[0] != '0')) {
+                /*
+                  Convert integer literal to decimal representation.
+                  Replace
+                    0x20
+                    040
+                  With
+                    32
+                */
+                QString replacement;
+                replacement.sprintf("%lu", value);
+                QuickFixOperation::Ptr op(new ConvertNumeric(state, start, start + numberLength, replacement));
+                op->setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Decimal"));
+                op->setPriority(priority);
+                result.append(op);
+            }
+        }
+
+        return result;
+    }
+
+private:
+    class ConvertNumeric: public CppQuickFixOperation
+    {
+    public:
+        ConvertNumeric(const CppQuickFixState &state, int start, int end, const QString &replacement)
+            : CppQuickFixOperation(state)
+            , start(start)
+            , end(end)
+            , replacement(replacement)
+        {}
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+            changes.replace(start, end, replacement);
+            refactoringChanges()->changeFile(fileName(), changes);
+        }
+
+    protected:
+        int start, end;
+        QString replacement;
+    };
+};
+
+/*
+  Adds missing case statements for "switch (enumVariable)"
+*/
+class CompleteSwitchCaseStatement: public CppQuickFixFactory
+{
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        const QList<AST *> &path = state.path();
+
+        if (path.isEmpty())
+            return noResult(); // nothing to do
+
+        // look for switch statement
+        for (int depth = path.size() - 1; depth >= 0; --depth) {
+            AST *ast = path.at(depth);
+            SwitchStatementAST *switchStatement = ast->asSwitchStatement();
+            if (switchStatement) {
+                if (!state.isCursorOn(switchStatement->switch_token) || !switchStatement->statement)
+                    return noResult();
+                CompoundStatementAST *compoundStatement = switchStatement->statement->asCompoundStatement();
+                if (!compoundStatement) // we ignore pathologic case "switch (t) case A: ;"
+                    return noResult();
+                // look if the condition's type is an enum
+                if (Enum *e = conditionEnum(state, switchStatement)) {
+                    // check the possible enum values
+                    QStringList values;
+                    Overview prettyPrint;
+                    for (unsigned i = 0; i < e->memberCount(); ++i) {
+                        if (Declaration *decl = e->memberAt(i)->asDeclaration()) {
+                            values << prettyPrint(LookupContext::fullyQualifiedName(decl));
+                        }
+                    }
+                    // Get the used values
+                    Block *block = switchStatement->symbol;
+                    CaseStatementCollector caseValues(state.document(), state.snapshot(),
+                        state.document()->scopeAt(block->line(), block->column()));
+                    QStringList usedValues = caseValues(switchStatement);
+                    // save the values that would be added
+                    foreach (const QString &usedValue, usedValues)
+                        values.removeAll(usedValue);
+                    if (values.isEmpty())
+                        return noResult();
+                    return singleResult(new Operation(state, depth, compoundStatement, values));
+                }
+                return noResult();
+            }
+        }
+
+        return noResult();
+    }
+
+protected:
+    Enum *conditionEnum(const CppQuickFixState &state, SwitchStatementAST *statement)
+    {
+        Block *block = statement->symbol;
+        Scope *scope = state.document()->scopeAt(block->line(), block->column());
+        TypeOfExpression typeOfExpression;
+        typeOfExpression.init(state.document(), state.snapshot());
+        const QList<LookupItem> results = typeOfExpression(statement->condition,
+                                                           state.document(),
+                                                           scope);
+        foreach (LookupItem result, results) {
+            FullySpecifiedType fst = result.type();
+            if (Enum *e = result.declaration()->type()->asEnumType())
+                return e;
+            if (NamedType *namedType = fst->asNamedType()) {
+                QList<LookupItem> candidates =
+                        typeOfExpression.context().lookup(namedType->name(), scope);
+                foreach (const LookupItem &r, candidates) {
+                    Symbol *candidate = r.declaration();
+                    if (Enum *e = candidate->asEnum()) {
+                        return e;
+                    }
+                }
+            }
+        }
+        return 0;
+    }
+
+    class CaseStatementCollector : public ASTVisitor
+    {
+    public:
+        CaseStatementCollector(Document::Ptr document, const Snapshot &snapshot,
+                               Scope *scope)
+            : ASTVisitor(document->translationUnit()),
+            document(document),
+            scope(scope)
+        {
+            typeOfExpression.init(document, snapshot);
+        }
+
+        QStringList operator ()(AST *ast)
+        {
+            values.clear();
+            foundCaseStatementLevel = false;
+            accept(ast);
+            return values;
+        }
+
+        bool preVisit(AST *ast) {
+            if (CaseStatementAST *cs = ast->asCaseStatement()) {
+                foundCaseStatementLevel = true;
+                ExpressionAST *expression = cs->expression->asSimpleName();
+                if (!expression)
+                    expression = cs->expression->asQualifiedName();
+                if (expression) {
+                    LookupItem item = typeOfExpression(expression,
+                                                       document,
+                                                       scope).first();
+                    values << prettyPrint(LookupContext::fullyQualifiedName(item.declaration()));
+                }
+                return true;
+            } else if (foundCaseStatementLevel) {
+                return false;
+            }
+            return true;
+        }
+
+        Overview prettyPrint;
+        bool foundCaseStatementLevel;
+        QStringList values;
+        TypeOfExpression typeOfExpression;
+        Document::Ptr document;
+        Scope *scope;
+    };
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority, CompoundStatementAST *compoundStatement, const QStringList &values)
+            : CppQuickFixOperation(state, priority)
+            , compoundStatement(compoundStatement)
+            , values(values)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix",
+                                                   "Complete Switch Statement"));
+        }
+
+
+        virtual void createChanges()
+        {
+            ChangeSet changes;
+            int start = endOf(compoundStatement->lbrace_token);
+            changes.insert(start, QLatin1String("\ncase ")
+                           + values.join(QLatin1String(":\nbreak;\ncase "))
+                           + QLatin1String(":\nbreak;"));
+            refactoringChanges()->changeFile(fileName(), changes);
+            refactoringChanges()->reindent(fileName(), range(compoundStatement));
+        }
+
+        CompoundStatementAST *compoundStatement;
+        QStringList values;
+    };
+};
+
+
+class FixForwardDeclarationOp: public CppQuickFixFactory
+{
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        const QList<AST *> &path = state.path();
+
+        for (int index = path.size() - 1; index != -1; --index) {
+            AST *ast = path.at(index);
+            if (NamedTypeSpecifierAST *namedTy = ast->asNamedTypeSpecifier()) {
+                if (Symbol *fwdClass = checkName(state, namedTy->name))
+                    return singleResult(new Operation(state, index, fwdClass));
+            } else if (ElaboratedTypeSpecifierAST *eTy = ast->asElaboratedTypeSpecifier()) {
+                if (Symbol *fwdClass = checkName(state, eTy->name))
+                    return singleResult(new Operation(state, index, fwdClass));
+            }
+        }
+
+        return noResult();
+    }
+
+protected:
+    static Symbol *checkName(const CppQuickFixState &state, NameAST *ast)
+    {
+        if (ast && state.isCursorOn(ast)) {
+            if (const Name *name = ast->name) {
+                unsigned line, column;
+                state.document()->translationUnit()->getTokenStartPosition(ast->firstToken(), &line, &column);
+
+                Symbol *fwdClass = 0;
+
+                foreach (const LookupItem &r, state.context().lookup(name, state.document()->scopeAt(line, column))) {
+                    if (! r.declaration())
+                        continue;
+                    else if (ForwardClassDeclaration *fwd = r.declaration()->asForwardClassDeclaration())
+                        fwdClass = fwd;
+                    else if (r.declaration()->isClass())
+                        return 0; // nothing to do.
+                }
+
+                return fwdClass;
+            }
+        }
+
+        return 0;
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority, Symbol *fwdClass)
+            : CppQuickFixOperation(state, priority)
+            , fwdClass(fwdClass)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix",
+                                                   "#include header file"));
+        }
+
+        virtual void createChanges()
+        {
+            Q_ASSERT(fwdClass != 0);
+
+            if (Class *k = state().snapshot().findMatchingClassDeclaration(fwdClass)) {
+                const QString headerFile = QString::fromUtf8(k->fileName(), k->fileNameLength());
+
+                // collect the fwd headers
+                Snapshot fwdHeaders;
+                fwdHeaders.insert(state().snapshot().document(headerFile));
+                foreach (Document::Ptr doc, state().snapshot()) {
+                    QFileInfo headerFileInfo(doc->fileName());
+                    if (doc->globalSymbolCount() == 0 && doc->includes().size() == 1)
+                        fwdHeaders.insert(doc);
+                    else if (headerFileInfo.suffix().isEmpty())
+                        fwdHeaders.insert(doc);
+                }
+
+
+                DependencyTable dep;
+                dep.build(fwdHeaders);
+                QStringList candidates = dep.dependencyTable().value(headerFile);
+
+                const QString className = QString::fromUtf8(k->identifier()->chars());
+
+                QString best;
+                foreach (const QString &c, candidates) {
+                    QFileInfo headerFileInfo(c);
+                    if (headerFileInfo.fileName() == className) {
+                        best = c;
+                        break;
+                    } else if (headerFileInfo.fileName().at(0).isUpper()) {
+                        best = c;
+                        // and continue
+                    } else if (! best.isEmpty()) {
+                        if (c.count(QLatin1Char('/')) < best.count(QLatin1Char('/')))
+                            best = c;
+                    }
+                }
+
+                if (best.isEmpty())
+                    best = headerFile;
+
+                int pos = startOf(1);
+
+                unsigned currentLine = state().textCursor().blockNumber() + 1;
+                unsigned bestLine = 0;
+                foreach (const Document::Include &incl, state().document()->includes()) {
+                    if (incl.line() < currentLine)
+                        bestLine = incl.line();
+                }
+
+                if (bestLine)
+                    pos = state().editor()->document()->findBlockByNumber(bestLine).position();
+
+                Utils::ChangeSet changes;
+                changes.insert(pos, QString("#include <%1>\n").arg(QFileInfo(best).fileName()));
+                refactoringChanges()->changeFile(fileName(), changes);
+            }
+        }
+
+    private:
+        Symbol *fwdClass;
+    };
+};
+
+class AddLocalDeclarationOp: public CppQuickFixFactory
+{
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        const QList<AST *> &path = state.path();
+
+        for (int index = path.size() - 1; index != -1; --index) {
+            if (BinaryExpressionAST *binary = path.at(index)->asBinaryExpression()) {
+                if (binary->left_expression && binary->right_expression && state.tokenAt(binary->binary_op_token).is(T_EQUAL)) {
+                    if (state.isCursorOn(binary->left_expression) && binary->left_expression->asSimpleName() != 0) {
+                        SimpleNameAST *nameAST = binary->left_expression->asSimpleName();
+                        const QList<LookupItem> results = state.context().lookup(nameAST->name, state.scopeAt(nameAST->firstToken()));
+                        Declaration *decl = 0;
+                        foreach (const LookupItem &r, results) {
+                            if (! r.declaration())
+                                continue;
+                            else if (Declaration *d = r.declaration()->asDeclaration()) {
+                                if (! d->type()->isFunctionType()) {
+                                    decl = d;
+                                    break;
+                                }
+                            }
+                        }
+
+                        if (! decl) {
+                            return singleResult(new Operation(state, index, binary));
+                        }
+                    }
+                }
+            }
+        }
+
+        return noResult();
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority, BinaryExpressionAST *binaryAST)
+            : CppQuickFixOperation(state, priority)
+            , binaryAST(binaryAST)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix", "Add local declaration"));
+        }
+
+        virtual void createChanges()
+        {
+            TypeOfExpression typeOfExpression;
+            typeOfExpression.init(state().document(), state().snapshot(), state().context().bindings());
+            const QList<LookupItem> result = typeOfExpression(state().textOf(binaryAST->right_expression),
+                                                              state().scopeAt(binaryAST->firstToken()),
+                                                              TypeOfExpression::Preprocess);
+
+            if (! result.isEmpty()) {
+
+                SubstitutionEnvironment env;
+                env.setContext(state().context());
+                env.switchScope(result.first().scope());
+                UseQualifiedNames q;
+                env.enter(&q);
+
+                Control *control = state().context().control().data();
+                FullySpecifiedType tn = rewriteType(result.first().type(), &env, control);
+
+                Overview oo;
+                QString ty = oo(tn);
+                if (! ty.isEmpty()) {
+                    const QChar ch = ty.at(ty.size() - 1);
+
+                    if (ch.isLetterOrNumber() || ch == QLatin1Char(' ') || ch == QLatin1Char('>'))
+                        ty += QLatin1Char(' ');
+
+                    Utils::ChangeSet changes;
+                    changes.insert(startOf(binaryAST), ty);
+                    refactoringChanges()->changeFile(fileName(), changes);
+                }
+            }
+        }
+
+    private:
+        BinaryExpressionAST *binaryAST;
+    };
+};
+
+/*
+ * Turns "an_example_symbol" into "anExampleSymbol" and
+ * "AN_EXAMPLE_SYMBOL" into "AnExampleSymbol".
+ */
+class ToCamelCaseConverter : public CppQuickFixFactory
+{
+public:
+    virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state)
+    {
+        const QList<AST *> &path = state.path();
+
+        if (path.isEmpty())
+            return noResult();
+
+        AST * const ast = path.last();
+        const Name *name = 0;
+        if (const NameAST * const nameAst = ast->asName()) {
+            if (nameAst->name && nameAst->name->asNameId())
+                name = nameAst->name;
+        } else if (const NamespaceAST * const namespaceAst = ast->asNamespace()) {
+            name = namespaceAst->symbol->name();
+        }
+
+        if (!name)
+            return noResult();
+
+        QString newName = QString::fromUtf8(name->identifier()->chars());
+        if (newName.length() < 3)
+            return noResult();
+        for (int i = 1; i < newName.length() - 1; ++i) {
+            if (Operation::isConvertibleUnderscore(newName, i))
+                return singleResult(new Operation(state, path.size() - 1, newName));
+        }
+
+        return noResult();
+    }
+
+private:
+    class Operation: public CppQuickFixOperation
+    {
+    public:
+        Operation(const CppQuickFixState &state, int priority, const QString &newName)
+            : CppQuickFixOperation(state, priority)
+            , m_name(newName)
+        {
+            setDescription(QApplication::translate("CppTools::QuickFix",
+                                                   "Convert to Camel Case ..."));
+        }
+
+        virtual void createChanges()
+        {
+            for (int i = 1; i < m_name.length(); ++i) {
+                QCharRef c = m_name[i];
+                if (c.isUpper()) {
+                    c = c.toLower();
+                } else if (i < m_name.length() - 1
+                           && isConvertibleUnderscore(m_name, i)) {
+                    m_name.remove(i, 1);
+                    m_name[i] = m_name.at(i).toUpper();
+                }
+            }
+            static_cast<CppEditor::Internal::CPPEditor*>(state().editor())->renameUsagesNow(m_name);
+        }
+
+        static bool isConvertibleUnderscore(const QString &name, int pos)
+        {
+            return name.at(pos) == QLatin1Char('_') && name.at(pos+1).isLetter()
+                    && !(pos == 1 && name.at(0) == QLatin1Char('m'));
+        }
+
+    private:
+        QString m_name;
+    };
+};
+
+} // end of anonymous namespace
+
+void CppQuickFixCollector::registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
+{
+    plugIn->addAutoReleasedObject(new UseInverseOp);
+    plugIn->addAutoReleasedObject(new FlipBinaryOp);
+    plugIn->addAutoReleasedObject(new RewriteLogicalAndOp);
+    plugIn->addAutoReleasedObject(new SplitSimpleDeclarationOp);
+    plugIn->addAutoReleasedObject(new AddBracesToIfOp);
+    plugIn->addAutoReleasedObject(new MoveDeclarationOutOfIfOp);
+    plugIn->addAutoReleasedObject(new MoveDeclarationOutOfWhileOp);
+    plugIn->addAutoReleasedObject(new SplitIfStatementOp);
+    plugIn->addAutoReleasedObject(new WrapStringLiteral);
+    plugIn->addAutoReleasedObject(new TranslateStringLiteral);
+    plugIn->addAutoReleasedObject(new CStringToNSString);
+    plugIn->addAutoReleasedObject(new ConvertNumericLiteral);
+    plugIn->addAutoReleasedObject(new CompleteSwitchCaseStatement);
+    plugIn->addAutoReleasedObject(new FixForwardDeclarationOp);
+    plugIn->addAutoReleasedObject(new AddLocalDeclarationOp);
+    plugIn->addAutoReleasedObject(new ToCamelCaseConverter);
+
+#if NOT_YET
+    plugIn->addAutoReleasedObject(new Internal::DeclFromDef);
+#endif
+}
diff --git a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
index 944d7b568a348c63325a182782b0eface4a81a2c..75da806ae7ff68665eadfc2643c885ee5405ae82 100644
--- a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
+++ b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp
@@ -40,11 +40,10 @@
 #include <QtCore/QFileInfo>
 
 using namespace QmlJS::AST;
+using namespace QmlJSEditor;
 using namespace QmlJSEditor::Internal;
 
-ComponentFromObjectDef::ComponentFromObjectDef(TextEditor::BaseTextEditor *editor)
-    : QmlJSQuickFixOperation(editor), _objDef(0)
-{}
+namespace {
 
 static QString getId(UiObjectDefinition *def)
 {
@@ -74,60 +73,71 @@ static QString getId(UiObjectDefinition *def)
     return QString();
 }
 
-QString ComponentFromObjectDef::description() const
+class Operation: public QmlJSQuickFixOperation
 {
-    return QCoreApplication::translate("QmlJSEditor::ComponentFromObjectDef",
-                                       "Extract Component");
-}
+    UiObjectDefinition *_objDef;
+
+public:
+    Operation(const QmlJSQuickFixState &state, UiObjectDefinition *objDef)
+        : QmlJSQuickFixOperation(state, 0)
+        , _objDef(objDef)
+    {
+        setDescription(QCoreApplication::translate("QmlJSEditor::ComponentFromObjectDef",
+                                                   "Extract Component"));
+    }
 
-void ComponentFromObjectDef::createChanges()
-{
-    Q_ASSERT(_objDef != 0);
+    virtual void createChanges()
+    {
+        Q_ASSERT(_objDef != 0);
 
-    QString componentName = getId(_objDef);
-    componentName[0] = componentName.at(0).toUpper();
+        QString componentName = getId(_objDef);
+        componentName[0] = componentName.at(0).toUpper();
 
-    const QString path = editor()->file()->fileName();
-    const QString newFileName = QFileInfo(path).path() + QDir::separator() + componentName + QLatin1String(".qml");
+        const QString path = fileName();
+        const QString newFileName = QFileInfo(path).path() + QDir::separator() + componentName + QLatin1String(".qml");
 
-    QString imports;
-    UiProgram *prog = semanticInfo().document->qmlProgram();
-    if (prog && prog->imports) {
-        const int start = startPosition(prog->imports->firstSourceLocation());
-        const int end = startPosition(prog->members->member->firstSourceLocation());
-        imports = textOf(start, end);
-    }
+        QString imports;
+        UiProgram *prog = state().semanticInfo().document->qmlProgram();
+        if (prog && prog->imports) {
+            const int start = startPosition(prog->imports->firstSourceLocation());
+            const int end = startPosition(prog->members->member->firstSourceLocation());
+            imports = state().textOf(start, end);
+        }
 
-    const int start = startPosition(_objDef->firstSourceLocation());
-    const int end = startPosition(_objDef->lastSourceLocation());
-    const QString txt = imports + textOf(start, end) + QLatin1String("}\n");
+        const int start = startPosition(_objDef->firstSourceLocation());
+        const int end = startPosition(_objDef->lastSourceLocation());
+        const QString txt = imports + state().textOf(start, end)
+                + QLatin1String("}\n");
 
-    Utils::ChangeSet changes;
-    changes.replace(start, end, componentName + QLatin1String(" {\n"));
-    qmljsRefactoringChanges()->changeFile(fileName(), changes);
-    qmljsRefactoringChanges()->reindent(fileName(), range(start, end + 1));
+        Utils::ChangeSet changes;
+        changes.replace(start, end, componentName + QLatin1String(" {\n"));
+        refactoringChanges()->changeFile(fileName(), changes);
+        refactoringChanges()->reindent(fileName(), range(start, end + 1));
 
-    qmljsRefactoringChanges()->createFile(newFileName, txt);
-    qmljsRefactoringChanges()->reindent(newFileName, range(0, txt.length() - 1));
-}
+        refactoringChanges()->createFile(newFileName, txt);
+        refactoringChanges()->reindent(newFileName, range(0, txt.length() - 1));
+    }
+};
+
+} // end of anonymous namespace
 
-int ComponentFromObjectDef::check()
+QList<QmlJSQuickFixOperation::Ptr> ComponentFromObjectDef::match(const QmlJSQuickFixState &state)
 {
-    _objDef = 0;
-    const int pos = textCursor().position();
+    QList<QmlJSQuickFixOperation::Ptr> result;
+    const int pos = state.textCursor().position();
 
-    QList<Node *> path = semanticInfo().astPath(pos);
+    QList<Node *> path = state.semanticInfo().astPath(pos);
     for (int i = path.size() - 1; i >= 0; --i) {
         Node *node = path.at(i);
         if (UiObjectDefinition *objDef = cast<UiObjectDefinition *>(node)) {
             if (i > 0 && !cast<UiProgram*>(path.at(i - 1))) { // node is not the root node
                 if (!getId(objDef).isEmpty()) {
-                    _objDef = objDef;
-                    return 0;
+                    result.append(QmlJSQuickFixOperation::Ptr(new Operation(state, objDef)));
+                    return result;
                 }
             }
         }
     }
 
-    return -1;
+    return result;
 }
diff --git a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.h b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.h
index 382e51c7f06fa93f815e6808edb4bfd1793b0d46..662ccf1877b191e256c650e4c50f1a96d99398f7 100644
--- a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.h
+++ b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.h
@@ -35,17 +35,10 @@
 namespace QmlJSEditor {
 namespace Internal {
 
-class ComponentFromObjectDef: public QmlJSQuickFixOperation
+class ComponentFromObjectDef: public QmlJSQuickFixFactory
 {
 public:
-    ComponentFromObjectDef(TextEditor::BaseTextEditor *editor);
-
-    virtual QString description() const;
-    virtual void createChanges();
-    virtual int check();
-
-private:
-    QmlJS::AST::UiObjectDefinition *_objDef;
+    virtual QList<QmlJSQuickFixOperation::Ptr> match(const QmlJSQuickFixState &state);
 };
 
 } // namespace Internal
diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp
index f67dd204fe7593076d9f7ff7e71f3305379a7eca..104e036ac92758ae2764f812efb4b670bd551c63 100644
--- a/src/plugins/qmljseditor/qmljseditorplugin.cpp
+++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp
@@ -179,6 +179,7 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e
 
     m_quickFixCollector = new QmlJSQuickFixCollector;
     addAutoReleasedObject(m_quickFixCollector);
+    QmlJSQuickFixCollector::registerQuickFixes(this);
 
     addAutoReleasedObject(new QmlJSOutlineWidgetFactory);
 
diff --git a/src/plugins/qmljseditor/qmljsquickfix.cpp b/src/plugins/qmljseditor/qmljsquickfix.cpp
index 2108147bb6178e885d72a2964ff5a9da641c540a..b7be83002c61ced07e64716baa6c4ef3cf60842e 100644
--- a/src/plugins/qmljseditor/qmljsquickfix.cpp
+++ b/src/plugins/qmljseditor/qmljsquickfix.cpp
@@ -33,6 +33,7 @@
 #include "qmljsrefactoringchanges.h"
 #include "qmljs/parser/qmljsast_p.h"
 
+#include <extensionsystem/iplugin.h>
 #include <extensionsystem/pluginmanager.h>
 
 #include <qmljs/qmljsmodelmanagerinterface.h>
@@ -40,146 +41,157 @@
 #include <QtGui/QApplication>
 #include <QtCore/QDebug>
 
+using namespace QmlJS;
+using namespace QmlJS::AST;
 using namespace QmlJSEditor;
 using namespace QmlJSEditor::Internal;
+using namespace TextEditor;
 using TextEditor::RefactoringChanges;
 
-class QmlJSQuickFixState: public TextEditor::QuickFixState
-{
-public:
-    SemanticInfo semanticInfo;
-};
-
 namespace {
 
-class SplitInitializerOp: public QmlJSQuickFixOperation {
+class SplitInitializerOp: public QmlJSQuickFixFactory
+{
 public:
-    SplitInitializerOp(TextEditor::BaseTextEditor *editor)
-        : QmlJSQuickFixOperation(editor), _objectInitializer(0)
-    {}
-
-    virtual QString description() const
+    virtual QList<QmlJSQuickFixOperation::Ptr> match(const QmlJSQuickFixState &state)
     {
-        return QApplication::translate("QmlJSEditor::QuickFix", "Split initializer");
-    }
+        QList<QmlJSQuickFixOperation::Ptr> result;
 
-    virtual void createChanges()
-    {
-        Q_ASSERT(_objectInitializer != 0);
+        UiObjectInitializer *objectInitializer = 0;
 
-        Utils::ChangeSet changes;
+        const int pos = state.textCursor().position();
 
-        for (QmlJS::AST::UiObjectMemberList *it = _objectInitializer->members; it; it = it->next) {
-            if (QmlJS::AST::UiObjectMember *member = it->member) {
-                const QmlJS::AST::SourceLocation loc = member->firstSourceLocation();
+        if (QmlJS::AST::Node *member = state.semanticInfo().declaringMember(pos)) {
+            if (QmlJS::AST::UiObjectBinding *b = QmlJS::AST::cast<QmlJS::AST::UiObjectBinding *>(member)) {
+                if (b->initializer->lbraceToken.startLine == b->initializer->rbraceToken.startLine)
+                    objectInitializer = b->initializer;
 
-                // insert a newline at the beginning of this binding
-                changes.insert(startPosition(loc), QLatin1String("\n"));
+            } else if (QmlJS::AST::UiObjectDefinition *b = QmlJS::AST::cast<QmlJS::AST::UiObjectDefinition *>(member)) {
+                if (b->initializer->lbraceToken.startLine == b->initializer->rbraceToken.startLine)
+                    objectInitializer = b->initializer;
             }
         }
 
-        // insert a newline before the closing brace
-        changes.insert(startPosition(_objectInitializer->rbraceToken),
-                       QLatin1String("\n"));
-
-        refactoringChanges()->changeFile(fileName(), changes);
-        refactoringChanges()->reindent(fileName(),
-                                       range(startPosition(_objectInitializer->lbraceToken),
-                                             startPosition(_objectInitializer->rbraceToken)));
+        if (objectInitializer)
+            result.append(QSharedPointer<QmlJSQuickFixOperation>(new Operation(state, objectInitializer)));
+        return result;
+    }
 
+    virtual QString description() const
+    {
+        return QApplication::translate("QmlJSEditor::QuickFix", "Split initializer");
     }
 
-    virtual int check()
+private:
+    class Operation: public QmlJSQuickFixOperation
     {
-        _objectInitializer = 0;
+        UiObjectInitializer *_objectInitializer;
 
-        const int pos = textCursor().position();
+    public:
+        Operation(const QmlJSQuickFixState &state, UiObjectInitializer *objectInitializer)
+            : QmlJSQuickFixOperation(state, 0)
+            , _objectInitializer(objectInitializer)
+        {}
 
-        if (QmlJS::AST::Node *member = semanticInfo().declaringMember(pos)) {
-            if (QmlJS::AST::UiObjectBinding *b = QmlJS::AST::cast<QmlJS::AST::UiObjectBinding *>(member)) {
-                if (b->initializer->lbraceToken.startLine == b->initializer->rbraceToken.startLine)
-                    _objectInitializer = b->initializer;
+        virtual void createChanges()
+        {
+            Q_ASSERT(_objectInitializer != 0);
 
-            } else if (QmlJS::AST::UiObjectDefinition *b = QmlJS::AST::cast<QmlJS::AST::UiObjectDefinition *>(member)) {
-                if (b->initializer->lbraceToken.startLine == b->initializer->rbraceToken.startLine)
-                    _objectInitializer = b->initializer;
+            Utils::ChangeSet changes;
+
+            for (QmlJS::AST::UiObjectMemberList *it = _objectInitializer->members; it; it = it->next) {
+                if (QmlJS::AST::UiObjectMember *member = it->member) {
+                    const QmlJS::AST::SourceLocation loc = member->firstSourceLocation();
+
+                    // insert a newline at the beginning of this binding
+                    changes.insert(startPosition(loc), QLatin1String("\n"));
+                }
             }
-        }
 
-        if (! _objectInitializer)
-            return -1;
+            // insert a newline before the closing brace
+            changes.insert(startPosition(_objectInitializer->rbraceToken),
+                           QLatin1String("\n"));
 
-        return 0; // very high priority
-    }
+            refactoringChanges()->changeFile(fileName(), changes);
+            refactoringChanges()->reindent(fileName(),
+                                           range(startPosition(_objectInitializer->lbraceToken),
+                                                 startPosition(_objectInitializer->rbraceToken)));
 
-private:
-    QmlJS::AST::UiObjectInitializer *_objectInitializer;
+        }
+    };
 };
 
-
 } // end of anonymous namespace
 
+QmlJSQuickFixState::QmlJSQuickFixState(TextEditor::BaseTextEditor *editor)
+    : QuickFixState(editor)
+{
+}
 
-QmlJSQuickFixOperation::QmlJSQuickFixOperation(TextEditor::BaseTextEditor *editor)
-    : TextEditor::QuickFixOperation(editor)
-    , _refactoringChanges(0)
+SemanticInfo QmlJSQuickFixState::semanticInfo() const
 {
+    return _semanticInfo;
 }
 
-QmlJSQuickFixOperation::~QmlJSQuickFixOperation()
+Snapshot QmlJSQuickFixState::snapshot() const
 {
-    if (_refactoringChanges)
-        delete _refactoringChanges;
+    return _semanticInfo.snapshot;
 }
 
-QmlJS::Document::Ptr QmlJSQuickFixOperation::document() const
+Document::Ptr QmlJSQuickFixState::document() const
 {
     return _semanticInfo.document;
 }
 
-const QmlJS::Snapshot &QmlJSQuickFixOperation::snapshot() const
+unsigned QmlJSQuickFixState::startPosition(const QmlJS::AST::SourceLocation &loc) const
 {
-    return _semanticInfo.snapshot;
+    return position(loc.startLine, loc.startColumn);
 }
 
-const SemanticInfo &QmlJSQuickFixOperation::semanticInfo() const
+QmlJSQuickFixOperation::QmlJSQuickFixOperation(const QmlJSQuickFixState &state, int priority)
+    : QuickFixOperation(priority)
+    , _state(state)
+    , _refactoringChanges(new QmlJSRefactoringChanges(ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>(),
+                                                      state.snapshot()))
 {
-    return _semanticInfo;
 }
 
-int QmlJSQuickFixOperation::match(TextEditor::QuickFixState *state)
+QmlJSQuickFixOperation::~QmlJSQuickFixOperation()
 {
-    QmlJS::ModelManagerInterface *modelManager = ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>();
-    QmlJSQuickFixState *s = static_cast<QmlJSQuickFixState *>(state);
-    _semanticInfo = s->semanticInfo;
-    if (_refactoringChanges) {
-        delete _refactoringChanges;
-    }
-    _refactoringChanges = new QmlJSRefactoringChanges(modelManager, _semanticInfo.snapshot);
-    return check();
+}
+
+const QmlJSQuickFixState &QmlJSQuickFixOperation::state() const
+{
+    return _state;
 }
 
 QString QmlJSQuickFixOperation::fileName() const
 {
-    return document()->fileName();
+    return state().document()->fileName();
 }
 
-void QmlJSQuickFixOperation::apply()
+QmlJSRefactoringChanges *QmlJSQuickFixOperation::refactoringChanges() const
 {
-    _refactoringChanges->apply();
+    return _refactoringChanges.data();
 }
 
-QmlJSRefactoringChanges *QmlJSQuickFixOperation::qmljsRefactoringChanges() const
-{ return _refactoringChanges; }
+QmlJSQuickFixFactory::QmlJSQuickFixFactory()
+{
+}
 
-RefactoringChanges *QmlJSQuickFixOperation::refactoringChanges() const
-{ return qmljsRefactoringChanges(); }
+QmlJSQuickFixFactory::~QmlJSQuickFixFactory()
+{
+}
 
-unsigned QmlJSQuickFixOperation::startPosition(const QmlJS::AST::SourceLocation &loc) const
+QList<QuickFixOperation::Ptr> QmlJSQuickFixFactory::matchingOperations(QuickFixState *state)
 {
-    return position(loc.startLine, loc.startColumn);
+    if (QmlJSQuickFixState *qmljsState = static_cast<QmlJSQuickFixState *>(state))
+        return match(*qmljsState);
+    else
+        return QList<TextEditor::QuickFixOperation::Ptr>();
 }
 
+
 QmlJSQuickFixCollector::QmlJSQuickFixCollector()
 {
 }
@@ -190,35 +202,39 @@ QmlJSQuickFixCollector::~QmlJSQuickFixCollector()
 
 bool QmlJSQuickFixCollector::supportsEditor(TextEditor::ITextEditable *editable)
 {
-    if (qobject_cast<QmlJSTextEditor *>(editable->widget()) != 0)
-        return true;
-
-    return false;
+    return qobject_cast<QmlJSTextEditor *>(editable->widget()) != 0;
 }
 
-TextEditor::QuickFixState *QmlJSQuickFixCollector::initializeCompletion(TextEditor::ITextEditable *editable)
+TextEditor::QuickFixState *QmlJSQuickFixCollector::initializeCompletion(TextEditor::BaseTextEditor *editor)
 {
-    if (QmlJSTextEditor *editor = qobject_cast<QmlJSTextEditor *>(editable->widget())) {
-        const SemanticInfo info = editor->semanticInfo();
+    if (QmlJSTextEditor *qmljsEditor = qobject_cast<QmlJSTextEditor *>(editor)) {
+        const SemanticInfo info = qmljsEditor->semanticInfo();
 
-        if (editor->isOutdated()) {
+        if (qmljsEditor->isOutdated()) {
             // outdated
             qWarning() << "TODO: outdated semantic info, force a reparse.";
             return 0;
         }
 
-        QmlJSQuickFixState *state = new QmlJSQuickFixState;
-        state->semanticInfo = info;
+        QmlJSQuickFixState *state = new QmlJSQuickFixState(editor);
+        state->_semanticInfo = info;
         return state;
     }
 
     return 0;
 }
 
-QList<TextEditor::QuickFixOperation::Ptr> QmlJSQuickFixCollector::quickFixOperations(TextEditor::BaseTextEditor *editor) const
+QList<TextEditor::QuickFixFactory *> QmlJSQuickFixCollector::quickFixFactories() const
+{
+    QList<TextEditor::QuickFixFactory *> results;
+    ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
+    foreach (QmlJSQuickFixFactory *f, pm->getObjects<QmlJSEditor::QmlJSQuickFixFactory>())
+        results.append(f);
+    return results;
+}
+
+void QmlJSQuickFixCollector::registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
 {
-    QList<TextEditor::QuickFixOperation::Ptr> quickFixOperations;
-    quickFixOperations.append(TextEditor::QuickFixOperation::Ptr(new SplitInitializerOp(editor)));
-    quickFixOperations.append(TextEditor::QuickFixOperation::Ptr(new ComponentFromObjectDef(editor)));
-    return quickFixOperations;
+    plugIn->addAutoReleasedObject(new SplitInitializerOp);
+    plugIn->addAutoReleasedObject(new ComponentFromObjectDef);
 }
diff --git a/src/plugins/qmljseditor/qmljsquickfix.h b/src/plugins/qmljseditor/qmljsquickfix.h
index 3fa6e7fad33e1ab84952d16b2f8d1946a2ac4e89..dbda6b59d7ce692d46b0fbf7f8dca7fc3141c0bf 100644
--- a/src/plugins/qmljseditor/qmljsquickfix.h
+++ b/src/plugins/qmljseditor/qmljsquickfix.h
@@ -31,49 +31,85 @@
 #define QMLJSQUICKFIX_H
 
 #include "qmljseditor.h"
+#include "qmljsrefactoringchanges.h"
 
 #include <texteditor/quickfix.h>
 #include <qmljs/parser/qmljsastfwd_p.h>
 #include <qmljs/qmljsdocument.h>
 
+namespace ExtensionSystem {
+class IPlugin;
+}
+
 namespace QmlJS {
     class ModelManagerInterface;
 }
 
 namespace QmlJSEditor {
-class QmlJSRefactoringChanges;
 
 namespace Internal {
+class QmlJSQuickFixCollector;
+} // end of namespace Internal
 
-class QmlJSQuickFixOperation: public TextEditor::QuickFixOperation
+class QMLJS_EXPORT QmlJSQuickFixState: public TextEditor::QuickFixState
 {
-    Q_DISABLE_COPY(QmlJSQuickFixOperation)
+    friend class Internal::QmlJSQuickFixCollector;
 
 public:
-    QmlJSQuickFixOperation(TextEditor::BaseTextEditor *editor);
-    virtual ~QmlJSQuickFixOperation();
+    QmlJSQuickFixState(TextEditor::BaseTextEditor *editor);
+    typedef Utils::ChangeSet::Range Range;
 
+    Internal::SemanticInfo semanticInfo() const;
+    QmlJS::Snapshot snapshot() const;
     QmlJS::Document::Ptr document() const;
-    const QmlJS::Snapshot &snapshot() const;
-    const SemanticInfo &semanticInfo() const;
 
-    virtual int check() = 0;
-    virtual int match(TextEditor::QuickFixState *state);
+    unsigned startPosition(const QmlJS::AST::SourceLocation &loc) const;
+
+private:
+    Internal::SemanticInfo _semanticInfo;
+};
+
+class QMLJS_EXPORT QmlJSQuickFixOperation: public TextEditor::QuickFixOperation
+{
+    Q_DISABLE_COPY(QmlJSQuickFixOperation)
+
+public:
+    QmlJSQuickFixOperation(const QmlJSQuickFixState &state, int priority = -1);
+    virtual ~QmlJSQuickFixOperation();
+
+    const QmlJSQuickFixState &state() const;
 
 protected:
     QString fileName() const;
 
-    virtual void apply();
-    QmlJSRefactoringChanges *qmljsRefactoringChanges() const;
-    virtual TextEditor::RefactoringChanges *refactoringChanges() const;
+    QmlJSRefactoringChanges *refactoringChanges() const;
 
-    unsigned startPosition(const QmlJS::AST::SourceLocation &loc) const;
+protected: // Utility functions forwarding to QmlJSQuickFixState
+    unsigned startPosition(const QmlJS::AST::SourceLocation &loc) const
+    { return state().startPosition(loc); }
+
+    static QmlJSQuickFixState::Range range(int start, int end)
+    { return QmlJSQuickFixState::range(start, end); }
 
 private:
-    SemanticInfo _semanticInfo;
-    QmlJSRefactoringChanges *_refactoringChanges;
+    QmlJSQuickFixState _state;
+    QScopedPointer<QmlJSRefactoringChanges> _refactoringChanges;
+};
+
+class QMLJS_EXPORT QmlJSQuickFixFactory: public TextEditor::QuickFixFactory
+{
+    Q_OBJECT
+
+public:
+    QmlJSQuickFixFactory();
+    virtual ~QmlJSQuickFixFactory();
+
+    virtual QList<TextEditor::QuickFixOperation::Ptr> matchingOperations(TextEditor::QuickFixState *state);
+    virtual QList<QmlJSQuickFixOperation::Ptr> match(const QmlJSQuickFixState &state) = 0;
 };
 
+namespace Internal {
+
 class QmlJSQuickFixCollector: public TextEditor::QuickFixCollector
 {
     Q_OBJECT
@@ -83,8 +119,11 @@ public:
     virtual ~QmlJSQuickFixCollector();
 
     virtual bool supportsEditor(TextEditor::ITextEditable *editor);
-    virtual TextEditor::QuickFixState *initializeCompletion(TextEditor::ITextEditable *editable);
-    virtual QList<TextEditor::QuickFixOperation::Ptr> quickFixOperations(TextEditor::BaseTextEditor *editor) const;
+    virtual TextEditor::QuickFixState *initializeCompletion(TextEditor::BaseTextEditor *editor);
+
+    virtual QList<TextEditor::QuickFixFactory *> quickFixFactories() const;
+
+    static void registerQuickFixes(ExtensionSystem::IPlugin *plugIn);
 };
 
 } // end of namespace Internal
diff --git a/src/plugins/qmljseditor/qmljsrefactoringchanges.h b/src/plugins/qmljseditor/qmljsrefactoringchanges.h
index 3a4198743dd0302143e20ce5ea24a01d70cbacb2..ef286a3f7bf79874ca40ab380fbe39b076da240d 100644
--- a/src/plugins/qmljseditor/qmljsrefactoringchanges.h
+++ b/src/plugins/qmljseditor/qmljsrefactoringchanges.h
@@ -40,7 +40,7 @@ class ModelManagerInterface;
 
 namespace QmlJSEditor {
 
-class QmlJSRefactoringChanges: public TextEditor::RefactoringChanges
+class QMLJS_EXPORT QmlJSRefactoringChanges: public TextEditor::RefactoringChanges
 {
 public:
     QmlJSRefactoringChanges(QmlJS::ModelManagerInterface *modelManager,
diff --git a/src/plugins/texteditor/quickfix.cpp b/src/plugins/texteditor/quickfix.cpp
index 8e5e024750e9c305d19f9b16e61002b09cd2d59f..415c0119abcf01490f6731451a66b16690aac417 100644
--- a/src/plugins/texteditor/quickfix.cpp
+++ b/src/plugins/texteditor/quickfix.cpp
@@ -37,58 +37,56 @@
 
 #include <QtCore/QDebug>
 
-using TextEditor::RefactoringChanges;
-using TextEditor::QuickFixOperation;
-using TextEditor::QuickFixCollector;
-using TextEditor::IQuickFixFactory;
+using namespace TextEditor;
 
-QuickFixOperation::QuickFixOperation(TextEditor::BaseTextEditor *editor)
+QuickFixState::QuickFixState(TextEditor::BaseTextEditor *editor)
     : _editor(editor)
+    , _textCursor(editor->textCursor())
 {
 }
 
-QuickFixOperation::~QuickFixOperation()
+QuickFixState::~QuickFixState()
 {
 }
 
-TextEditor::BaseTextEditor *QuickFixOperation::editor() const
+TextEditor::BaseTextEditor *QuickFixState::editor() const
 {
     return _editor;
 }
 
-QTextCursor QuickFixOperation::textCursor() const
+QTextCursor QuickFixState::textCursor() const
 {
     return _textCursor;
 }
 
-void QuickFixOperation::setTextCursor(const QTextCursor &cursor)
+void QuickFixState::setCursor(const QTextCursor &cursor)
 {
     _textCursor = cursor;
 }
 
-int QuickFixOperation::selectionStart() const
+int QuickFixState::selectionStart() const
 {
     return _textCursor.selectionStart();
 }
 
-int QuickFixOperation::selectionEnd() const
+int QuickFixState::selectionEnd() const
 {
     return _textCursor.selectionEnd();
 }
 
-int QuickFixOperation::position(int line, int column) const
+int QuickFixState::position(int line, int column) const
 {
     QTextDocument *doc = editor()->document();
     return doc->findBlockByNumber(line - 1).position() + column - 1;
 }
 
-QChar QuickFixOperation::charAt(int offset) const
+QChar QuickFixState::charAt(int offset) const
 {
     QTextDocument *doc = _textCursor.document();
     return doc->characterAt(offset);
 }
 
-QString QuickFixOperation::textOf(int start, int end) const
+QString QuickFixState::textOf(int start, int end) const
 {
     QTextCursor tc = _textCursor;
     tc.setPosition(start);
@@ -96,51 +94,98 @@ QString QuickFixOperation::textOf(int start, int end) const
     return tc.selectedText();
 }
 
-TextEditor::RefactoringChanges::Range QuickFixOperation::range(int start, int end)
+TextEditor::RefactoringChanges::Range QuickFixState::range(int start, int end)
 {
     return TextEditor::RefactoringChanges::Range(start, end);
 }
 
+QuickFixOperation::QuickFixOperation(int priority)
+{
+    setPriority(priority);
+}
+
+QuickFixOperation::~QuickFixOperation()
+{
+}
+
+int QuickFixOperation::priority() const
+{
+    return _priority;
+}
+
+void QuickFixOperation::setPriority(int priority)
+{
+    _priority = priority;
+}
+
+QString QuickFixOperation::description() const
+{
+    return _description;
+}
+
+void QuickFixOperation::setDescription(const QString &description)
+{
+    _description = description;
+}
+
 void QuickFixOperation::perform()
 {
     createChanges();
-    apply();
+    refactoringChanges()->apply();
+}
+
+QuickFixFactory::QuickFixFactory(QObject *parent)
+    : QObject(parent)
+{
+}
+
+QuickFixFactory::~QuickFixFactory()
+{
 }
 
 QuickFixCollector::QuickFixCollector()
     : _editable(0)
-{ }
+{
+}
 
 QuickFixCollector::~QuickFixCollector()
-{ }
+{
+}
 
 TextEditor::ITextEditable *QuickFixCollector::editor() const
-{ return _editable; }
+{
+    return _editable;
+}
 
 int QuickFixCollector::startPosition() const
-{ return _editable->position(); }
+{
+    return _editable->position();
+}
 
 bool QuickFixCollector::triggersCompletion(TextEditor::ITextEditable *)
-{ return false; }
+{
+    return false;
+}
 
 int QuickFixCollector::startCompletion(TextEditor::ITextEditable *editable)
 {
     Q_ASSERT(editable != 0);
 
     _editable = editable;
+    TextEditor::BaseTextEditor *editor = qobject_cast<TextEditor::BaseTextEditor *>(editable->widget());
+    Q_ASSERT(editor != 0);
 
-    if (TextEditor::QuickFixState *state = initializeCompletion(editable)) {
-        TextEditor::BaseTextEditor *editor = qobject_cast<TextEditor::BaseTextEditor *>(editable->widget());
-        Q_ASSERT(editor != 0);
+    if (TextEditor::QuickFixState *state = initializeCompletion(editor)) {
+        QMap<int, QList<QuickFixOperation::Ptr> > matchedOps;
 
-        const QList<TextEditor::QuickFixOperation::Ptr> quickFixOperations = this->quickFixOperations(editor);
-        QMap<int, QList<TextEditor::QuickFixOperation::Ptr> > matchedOps;
+        foreach (QuickFixFactory *factory, quickFixFactories()) {
+            QList<QuickFixOperation::Ptr> ops = factory->matchingOperations(state);
 
-        foreach (TextEditor::QuickFixOperation::Ptr op, quickFixOperations) {
-            op->setTextCursor(editor->textCursor());
-            int priority = op->match(state);
-            if (priority != -1)
-                matchedOps[priority].append(op);
+            foreach (QuickFixOperation::Ptr op, ops) {
+                const int priority = op->priority();
+                if (priority != -1)
+                    matchedOps[priority].append(op);
+            }
         }
 
         QMapIterator<int, QList<TextEditor::QuickFixOperation::Ptr> > it(matchedOps);
@@ -185,26 +230,3 @@ void QuickFixCollector::cleanup()
 {
     _quickFixes.clear();
 }
-
-QList<TextEditor::QuickFixOperation::Ptr> QuickFixCollector::quickFixOperations(TextEditor::BaseTextEditor *editor) const
-{
-    QList<TextEditor::IQuickFixFactory *> factories =
-            ExtensionSystem::PluginManager::instance()->getObjects<TextEditor::IQuickFixFactory>();
-
-    QList<TextEditor::QuickFixOperation::Ptr> quickFixOperations;
-
-    foreach (TextEditor::IQuickFixFactory *factory, factories)
-        quickFixOperations += factory->quickFixOperations(editor);
-
-    return quickFixOperations;
-}
-
-IQuickFixFactory::IQuickFixFactory(QObject *parent)
-    : QObject(parent)
-{
-}
-
-IQuickFixFactory::~IQuickFixFactory()
-{
-
-}
diff --git a/src/plugins/texteditor/quickfix.h b/src/plugins/texteditor/quickfix.h
index 2ad179e0ac9d19e5420ba572b1381b334bb36fad..342fce4ecfe603e1d967c5b19a3dff6b1ca54455 100644
--- a/src/plugins/texteditor/quickfix.h
+++ b/src/plugins/texteditor/quickfix.h
@@ -42,43 +42,28 @@
 namespace TextEditor {
 
 class BaseTextEditor;
-class QuickFixOperation;
 
 class TEXTEDITOR_EXPORT QuickFixState
 {
-    Q_DISABLE_COPY(QuickFixState)
-
 public:
-    QuickFixState() {}
-    virtual ~QuickFixState() {}
-};
-
-class TEXTEDITOR_EXPORT QuickFixOperation
-{
-    Q_DISABLE_COPY(QuickFixOperation)
-
-public:
-    typedef QSharedPointer<QuickFixOperation> Ptr;
-
-public:
-    QuickFixOperation(TextEditor::BaseTextEditor *editor);
-    virtual ~QuickFixOperation();
-
-    virtual QString description() const = 0;
-    virtual void createChanges() = 0;
-
-    virtual int match(QuickFixState *state) = 0;
-
-    void perform();
+    QuickFixState(TextEditor::BaseTextEditor *editor);
+    virtual ~QuickFixState();
 
     TextEditor::BaseTextEditor *editor() const;
 
     QTextCursor textCursor() const;
-    void setTextCursor(const QTextCursor &cursor);
+    void setCursor(const QTextCursor &cursor);
 
     int selectionStart() const;
     int selectionEnd() const;
 
+    /**
+     * Calculates the offset in the document for the given line and column.
+     *
+     * \param line The line number, 1-based.
+     * \param column The column number, 1-based.
+     * \return The offset in the \c QTextDocument of the editor.
+     */
     int position(int line, int column) const;
 
     QChar charAt(int offset) const;
@@ -86,15 +71,50 @@ public:
 
     static TextEditor::RefactoringChanges::Range range(int start, int end);
 
+private:
+    TextEditor::BaseTextEditor *_editor;
+    QTextCursor _textCursor;
+};
+
+class TEXTEDITOR_EXPORT QuickFixOperation
+{
+    Q_DISABLE_COPY(QuickFixOperation)
+
+public:
+    typedef QSharedPointer<QuickFixOperation> Ptr;
+
+public:
+    QuickFixOperation(int priority = -1);
+    virtual ~QuickFixOperation();
+
+    virtual int priority() const;
+    void setPriority(int priority);
+    virtual QString description() const;
+    void setDescription(const QString &description);
+
+    virtual void perform();
+
+    virtual void createChanges() = 0;
+
 protected:
-    virtual void apply() = 0;
     virtual TextEditor::RefactoringChanges *refactoringChanges() const = 0;
 
 private:
     TextEditor::BaseTextEditor *_editor;
-    QTextCursor _textCursor;
+    int _priority;
+    QString _description;
 };
 
+class TEXTEDITOR_EXPORT QuickFixFactory: public QObject
+{
+    Q_OBJECT
+
+public:
+    QuickFixFactory(QObject *parent = 0);
+    virtual ~QuickFixFactory() = 0;
+
+    virtual QList<QuickFixOperation::Ptr> matchingOperations(QuickFixState *state) = 0;
+};
 
 class TEXTEDITOR_EXPORT QuickFixCollector: public TextEditor::IQuickFixCollector
 {
@@ -114,23 +134,13 @@ public:
     virtual void fix(const TextEditor::CompletionItem &item);
     virtual void cleanup();
 
-    virtual TextEditor::QuickFixState *initializeCompletion(TextEditor::ITextEditable *editable) = 0;
-    virtual QList<TextEditor::QuickFixOperation::Ptr> quickFixOperations(TextEditor::BaseTextEditor *editor) const;
+    virtual TextEditor::QuickFixState *initializeCompletion(BaseTextEditor *editable) = 0;
+
+    virtual QList<QuickFixFactory *> quickFixFactories() const = 0;
 
 private:
     TextEditor::ITextEditable *_editable;
-    QList<TextEditor::QuickFixOperation::Ptr> _quickFixes;
-};
-
-class TEXTEDITOR_EXPORT IQuickFixFactory: public QObject
-{
-    Q_OBJECT
-
-public:
-    IQuickFixFactory(QObject *parent = 0);
-    virtual ~IQuickFixFactory();
-
-    virtual QList<QuickFixOperation::Ptr> quickFixOperations(TextEditor::BaseTextEditor *editor) = 0;
+    QList<QuickFixOperation::Ptr> _quickFixes;
 };
 
 } // end of namespace TextEditor
diff --git a/tests/manual/cppquickfix/convertnumericliteral.cpp b/tests/manual/cppquickfix/convertnumericliteral.cpp
index 6c1a27a2e489c449b657e3e08afae05a821bade2..6d64c98e7f90c36bd6fcce798796e28bb0eadc65 100644
--- a/tests/manual/cppquickfix/convertnumericliteral.cpp
+++ b/tests/manual/cppquickfix/convertnumericliteral.cpp
@@ -5,7 +5,7 @@ int main()
     074;
     0x856A;
     // with type specifier
-    199L;
+    199LL;
     074L;
     0xFA0Bu;
     // uppercase X