diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index 40e3ff5a72d..af2c9257556 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -514,6 +514,7 @@ Check::Check(Document::Ptr doc, const ContextPtr &context) , _scopeBuilder(&_scopeChain) , _lastValue(0) , _importsOk(false) + , _inStatementBinding(false) { const Imports *imports = context->imports(doc.data()); if (imports && !imports->importFailed()) @@ -736,7 +737,9 @@ bool Check::visit(UiScriptBinding *ast) Node::accept(ast->qualifiedId, this); _scopeBuilder.push(ast); + _inStatementBinding = true; Node::accept(ast->statement, this); + _inStatementBinding = false; _scopeBuilder.pop(); return false; @@ -791,7 +794,9 @@ bool Check::visit(UiPublicMember *ast) checkBindingRhs(ast->statement); _scopeBuilder.push(ast); + _inStatementBinding = true; Node::accept(ast->statement, this); + _inStatementBinding = false; Node::accept(ast->binding, this); _scopeBuilder.pop(); } @@ -866,9 +871,14 @@ bool Check::visit(FunctionExpression *ast) addMessages(unreachableCheck(ast->body)); Node::accept(ast->formals, this); + + const bool wasInStatementBinding = _inStatementBinding; + _inStatementBinding = false; _scopeBuilder.push(ast); Node::accept(ast->body, this); _scopeBuilder.pop(); + _inStatementBinding = wasInStatementBinding; + return false; } @@ -1027,20 +1037,7 @@ bool Check::visit(ExpressionStatement *ast) } } if (!ok) { - for (int i = 0; Node *p = parent(i); ++i) { - if (UiScriptBinding *binding = cast(p)) { - if (!cast(binding->statement)) { - ok = true; - break; - } - } - if (UiPublicMember *member = cast(p)) { - if (!cast(member->statement)) { - ok = true; - break; - } - } - } + ok = _inStatementBinding; } if (!ok) { diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h index 39ed5493c5b..527fa1bf9e4 100644 --- a/src/libs/qmljs/qmljscheck.h +++ b/src/libs/qmljs/qmljscheck.h @@ -148,6 +148,7 @@ private: QHash< int, QList > m_disabledMessageTypesByLine; bool _importsOk; + bool _inStatementBinding; }; } // namespace QmlJS diff --git a/tests/auto/qml/codemodel/check/expression-statement.qml b/tests/auto/qml/codemodel/check/expression-statement.qml index f3ea9d8ced1..953d7aa1b0f 100644 --- a/tests/auto/qml/codemodel/check/expression-statement.qml +++ b/tests/auto/qml/codemodel/check/expression-statement.qml @@ -10,4 +10,17 @@ Rectangle { a += 12 d().foo // 127 9 15 } + x: a + b + y: { a + b } + z: if (a) + b + else + c + width: { + function foo() { + a // 127 13 13 + } + foo() + a + } } diff --git a/tests/auto/qml/codemodel/check/tst_check.cpp b/tests/auto/qml/codemodel/check/tst_check.cpp index 0c529428877..7365bc5b69a 100644 --- a/tests/auto/qml/codemodel/check/tst_check.cpp +++ b/tests/auto/qml/codemodel/check/tst_check.cpp @@ -154,15 +154,15 @@ void tst_Check::test() } for (int i = 0; i < messages.size(); ++i) { - Message expected; - if (i < expectedMessages.size()) - expected = expectedMessages.at(i); + if (i >= expectedMessages.size()) + break; Message actual = messages.at(i); + Message expected = expectedMessages.at(i); bool fail = false; fail |= !QCOMPARE_NOEXIT(actual.location.startLine, expected.location.startLine); + fail |= !QCOMPARE_NOEXIT((int)actual.type, (int)expected.type); if (fail) return; - fail |= !QCOMPARE_NOEXIT((int)actual.type, (int)expected.type); fail |= !QCOMPARE_NOEXIT(actual.location.startColumn, expected.location.startColumn); fail |= !QCOMPARE_NOEXIT(actual.location.offset, expected.location.offset); fail |= !QCOMPARE_NOEXIT(actual.location.length, expected.location.length); @@ -178,6 +178,13 @@ void tst_Check::test() } QFAIL("more messages expected"); } + if (expectedMessages.size() < messages.size()) { + for (int i = expectedMessages.size(); i < messages.size(); ++i) { + Message extraMessage = messages.at(i); + qDebug() << "unexpected message of type" << extraMessage.type << "on line" << extraMessage.location.startLine; + } + QFAIL("fewer messages expected"); + } } QTEST_MAIN(tst_Check);