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) {
|
switch (kind) {
|
||||||
case Semicolon: leave(true); break;
|
case Semicolon: leave(true); break;
|
||||||
case If: enter(if_statement); 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 LeftBrace: enter(jsblock_open); break;
|
||||||
case On:
|
case On:
|
||||||
case As:
|
case As:
|
||||||
@@ -377,14 +380,18 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case maybe_else:
|
case maybe_else:
|
||||||
if (kind == Else) {
|
switch (kind) {
|
||||||
turnInto(else_clause);
|
case Else: turnInto(else_clause); enter(substatement); break;
|
||||||
enter(substatement);
|
default: leave(true); continue;
|
||||||
break;
|
} break;
|
||||||
} else {
|
|
||||||
leave(true);
|
case maybe_catch_or_finally:
|
||||||
continue;
|
dump();
|
||||||
}
|
switch (kind) {
|
||||||
|
case Catch: turnInto(catch_statement); break;
|
||||||
|
case Finally: turnInto(finally_statement); break;
|
||||||
|
default: leave(true); continue;
|
||||||
|
} break;
|
||||||
|
|
||||||
case else_clause:
|
case else_clause:
|
||||||
// ### shouldn't happen
|
// ### shouldn't happen
|
||||||
@@ -407,6 +414,7 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case switch_statement:
|
case switch_statement:
|
||||||
|
case catch_statement:
|
||||||
case statement_with_condition:
|
case statement_with_condition:
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case LeftParenthesis: enter(statement_with_condition_paren_open); break;
|
case LeftParenthesis: enter(statement_with_condition_paren_open); break;
|
||||||
@@ -420,7 +428,8 @@ void CodeFormatter::recalculateStateAfter(const QTextBlock &block)
|
|||||||
case RightParenthesis: turnInto(substatement); break;
|
case RightParenthesis: turnInto(substatement); break;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case statement_with_block:
|
case try_statement:
|
||||||
|
case finally_statement:
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case LeftBrace: enter(jsblock_open); break;
|
case LeftBrace: enter(jsblock_open); break;
|
||||||
default: leave(true); break;
|
default: leave(true); break;
|
||||||
@@ -633,6 +642,8 @@ void CodeFormatter::enter(int newState)
|
|||||||
m_currentState.push(s);
|
m_currentState.push(s);
|
||||||
m_newStates.push(s);
|
m_newStates.push(s);
|
||||||
|
|
||||||
|
//qDebug() << "enter state" << stateToString(newState);
|
||||||
|
|
||||||
if (newState == bracket_open)
|
if (newState == bracket_open)
|
||||||
enter(bracket_element_start);
|
enter(bracket_element_start);
|
||||||
}
|
}
|
||||||
@@ -652,10 +663,10 @@ void CodeFormatter::leave(bool statementDone)
|
|||||||
|
|
||||||
int topState = m_currentState.top().type;
|
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 statement is done, may need to leave recursively
|
||||||
if (statementDone) {
|
if (statementDone) {
|
||||||
if (!isExpressionEndState(topState))
|
|
||||||
leave(true);
|
|
||||||
if (topState == if_statement) {
|
if (topState == if_statement) {
|
||||||
if (poppedState.type != maybe_else)
|
if (poppedState.type != maybe_else)
|
||||||
enter(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 the else *and* the surrounding if, to prevent another else
|
||||||
leave();
|
leave();
|
||||||
leave(true);
|
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);
|
enter(case_start);
|
||||||
return true;
|
return true;
|
||||||
case Try:
|
case Try:
|
||||||
case Finally:
|
enter(try_statement);
|
||||||
enter(statement_with_block);
|
|
||||||
return true;
|
return true;
|
||||||
case LeftBrace:
|
case LeftBrace:
|
||||||
enter(jsblock_open);
|
enter(jsblock_open);
|
||||||
@@ -787,9 +806,7 @@ bool CodeFormatter::isExpressionEndState(int type) const
|
|||||||
type == topmost_intro ||
|
type == topmost_intro ||
|
||||||
type == top_js ||
|
type == top_js ||
|
||||||
type == objectdefinition_open ||
|
type == objectdefinition_open ||
|
||||||
type == if_statement ||
|
|
||||||
type == do_statement ||
|
type == do_statement ||
|
||||||
type == else_clause ||
|
|
||||||
type == jsblock_open ||
|
type == jsblock_open ||
|
||||||
type == substatement_open ||
|
type == substatement_open ||
|
||||||
type == bracket_open ||
|
type == bracket_open ||
|
||||||
@@ -988,16 +1005,20 @@ CodeFormatter::TokenKind CodeFormatter::extendedTokenKind(const QmlJS::Token &to
|
|||||||
|
|
||||||
void CodeFormatter::dump() const
|
void CodeFormatter::dump() const
|
||||||
{
|
{
|
||||||
QMetaEnum metaEnum = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("StateType"));
|
|
||||||
|
|
||||||
qDebug() << "Current token index" << m_tokenIndex;
|
qDebug() << "Current token index" << m_tokenIndex;
|
||||||
qDebug() << "Current state:";
|
qDebug() << "Current state:";
|
||||||
foreach (const State &s, m_currentState) {
|
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;
|
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()
|
QtStyleCodeFormatter::QtStyleCodeFormatter()
|
||||||
: m_indentSize(4)
|
: m_indentSize(4)
|
||||||
{}
|
{}
|
||||||
@@ -1158,7 +1179,9 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
|
|||||||
|
|
||||||
|
|
||||||
case statement_with_condition:
|
case statement_with_condition:
|
||||||
case statement_with_block:
|
case try_statement:
|
||||||
|
case catch_statement:
|
||||||
|
case finally_statement:
|
||||||
case if_statement:
|
case if_statement:
|
||||||
case do_statement:
|
case do_statement:
|
||||||
case switch_statement:
|
case switch_statement:
|
||||||
@@ -1176,14 +1199,13 @@ void QtStyleCodeFormatter::onEnter(int newState, int *indentDepth, int *savedInd
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case maybe_else: {
|
case maybe_else:
|
||||||
// set indent to outermost braceless savedIndent
|
case maybe_catch_or_finally: {
|
||||||
int outermostBraceless = 0;
|
// set indent to where leave(true) would put it
|
||||||
while (isBracelessState(state(outermostBraceless + 1).type))
|
int lastNonEndState = 0;
|
||||||
++outermostBraceless;
|
while (!isExpressionEndState(state(lastNonEndState + 1).type))
|
||||||
*indentDepth = state(outermostBraceless).savedIndentDepth;
|
++lastNonEndState;
|
||||||
// this is where the else should go, if one appears - aligned to if_statement
|
*indentDepth = state(lastNonEndState).savedIndentDepth;
|
||||||
*savedIndentDepth = state().savedIndentDepth;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1278,7 +1300,7 @@ void QtStyleCodeFormatter::adjustIndent(const QList<Token> &tokens, int startLex
|
|||||||
|
|
||||||
case Else:
|
case Else:
|
||||||
if (topState.type == maybe_else) {
|
if (topState.type == maybe_else) {
|
||||||
*indentDepth = topState.savedIndentDepth;
|
*indentDepth = state(1).savedIndentDepth;
|
||||||
} else if (topState.type == expression_maybe_continuation) {
|
} else if (topState.type == expression_maybe_continuation) {
|
||||||
bool hasElse = false;
|
bool hasElse = false;
|
||||||
for (int i = 1; state(i).type != topmost_intro; ++i) {
|
for (int i = 1; state(i).type != topmost_intro; ++i) {
|
||||||
@@ -1297,6 +1319,12 @@ void QtStyleCodeFormatter::adjustIndent(const QList<Token> &tokens, int startLex
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Catch:
|
||||||
|
case Finally:
|
||||||
|
if (topState.type == maybe_catch_or_finally)
|
||||||
|
*indentDepth = state(1).savedIndentDepth;
|
||||||
|
break;
|
||||||
|
|
||||||
case Colon:
|
case Colon:
|
||||||
if (topState.type == ternary_op) {
|
if (topState.type == ternary_op) {
|
||||||
*indentDepth -= 2;
|
*indentDepth -= 2;
|
||||||
|
|||||||
@@ -167,10 +167,13 @@ public: // must be public to make Q_GADGET introspection work
|
|||||||
return_statement, // After 'return'
|
return_statement, // After 'return'
|
||||||
throw_statement, // After 'throw'
|
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_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, // after 'do'
|
||||||
do_statement_while_paren_open, // after '(' in while clause
|
do_statement_while_paren_open, // after '(' in while clause
|
||||||
@@ -278,6 +281,7 @@ protected:
|
|||||||
bool isExpressionEndState(int type) const;
|
bool isExpressionEndState(int type) const;
|
||||||
|
|
||||||
void dump() const;
|
void dump() const;
|
||||||
|
QString stateToString(int type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void recalculateStateAfter(const QTextBlock &block);
|
void recalculateStateAfter(const QTextBlock &block);
|
||||||
|
|||||||
@@ -61,6 +61,11 @@ private Q_SLOTS:
|
|||||||
void ifBinding1();
|
void ifBinding1();
|
||||||
void ifBinding2();
|
void ifBinding2();
|
||||||
void ifBinding3();
|
void ifBinding3();
|
||||||
|
void withBinding();
|
||||||
|
void tryBinding1();
|
||||||
|
void tryBinding2();
|
||||||
|
void tryBinding3();
|
||||||
|
void switchBinding();
|
||||||
void ifStatementWithoutBraces1();
|
void ifStatementWithoutBraces1();
|
||||||
void ifStatementWithoutBraces2();
|
void ifStatementWithoutBraces2();
|
||||||
void ifStatementWithoutBraces3();
|
void ifStatementWithoutBraces3();
|
||||||
@@ -98,7 +103,6 @@ private Q_SLOTS:
|
|||||||
void labelledStatements3();
|
void labelledStatements3();
|
||||||
void json1();
|
void json1();
|
||||||
void multilineTernaryInProperty();
|
void multilineTernaryInProperty();
|
||||||
void bug1();
|
|
||||||
void multilineString();
|
void multilineString();
|
||||||
void bug1();
|
void bug1();
|
||||||
};
|
};
|
||||||
@@ -538,6 +542,108 @@ void tst_QMLCodeFormatter::ifBinding3()
|
|||||||
checkIndent(data);
|
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()
|
void tst_QMLCodeFormatter::ifStatementWithoutBraces1()
|
||||||
{
|
{
|
||||||
QList<Line> data;
|
QList<Line> data;
|
||||||
@@ -1301,20 +1407,6 @@ void tst_QMLCodeFormatter::multilineTernaryInProperty()
|
|||||||
checkIndent(data);
|
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()
|
void tst_QMLCodeFormatter::multilineString()
|
||||||
{
|
{
|
||||||
QList<Line> data;
|
QList<Line> data;
|
||||||
|
|||||||
Reference in New Issue
Block a user