From 0f6551c43f12512ecd57242bead784f67d2a3fab Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Mon, 1 Feb 2010 13:54:44 +0100 Subject: [PATCH] Introduced ASTObjectValue. --- src/libs/qmljs/qmljsbind.cpp | 34 ++++++- src/libs/qmljs/qmljsinterpreter.cpp | 139 +++++++++++++++++++--------- src/libs/qmljs/qmljsinterpreter.h | 4 + 3 files changed, 131 insertions(+), 46 deletions(-) diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp index 94889f637fd..a5d61af7969 100644 --- a/src/libs/qmljs/qmljsbind.cpp +++ b/src/libs/qmljs/qmljsbind.cpp @@ -39,6 +39,36 @@ using namespace QmlJS::Interpreter; namespace { +class ASTObjectValue: public ObjectValue +{ + UiQualifiedId *_typeName; + UiObjectInitializer *_initializer; + +public: + ASTObjectValue(UiQualifiedId *typeName, UiObjectInitializer *initializer, Interpreter::Engine *engine) + : ObjectValue(engine), _typeName(typeName), _initializer(initializer) + { + } + + virtual void processMembers(MemberProcessor *processor) const + { + if (_initializer) { + for (UiObjectMemberList *it = _initializer->members; it; it = it->next) { + UiObjectMember *member = it->member; + if (UiPublicMember *def = cast<UiPublicMember *>(member)) { + if (def->name && def->memberType) { + const QString propName = def->name->asString(); + const QString propType = def->memberType->asString(); + + processor->processProperty(propName, engine()->defaultValueForBuiltinType(propType)); + } + } + } + } + ObjectValue::processMembers(processor); + } +}; + class ASTFunctionValue: public FunctionValue { FunctionDeclaration *_ast; @@ -175,7 +205,7 @@ ObjectValue *Bind::bindObject(UiQualifiedId *qualifiedTypeNameId, UiObjectInitia // Script blocks all contribute to the same scope parentObjectValue = switchObjectValue(_functionEnvironment); } else { // normal component instance - ObjectValue *objectValue = _interp->newObject(/*prototype =*/0); + ASTObjectValue *objectValue = new ASTObjectValue(qualifiedTypeNameId, initializer, _interp); parentObjectValue = switchObjectValue(objectValue); if (parentObjectValue) objectValue->setProperty("parent", parentObjectValue); @@ -257,12 +287,14 @@ bool Bind::visit(UiImport *ast) bool Bind::visit(UiPublicMember *ast) { +#if 0 if (_currentObjectValue && ast->name && ast->memberType) { const QString propName = ast->name->asString(); const QString propType = ast->memberType->asString(); _currentObjectValue->setProperty(propName, _interp->defaultValueForBuiltinType(propType)); } +#endif return false; } diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 4b101bc5cb1..9767de7c08c 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -43,8 +43,64 @@ using namespace QmlJS::Interpreter; +namespace { + +class LookupMember: public MemberProcessor +{ + QString _name; + const Value *_value; + + bool process(const QString &name, const Value *value) + { + if (_value) + return false; + + if (name == _name) { + _value = value; + return false; + } + + return true; + } + +public: + LookupMember(const QString &name) + : _name(name), _value(0) {} + + const Value *value() const { return _value; } + + virtual bool processProperty(const QString &name, const Value *value) + { + return process(name, value); + } + + virtual bool processEnumerator(const QString &name, const Value *value) + { + return process(name, value); + } + + virtual bool processSignal(const QString &name, const Value *value) + { + return process(name, value); + } + + virtual bool processSlot(const QString &name, const Value *value) + { + return process(name, value); + } + + virtual bool processGeneratedSlot(const QString &name, const Value *value) + { + return process(name, value); + } +}; + +} // end of anonymous namespace + #ifndef NO_DECLARATIVE_BACKEND +namespace { + class MetaFunction: public FunctionValue { QMetaMethod _method; @@ -89,6 +145,8 @@ public: } }; +} // end of anonymous namespace + QmlObjectValue::QmlObjectValue(const QMetaObject *metaObject, const QString &qmlTypeName, int majorVersion, int minorVersion, Engine *engine) : ObjectValue(engine), @@ -104,46 +162,29 @@ QmlObjectValue::~QmlObjectValue() {} const Value *QmlObjectValue::lookupMember(const QString &name) const { - for (int index = 0; index < _metaObject->propertyCount(); ++index) { - QMetaProperty prop = _metaObject->property(index); - - if (name == QString::fromUtf8(prop.name())) - return propertyValue(prop); - } - - for (int index = 0; index < _metaObject->methodCount(); ++index) { - QMetaMethod method = _metaObject->method(index); - - const QString signature = QString::fromUtf8(method.signature()); - - const int indexOfParen = signature.indexOf(QLatin1Char('(')); - if (indexOfParen == -1) - continue; // skip it, invalid signature. - - const QString methodName = signature.left(indexOfParen); + return ObjectValue::lookupMember(name); +} - if (methodName != name) { - continue; +const Value *QmlObjectValue::findOrCreateSignature(int index, const QMetaMethod &method, QString *methodName) const +{ + const QString signature = QString::fromUtf8(method.signature()); - } else if (method.methodType() == QMetaMethod::Slot && method.access() == QMetaMethod::Public) { - return new MetaFunction(method, engine()); + const int indexOfParen = signature.indexOf(QLatin1Char('(')); + if (indexOfParen == -1) + return engine()->undefinedValue(); // skip it, invalid signature. - } else if (method.methodType() == QMetaMethod::Signal && method.access() != QMetaMethod::Private) { - return new MetaFunction(method, engine()); - } + *methodName = signature.left(indexOfParen); + const Value *value = _metaSignature.value(index); + if (! value) { + value = new MetaFunction(method, engine()); + _metaSignature.insert(index, value); } - - return ObjectValue::lookupMember(name); + return value; } void QmlObjectValue::processMembers(MemberProcessor *processor) const { - for (int index = 0; index < _metaObject->propertyCount(); ++index) { - QMetaProperty prop = _metaObject->property(index); - - processor->processProperty(prop.name(), propertyValue(prop)); - } - + // process the meta enums for (int index = _metaObject->enumeratorOffset(); index < _metaObject->propertyCount(); ++index) { QMetaEnum e = _metaObject->enumerator(index); @@ -152,23 +193,25 @@ void QmlObjectValue::processMembers(MemberProcessor *processor) const } } - for (int index = 0; index < _metaObject->methodCount(); ++index) { - QMetaMethod method = _metaObject->method(index); - - const QString signature = QString::fromUtf8(method.signature()); + // process the meta properties + for (int index = 0; index < _metaObject->propertyCount(); ++index) { + QMetaProperty prop = _metaObject->property(index); - const int indexOfParen = signature.indexOf(QLatin1Char('(')); - if (indexOfParen == -1) - continue; // skip it, invalid signature. + processor->processProperty(prop.name(), propertyValue(prop)); + } - const QString methodName = signature.left(indexOfParen); + // process the meta methods + for (int index = 0; index < _metaObject->methodCount(); ++index) { + QMetaMethod method = _metaObject->method(index); + QString methodName; + const Value *signature = findOrCreateSignature(index, method, &methodName); if (method.methodType() == QMetaMethod::Slot && method.access() == QMetaMethod::Public) { - processor->processSlot(methodName, engine()->undefinedValue()); + processor->processSlot(methodName, signature); } else if (method.methodType() == QMetaMethod::Signal && method.access() != QMetaMethod::Private) { // process the signal - processor->processSignal(methodName, engine()->undefinedValue()); + processor->processSignal(methodName, signature); QString slotName; slotName += QLatin1String("on"); @@ -176,7 +219,7 @@ void QmlObjectValue::processMembers(MemberProcessor *processor) const slotName += methodName.midRef(1); // process the generated slot - processor->processGeneratedSlot(slotName, engine()->undefinedValue()); + processor->processGeneratedSlot(slotName, signature); } } @@ -599,8 +642,8 @@ const Value *Environment::lookup(const QString &name) const return 0; } -const Value *Environment::lookupMember(const QString &name) const { - Q_UNUSED(name); +const Value *Environment::lookupMember(const QString &) const +{ return 0; } @@ -806,6 +849,12 @@ const Value *ObjectValue::lookupMember(const QString &name) const { if (const Value *m = _members.value(name)) return m; + else { + LookupMember slowLookup(name); + processMembers(&slowLookup); + if (slowLookup.value()) + return slowLookup.value(); + } if (_prototype) { if (const Value *m = _prototype->lookup(name)) diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 54251a87ff3..ba4b7606560 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -273,11 +273,15 @@ public: int minorVersion() const { return _minorVersion; } +protected: + const Value *findOrCreateSignature(int index, const QMetaMethod &method, QString *methodName) const; + private: const QMetaObject *_metaObject; QString _qmlTypeName; int _majorVersion; int _minorVersion; + mutable QHash<int, const Value *> _metaSignature; }; #endif // !NO_DECLARATIVE_BACKEND -- GitLab