summaryrefslogtreecommitdiff
path: root/src/libs/qmljs/qmljscodeformatter.cpp
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2011-10-17 13:56:48 +0200
committerChristian Kamm <christian.d.kamm@nokia.com>2011-10-19 08:33:21 +0200
commit4a487b1addb1a2be1b66c1b5ccaf3afc45b7f64c (patch)
tree1f7f79fd4f61daeee6b3d66dd64aa52992152016 /src/libs/qmljs/qmljscodeformatter.cpp
parent6f613bc2f17cd7ea3558e1179e41a16be5fd33e0 (diff)
downloadqt-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.cpp317
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;
+ }
+}