diff options
author | Christian Kamm <christian.d.kamm@nokia.com> | 2011-10-17 13:56:48 +0200 |
---|---|---|
committer | Christian Kamm <christian.d.kamm@nokia.com> | 2011-10-19 08:33:21 +0200 |
commit | 4a487b1addb1a2be1b66c1b5ccaf3afc45b7f64c (patch) | |
tree | 1f7f79fd4f61daeee6b3d66dd64aa52992152016 /src/libs/qmljs/qmljscodeformatter.cpp | |
parent | 6f613bc2f17cd7ea3558e1179e41a16be5fd33e0 (diff) | |
download | qt-creator-4a487b1addb1a2be1b66c1b5ccaf3afc45b7f64c.tar.gz |
QmlJS indenter: Move reusable code to qmljs lib.
Change-Id: I5ab50b586109a9736cda48245807571ce10dfb5b
Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com>
Diffstat (limited to 'src/libs/qmljs/qmljscodeformatter.cpp')
-rw-r--r-- | src/libs/qmljs/qmljscodeformatter.cpp | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/src/libs/qmljs/qmljscodeformatter.cpp b/src/libs/qmljs/qmljscodeformatter.cpp index d8a4fb1ed1..5bbc32cf4f 100644 --- a/src/libs/qmljs/qmljscodeformatter.cpp +++ b/src/libs/qmljs/qmljscodeformatter.cpp @@ -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; + } +} |