aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/qmljs/qmljscheck.cpp
diff options
context:
space:
mode:
authorChristian Kamm <[email protected]>2010-02-16 11:53:21 +0100
committerChristian Kamm <[email protected]>2010-02-16 11:55:41 +0100
commite6d9d9e3870327953618e11d0cb946e15c943bc3 (patch)
tree99c2b830450bbe665b3e6288279bcab604dcdc15 /src/libs/qmljs/qmljscheck.cpp
parent866b8fa5c32a97133af3985dd659c815ab1d98d5 (diff)
Fix incorrect 'invalid property' errors for PropertyChanges.
Reviewed-by: Roberto Raggi
Diffstat (limited to 'src/libs/qmljs/qmljscheck.cpp')
-rw-r--r--src/libs/qmljs/qmljscheck.cpp66
1 files changed, 57 insertions, 9 deletions
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index 7a4108cf57b..d265f2d6333 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -30,6 +30,7 @@
#include "qmljscheck.h"
#include "qmljsbind.h"
#include "qmljsinterpreter.h"
+#include "qmljsevaluate.h"
#include "parser/qmljsast_p.h"
#include <QtCore/QDebug>
@@ -43,6 +44,8 @@ Check::Check(Document::Ptr doc, const Snapshot &snapshot)
, _snapshot(snapshot)
, _context(&_engine)
, _link(&_context, doc, snapshot)
+ , _extraScope(0)
+ , _allowAnyProperty(false)
{
}
@@ -68,12 +71,7 @@ bool Check::visit(UiProgram *ast)
bool Check::visit(UiObjectDefinition *ast)
{
- const ObjectValue *oldScopeObject = _context.qmlScopeObject();
- _context.setQmlScopeObject(_doc->bind()->findQmlObject(ast));
-
- Node::accept(ast->initializer, this);
-
- _context.setQmlScopeObject(oldScopeObject);
+ visitQmlObject(ast, ast->initializer);
return false;
}
@@ -81,13 +79,58 @@ bool Check::visit(UiObjectBinding *ast)
{
checkScopeObjectMember(ast->qualifiedId);
+ visitQmlObject(ast, ast->initializer);
+ return false;
+}
+
+void Check::visitQmlObject(AST::Node *ast, AST::UiObjectInitializer *initializer)
+{
const ObjectValue *oldScopeObject = _context.qmlScopeObject();
- _context.setQmlScopeObject(_doc->bind()->findQmlObject(ast));
+ const ObjectValue *oldExtraScope = _extraScope;
+ const bool oldAllowAnyProperty = _allowAnyProperty;
+ const ObjectValue *scopeObject = _doc->bind()->findQmlObject(ast);
+ _context.setQmlScopeObject(scopeObject);
+
+#ifndef NO_DECLARATIVE_BACKEND
+ // check if the object has a Qt.PropertyChanges ancestor
+ const ObjectValue *prototype = scopeObject->prototype(&_context);
+ while (prototype) {
+ if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
+ // ### Also check for Qt package. Involves changes in QmlObjectValue.
+ if (qmlMetaObject->qmlTypeName() == QLatin1String("PropertyChanges"))
+ break;
+ }
+ prototype = prototype->prototype(&_context);
+ }
+
+ // find the target script binding
+ if (prototype && initializer) {
+ for (UiObjectMemberList *m = initializer->members; m; m = m->next) {
+ if (UiScriptBinding *scriptBinding = cast<UiScriptBinding *>(m->member)) {
+ if (scriptBinding->qualifiedId
+ && scriptBinding->qualifiedId->name->asString() == QLatin1String("target")
+ && ! scriptBinding->qualifiedId->next) {
+ if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(scriptBinding->statement)) {
+ Evaluate evaluator(&_context);
+ const Value *targetValue = evaluator(expStmt->expression);
+
+ if (const ObjectValue *target = value_cast<const ObjectValue *>(targetValue)) {
+ _extraScope = target;
+ } else {
+ _allowAnyProperty = true;
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
- Node::accept(ast->initializer, this);
+ Node::accept(initializer, this);
_context.setQmlScopeObject(oldScopeObject);
- return false;
+ _extraScope = oldExtraScope;
+ _allowAnyProperty = oldAllowAnyProperty;
}
bool Check::visit(UiScriptBinding *ast)
@@ -106,6 +149,9 @@ bool Check::visit(UiArrayBinding *ast)
void Check::checkScopeObjectMember(const AST::UiQualifiedId *id)
{
+ if (_allowAnyProperty)
+ return;
+
const ObjectValue *scopeObject = _context.qmlScopeObject();
if (! id)
@@ -121,6 +167,8 @@ void Check::checkScopeObjectMember(const AST::UiQualifiedId *id)
scopeObject = _context.typeEnvironment(_doc.data());
const Value *value = scopeObject->lookupMember(propertyName, &_context);
+ if (_extraScope && !value)
+ value = _extraScope->lookupMember(propertyName, &_context);
if (!value) {
error(id->identifierToken,
QString("'%1' is not a valid property name").arg(propertyName));