diff --git a/src/plugins/duieditor/qmllookupcontext.cpp b/src/plugins/duieditor/qmllookupcontext.cpp index 8694959c1c8634cca207b27b84f8edff669464c3..1847f35536179aa335b2b709c7d23e876cfb1c51 100644 --- a/src/plugins/duieditor/qmllookupcontext.cpp +++ b/src/plugins/duieditor/qmllookupcontext.cpp @@ -26,7 +26,10 @@ QmlLookupContext::~QmlLookupContext() QmlSymbol *QmlLookupContext::resolve(const QString &name) { - // ### TODO: look at property definitions + // look at property definitions + if (QmlSymbol *propertySymbol = resolveProperty(name, _scopes.top(), _doc->fileName())) + return propertySymbol; + if (name == "parent") { for (int i = _scopes.size() - 2; i >= 0; --i) { Node *scope = _scopes.at(i); @@ -56,9 +59,14 @@ QmlSymbol *QmlLookupContext::createSymbol(const QString &fileName, QmlJS::AST::U return symbol; } -QmlSymbol *QmlLookupContext::resolveType(const QString &name) +QmlSymbol *QmlLookupContext::resolveType(const QString &name, const QString &fileName) { - UiProgram *prog = _doc->program(); + // TODO: handle import-as. + DuiDocument::Ptr document = _snapshot[fileName]; + if (document.isNull()) + return 0; + + UiProgram *prog = document->program(); if (!prog) return 0; @@ -76,7 +84,7 @@ QmlSymbol *QmlLookupContext::resolveType(const QString &name) const QString path = import->fileName->asString(); - const QMap<QString, DuiDocument::Ptr> importedTypes = _snapshot.componentsDefinedByImportedDocuments(_doc, path); + const QMap<QString, DuiDocument::Ptr> importedTypes = _snapshot.componentsDefinedByImportedDocuments(document, path); if (importedTypes.contains(name)) { DuiDocument::Ptr importedDoc = importedTypes.value(name); @@ -88,3 +96,75 @@ QmlSymbol *QmlLookupContext::resolveType(const QString &name) return 0; } + +QmlSymbol *QmlLookupContext::resolveProperty(const QString &name, Node *scope, const QString &fileName) +{ + UiQualifiedId *typeName = 0; + + if (UiObjectBinding *binding = cast<UiObjectBinding*>(scope)) { + if (QmlSymbol *symbol = resolveProperty(name, binding->initializer, fileName)) + return symbol; + else + typeName = binding->qualifiedTypeNameId; + } else if (UiObjectDefinition *definition = cast<UiObjectDefinition*>(scope)) { + if (QmlSymbol *symbol = resolveProperty(name, definition->initializer, fileName)) + return symbol; + else + typeName = definition->qualifiedTypeNameId; + } // TODO: extend this to handle (JavaScript) block scopes. + + if (typeName == 0) + return 0; + + QmlSymbol *typeSymbol = resolveType(toString(typeName), fileName); + if (typeSymbol && typeSymbol->isSymbolFromFile()) { + return resolveProperty(name, typeSymbol->asSymbolFromFile()->node(), typeSymbol->asSymbolFromFile()->fileName()); + } + + return 0; +} + +QmlSymbol *QmlLookupContext::resolveProperty(const QString &name, QmlJS::AST::UiObjectInitializer *initializer, const QString &fileName) +{ + if (!initializer) + return 0; + + for (UiObjectMemberList *iter = initializer->members; iter; iter = iter->next) { + UiObjectMember *member = iter->member; + if (!member) + continue; + + if (UiPublicMember *publicMember = cast<UiPublicMember*>(member)) { + if (name == publicMember->name->asString()) + return createSymbol(fileName, publicMember); + } else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(member)) { + if (name == toString(objectBinding->qualifiedId)) + return createSymbol(fileName, objectBinding); + } else if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(member)) { + if (name == toString(arrayBinding->qualifiedId)) + return createSymbol(fileName, arrayBinding); + } else if (UiScriptBinding *scriptBinding = cast<UiScriptBinding*>(member)) { + if (name == toString(scriptBinding->qualifiedId)) + return createSymbol(fileName, scriptBinding); + } + } + + return 0; +} + +QString QmlLookupContext::toString(UiQualifiedId *id) +{ + QString str; + + for (UiQualifiedId *iter = id; iter; iter = iter->next) { + if (!(iter->name)) + continue; + + str.append(iter->name->asString()); + + if (iter->next) + str.append('.'); + } + + return str; +} diff --git a/src/plugins/duieditor/qmllookupcontext.h b/src/plugins/duieditor/qmllookupcontext.h index 3c98e056344216f63a4c1babddcef59a83ef5665..4813f37e30cbea332daf8cf68ea86a8d9e2bd3ec 100644 --- a/src/plugins/duieditor/qmllookupcontext.h +++ b/src/plugins/duieditor/qmllookupcontext.h @@ -19,7 +19,10 @@ public: ~QmlLookupContext(); QmlSymbol *resolve(const QString &name); - QmlSymbol *resolveType(const QString &name); + QmlSymbol *resolveType(const QString &name) + { return resolveType(name, _doc->fileName()); } + QmlSymbol *resolveType(QmlJS::AST::UiQualifiedId *name) + { return resolveType(toString(name), _doc->fileName()); } DuiDocument::Ptr document() const { return _doc; } @@ -27,6 +30,12 @@ public: private: QmlSymbol *createSymbol(const QString &fileName, QmlJS::AST::UiObjectMember *node); + QmlSymbol *resolveType(const QString &name, const QString &fileName); + QmlSymbol *resolveProperty(const QString &name, QmlJS::AST::Node *scope, const QString &fileName); + QmlSymbol *resolveProperty(const QString &name, QmlJS::AST::UiObjectInitializer *initializer, const QString &fileName); + + static QString toString(QmlJS::AST::UiQualifiedId *id); + private: QStack<QmlJS::AST::Node *> _scopes; DuiDocument::Ptr _doc; diff --git a/src/plugins/duieditor/qmlresolveexpression.cpp b/src/plugins/duieditor/qmlresolveexpression.cpp index 390ca5586b50bf0af5c77857c6fa6da0e200ec7b..02fc21daa7f4004d9f69dacf25e4789b32324795 100644 --- a/src/plugins/duieditor/qmlresolveexpression.cpp +++ b/src/plugins/duieditor/qmlresolveexpression.cpp @@ -108,26 +108,9 @@ bool QmlResolveExpression::visit(FieldMemberExpression *ast) return false; } -static inline QString toString(UiQualifiedId *id) -{ - QString str; - - for (UiQualifiedId *iter = id; iter; iter = iter->next) { - if (!(iter->name)) - continue; - - str.append(iter->name->asString()); - - if (iter->next) - str.append('.'); - } - - return str; -} - bool QmlResolveExpression::visit(QmlJS::AST::UiQualifiedId *ast) { - _value = _context.resolveType(toString(ast)); + _value = _context.resolveType(ast); return false; }