forked from qt-creator/qt-creator
		
	QmlJS indenter: Move reusable code to qmljs lib.
Change-Id: I5ab50b586109a9736cda48245807571ce10dfb5b Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com>
This commit is contained in:
		@@ -989,3 +989,320 @@ void CodeFormatter::dump() const
 | 
			
		||||
    }
 | 
			
		||||
    qDebug() << "Current indent depth:" << m_indentDepth;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QtStyleCodeFormatter::QtStyleCodeFormatter()
 | 
			
		||||
    : m_indentSize(4)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
void QtStyleCodeFormatter::setIndentSize(int size)
 | 
			
		||||
{
 | 
			
		||||
    m_indentSize = size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedIndentDepth) const
 | 
			
		||||
{
 | 
			
		||||
    const State &parentState = state();
 | 
			
		||||
    const Token &tk = currentToken();
 | 
			
		||||
    const int tokenPosition = column(tk.begin());
 | 
			
		||||
    const bool firstToken = (tokenIndex() == 0);
 | 
			
		||||
    const bool lastToken = (tokenIndex() == tokenCount() - 1);
 | 
			
		||||
 | 
			
		||||
    switch (newState) {
 | 
			
		||||
    case objectdefinition_open: {
 | 
			
		||||
        // special case for things like "gradient: Gradient {"
 | 
			
		||||
        if (parentState.type == binding_assignment)
 | 
			
		||||
            *savedIndentDepth = state(1).savedIndentDepth;
 | 
			
		||||
 | 
			
		||||
        if (firstToken)
 | 
			
		||||
            *savedIndentDepth = tokenPosition;
 | 
			
		||||
 | 
			
		||||
        *indentDepth = *savedIndentDepth + m_indentSize;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case binding_or_objectdefinition:
 | 
			
		||||
        if (firstToken)
 | 
			
		||||
            *indentDepth = *savedIndentDepth = tokenPosition;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case binding_assignment:
 | 
			
		||||
    case objectliteral_assignment:
 | 
			
		||||
        if (lastToken)
 | 
			
		||||
            *indentDepth = *savedIndentDepth + 4;
 | 
			
		||||
        else
 | 
			
		||||
            *indentDepth = column(tokenAt(tokenIndex() + 1).begin());
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case expression_or_objectdefinition:
 | 
			
		||||
        *indentDepth = tokenPosition;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case expression_or_label:
 | 
			
		||||
        if (*indentDepth == tokenPosition)
 | 
			
		||||
            *indentDepth += 2*m_indentSize;
 | 
			
		||||
        else
 | 
			
		||||
            *indentDepth = tokenPosition;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case expression:
 | 
			
		||||
        if (*indentDepth == tokenPosition) {
 | 
			
		||||
            // expression_or_objectdefinition doesn't want the indent
 | 
			
		||||
            // expression_or_label already has it
 | 
			
		||||
            if (parentState.type != expression_or_objectdefinition
 | 
			
		||||
                    && parentState.type != expression_or_label
 | 
			
		||||
                    && parentState.type != binding_assignment) {
 | 
			
		||||
                *indentDepth += 2*m_indentSize;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // expression_or_objectdefinition and expression_or_label have already consumed the first token
 | 
			
		||||
        else if (parentState.type != expression_or_objectdefinition
 | 
			
		||||
                 && parentState.type != expression_or_label) {
 | 
			
		||||
            *indentDepth = tokenPosition;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case expression_maybe_continuation:
 | 
			
		||||
        // set indent depth to indent we'd get if the expression ended here
 | 
			
		||||
        for (int i = 1; state(i).type != topmost_intro; ++i) {
 | 
			
		||||
            const int type = state(i).type;
 | 
			
		||||
            if (isExpressionEndState(type) && !isBracelessState(type)) {
 | 
			
		||||
                *indentDepth = state(i - 1).savedIndentDepth;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case bracket_open:
 | 
			
		||||
        if (parentState.type == expression && state(1).type == binding_assignment) {
 | 
			
		||||
            *savedIndentDepth = state(2).savedIndentDepth;
 | 
			
		||||
            *indentDepth = *savedIndentDepth + m_indentSize;
 | 
			
		||||
        } else if (parentState.type == objectliteral_assignment) {
 | 
			
		||||
            *savedIndentDepth = parentState.savedIndentDepth;
 | 
			
		||||
            *indentDepth = *savedIndentDepth + m_indentSize;
 | 
			
		||||
        } else if (!lastToken) {
 | 
			
		||||
            *indentDepth = tokenPosition + 1;
 | 
			
		||||
        } else {
 | 
			
		||||
            *indentDepth = *savedIndentDepth + m_indentSize;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case function_start:
 | 
			
		||||
        if (parentState.type == expression) {
 | 
			
		||||
            // undo the continuation indent of the expression
 | 
			
		||||
            *indentDepth = parentState.savedIndentDepth;
 | 
			
		||||
            *savedIndentDepth = *indentDepth;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case do_statement_while_paren_open:
 | 
			
		||||
    case statement_with_condition_paren_open:
 | 
			
		||||
    case signal_arglist_open:
 | 
			
		||||
    case function_arglist_open:
 | 
			
		||||
    case paren_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 jsblock_open:
 | 
			
		||||
        // closing brace should be aligned to case
 | 
			
		||||
        if (parentState.type == case_cont) {
 | 
			
		||||
            *savedIndentDepth = parentState.savedIndentDepth;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        // fallthrough
 | 
			
		||||
    case substatement_open:
 | 
			
		||||
        // special case for "foo: {" and "property int foo: {"
 | 
			
		||||
        if (parentState.type == binding_assignment)
 | 
			
		||||
            *savedIndentDepth = state(1).savedIndentDepth;
 | 
			
		||||
        *indentDepth = *savedIndentDepth + m_indentSize;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case substatement:
 | 
			
		||||
        *indentDepth += m_indentSize;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case objectliteral_open:
 | 
			
		||||
        if (parentState.type == expression
 | 
			
		||||
                || parentState.type == objectliteral_assignment) {
 | 
			
		||||
            // undo the continuation indent of the expression
 | 
			
		||||
            if (state(1).type == expression_or_label)
 | 
			
		||||
                *indentDepth = state(1).savedIndentDepth;
 | 
			
		||||
            else
 | 
			
		||||
                *indentDepth = parentState.savedIndentDepth;
 | 
			
		||||
            *savedIndentDepth = *indentDepth;
 | 
			
		||||
        }
 | 
			
		||||
        *indentDepth += m_indentSize;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    case statement_with_condition:
 | 
			
		||||
    case statement_with_block:
 | 
			
		||||
    case if_statement:
 | 
			
		||||
    case do_statement:
 | 
			
		||||
    case switch_statement:
 | 
			
		||||
        if (firstToken || parentState.type == binding_assignment)
 | 
			
		||||
            *savedIndentDepth = tokenPosition;
 | 
			
		||||
        // ### continuation
 | 
			
		||||
        *indentDepth = *savedIndentDepth; // + 2*m_indentSize;
 | 
			
		||||
        // special case for 'else if'
 | 
			
		||||
        if (!firstToken
 | 
			
		||||
                && newState == if_statement
 | 
			
		||||
                && parentState.type == substatement
 | 
			
		||||
                && state(1).type == else_clause) {
 | 
			
		||||
            *indentDepth = state(1).savedIndentDepth;
 | 
			
		||||
            *savedIndentDepth = *indentDepth;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case maybe_else: {
 | 
			
		||||
        // set indent to outermost braceless savedIndent
 | 
			
		||||
        int outermostBraceless = 0;
 | 
			
		||||
        while (isBracelessState(state(outermostBraceless + 1).type))
 | 
			
		||||
            ++outermostBraceless;
 | 
			
		||||
        *indentDepth = state(outermostBraceless).savedIndentDepth;
 | 
			
		||||
        // this is where the else should go, if one appears - aligned to if_statement
 | 
			
		||||
        *savedIndentDepth = state().savedIndentDepth;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case condition_open:
 | 
			
		||||
        // 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 case_start:
 | 
			
		||||
        *savedIndentDepth = tokenPosition;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case case_cont:
 | 
			
		||||
        *indentDepth += m_indentSize;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case multiline_comment_start:
 | 
			
		||||
        *indentDepth = tokenPosition + 2;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case multiline_comment_cont:
 | 
			
		||||
        *indentDepth = tokenPosition;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QtStyleCodeFormatter::adjustIndent(const QList<Token> &tokens, int lexerState, int *indentDepth) const
 | 
			
		||||
{
 | 
			
		||||
    Q_UNUSED(lexerState)
 | 
			
		||||
 | 
			
		||||
    State topState = state();
 | 
			
		||||
    State previousState = state(1);
 | 
			
		||||
 | 
			
		||||
    // keep user-adjusted indent in multiline comments
 | 
			
		||||
    if (topState.type == multiline_comment_start
 | 
			
		||||
            || topState.type == multiline_comment_cont) {
 | 
			
		||||
        if (!tokens.isEmpty()) {
 | 
			
		||||
            *indentDepth = column(tokens.at(0).begin());
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const int kind = extendedTokenKind(tokenAt(0));
 | 
			
		||||
    switch (kind) {
 | 
			
		||||
    case LeftBrace:
 | 
			
		||||
        if (topState.type == substatement
 | 
			
		||||
                || topState.type == binding_assignment
 | 
			
		||||
                || topState.type == case_cont) {
 | 
			
		||||
            *indentDepth = topState.savedIndentDepth;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case RightBrace: {
 | 
			
		||||
        if (topState.type == jsblock_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 == objectdefinition_open
 | 
			
		||||
                    || type == jsblock_open
 | 
			
		||||
                    || type == substatement_open
 | 
			
		||||
                    || type == objectliteral_open) {
 | 
			
		||||
                *indentDepth = state(i).savedIndentDepth;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case RightBracket:
 | 
			
		||||
        for (int i = 0; state(i).type != topmost_intro; ++i) {
 | 
			
		||||
            const int type = state(i).type;
 | 
			
		||||
            if (type == bracket_open) {
 | 
			
		||||
                *indentDepth = state(i).savedIndentDepth;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case LeftBracket:
 | 
			
		||||
    case LeftParenthesis:
 | 
			
		||||
    case Delimiter:
 | 
			
		||||
        if (topState.type == expression_maybe_continuation)
 | 
			
		||||
            *indentDepth = topState.savedIndentDepth;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case Else:
 | 
			
		||||
        if (topState.type == maybe_else) {
 | 
			
		||||
            *indentDepth = topState.savedIndentDepth;
 | 
			
		||||
        } else if (topState.type == expression_maybe_continuation) {
 | 
			
		||||
            bool hasElse = false;
 | 
			
		||||
            for (int i = 1; state(i).type != topmost_intro; ++i) {
 | 
			
		||||
                const int type = state(i).type;
 | 
			
		||||
                if (type == else_clause)
 | 
			
		||||
                    hasElse = true;
 | 
			
		||||
                if (type == if_statement) {
 | 
			
		||||
                    if (hasElse) {
 | 
			
		||||
                        hasElse = false;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        *indentDepth = state(i).savedIndentDepth;
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case Colon:
 | 
			
		||||
        if (topState.type == ternary_op) {
 | 
			
		||||
            *indentDepth -= 2;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case Question:
 | 
			
		||||
        if (topState.type == expression_maybe_continuation)
 | 
			
		||||
            *indentDepth = topState.savedIndentDepth;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case Default:
 | 
			
		||||
    case 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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user