forked from qt-creator/qt-creator
QmlJS indenter: Fix braceless switch/try/with bindings.
Change-Id: Iee25f3f9ec38b1b7fc2697f390386c9a60cb8347 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
This commit is contained in:
@@ -156,6 +156,9 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
switch (kind) {
|
||||
case Semicolon: leave(true); break;
|
||||
case If: enter(if_statement); break;
|
||||
case With: enter(statement_with_condition); break;
|
||||
case Try: enter(try_statement); break;
|
||||
case Switch: enter(switch_statement); break;
|
||||
case LeftBrace: enter(jsblock_open); break;
|
||||
case On:
|
||||
case As:
|
||||
@@ -377,14 +380,18 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
} break;
|
||||
|
||||
case maybe_else:
|
||||
if (kind == Else) {
|
||||
turnInto(else_clause);
|
||||
enter(substatement);
|
||||
break;
|
||||
} else {
|
||||
leave(true);
|
||||
continue;
|
||||
}
|
||||
switch (kind) {
|
||||
case Else: turnInto(else_clause); enter(substatement); break;
|
||||
default: leave(true); continue;
|
||||
} break;
|
||||
|
||||
case maybe_catch_or_finally:
|
||||
dump();
|
||||
switch (kind) {
|
||||
case Catch: turnInto(catch_statement); break;
|
||||
case Finally: turnInto(finally_statement); break;
|
||||
default: leave(true); continue;
|
||||
} break;
|
||||
|
||||
case else_clause:
|
||||
// ### shouldn't happen
|
||||
@@ -407,6 +414,7 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
} break;
|
||||
|
||||
case switch_statement:
|
||||
case catch_statement:
|
||||
case statement_with_condition:
|
||||
switch (kind) {
|
||||
case LeftParenthesis: enter(statement_with_condition_paren_open); break;
|
||||
@@ -420,7 +428,8 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
||||
case RightParenthesis: turnInto(substatement); break;
|
||||
} break;
|
||||
|
||||
case statement_with_block:
|
||||
case try_statement:
|
||||
case finally_statement:
|
||||
switch (kind) {
|
||||
case LeftBrace: enter(jsblock_open); break;
|
||||
default: leave(true); break;
|
||||
@@ -633,6 +642,8 @@ void CodeFormatter::enter(int newState)
|
||||
m_currentState.push(s);
|
||||
m_newStates.push(s);
|
||||
|
||||
//qDebug() << "enter state" << stateToString(newState);
|
||||
|
||||
if (newState == bracket_open)
|
||||
enter(bracket_element_start);
|
||||
}
|
||||
@@ -652,10 +663,10 @@ void CodeFormatter::leave(bool statementDone)
|
||||
|
||||
int topState = m_currentState.top().type;
|
||||
|
||||
//qDebug() << "left state" << stateToString(poppedState.type) << ", now in state" << stateToString(topState);
|
||||
|
||||
// if statement is done, may need to leave recursively
|
||||
if (statementDone) {
|
||||
if (!isExpressionEndState(topState))
|
||||
leave(true);
|
||||
if (topState == if_statement) {
|
||||
if (poppedState.type != maybe_else)
|
||||
enter(maybe_else);
|
||||
@@ -665,6 +676,15 @@ void CodeFormatter::leave(bool statementDone)
|
||||
// leave the else *and* the surrounding if, to prevent another else
|
||||
leave();
|
||||
leave(true);
|
||||
} else if (topState == try_statement) {
|
||||
if (poppedState.type != maybe_catch_or_finally
|
||||
&& poppedState.type != finally_statement) {
|
||||
enter(maybe_catch_or_finally);
|
||||
} else {
|
||||
leave(true);
|
||||
}
|
||||
} else if (!isExpressionEndState(topState)) {
|
||||
leave(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -740,8 +760,7 @@ bool CodeFormatter::tryStatement()
|
||||
enter(case_start);
|
||||
return true;
|
||||
case Try:
|
||||
case Finally:
|
||||
enter(statement_with_block);
|
||||
enter(try_statement);
|
||||
return true;
|
||||
case LeftBrace:
|
||||
enter(jsblock_open);
|
||||
@@ -787,9 +806,7 @@ bool CodeFormatter::isExpressionEndState(int type) const
|
||||
type == topmost_intro ||
|
||||
type == top_js ||
|
||||
type == objectdefinition_open ||
|
||||
type == if_statement ||
|
||||
type == do_statement ||
|
||||
type == else_clause ||
|
||||
type == jsblock_open ||
|
||||
type == substatement_open ||
|
||||
type == bracket_open ||
|
||||
@@ -988,16 +1005,20 @@ CodeFormatter::TokenKind CodeFormatter::extendedTokenKind(const QmlJS::Token &to
|
||||
|
||||
void CodeFormatter::dump() const
|
||||
{
|
||||
QMetaEnum metaEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("StateType"));
|
||||
|
||||
qDebug() << "Current token index" << m_tokenIndex;
|
||||
qDebug() << "Current state:";
|
||||
foreach (const State &s, m_currentState) {
|
||||
qDebug() << metaEnum.valueToKey(s.type) << s.savedIndentDepth;
|
||||
qDebug() << stateToString(s.type) << s.savedIndentDepth;
|
||||
}
|
||||
qDebug() << "Current indent depth:" << m_indentDepth;
|
||||
}
|
||||
|
||||
QString CodeFormatter::stateToString(int type) const
|
||||
{
|
||||
const QMetaEnum &metaEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("StateType"));
|
||||
return metaEnum.valueToKey(type);
|
||||
}
|
||||
|
||||
QtStyleCodeFormatter::QtStyleCodeFormatter()
|
||||
: m_indentSize(4)
|
||||
{}
|
||||
@@ -1158,7 +1179,9 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
|
||||
|
||||
|
||||
case statement_with_condition:
|
||||
case statement_with_block:
|
||||
case try_statement:
|
||||
case catch_statement:
|
||||
case finally_statement:
|
||||
case if_statement:
|
||||
case do_statement:
|
||||
case switch_statement:
|
||||
@@ -1176,14 +1199,13 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
|
||||
}
|
||||
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;
|
||||
case maybe_else:
|
||||
case maybe_catch_or_finally: {
|
||||
// set indent to where leave(true) would put it
|
||||
int lastNonEndState = 0;
|
||||
while (!isExpressionEndState(state(lastNonEndState + 1).type))
|
||||
++lastNonEndState;
|
||||
*indentDepth = state(lastNonEndState).savedIndentDepth;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1278,7 +1300,7 @@ void QtStyleCodeFormatter::adjustIndent(const QList<Token> &tokens, int startLex
|
||||
|
||||
case Else:
|
||||
if (topState.type == maybe_else) {
|
||||
*indentDepth = topState.savedIndentDepth;
|
||||
*indentDepth = state(1).savedIndentDepth;
|
||||
} else if (topState.type == expression_maybe_continuation) {
|
||||
bool hasElse = false;
|
||||
for (int i = 1; state(i).type != topmost_intro; ++i) {
|
||||
@@ -1297,6 +1319,12 @@ void QtStyleCodeFormatter::adjustIndent(const QList<Token> &tokens, int startLex
|
||||
}
|
||||
break;
|
||||
|
||||
case Catch:
|
||||
case Finally:
|
||||
if (topState.type == maybe_catch_or_finally)
|
||||
*indentDepth = state(1).savedIndentDepth;
|
||||
break;
|
||||
|
||||
case Colon:
|
||||
if (topState.type == ternary_op) {
|
||||
*indentDepth -= 2;
|
||||
|
||||
@@ -167,10 +167,13 @@ public: // must be public to make Q_GADGET introspection work
|
||||
return_statement, // After 'return'
|
||||
throw_statement, // After 'throw'
|
||||
|
||||
statement_with_condition, // After the 'for', 'while', 'catch', ... token
|
||||
statement_with_condition, // After the 'for', 'while', ... token
|
||||
statement_with_condition_paren_open, // While inside the (...)
|
||||
|
||||
statement_with_block, // try, finally
|
||||
try_statement, // after 'try'
|
||||
catch_statement, // after 'catch', nested in try_statement
|
||||
finally_statement, // after 'finally', nested in try_statement
|
||||
maybe_catch_or_finally, // after ther closing '}' of try_statement and catch_statement, nested in try_statement
|
||||
|
||||
do_statement, // after 'do'
|
||||
do_statement_while_paren_open, // after '(' in while clause
|
||||
@@ -278,6 +281,7 @@ protected:
|
||||
bool isExpressionEndState(int type) const;
|
||||
|
||||
void dump() const;
|
||||
QString stateToString(int type) const;
|
||||
|
||||
private:
|
||||
void recalculateStateAfter(const QTextBlock &block);
|
||||
|
||||
@@ -61,6 +61,11 @@ private Q_SLOTS:
|
||||
void ifBinding1();
|
||||
void ifBinding2();
|
||||
void ifBinding3();
|
||||
void withBinding();
|
||||
void tryBinding1();
|
||||
void tryBinding2();
|
||||
void tryBinding3();
|
||||
void switchBinding();
|
||||
void ifStatementWithoutBraces1();
|
||||
void ifStatementWithoutBraces2();
|
||||
void ifStatementWithoutBraces3();
|
||||
@@ -98,7 +103,6 @@ private Q_SLOTS:
|
||||
void labelledStatements3();
|
||||
void json1();
|
||||
void multilineTernaryInProperty();
|
||||
void bug1();
|
||||
void multilineString();
|
||||
void bug1();
|
||||
};
|
||||
@@ -538,6 +542,108 @@ void tst_QMLCodeFormatter::ifBinding3()
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_QMLCodeFormatter::withBinding()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("Rectangle {")
|
||||
<< Line(" foo: with(pos) { x }")
|
||||
<< Line(" foo: with(pos) {")
|
||||
<< Line(" x")
|
||||
<< Line(" }")
|
||||
<< Line(" foo: 12")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_QMLCodeFormatter::tryBinding1()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("Rectangle {")
|
||||
<< Line(" foo: try { x } finally { y }")
|
||||
<< Line(" foo: try {")
|
||||
<< Line(" x")
|
||||
<< Line(" } finally {")
|
||||
<< Line(" y")
|
||||
<< Line(" }")
|
||||
<< Line(" foo: try {")
|
||||
<< Line(" x")
|
||||
<< Line(" }")
|
||||
<< Line(" finally {")
|
||||
<< Line(" y")
|
||||
<< Line(" }")
|
||||
<< Line(" foo: 12")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_QMLCodeFormatter::tryBinding2()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("Rectangle {")
|
||||
<< Line(" foo: try { x } catch (x) { y }")
|
||||
<< Line(" foo: try {")
|
||||
<< Line(" x")
|
||||
<< Line(" } catch (e) {")
|
||||
<< Line(" e")
|
||||
<< Line(" }")
|
||||
<< Line(" foo: try {")
|
||||
<< Line(" x")
|
||||
<< Line(" }")
|
||||
<< Line(" catch (e) {")
|
||||
<< Line(" e")
|
||||
<< Line(" }")
|
||||
<< Line(" foo: 12")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_QMLCodeFormatter::tryBinding3()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("Rectangle {")
|
||||
<< Line(" foo: try { x } catch (x) { y } finally { z }")
|
||||
<< Line(" foo: try {")
|
||||
<< Line(" x")
|
||||
<< Line(" } catch (e) {")
|
||||
<< Line(" e")
|
||||
<< Line(" } finally {")
|
||||
<< Line(" z")
|
||||
<< Line(" }")
|
||||
<< Line(" foo: try {")
|
||||
<< Line(" x")
|
||||
<< Line(" }")
|
||||
<< Line(" catch (e) {")
|
||||
<< Line(" e")
|
||||
<< Line(" }")
|
||||
<< Line(" finally {")
|
||||
<< Line(" z")
|
||||
<< Line(" }")
|
||||
<< Line(" foo: 12")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_QMLCodeFormatter::switchBinding()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("Rectangle {")
|
||||
<< Line(" foo: switch (a) {")
|
||||
<< Line(" case 1:")
|
||||
<< Line(" x; break")
|
||||
<< Line(" case 2:")
|
||||
<< Line(" case 3:")
|
||||
<< Line(" return y")
|
||||
<< Line(" }")
|
||||
<< Line(" foo: 12")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_QMLCodeFormatter::ifStatementWithoutBraces1()
|
||||
{
|
||||
QList<Line> data;
|
||||
@@ -1301,20 +1407,6 @@ void tst_QMLCodeFormatter::multilineTernaryInProperty()
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_QMLCodeFormatter::bug1()
|
||||
{
|
||||
QList<Line> data;
|
||||
data << Line("Item {")
|
||||
<< Line(" x: {")
|
||||
<< Line(" if (a==a) {}")
|
||||
<< Line(" else (b==b) {}")
|
||||
<< Line(" foo()")
|
||||
<< Line(" }")
|
||||
<< Line("}")
|
||||
;
|
||||
checkIndent(data);
|
||||
}
|
||||
|
||||
void tst_QMLCodeFormatter::multilineString()
|
||||
{
|
||||
QList<Line> data;
|
||||
|
||||
Reference in New Issue
Block a user