Skip to content
Snippets Groups Projects
cppcodeformatter.cpp 33.8 KiB
Newer Older
        *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: {
        if (topState.type == case_cont) {
            *indentDepth = topState.savedIndentDepth;
        // function definition - argument list is expression state
        } else if (topState.type == expression && previousState.type == declaration_start) {
            *indentDepth = previousState.savedIndentDepth;
            if (m_indentDeclarationBraces)
                *indentDepth += m_indentSize;
        } else if (topState.type == class_start) {
            *indentDepth = topState.savedIndentDepth;
            if (m_indentDeclarationBraces)
                *indentDepth += m_indentSize;
        } else if (topState.type == substatement) {
            *indentDepth = topState.savedIndentDepth;
            if (m_indentSubstatementBraces)
                *indentDepth += m_indentSize;
        } else if (topState.type != defun_open
                && topState.type != block_open
            *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
                    || type == enum_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;
    }
}