diff --git a/src/plugins/cpptools/cppcodeformatter.cpp b/src/plugins/cpptools/cppcodeformatter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8ab36724ffe0ad24d3e4b260d418844b936014c3
--- /dev/null
+++ b/src/plugins/cpptools/cppcodeformatter.cpp
@@ -0,0 +1,1067 @@
+#include "cppcodeformatter.h"
+
+#include <Token.h>
+#include <Lexer.h>
+
+#include <texteditor/basetextdocumentlayout.h>
+
+#include <QtCore/QDebug>
+#include <QtGui/QTextDocument>
+#include <QtGui/QTextCursor>
+#include <QtGui/QTextBlock>
+
+namespace CppTools {
+namespace Internal {
+    class CppCodeFormatterData: public TextEditor::CodeFormatterData
+    {
+    public:
+        CppCodeFormatterData(int blockRevision,
+                             const QStack<CodeFormatter::State> &beginState,
+                             const QStack<CodeFormatter::State> &endState,
+                             int indentDepth)
+            : CodeFormatterData(blockRevision)
+            , m_beginState(beginState)
+            , m_endState(endState)
+            , m_indentDepth(indentDepth)
+        {}
+
+        QStack<CodeFormatter::State> m_beginState;
+        QStack<CodeFormatter::State> m_endState;
+        int m_indentDepth;
+    };
+}
+}
+
+using namespace CPlusPlus;
+using namespace CppTools;
+using namespace TextEditor;
+using namespace CppTools::Internal;
+
+CodeFormatter::CodeFormatter()
+    : m_document(0)
+    , m_indentDepth(0)
+{
+}
+
+CodeFormatter::~CodeFormatter()
+{
+}
+
+void CodeFormatter::setDocument(QTextDocument *document)
+{
+    m_document = document;
+}
+
+void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
+{
+    restoreBlockState(block.previous());
+
+    bool endedJoined = false;
+    const int lexerState = tokenizeBlock(block, &endedJoined);
+    m_tokenIndex = 0;
+
+    if (tokenAt(0).kind() == T_POUND) {
+        enter(cpp_macro_start);
+        m_tokenIndex = 1;
+    }
+
+    for (; m_tokenIndex < m_tokens.size(); ) {
+        m_currentToken = tokenAt(m_tokenIndex);
+        const int kind = m_currentToken.kind();
+
+        switch (m_currentState.top().type) {
+        case topmost_intro:
+            if (tryDeclaration())
+                break;
+            switch (kind) {
+            case T_NAMESPACE:   enter(namespace_start); break;
+            case T_STRUCT:
+            case T_UNION:
+            case T_CLASS:       enter(class_start); break;
+            case T_ENUM:        enter(enum_start); break;
+            case T_USING:       enter(using_start); break;
+            } break;
+
+        case namespace_start:
+            switch (kind) {
+            case T_LBRACE:      turnInto(namespace_open); break;
+            } break;
+
+        case namespace_open:
+            if (tryDeclaration())
+                break;
+            switch (kind) {
+            case T_NAMESPACE:   enter(namespace_start); break;
+            case T_RBRACE:      leave(); break;
+            case T_STRUCT:
+            case T_UNION:
+            case T_CLASS:       enter(class_start); break;
+            case T_ENUM:        enter(enum_start); break;
+            case T_USING:       enter(using_start); break;
+            } break;
+
+        case class_start:
+            switch (kind) {
+            case T_SEMICOLON:   leave(); break;
+            case T_LBRACE:      turnInto(class_open); break;
+            } break;
+
+        case class_open:
+            if (tryDeclaration())
+                break;
+            switch (kind) {
+            case T_RBRACE:      leave(); break;
+            case T_STRUCT:
+            case T_UNION:
+            case T_CLASS:       enter(class_start); break;
+            case T_ENUM:        enter(enum_start); break;
+            case T_USING:       enter(using_start); break;
+            } break;
+
+        case enum_start:
+            switch (kind) {
+            case T_SEMICOLON:   leave(); break;
+            case T_LBRACE:      turnInto(brace_list_open); break;
+            } break;
+
+        case brace_list_open:
+            switch (kind) {
+            case T_RBRACE:      leave(); break;
+            case T_LBRACE:      enter(brace_list_open); break; // ### Other, nested brace list?
+            } break;
+
+        case using_start:
+            switch (kind) {
+            case T_SEMICOLON:   leave(); break;
+            } break;
+
+        case template_start:
+            switch (kind) {
+            case T_LESS:        turnInto(template_param); break;
+            } break;
+
+        case template_param:
+            switch (kind) {
+            case T_LESS:        enter(template_param); break;
+            case T_GREATER:     leave(); break;
+            } break;
+
+        case operator_declaration:
+            switch (kind) {
+            case T_LPAREN:      break;
+            default:            leave(); break;
+            } break;
+
+        case declaration_start:
+            if (tryExpression(true))
+                break;
+            switch (kind) {
+            case T_SEMICOLON:   leave(true); break;
+            case T_EQUAL:       enter(initializer); break;
+            case T_LBRACE:      turnInto(defun_open); break;
+            case T_COLON:       turnInto(member_init_open); break;
+            case T_OPERATOR:    enter(operator_declaration); break;
+            } break;
+
+        case initializer:
+            switch (kind) {
+            case T_LBRACE:      enter(brace_list_open); break;
+            default:            turnInto(expression); continue;
+            } break;
+
+        case expression:
+            if (tryExpression())
+                break;
+            switch (kind) {
+            case T_SEMICOLON:   leave(); continue;
+            case T_LBRACE:
+            case T_COLON:
+                if (m_currentState.at(m_currentState.size() - 2).type == declaration_start) {
+                    // oops, the expression was a function declaration argument list, hand lbrace/colon to declaration_start
+                    leave();
+                    continue;
+                }
+                break;
+            } break;
+
+        case arglist_open:
+            if (tryExpression())
+                break;
+            switch (kind) {
+            case T_RPAREN:      leave(); break;
+            } break;
+
+        case ternary_op:
+            if (tryExpression())
+                break;
+            switch (kind) {
+            case T_RPAREN:
+            case T_COMMA:
+            case T_SEMICOLON:   leave(); continue; // always nested, propagate
+            } break;
+
+        case stream_op:
+            if (tryExpression())
+                break;
+            switch (kind) {
+            case T_COMMA:
+            case T_SEMICOLON:   leave(); continue; // always nested, propagate semicolon
+            } break;
+
+        case member_init_open:
+            switch (kind) {
+            case T_LBRACE:      turnInto(defun_open); break;
+            case T_SEMICOLON:   leave(); break; // ### so we don't break completely if it's a bitfield or ternary
+            } break;
+
+        case defun_open:
+            if (tryStatement())
+                break;
+            switch (kind) {
+            case T_RBRACE:      leave(); break;
+            } break;
+
+        case switch_statement:
+        case statement_with_condition:
+        case if_statement:
+            switch (kind) {
+            case T_LPAREN:      enter(condition_open); break;
+            } break;
+
+        case maybe_else:
+            if (m_currentToken.isComment()) {
+                break;
+            } else if (kind == T_ELSE) {
+                turnInto(else_clause);
+                enter(substatement);
+                break;
+            } else {
+                leave(true);
+                continue;
+            }
+
+        case else_clause:
+            // ### shouldn't happen
+            dump();
+            Q_ASSERT(false);
+            leave(true);
+            break;
+
+        case do_statement:
+            // ### shouldn't happen
+            dump();
+            Q_ASSERT(false);
+            leave(true);
+            break;
+
+        case return_statement:
+            switch (kind) {
+            case T_SEMICOLON:   leave(true); break;
+            } break;
+
+        case substatement:
+            // prefer substatement_open over block_open
+            if (kind != T_LBRACE && tryStatement())
+                break;
+            switch (kind) {
+            case T_LBRACE:      turnInto(substatement_open); break;
+            case T_SEMICOLON:   leave(true); break;
+            } break;
+
+        case for_statement:
+            switch (kind) {
+            case T_LPAREN:      enter(for_statement_paren_open); break;
+            } break;
+
+        case for_statement_paren_open:
+            enter(for_statement_init); continue;
+
+        case for_statement_init:
+            switch (kind) {
+            case T_SEMICOLON:   turnInto(for_statement_condition); break;
+            case T_LPAREN:      enter(condition_paren_open); break;
+            } break;
+
+        case for_statement_condition:
+            switch (kind) {
+            case T_SEMICOLON:   turnInto(for_statement_expression); break;
+            case T_LPAREN:      enter(condition_paren_open); break;
+            } break;
+
+        case for_statement_expression:
+            switch (kind) {
+            case T_RPAREN:      leave(); turnInto(substatement); break;
+            case T_LPAREN:      enter(condition_paren_open); break;
+            } break;
+
+        case case_start:
+            switch (kind) {
+            case T_COLON:       turnInto(case_cont); break;
+            } break;
+
+        case case_cont:
+            if (kind != T_CASE && kind != T_DEFAULT && tryStatement())
+                break;
+            switch (kind) {
+            case T_RBRACE:      leave(); continue;
+            case T_DEFAULT:
+            case T_CASE:        leave(); continue;
+            } break;
+
+        case substatement_open:
+            if (tryStatement())
+                break;
+            switch (kind) {
+            case T_RBRACE:      leave(true); break;
+            } break;
+
+        case condition_open:
+            switch (kind) {
+            case T_RPAREN:      turnInto(substatement); break;
+            case T_LPAREN:      enter(condition_paren_open); break;
+            } break;
+
+        case block_open:
+            if (tryStatement())
+                break;
+            switch(kind) {
+            case T_RBRACE:      leave(true); break;
+            } break;
+
+        // paren nesting
+        case condition_paren_open:
+            switch (kind) {
+            case T_RPAREN:      leave(); break;
+            case T_LPAREN:      enter(condition_paren_open); break;
+            } break;
+
+        case qt_like_macro:
+            switch (kind) {
+            case T_LPAREN:      enter(arglist_open); break;
+            case T_SEMICOLON:   leave(true); break;
+            default:            leave(); continue;
+            } break;
+
+        case multiline_comment_start:
+        case multiline_comment_cont:
+            if (kind != T_COMMENT && kind != T_DOXY_COMMENT) {
+                leave();
+                continue;
+            } else if (m_tokenIndex == m_tokens.size() - 1
+                    && lexerState == Lexer::State_Default) {
+                leave();
+            } else if (m_tokenIndex == 0 && m_currentToken.isComment()) {
+                // to allow enter/leave to update the indentDepth
+                turnInto(multiline_comment_cont);
+            }
+            break;
+
+        case cpp_macro_start: {
+            const int size = m_currentState.size();
+
+            int previousMarker = -1;
+            int previousPreviousMarker = -1;
+            for (int i = size - 1; i >= 0; --i) {
+                if (m_currentState.at(i).type == cpp_macro_conditional) {
+                    if (previousMarker == -1)
+                        previousMarker = i;
+                    else {
+                        previousPreviousMarker = i;
+                        break;
+                    }
+                }
+            }
+
+            QStringRef tokenText = currentTokenText();
+            if (tokenText == QLatin1String("ifdef")
+                    || tokenText == QLatin1String("if")
+                    || tokenText == QLatin1String("ifndef")) {
+                enter(cpp_macro_conditional);
+                // copy everything right of previousMarker, excluding cpp_macro_conditional
+                for (int i = previousMarker + 1; i < size; ++i)
+                    m_currentState += m_currentState.at(i);
+            }
+            if (previousMarker != -1) {
+                if (tokenText == QLatin1String("endif")) {
+                    QStack<State>::iterator begin = m_currentState.begin() + previousPreviousMarker + 1;
+                    QStack<State>::iterator end = m_currentState.begin() + previousMarker + 1;
+                    m_currentState.erase(begin, end);
+                } else if (tokenText == QLatin1String("else")
+                        || tokenText == QLatin1String("elif")) {
+                    m_currentState.resize(previousMarker + 1);
+                    for (int i = previousPreviousMarker + 1; i < previousMarker; ++i)
+                        m_currentState += m_currentState.at(i);
+                }
+            }
+
+            turnInto(cpp_macro);
+            break;
+        }
+
+        case cpp_macro:
+        case cpp_macro_cont:
+            break;
+
+        default:
+            qWarning() << "Unhandled state" << m_currentState.top().type;
+            break;
+
+        } // end of state switch
+
+        ++m_tokenIndex;
+    }
+
+    int topState = m_currentState.top().type;
+
+    if (topState != multiline_comment_start
+            && topState != multiline_comment_cont
+            && (lexerState == Lexer::State_MultiLineComment
+                || lexerState == Lexer::State_MultiLineDoxyComment)) {
+        enter(multiline_comment_start);
+    }
+
+    if (topState == qt_like_macro)
+        leave(true);
+
+    if ((topState == cpp_macro_cont
+            || topState == cpp_macro) && !endedJoined)
+        leave();
+
+    if (topState == cpp_macro && endedJoined)
+        turnInto(cpp_macro_cont);
+
+    storeBlockState(block);
+}
+
+int CodeFormatter::indentFor(const QTextBlock &block)
+{
+//    qDebug() << "indenting for" << block.blockNumber() + 1;
+
+    Q_ASSERT(m_document);
+    Q_ASSERT(m_document == block.document());
+
+    requireStatesUntil(block);
+    correctIndentation(block);
+    return m_indentDepth;
+}
+
+void CodeFormatter::requireStatesUntil(const QTextBlock &endBlock)
+{
+    QStack<State> previousState = initialState();
+    QTextBlock it = m_document->firstBlock();
+    for (; it.isValid() && it != endBlock; it = it.next()) {
+        TextBlockUserData *userData = BaseTextDocumentLayout::userData(it);
+        CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
+        if (!cppData)
+            break;
+        if (cppData->blockRevision() != it.revision())
+            break;
+        if (previousState != cppData->m_beginState)
+            break;
+        if (TextBlockUserData::lexerState(it) == -1)
+            break;
+
+        previousState = cppData->m_endState;
+    }
+    for (; it.isValid() && it != endBlock; it = it.next()) {
+        //qDebug() << "recalc line" << it.blockNumber() + 1;
+        recalculateStateAfter(it);
+    }
+    restoreBlockState(endBlock.previous());
+}
+
+CodeFormatter::State CodeFormatter::state(int belowTop) const
+{
+    if (belowTop < m_currentState.size())
+        return m_currentState.at(m_currentState.size() - 1 - belowTop);
+    else
+        return State();
+}
+
+int CodeFormatter::tokenIndex() const
+{
+    return m_tokenIndex;
+}
+
+int CodeFormatter::tokenIndexFromEnd() const
+{
+    return m_tokens.size() - 1 - m_tokenIndex;
+}
+
+const CPlusPlus::Token &CodeFormatter::currentToken() const
+{
+    return m_currentToken;
+}
+
+void CodeFormatter::invalidateCache()
+{
+    QTextBlock it = m_document->firstBlock();
+    for (; it.isValid(); it = it.next()) {
+        TextBlockUserData *userData = BaseTextDocumentLayout::userData(it);
+        CppCodeFormatterData *cppData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
+        if (!cppData)
+            break;
+        cppData->setBlockRevision(-1);
+    }
+}
+
+void CodeFormatter::enter(int newState)
+{
+    int savedIndentDepth = m_indentDepth;
+    onEnter(newState, &m_indentDepth, &savedIndentDepth);
+    m_currentState.push(State(newState, savedIndentDepth));
+}
+
+void CodeFormatter::leave(bool statementDone)
+{
+    Q_ASSERT(m_currentState.size() > 1);
+    if (m_currentState.top().type == topmost_intro)
+        return;
+
+    // restore indent depth
+    State poppedState = m_currentState.pop();
+    m_indentDepth = poppedState.savedIndentDepth;
+
+    int topState = m_currentState.top().type;
+
+    // does it suffice to check if token is T_SEMICOLON or T_RBRACE?
+    // maybe distinction between leave and turnInto?
+    if (statementDone) {
+        if (topState == substatement
+                || topState == statement_with_condition
+                || topState == for_statement
+                || topState == switch_statement
+                || topState == do_statement) {
+            leave(true);
+        } else if (topState == if_statement) {
+            if (poppedState.type != maybe_else)
+                enter(maybe_else);
+            else
+                leave(true);
+        } else if (topState == else_clause) {
+            // leave the else *and* the surrounding if, to prevent another else
+            leave();
+            leave(true);
+        }
+    }
+}
+
+void CodeFormatter::correctIndentation(const QTextBlock &block)
+{
+    const int lexerState = tokenizeBlock(block);
+    Q_ASSERT(m_currentState.size() >= 1);
+
+    adjustIndent(m_tokens, lexerState, &m_indentDepth);
+}
+
+bool CodeFormatter::tryExpression(bool alsoExpression)
+{    
+    int newState = -1;
+
+    const int kind = m_currentToken.kind();
+    switch (kind) {
+    case T_LPAREN:          newState = arglist_open; break;
+    case T_QUESTION:        newState = ternary_op; break;
+
+    case T_LESS_LESS:
+    case T_GREATER_GREATER:
+        // don't go into stream operator state inside arglist_open
+        // or another stream_op
+        newState = stream_op;
+        for (int i = m_currentState.size() - 1; i >= 0; --i) {
+            const int type = m_currentState.at(i).type;
+            if (type == arglist_open || type == stream_op) {
+                newState = -1;
+                break;
+            }
+            if (type == topmost_intro
+                    || type == substatement_open
+                    || type == defun_open
+                    || type == namespace_open
+                    || type == class_open
+                    || type == brace_list_open) {
+                break;
+            }
+        }
+        break;
+    }
+
+    if (newState != -1) {
+        if (alsoExpression)
+            enter(expression);
+        enter(newState);
+        return true;
+    }
+
+    return false;
+}
+
+bool CodeFormatter::tryDeclaration()
+{
+    const int kind = m_currentToken.kind();
+    switch (kind) {
+    case T_Q_ENUMS:
+    case T_Q_PROPERTY:
+    case T_Q_FLAGS:
+    case T_Q_GADGET:
+    case T_Q_OBJECT:
+    case T_Q_INTERFACES:
+    case T_Q_DECLARE_INTERFACE:
+    case T_Q_PRIVATE_SLOT:
+        enter(qt_like_macro);
+        return true;
+    case T_IDENTIFIER:
+        if (m_tokenIndex == 0) {
+            QString tokenText = currentTokenText().toString();
+            if (tokenText.startsWith(QLatin1String("Q_"))
+                    || tokenText.startsWith(QLatin1String("QT_"))
+                    || tokenText.startsWith(QLatin1String("QDOC_"))) {
+                enter(qt_like_macro);
+                return true;
+            }
+        }
+        // fallthrough
+    case T_CHAR:
+    case T_WCHAR_T:
+    case T_BOOL:
+    case T_SHORT:
+    case T_INT:
+    case T_LONG:
+    case T_SIGNED:
+    case T_UNSIGNED:
+    case T_FLOAT:
+    case T_DOUBLE:
+    case T_VOID:
+    case T_AUTO:
+    case T___TYPEOF__:
+    case T___ATTRIBUTE__:
+    case T_STATIC:
+    case T_FRIEND:
+    case T_CONST:
+    case T_VOLATILE:
+    case T_INLINE:
+        enter(declaration_start);
+        return true;
+
+    case T_TEMPLATE:
+        enter(template_start);
+        return true;
+
+    default:
+        return false;
+    }
+}
+
+bool CodeFormatter::tryStatement()
+{
+    const int kind = m_currentToken.kind();
+    if (tryDeclaration())
+        return true;
+    switch (kind) {
+    case T_RETURN:
+        enter(return_statement);
+        enter(expression);
+        return true;
+    case T_FOR:
+        enter(for_statement);
+        return true;
+    case T_SWITCH:
+        enter(switch_statement);
+        return true;
+    case T_IF:
+        enter(if_statement);
+        return true;
+    case T_WHILE:
+    case T_Q_FOREACH:
+        enter(statement_with_condition);
+        return true;
+    case T_DO:
+        enter(do_statement);
+        enter(substatement);
+        return true;
+    case T_CASE:
+    case T_DEFAULT:
+        enter(case_start);
+        return true;
+    case T_LBRACE:
+        enter(block_open);
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool CodeFormatter::isBracelessState(int type) const
+{
+    return type == substatement
+        || type == if_statement
+        || type == else_clause
+        || type == statement_with_condition
+        || type == for_statement
+        || type == do_statement;
+}
+
+const Token &CodeFormatter::tokenAt(int idx) const
+{
+    static const Token empty;
+    if (idx < 0 || idx >= m_tokens.size())
+        return empty;
+    else
+        return m_tokens.at(idx);
+}
+
+QStringRef CodeFormatter::currentTokenText() const
+{
+    return m_currentLine.midRef(m_currentToken.begin(), m_currentToken.length());
+}
+
+void CodeFormatter::turnInto(int newState)
+{
+    leave(false);
+    enter(newState);
+}
+
+void CodeFormatter::storeBlockState(const QTextBlock &block)
+{
+    if (!block.isValid())
+        return;
+
+    TextBlockUserData *userData = BaseTextDocumentLayout::userData(block);
+    userData->setCodeFormatterData(
+            new CppCodeFormatterData(block.revision(), m_beginState, m_currentState, m_indentDepth));
+}
+
+void CodeFormatter::restoreBlockState(const QTextBlock &block)
+{
+    if (block.isValid()) {             
+        TextBlockUserData *userData = BaseTextDocumentLayout::userData(block);
+        CppCodeFormatterData *oldData = static_cast<CppCodeFormatterData *>(userData->codeFormatterData());
+        if (oldData) {
+            m_currentState = oldData->m_endState;
+            m_beginState = m_currentState;
+            m_indentDepth = oldData->m_indentDepth;
+            return;
+        }
+    }
+
+    m_currentState = initialState();
+    m_beginState = m_currentState;
+    m_indentDepth = 0;
+}
+
+QStack<CodeFormatter::State> CodeFormatter::initialState()
+{
+    static QStack<CodeFormatter::State> initialState;
+    if (initialState.isEmpty())
+        initialState.push(State(topmost_intro, 0));
+    return initialState;
+}
+
+int CodeFormatter::tokenizeBlock(const QTextBlock &block, bool *endedJoined)
+{
+    int startState = TextBlockUserData::lexerState(block.previous());
+    if (block.blockNumber() == 0)
+        startState = 0;
+    Q_ASSERT(startState != -1);
+
+    SimpleLexer tokenize;
+    tokenize.setQtMocRunEnabled(true);
+    tokenize.setObjCEnabled(true);
+
+    m_currentLine = block.text();
+    // to determine whether a line was joined, Tokenizer needs a
+    // newline character at the end
+    m_currentLine.append(QLatin1Char('\n'));
+    m_tokens = tokenize(m_currentLine, startState);
+
+    if (endedJoined)
+        *endedJoined = tokenize.endedJoined();
+
+    const int lexerState = tokenize.state();
+    TextBlockUserData::setLexerState(block, lexerState);
+    return lexerState;
+}
+
+void CodeFormatter::dump()
+{
+    qDebug() << "Current token index" << m_tokenIndex;
+    qDebug() << "Current state:";
+    foreach (State s, m_currentState) {
+        qDebug() << s.type << s.savedIndentDepth;
+    }
+    qDebug() << "Current indent depth:" << m_indentDepth;
+}
+
+QtStyleCodeFormatter::QtStyleCodeFormatter()
+    : m_indentSize(4)
+{
+}
+
+void QtStyleCodeFormatter::setIndentSize(int size)
+{
+    if (size != m_indentSize) {
+        m_indentSize = size;
+        invalidateCache();
+    }
+}
+
+void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedIndentDepth) const
+{
+    const State &parentState = state();
+    const Token &tk = currentToken();
+    const int tokenPosition = tk.begin();
+    const bool firstToken = (tokenIndex() == 0);
+    const bool lastToken = (tokenIndexFromEnd() == 0);
+
+    switch (newState) {
+    case namespace_start:
+        if (firstToken)
+            *savedIndentDepth = tokenPosition;
+        *indentDepth = tokenPosition;
+        break;
+
+    case enum_start:
+    case class_start:
+        if (firstToken)
+            *savedIndentDepth = tokenPosition;
+        *indentDepth = tokenPosition + 2*m_indentSize;
+        break;
+
+    case template_param:
+        if (!lastToken)
+            *indentDepth = tokenPosition + tk.length();
+        else
+            *indentDepth += 2*m_indentSize;
+        break;
+
+    case statement_with_condition:
+    case for_statement:
+    case switch_statement:
+    case declaration_start:
+    case if_statement:
+    case return_statement:
+        if (firstToken)
+            *savedIndentDepth = tokenPosition;
+        *indentDepth = *savedIndentDepth + 2*m_indentSize;
+        break;
+
+    case arglist_open:
+    case condition_paren_open:
+        if (!lastToken)
+            *indentDepth = tokenPosition + 1;
+        else
+            *indentDepth += m_indentSize;
+        break;
+
+    case ternary_op:
+        if (!lastToken)
+            *indentDepth = tokenPosition + tk.length() + 1;
+        else
+            *indentDepth += m_indentSize;
+        break;
+
+    case stream_op:
+        *indentDepth = tokenPosition + tk.length() + 1;
+        break;
+
+    case member_init_open:
+        if (firstToken)
+            *indentDepth = tokenPosition + tk.length() + 1;
+        else
+            *indentDepth += m_indentSize;
+        break;
+
+    case defun_open:
+    case class_open:
+    case case_cont:
+        *indentDepth += m_indentSize;
+        break;
+
+    case substatement_open:
+        if (parentState.type != switch_statement)
+            *indentDepth += m_indentSize;
+        break;
+
+    case brace_list_open:
+        if (parentState.type != initializer)
+            *indentDepth = parentState.savedIndentDepth + m_indentSize;
+        break;
+
+    case block_open:
+        if (parentState.type != case_cont)
+            *indentDepth += m_indentSize;
+        break;
+
+    case condition_open:
+        // undo the continuation indent of the parent
+        *indentDepth = parentState.savedIndentDepth;
+        *savedIndentDepth = *indentDepth;
+
+        // fixed extra indent when continuing 'if (', but not for 'else if ('
+        if (tokenPosition <= *indentDepth + m_indentSize)
+            *indentDepth += 2*m_indentSize;
+        else
+            *indentDepth = tokenPosition + 1;
+        break;
+
+    case substatement:
+        // undo the continuation indent of the parent
+        *indentDepth = parentState.savedIndentDepth;
+        *savedIndentDepth = *indentDepth;
+        break;
+
+    case maybe_else: {
+        // set indent to outermost braceless savedIndent
+        int outermostBraceless = 0;
+        while (isBracelessState(state(outermostBraceless).type))
+            ++outermostBraceless;
+        *indentDepth = state(outermostBraceless - 1).savedIndentDepth;
+    }   break;
+
+    case for_statement_paren_open:
+        *indentDepth = tokenPosition + 1;
+        break;
+
+    case multiline_comment_start:
+        *indentDepth = tokenPosition + 2;
+        break;
+
+    case multiline_comment_cont:
+        *indentDepth = tokenPosition;
+        break;
+
+    case cpp_macro:
+    case cpp_macro_cont:
+        *indentDepth = m_indentSize;
+        break;
+    }
+}
+
+void QtStyleCodeFormatter::adjustIndent(const QList<CPlusPlus::Token> &tokens, int lexerState, int *indentDepth) const
+{
+    State topState = state();
+    State previousState = state(1);
+
+    const bool topWasMaybeElse = (topState.type == maybe_else);
+    if (topWasMaybeElse) {
+        int outermostBraceless = 1;
+        while (state(outermostBraceless).type != invalid && isBracelessState(state(outermostBraceless).type))
+            ++outermostBraceless;
+
+        topState = state(outermostBraceless);
+        previousState = state(outermostBraceless + 1);
+    }
+
+
+    // adjusting the indentDepth here instead of in enter() gives 'else if' the correct indentation
+    // ### could be moved?
+    if (topState.type == substatement)
+        *indentDepth += m_indentSize;
+
+    // keep user-adjusted indent in multiline comments
+    if (topState.type == multiline_comment_start
+            || topState.type == multiline_comment_cont) {
+        if (!tokens.isEmpty()) {
+            *indentDepth = tokens.at(0).begin();
+            return;
+        }
+    }
+
+    const int kind = tokenAt(0).kind();
+    switch (kind) {
+    case T_POUND: *indentDepth = 0; break;
+    case T_COLON:
+        // ### ok for constructor initializer lists - what about ? and bitfields?
+        if (topState.type == expression && previousState.type == declaration_start) {
+            *indentDepth = previousState.savedIndentDepth + m_indentSize;
+        } else if (topState.type == ternary_op) {
+            *indentDepth -= 2;
+        }
+        break;
+    case T_COMMA:
+        if (topState.type == member_init_open) {
+            *indentDepth -= 2;
+        }
+        break;
+    case T_LBRACE: {
+        // function definition - argument list is expression state
+        if (topState.type == case_cont)
+            *indentDepth = topState.savedIndentDepth;
+        else if (topState.type == expression && previousState.type == declaration_start)
+            *indentDepth = previousState.savedIndentDepth;
+        else if (topState.type != defun_open
+                && topState.type != substatement_open
+                && topState.type != block_open
+                && !topWasMaybeElse)
+            *indentDepth = topState.savedIndentDepth;
+        break;
+    }
+    case T_RBRACE: {
+        if (topState.type == block_open && previousState.type == case_cont) {
+            *indentDepth = previousState.savedIndentDepth;
+            break;
+        }
+        for (int i = 0; state(i).type != topmost_intro; ++i) {
+            const int type = state(i).type;
+            if (type == defun_open
+                    || type == substatement_open
+                    || type == class_open
+                    || type == brace_list_open
+                    || type == namespace_open
+                    || type == block_open) {
+                *indentDepth = state(i).savedIndentDepth;
+                break;
+            }
+        }
+        break;
+    }
+    case T_RPAREN:
+        if (topState.type == condition_open) {
+            *indentDepth = previousState.savedIndentDepth;
+        }
+        break;
+    case T_DEFAULT:
+    case T_CASE:
+        for (int i = 0; state(i).type != topmost_intro; ++i) {
+            const int type = state(i).type;
+            if (type == switch_statement || type == case_cont) {
+                *indentDepth = state(i).savedIndentDepth;
+                break;
+            } else if (type == topmost_intro) {
+                break;
+            }
+        }
+        break;
+    case T_PUBLIC:
+    case T_PRIVATE:
+    case T_PROTECTED:
+    case T_Q_SIGNALS:
+        if (topState.type == class_open) {
+            if (tokenAt(1).is(T_COLON) || tokenAt(2).is(T_COLON))
+                *indentDepth = topState.savedIndentDepth;
+        }
+        break;
+    case T_ELSE:
+        if (topWasMaybeElse)
+            *indentDepth = state().savedIndentDepth; // topSavedIndent is actually the previous
+        break;
+    case T_LESS_LESS:
+    case T_GREATER_GREATER:
+        if (topState.type == stream_op)
+            *indentDepth -= 3; // to align << with <<
+        break;
+    case T_COMMENT:
+    case T_DOXY_COMMENT:
+    case T_CPP_COMMENT:
+    case T_CPP_DOXY_COMMENT:
+        // unindent the last line of a comment
+        if ((topState.type == multiline_comment_cont
+             || topState.type == multiline_comment_start)
+                && (kind == T_COMMENT || kind == T_DOXY_COMMENT)
+                && (lexerState == Lexer::State_Default
+                    || tokens.size() != 1)) {
+            *indentDepth -= m_indentSize;
+        }
+        break;
+    }
+}
diff --git a/src/plugins/cpptools/cppcodeformatter.h b/src/plugins/cpptools/cppcodeformatter.h
new file mode 100644
index 0000000000000000000000000000000000000000..051b5f2aac3dfaee39b240fc20fa603c24242bdb
--- /dev/null
+++ b/src/plugins/cpptools/cppcodeformatter.h
@@ -0,0 +1,195 @@
+#ifndef CPPCODEFORMATTER_H
+#define CPPCODEFORMATTER_H
+
+#include "cpptools_global.h"
+
+#include <cplusplus/SimpleLexer.h>
+#include <Token.h>
+
+#include <QtCore/QChar>
+#include <QtCore/QStack>
+#include <QtCore/QList>
+#include <QtCore/QVector>
+#include <QtCore/QPointer>
+
+QT_BEGIN_NAMESPACE
+class QTextDocument;
+class QTextBlock;
+QT_END_NAMESPACE
+
+namespace CppTools {    
+namespace Internal {
+class CppCodeFormatterData;
+}
+
+class CPPTOOLS_EXPORT CodeFormatter
+{
+public:
+    CodeFormatter();
+    virtual ~CodeFormatter();
+
+    void setDocument(QTextDocument *document);
+
+    int indentFor(const QTextBlock &block);
+
+protected:
+    virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const = 0;
+    virtual void adjustIndent(const QList<CPlusPlus::Token> &tokens, int lexerState, int *indentDepth) const = 0;
+
+protected:
+    enum StateType {
+        invalid = 0,
+
+        topmost_intro, // The first line in a "topmost" definition.
+
+        multiline_comment_start, // Inside the first line of a multi-line C style block comment.
+        multiline_comment_cont, // Inside the following lines of a multi-line C style block comment.
+        cpp_macro_start, // After the '#' token
+        cpp_macro, // The start of a C preprocessor macro definition.
+        cpp_macro_cont, // Subsequent lines of a multi-line C preprocessor macro definition.
+        cpp_macro_conditional, // Special marker used for separating saved from current state when dealing with #ifdef
+        qt_like_macro, // after an identifier starting with Q_ or QT_ at the beginning of the line
+
+        defun_open, // Brace that opens a top-level function definition.
+        using_start, // right after the "using" token
+
+        class_start, // after the 'class' token
+        class_open, // Brace that opens a class definition.
+        member_init_open, // After ':' that starts a member initialization list.
+
+        enum_start, // After 'enum'
+        brace_list_open, // Open brace of an enum or static array list.
+
+        namespace_start, // after the namespace token, before the opening brace.
+        namespace_open, // Brace that opens a C++ namespace block.
+
+        declaration_start, // shifted a token which could start a declaration.
+        operator_declaration, // after 'operator' in declaration_start
+
+        template_start, // after the 'template' token
+        template_param, // after the '<' in a template_start
+
+        if_statement, // After 'if'
+        maybe_else, // after the first substatement in an if
+        else_clause, // The else line of an if-else construct.
+
+        for_statement, // After the 'for' token
+        for_statement_paren_open, // While inside the (...)
+        for_statement_init, // The initializer part of the for statement
+        for_statement_condition, // The condition part of the for statement
+        for_statement_expression, // The expression part of the for statement
+
+        switch_statement, // After 'switch' token
+        case_start, // after a 'case' or 'default' token
+        case_cont, // after the colon in a case/default
+
+        statement_with_condition, // A statement that takes a condition after the start token.
+        do_statement, // After 'do' token
+        return_statement, // After 'return'
+        block_open, // Statement block open brace.
+
+        substatement, // The first line after a conditional or loop construct.
+        substatement_open, // The brace that opens a substatement block.
+
+        arglist_open, // after the lparen. TODO: check if this is enough.
+        stream_op, // Lines continuing a stream operator (C++ only).
+        ternary_op, // The ? : operator
+
+        condition_open, // Start of a condition in 'if', 'while', entered after opening paren
+        condition_paren_open, // After an lparen in a condition
+
+        assign_open, // after an assignment token
+
+        expression, // after a '=' in a declaration_start once we're sure it's not '= {'
+        initializer, // after a '=' in a declaration start
+    };
+
+    struct State {
+        State()
+            : savedIndentDepth(0)
+            , type(0)
+        {}
+
+        State(quint8 ty, quint16 savedDepth)
+            : savedIndentDepth(savedDepth)
+            , type(ty)
+        {}
+
+        quint16 savedIndentDepth;
+        quint8 type;
+
+        bool operator==(const State &other) const {
+            return type == other.type
+                && savedIndentDepth == other.savedIndentDepth;
+        }
+    };
+
+    State state(int belowTop = 0) const;
+    int tokenIndex() const;
+    int tokenIndexFromEnd() const;
+    const CPlusPlus::Token &currentToken() const;
+    const CPlusPlus::Token &tokenAt(int idx) const;
+
+    bool isBracelessState(int type) const;
+
+    void invalidateCache();
+
+private:
+    void requireStatesUntil(const QTextBlock &block);
+    void recalculateStateAfter(const QTextBlock &block);
+    void storeBlockState(const QTextBlock &block);
+    void restoreBlockState(const QTextBlock &block);
+
+    QStringRef currentTokenText() const;
+
+    int tokenizeBlock(const QTextBlock &block, bool *endedJoined = 0);
+
+    void turnInto(int newState);
+
+    bool tryExpression(bool alsoExpression = false);
+    bool tryDeclaration();
+    bool tryStatement();
+
+    void enter(int newState);
+    void leave(bool statementDone = false);
+    void correctIndentation(const QTextBlock &block);
+
+    void dump();
+
+private:
+    static QStack<State> initialState();
+
+    QPointer<QTextDocument> m_document;
+
+    QStack<State> m_beginState;
+    QStack<State> m_currentState;
+
+    QList<CPlusPlus::Token> m_tokens;
+    QString m_currentLine;
+    CPlusPlus::Token m_currentToken;
+    int m_tokenIndex;
+
+    // should store indent level and padding instead
+    int m_indentDepth;
+
+    friend class Internal::CppCodeFormatterData;
+};
+
+class CPPTOOLS_EXPORT QtStyleCodeFormatter : public CodeFormatter
+{
+public:
+    QtStyleCodeFormatter();
+
+    void setIndentSize(int size);
+
+protected:
+    virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth) const;
+    virtual void adjustIndent(const QList<CPlusPlus::Token> &tokens, int lexerState, int *indentDepth) const;
+
+private:
+    int m_indentSize;
+};
+
+} // namespace CppTools
+
+#endif // CPPCODEFORMATTER_H
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index de7adcd66f672bc640f4525dc42d2622927f9ccd..6ab11b6058ce35ce2d4a928cb0aefe860fefb80d 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -23,7 +23,8 @@ HEADERS += completionsettingspage.h \
     searchsymbols.h \
     cppdoxygen.h \
     cppfilesettingspage.h \
-    cppfindreferences.h
+    cppfindreferences.h \
+    cppcodeformatter.h
 
 SOURCES += completionsettingspage.cpp \
     cppclassesfilter.cpp \
@@ -38,7 +39,8 @@ SOURCES += completionsettingspage.cpp \
     cppdoxygen.cpp \
     cppfilesettingspage.cpp \
     abstracteditorsupport.cpp \
-    cppfindreferences.cpp
+    cppfindreferences.cpp \
+    cppcodeformatter.cpp
 
 FORMS += completionsettingspage.ui \
     cppfilesettingspage.ui
diff --git a/src/plugins/texteditor/basetextdocumentlayout.cpp b/src/plugins/texteditor/basetextdocumentlayout.cpp
index 58427566bb04e12c8879552c2907a65d5a6a561a..871cab0e1318e219d736c8338bd4947cfb175806 100644
--- a/src/plugins/texteditor/basetextdocumentlayout.cpp
+++ b/src/plugins/texteditor/basetextdocumentlayout.cpp
@@ -31,6 +31,15 @@
 
 using namespace TextEditor;
 
+CodeFormatterData::CodeFormatterData(int blockRevision)
+    : m_blockRevision(blockRevision)
+{
+}
+
+CodeFormatterData::~CodeFormatterData()
+{
+}
+
 TextBlockUserData::~TextBlockUserData()
 {
     TextMarks marks = m_marks;
@@ -38,6 +47,9 @@ TextBlockUserData::~TextBlockUserData()
     foreach (ITextMark *mrk, marks) {
         mrk->removedFromEditor();
     }
+
+    if (m_codeFormatterData)
+        delete m_codeFormatterData;
 }
 
 int TextBlockUserData::braceDepthDelta() const
@@ -359,6 +371,35 @@ TextBlockUserData::MatchType TextBlockUserData::matchCursorForward(QTextCursor *
     return NoMatch;
 }
 
+int TextBlockUserData::lexerState(const QTextBlock &block)
+{
+    if (!block.isValid())
+        return -1;
+
+    int data = block.userState();
+    if (data == -1)
+        return -1;
+    return data & 0xFF;
+}
+
+void TextBlockUserData::setLexerState(QTextBlock block, int state)
+{
+    if (!block.isValid())
+        return;
+
+    int data = block.userState();
+    if (data == -1)
+        data = 0;
+    block.setUserState((data & ~0xFF) | (state & 0xFF));
+}
+
+void TextBlockUserData::setCodeFormatterData(CodeFormatterData *data)
+{
+    if (m_codeFormatterData)
+        delete m_codeFormatterData;
+
+    m_codeFormatterData = data;
+}
 
 BaseTextDocumentLayout::BaseTextDocumentLayout(QTextDocument *doc)
     :QPlainTextDocumentLayout(doc) {
@@ -528,6 +569,3 @@ QSizeF BaseTextDocumentLayout::documentSize() const
     size.setWidth(qMax((qreal)m_requiredWidth, size.width()));
     return size;
 }
-
-
-
diff --git a/src/plugins/texteditor/basetextdocumentlayout.h b/src/plugins/texteditor/basetextdocumentlayout.h
index b3b20ce2d4ea48748e4000eaf4ee1bb3c8966ed0..76323c63841541142ff9b3d58e5d569368fed37f 100644
--- a/src/plugins/texteditor/basetextdocumentlayout.h
+++ b/src/plugins/texteditor/basetextdocumentlayout.h
@@ -54,6 +54,18 @@ struct TEXTEDITOR_EXPORT Parenthesis
     int pos;
 };
 
+class TEXTEDITOR_EXPORT CodeFormatterData
+{
+public:
+    CodeFormatterData(int blockRevision);
+    virtual ~CodeFormatterData();
+
+    int blockRevision() const { return m_blockRevision; }
+    void setBlockRevision(int revision) { m_blockRevision = revision; }
+
+private:
+    int m_blockRevision;
+};
 
 class TEXTEDITOR_EXPORT TextBlockUserData : public QTextBlockUserData
 {
@@ -64,7 +76,9 @@ public:
           m_ifdefedOut(false),
           m_foldingIndent(0),
           m_foldingStartIncluded(false),
-          m_foldingEndIncluded(false){}
+          m_foldingEndIncluded(false),
+          m_codeFormatterData(0)
+    {}
     ~TextBlockUserData();
 
     inline TextMarks marks() const { return m_marks; }
@@ -106,6 +120,11 @@ public:
     void setFoldingEndIncluded(bool included) { m_foldingEndIncluded = included; }
     bool foldingEndIncluded() const { return m_foldingEndIncluded; }
 
+    static int lexerState(const QTextBlock &block);
+    static void setLexerState(QTextBlock block, int state);
+
+    CodeFormatterData *codeFormatterData() const { return m_codeFormatterData; }
+    void setCodeFormatterData(CodeFormatterData *data);
 
 private:
     TextMarks m_marks;
@@ -115,6 +134,7 @@ private:
     uint m_foldingStartIncluded : 1;
     uint m_foldingEndIncluded : 1;
     Parentheses m_parentheses;
+    CodeFormatterData *m_codeFormatterData;
 };
 
 
diff --git a/tests/auto/cplusplus/codeformatter/codeformatter.pro b/tests/auto/cplusplus/codeformatter/codeformatter.pro
new file mode 100644
index 0000000000000000000000000000000000000000..de80180f9f67b70aa54f31bec59e5d9482e0e551
--- /dev/null
+++ b/tests/auto/cplusplus/codeformatter/codeformatter.pro
@@ -0,0 +1,19 @@
+TEMPLATE = app
+CONFIG += qt warn_on console depend_includepath
+QT += testlib
+
+include(../shared/shared.pri)
+
+SRCDIR = ../../../../src
+
+SOURCES += \
+    tst_codeformatter.cpp \
+    $$SRCDIR/plugins/cpptools/cppcodeformatter.cpp \
+    $$SRCDIR/plugins/texteditor/basetextdocumentlayout.cpp
+
+HEADERS += \
+    $$SRCDIR/plugins/texteditor/basetextdocumentlayout.h
+
+INCLUDEPATH += $$SRCDIR/plugins $$SRCDIR/libs
+
+TARGET=tst_$$TARGET
diff --git a/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7082c21b94f14218302d10d8c9d428a2ac1bd70d
--- /dev/null
+++ b/tests/auto/cplusplus/codeformatter/tst_codeformatter.cpp
@@ -0,0 +1,695 @@
+#include <QtTest>
+#include <QObject>
+#include <QList>
+#include <QTextDocument>
+#include <QTextBlock>
+
+#include <cpptools/cppcodeformatter.h>
+using namespace CppTools;
+
+class tst_CodeFormatter: public QObject
+{
+    Q_OBJECT
+
+private Q_SLOTS:
+    void ifStatementWithoutBraces1();
+    void ifStatementWithoutBraces2();
+    void ifStatementWithBraces1();
+    void ifStatementWithBraces2();
+    void ifStatementMixed();
+    void ifStatementAndComments();
+    void ifStatementLongCondition();
+    void strayElse();
+    void macrosNoSemicolon();
+    void oneLineIf();
+    void doWhile();
+    void closingCurlies();
+    void ifdefedInsideIf();
+    void ifdefs();
+    void preprocessorContinuation();
+    void cStyleComments();
+    void cppStyleComments();
+    void expressionContinuation();
+    void classAccess();
+    void ternary();
+    void objcAtDeclarations();
+    void braceList();
+    void bug1();
+    void bug2();
+    void switch1();
+    void memberInitializer();
+    void templates();
+    void operatorOverloads();
+};
+
+struct Line {
+    Line(QString l)
+        : line(l)
+    {
+        for (int i = 0; i < l.size(); ++i) {
+            if (!l.at(i).isSpace()) {
+                expectedIndent = i;
+                return;
+            }
+        }
+        expectedIndent = l.size();
+    }
+
+    Line(QString l, int expect)
+        : line(l), expectedIndent(expect)
+    {}
+
+    QString line;
+    int expectedIndent;
+};
+
+QString concatLines(QList<Line> lines)
+{
+    QString result;
+    foreach (const Line &l, lines) {
+        result += l.line;
+        result += "\n";
+    }
+    return result;
+}
+
+void checkIndent(QList<Line> data)
+{
+    QString text = concatLines(data);
+    QTextDocument document(text);
+    QtStyleCodeFormatter formatter;
+    formatter.setDocument(&document);
+
+    int i = 0;
+    foreach (const Line &l, data) {
+        if (l.expectedIndent != -1) {
+            int actualIndent = formatter.indentFor(document.findBlockByLineNumber(i));
+            if (actualIndent != l.expectedIndent) {
+                QFAIL(QString("Wrong indent in line %1 with text '%2', expected indent %3, got %4").arg(
+                        QString::number(i+1), l.line, QString::number(l.expectedIndent), QString::number(actualIndent)).toLatin1().constData());
+            }
+        }
+        ++i;
+    }
+}
+
+void tst_CodeFormatter::ifStatementWithoutBraces1()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    if (a)")
+         << Line("        if (b)")
+         << Line("            foo;")
+         << Line("        else if (c)")
+         << Line("            foo;")
+         << Line("        else")
+         << Line("            if (d)")
+         << Line("                foo;")
+         << Line("            else")
+         << Line("                while (e)")
+         << Line("                    bar;")
+         << Line("    else")
+         << Line("        foo;")         
+         << Line("}")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::ifStatementWithoutBraces2()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    if (a)")
+         << Line("        if (b)")
+         << Line("            foo;")
+         << Line("    if (a) b();")
+         << Line("    if (a) b(); else")
+         << Line("        foo;")
+         << Line("    if (a)")
+         << Line("        if (b)")
+         << Line("            foo;")
+         << Line("        else if (c)")
+         << Line("            foo;")
+         << Line("        else")
+         << Line("            if (d)")
+         << Line("                foo;")
+         << Line("            else")
+         << Line("                while (e)")
+         << Line("                    bar;")
+         << Line("    else")
+         << Line("        foo;")
+         << Line("}")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::ifStatementWithBraces1()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    if (a) {")
+         << Line("        if (b) {")
+         << Line("            foo;")
+         << Line("        } else if (c) {")
+         << Line("            foo;")
+         << Line("        } else {")
+         << Line("            if (d) {")
+         << Line("                foo;")
+         << Line("            } else {")
+         << Line("                foo;")
+         << Line("            }")
+         << Line("        }")
+         << Line("    } else {")
+         << Line("        foo;")
+         << Line("    }")
+         << Line("}");
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::ifStatementWithBraces2()
+{
+    QList<Line> data;
+    data << Line("void foo()")
+         << Line("{")
+         << Line("    if (a)")
+         << Line("    {")
+         << Line("        if (b)")
+         << Line("        {")
+         << Line("            foo;")
+         << Line("        }")
+         << Line("        else if (c)")
+         << Line("        {")
+         << Line("            foo;")
+         << Line("        }")
+         << Line("        else")
+         << Line("        {")
+         << Line("            if (d)")
+         << Line("            {")
+         << Line("                foo;")
+         << Line("            }")
+         << Line("            else")
+         << Line("            {")
+         << Line("                foo;")
+         << Line("            }")
+         << Line("        }")
+         << Line("    }")
+         << Line("    else")
+         << Line("    {")
+         << Line("        foo;")
+         << Line("    }")
+         << Line("}");
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::ifStatementMixed()
+{
+    QList<Line> data;
+    data << Line("void foo()")
+         << Line("{")
+         << Line("    if (foo)")
+         << Line("        if (bar)")
+         << Line("        {")
+         << Line("            foo;")
+         << Line("        }")
+         << Line("        else")
+         << Line("            if (car)")
+         << Line("            {}")
+         << Line("            else doo;")
+         << Line("    else abc;")
+         << Line("}");
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::ifStatementAndComments()
+{
+    QList<Line> data;
+    data << Line("void foo()")
+         << Line("{")
+         << Line("    if (foo)")
+         << Line("        ; // bla")
+         << Line("    else if (bar)")
+         << Line("        ;")
+         << Line("    if (foo)")
+         << Line("        ; /* bla")
+         << Line("      bla */")
+         << Line("    else if (bar)")
+         << Line("        // foobar")
+         << Line("        ;")
+         << Line("    else if (bar)")
+         << Line("        /* bla")
+         << Line("  bla */")
+         << Line("        ;")
+         << Line("}");
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::ifStatementLongCondition()
+{
+    QList<Line> data;
+    data << Line("void foo()")
+         << Line("{")
+         << Line("    if (foo &&")
+         << Line("            bar")
+         << Line("            || (a + b > 4")
+         << Line("                && foo(bar)")
+         << Line("                )")
+         << Line("    ) {")
+         << Line("        foo;")
+         << Line("    }")
+         << Line("}");
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::strayElse()
+{
+    QList<Line> data;
+    data << Line("void foo()")
+         << Line("{")
+         << Line("    while( true ) {}")
+         << Line("    else", -1)
+         << Line("    else {", -1)
+         << Line("    }", -1)
+         << Line("}");
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::macrosNoSemicolon()
+{
+    QList<Line> data;
+    data << Line("QT_DECLARE_METATYPE(foo)")
+         << Line("int i;")
+         << Line("Q_BLABLA")
+         << Line("int i;")
+         << Line("Q_BLABLA;")
+         << Line("int i;")
+         << Line("Q_BLABLA();")
+         << Line("int i;")
+         << Line("Q_PROPERTY(abc)")
+         << Line("QDOC_PROPERTY(abc)")
+         << Line("void foo() {")
+         << Line("    QT_DECLARE_METATYPE(foo)")
+         << Line("    int i;")
+         << Line("    Q_BLABLA")
+         << Line("    int i;")
+         << Line("    Q_BLABLA;")
+         << Line("    int i;")
+         << Line("    Q_BLABLA();")
+         << Line("    Q_PROPERTY(abc)")
+         << Line("    QDOC_PROPERTY(abc)")
+         << Line("    int i;")
+         << Line("}")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::oneLineIf()
+{
+    QList<Line> data;
+    data << Line("class F {")
+         << Line("    void foo()")
+         << Line("    { if (showIt) show(); }")
+         << Line("};")
+         ;
+    checkIndent(data);
+
+}
+
+void tst_CodeFormatter::doWhile()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    do { if (c) foo; } while(a);")
+         << Line("    do {")
+         << Line("        if(a);")
+         << Line("    } while(a);")
+         << Line("    do")
+         << Line("        foo;")
+         << Line("    while(a);")
+         << Line("    do foo; while(a);")
+         << Line("};")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::closingCurlies()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    if (a)")
+         << Line("        if (b) {")
+         << Line("            foo;")
+         << Line("        }")
+         << Line("    {")
+         << Line("        foo();")
+         << Line("    }")
+         << Line("    foo();")
+         << Line("    {")
+         << Line("        foo();")
+         << Line("    }")
+         << Line("    while (a) {")
+         << Line("        if (a);")
+         << Line("    }")
+         << Line("};")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::ifdefedInsideIf()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    if (a) {")
+         << Line("#ifndef Q_WS_WINCE")
+         << Line("        if (b) {")
+         << Line("#else")
+         << Line("        if (c) {")
+         << Line("#endif")
+         << Line("        }")
+         << Line("    } else if (d) {")
+         << Line("    }")
+         << Line("    if (a)")
+         << Line("        ;")
+         << Line("    else if (type == Qt::Dialog || type == Qt::Sheet)")
+         << Line("#ifndef Q_WS_WINCE")
+         << Line("        flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint | Qt::WindowCloseButtonHint;")
+         << Line("#else")
+         << Line("        bar;")
+         << Line("#endif")
+         << Line("};")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::ifdefs()
+{
+    QList<Line> data;
+    data << Line("#ifdef FOO")
+         << Line("#include <bar>")
+         << Line("void foo()")
+         << Line("{")
+         << Line("    if (bar)")
+         << Line("#if 1")
+         << Line("        foo;")
+         << Line("    else")
+         << Line("#endif")
+         << Line("        foo;")
+         << Line("}")
+         << Line("#endif")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::preprocessorContinuation()
+{
+    QList<Line> data;
+    data << Line("#define x \\")
+         << Line("    foo(x) + \\")
+         << Line("    bar(x)")
+         << Line("int i;")
+         << Line("void foo() {")
+         << Line("#define y y")
+         << Line("#define x \\")
+         << Line("    foo(x) + \\")
+         << Line("    bar(x)")
+         << Line("    int j;")
+         << Line("};")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::cStyleComments()
+{
+    QList<Line> data;
+    data << Line("/*")
+         << Line("  ")
+         << Line("      foo")
+         << Line("      ")
+         << Line("   foo")
+         << Line("   ")
+         << Line("*/")
+         << Line("void foo() {")
+         << Line("    /*")
+         << Line("      ")
+         << Line("   foo")
+         << Line("   ")
+         << Line("    */")
+         << Line("    /* bar */")
+         << Line("}")
+         << Line("struct s {")
+         << Line("    /* foo */")
+         << Line("    /*")
+         << Line("      ")
+         << Line("   foo")
+         << Line("   ")
+         << Line("    */")
+         << Line("    /* bar */")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::cppStyleComments()
+{
+    QList<Line> data;
+    data << Line("// abc")
+         << Line("class C {  ")
+         << Line("    // ghij")
+         << Line("    // def")
+         << Line("    // ghij")
+         << Line("    int i; // hik")
+         << Line("    // doo")
+         << Line("} // ba")
+         << Line("// ba")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::expressionContinuation()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    return (a <= b &&")
+         << Line("            c <= d);")
+         << Line("    return (qMax <= qMin() &&")
+         << Line("            qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));")
+         << Line("    return a")
+         << Line("            == b && c == d;")
+         << Line("    return a ==")
+         << Line("            b && c == d;")
+         << Line("    return a == b")
+         << Line("            && c == d;")
+         << Line("    return a == b &&")
+         << Line("            c == d;")
+         << Line("    return a == b && c")
+         << Line("            == d;")
+         << Line("    return a == b && c ==")
+         << Line("            d;")
+         << Line("    return a == b && c == d;")
+         << Line("    qDebug() << foo")
+         << Line("             << bar << moose")
+         << Line("             << bar +")
+         << Line("                foo - blah(1)")
+         << Line("             << '?'")
+         << Line("             << \"\\n\";")
+         << Line("    i += foo(")
+         << Line("                bar,")
+         << Line("                2);")
+         << Line("}")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::classAccess()
+{
+    QList<Line> data;
+    data << Line("class foo {")
+         << Line("    int i;")
+         << Line("public:")
+         << Line("    class bar {")
+         << Line("    private:")
+         << Line("        int i;")
+         << Line("    public:")
+         << Line("    private slots:")
+         << Line("        void foo();")
+         << Line("    public Q_SLOTS:")
+         << Line("    Q_SIGNALS:")
+         << Line("    };")
+         << Line("    float f;")
+         << Line("private:")
+         << Line("    void bar(){}")
+         << Line("}")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::ternary()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    int i = a ? b : c;")
+         << Line("    foo += a_bigger_condition ?")
+         << Line("                b")
+         << Line("              : c;")
+         << Line("    int i = a ?")
+         << Line("                b : c;")
+         << Line("    int i = a ? b")
+         << Line("              : c +")
+         << Line("                2;")
+         << Line("    int i = (a ? b : c) + (foo")
+         << Line("                           bar);")
+         << Line("}")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::bug1()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    if (attribute < int(8*sizeof(uint))) {")
+         << Line("        if (on)")
+         << Line("            data->widget_attributes |= (1<<attribute);")
+         << Line("        else")
+         << Line("            data->widget_attributes &= ~(1<<attribute);")
+         << Line("    } else {")
+         << Line("        const int x = attribute - 8*sizeof(uint);")
+         << Line("    }")
+         << Line("    int i;")
+         << Line("}")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::bug2()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    const int sourceY = foo(")
+         << Line("                bar(")
+         << Line("                    car(a,")
+         << Line("                        b),")
+         << Line("                    b),")
+         << Line("                foo);")
+         << Line("    const int sourceY =")
+         << Line("            foo(")
+         << Line("                bar(a,")
+         << Line("                    b),")
+         << Line("                b);")
+         << Line("    int j;")
+         << Line("    const int sourceY =")
+         << Line("            (direction == DirectionEast || direction == DirectionWest) ?")
+         << Line("                (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2)")
+         << Line("              : (direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top());")
+         << Line("}")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::braceList()
+{
+    QList<Line> data;
+    data << Line("enum Foo {")
+         << Line("    a,")
+         << Line("    b,")
+         << Line("};")
+         << Line("void foo () {")
+         << Line("    int[] a = { foo, bar, ")
+         << Line("            car };")
+         << Line("    int k;")
+         ;
+    checkIndent(data);
+
+}
+
+void tst_CodeFormatter::objcAtDeclarations()
+{
+    QList<Line> data;
+    data << Line("@class Forwarded;")
+         << Line("@protocol Forwarded;")
+         << Line("int i;")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::switch1()
+{
+    QList<Line> data;
+    data << Line("void foo() {")
+         << Line("    switch (a) {")
+         << Line("    case 1:")
+         << Line("        foo;")
+         << Line("        if (a);")
+         << Line("    case 2:")
+         << Line("    case 3: {")
+         << Line("        foo;")
+         << Line("    }")
+         << Line("    case 4:")
+         << Line("    {")
+         << Line("        foo;")
+         << Line("    }")
+         << Line("    case bar:")
+         << Line("        break;")
+         << Line("    }")
+         << Line("    case 4:")
+         << Line("    {")
+         << Line("        if (a) {")
+         << Line("        }")
+         << Line("    }")
+         << Line("}")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::memberInitializer()
+{
+    QList<Line> data;
+    data << Line("void foo()")
+         << Line("    : baR()")
+         << Line("    , m_member(23)")
+         << Line("{")
+         << Line("}")
+         << Line("class Foo {")
+         << Line("    Foo()")
+         << Line("        : baR(),")
+         << Line("          moo(barR)")
+         << Line("    {}")
+         << Line("}")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::templates()
+{
+    QList<Line> data;
+    data << Line("template <class T, typename F, int i>")
+         << Line("class Foo {")
+         << Line("private:")
+         << Line("};")
+         << Line("template <class T,")
+         << Line("          typename F, int i")
+         << Line("          >")
+         << Line("class Foo {")
+         << Line("private:")
+         << Line("};")
+         ;
+    checkIndent(data);
+}
+
+void tst_CodeFormatter::operatorOverloads()
+{
+    QList<Line> data;
+    data << Line("struct S {")
+         << Line("    void operator()() {")
+         << Line("        foo;")
+         << Line("    }")
+         << Line("    void operator<<() {")
+         << Line("        foo;")
+         << Line("    }")
+         << Line("};")
+         ;
+    checkIndent(data);
+}
+
+QTEST_APPLESS_MAIN(tst_CodeFormatter)
+#include "tst_codeformatter.moc"
+
+
diff --git a/tests/auto/cplusplus/cplusplus.pro b/tests/auto/cplusplus/cplusplus.pro
index 5b80ab98e063df1ab8e4b581d1202f4ac9ff777f..947a140b4e0c9db3ba13bf30b13528ccb7c85f18 100644
--- a/tests/auto/cplusplus/cplusplus.pro
+++ b/tests/auto/cplusplus/cplusplus.pro
@@ -1,3 +1,3 @@
 TEMPLATE = subdirs
-SUBDIRS = shared ast semantic lookup preprocessor findusages typeprettyprinter
+SUBDIRS = shared ast semantic lookup preprocessor findusages typeprettyprinter codeformatter
 CONFIG += ordered