From 6c925cf0fc4f0c6494e5e5639e84970d67ea248b Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 16 Sep 2011 13:55:10 +0200 Subject: QmlJS: Rework exported C++ type registry. The problem was that if you exported A 1.0, A 1.1 and B 1.0 where A is the prototype of B the code model had not enough information to know that, depending on the import, B 1.0's prototype should be A 1.1 or A 1.0. To solve this problem QmlObjectValues now store the import's version as well as the local component version. In the example above B 1.0 would have import version 1.1 if the 1.1 module was imported and thus be able to choose the right prototype. Change-Id: I7ef33f12ca5a528c62b2a8240f4b5720b0ebd4c3 Reviewed-on: http://codereview.qt-project.org/5129 Reviewed-by: Thomas Hartmann --- src/libs/qmljs/qmljsinterpreter.cpp | 298 +++++++++------------ src/libs/qmljs/qmljsinterpreter.h | 53 ++-- src/libs/qmljs/qmljslink.cpp | 38 ++- src/libs/qmljs/qmljsscopebuilder.cpp | 8 +- src/libs/qmljs/qmljsvalueowner.cpp | 3 +- .../designercore/metainfo/nodemetainfo.cpp | 106 +++----- .../designercore/model/texttomodelmerger.cpp | 6 +- src/plugins/qmljseditor/qmljscompletionassist.cpp | 268 +++++++++--------- src/plugins/qmljseditor/qmljscompletionassist.h | 14 - .../qmljseditor/qmljssemantichighlighter.cpp | 2 +- 10 files changed, 363 insertions(+), 433 deletions(-) (limited to 'src') diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 716a8a913d..bb28532503 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -43,6 +43,7 @@ #include "parser/qmljsast_p.h" #include +#include #include #include @@ -54,6 +55,8 @@ #include #include +#include + using namespace LanguageUtils; using namespace QmlJS; using namespace QmlJS::AST; @@ -157,12 +160,14 @@ public: } // end of anonymous namespace QmlObjectValue::QmlObjectValue(FakeMetaObject::ConstPtr metaObject, const QString &className, - const QString &packageName, const ComponentVersion version, ValueOwner *valueOwner) + const QString &packageName, const ComponentVersion &componentVersion, + const ComponentVersion &importVersion, ValueOwner *valueOwner) : ObjectValue(valueOwner), _attachedType(0), _metaObject(metaObject), - _packageName(packageName), - _componentVersion(version) + _moduleName(packageName), + _componentVersion(componentVersion), + _importVersion(importVersion) { setClassName(className); int nEnums = metaObject->enumeratorCount(); @@ -258,15 +263,18 @@ void QmlObjectValue::processMembers(MemberProcessor *processor) const const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const { QString typeName = prop.typeName(); + const CppQmlTypes &cppTypes = valueOwner()->cppQmlTypes(); - // ### Verify type resolving. - QmlObjectValue *objectValue = valueOwner()->cppQmlTypes().typeByCppName(typeName); - if (objectValue) { - FakeMetaObject::Export exp = objectValue->metaObject()->exportInPackage(packageName()); - if (exp.isValid()) - objectValue = valueOwner()->cppQmlTypes().typeByQualifiedName(exp.packageNameVersion); + // check in the same package/version first + const QmlObjectValue *objectValue = cppTypes.objectByQualifiedName( + _moduleName, typeName, _importVersion); + if (objectValue) + return objectValue; + + // fallback to plain cpp name + objectValue = cppTypes.objectByCppName(typeName); + if (objectValue) return objectValue; - } // try qml builtin type names if (const Value *v = valueOwner()->defaultValueForBuiltinType(typeName)) { @@ -309,7 +317,7 @@ const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const const QmlObjectValue *base = this; const QStringList components = typeName.split(QLatin1String("::")); if (components.size() == 2) { - base = valueOwner()->cppQmlTypes().typeByCppName(components.first()); + base = valueOwner()->cppQmlTypes().objectByCppName(components.first()); typeName = components.last(); } if (base) { @@ -341,12 +349,15 @@ FakeMetaObject::ConstPtr QmlObjectValue::metaObject() const return _metaObject; } -QString QmlObjectValue::packageName() const -{ return _packageName; } +QString QmlObjectValue::moduleName() const +{ return _moduleName; } -ComponentVersion QmlObjectValue::version() const +ComponentVersion QmlObjectValue::componentVersion() const { return _componentVersion; } +ComponentVersion QmlObjectValue::importVersion() const +{ return _importVersion; } + QString QmlObjectValue::defaultPropertyName() const { return _metaObject->defaultPropertyName(); } @@ -448,28 +459,6 @@ bool QmlObjectValue::hasProperty(const QString &propertyName) const return false; } -// Returns true if this object is in a package or if there is an object that -// has this one in its prototype chain and is itself in a package. -bool QmlObjectValue::hasChildInPackage() const -{ - if (!packageName().isEmpty() - && packageName() != CppQmlTypes::cppPackage) - return true; - QHashIterator it(valueOwner()->cppQmlTypes().types()); - while (it.hasNext()) { - it.next(); - FakeMetaObject::ConstPtr otherMeta = it.value()->_metaObject; - // if it has only a cpp-package export, it is not really exported - if (otherMeta->exports().size() <= 1) - continue; - for (const QmlObjectValue *other = it.value(); other; other = other->prototype()) { - if (other->metaObject() == _metaObject) // this object is a parent of other - return true; - } - } - return false; -} - bool QmlObjectValue::isDerivedFrom(FakeMetaObject::ConstPtr base) const { for (const QmlObjectValue *it = this; it; it = it->prototype()) { @@ -1248,172 +1237,145 @@ void CppQmlTypesLoader::parseQmlTypeDescriptions(const QByteArray &xml, *warningMessage = reader.warningMessage(); } +CppQmlTypes::CppQmlTypes(ValueOwner *valueOwner) + : _valueOwner(valueOwner) +{ +} + const QLatin1String CppQmlTypes::defaultPackage(""); const QLatin1String CppQmlTypes::cppPackage(""); template -QList CppQmlTypes::load(ValueOwner *valueOwner, const T &objects) -{ - // load - QList loadedObjects; - QList newObjects; - foreach (FakeMetaObject::ConstPtr metaObject, objects) { - foreach (const FakeMetaObject::Export &exp, metaObject->exports()) { - bool wasCreated; - QmlObjectValue *loadedObject = getOrCreate(valueOwner, metaObject, exp, &wasCreated); - loadedObjects += loadedObject; - if (wasCreated) - newObjects += loadedObject; +void CppQmlTypes::load(const T &fakeMetaObjects, const QString &overridePackage) +{ + QList newCppTypes; + foreach (const FakeMetaObject::ConstPtr &fmo, fakeMetaObjects) { + foreach (const FakeMetaObject::Export &exp, fmo->exports()) { + QString package = exp.package; + if (package.isEmpty()) + package = overridePackage; + _fakeMetaObjectsByPackage[package].insert(fmo); + + // make versionless cpp types directly + // needed for access to property types that are not exported, like QDeclarativeAnchors + if (exp.package == cppPackage) { + QTC_ASSERT(exp.version == ComponentVersion(), continue); + QTC_ASSERT(exp.type == fmo->className(), continue); + QmlObjectValue *cppValue = new QmlObjectValue( + fmo, fmo->className(), cppPackage, ComponentVersion(), ComponentVersion(), _valueOwner); + _objectsByQualifiedName[exp.packageNameVersion] = cppValue; + newCppTypes += cppValue; + } } } - // set prototypes - foreach (QmlObjectValue *object, newObjects) { - setPrototypes(object); + // set prototypes of cpp types + foreach (QmlObjectValue *object, newCppTypes) { + const QString &protoCppName = object->metaObject()->superclassName(); + const QmlObjectValue *proto = objectByCppName(protoCppName); + if (proto) + object->setPrototype(proto); } - - return loadedObjects; } // explicitly instantiate load for list and hash -template QList CppQmlTypes::load< QList >(ValueOwner *, const QList &); -template QList CppQmlTypes::load< QHash >(ValueOwner *, const QHash &); - -QList CppQmlTypes::typesForImport(const QString &packageName, ComponentVersion version) const -{ - QHash objectValuesByName; - - foreach (QmlObjectValue *qmlObjectValue, _typesByPackage.value(packageName)) { - if (qmlObjectValue->version() <= version) { - // we got a candidate. - const QString typeName = qmlObjectValue->className(); - QmlObjectValue *previousCandidate = objectValuesByName.value(typeName, 0); - if (previousCandidate) { - // check if our new candidate is newer than the one we found previously - if (previousCandidate->version() < qmlObjectValue->version()) { - // the new candidate has a higher version no. than the one we found previously, so replace it - objectValuesByName.insert(typeName, qmlObjectValue); - } - } else { - objectValuesByName.insert(typeName, qmlObjectValue); - } +template void CppQmlTypes::load< QList >(const QList &, const QString &); +template void CppQmlTypes::load< QHash >(const QHash &, const QString &); + +QList CppQmlTypes::createObjectsForImport(const QString &package, ComponentVersion version) +{ + QList exportedObjects; + + // make new exported objects + foreach (const FakeMetaObject::ConstPtr &fmo, _fakeMetaObjectsByPackage.value(package)) { + // find the highest-version export + FakeMetaObject::Export bestExport; + foreach (const FakeMetaObject::Export &exp, fmo->exports()) { + if (exp.package != package || (version.isValid() && exp.version > version)) + continue; + if (!bestExport.isValid() || exp.version > bestExport.version) + bestExport = exp; } + if (!bestExport.isValid()) + continue; + + // if it already exists, skip + const QString key = qualifiedName(package, fmo->className(), version); + if (_objectsByQualifiedName.contains(key)) + continue; + + QmlObjectValue *newObject = new QmlObjectValue( + fmo, bestExport.type, package, bestExport.version, version, _valueOwner); + + // use package.cppname importversion as key + _objectsByQualifiedName.insert(key, newObject); + exportedObjects += newObject; } - return objectValuesByName.values(); -} + // set their prototypes, creating them if necessary + foreach (const QmlObjectValue *cobject, exportedObjects) { + QmlObjectValue *object = const_cast(cobject); + while (!object->prototype()) { + const QString &protoCppName = object->metaObject()->superclassName(); + if (protoCppName.isEmpty()) + break; -QmlObjectValue *CppQmlTypes::typeByCppName(const QString &cppName) const -{ - return typeByQualifiedName(cppPackage, cppName, ComponentVersion()); + // if the prototype already exists, done + const QString key = qualifiedName(object->moduleName(), protoCppName, version); + if (const QmlObjectValue *proto = _objectsByQualifiedName.value(key)) { + object->setPrototype(proto); + break; + } + + // get the fmo via the cpp name + const QmlObjectValue *cppProto = objectByCppName(protoCppName); + if (!cppProto) + break; + FakeMetaObject::ConstPtr protoFmo = cppProto->metaObject(); + + // make a new object + QmlObjectValue *proto = new QmlObjectValue( + protoFmo, protoCppName, object->moduleName(), ComponentVersion(), + object->importVersion(), _valueOwner); + _objectsByQualifiedName.insert(key, proto); + object->setPrototype(proto); + + // maybe set prototype of prototype + object = proto; + } + } + + return exportedObjects; } -bool CppQmlTypes::hasPackage(const QString &package) const +bool CppQmlTypes::hasModule(const QString &module) const { - return _typesByPackage.contains(package); + return _fakeMetaObjectsByPackage.contains(module); } -QString CppQmlTypes::qualifiedName(const QString &package, const QString &type, ComponentVersion version) +QString CppQmlTypes::qualifiedName(const QString &module, const QString &type, ComponentVersion version) { return QString("%1/%2 %3").arg( - package, type, + module, type, version.toString()); } -QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &name) const +const QmlObjectValue *CppQmlTypes::objectByQualifiedName(const QString &name) const { - return _typesByFullyQualifiedName.value(name); + return _objectsByQualifiedName.value(name); } -QmlObjectValue *CppQmlTypes::typeByQualifiedName(const QString &package, const QString &type, ComponentVersion version) const +const QmlObjectValue *CppQmlTypes::objectByQualifiedName(const QString &package, const QString &type, + ComponentVersion version) const { - return typeByQualifiedName(qualifiedName(package, type, version)); + return objectByQualifiedName(qualifiedName(package, type, version)); } -QmlObjectValue *CppQmlTypes::getOrCreate( - ValueOwner *valueOwner, - FakeMetaObject::ConstPtr metaObject, - const LanguageUtils::FakeMetaObject::Export &exp, - bool *wasCreated) +const QmlObjectValue *CppQmlTypes::objectByCppName(const QString &cppName) const { - // make sure we're not loading duplicate objects - if (QmlObjectValue *existing = _typesByFullyQualifiedName.value(exp.packageNameVersion)) { - if (wasCreated) - *wasCreated = false; - return existing; - } - - QmlObjectValue *objectValue = new QmlObjectValue( - metaObject, exp.type, exp.package, exp.version, valueOwner); - _typesByPackage[exp.package].append(objectValue); - _typesByFullyQualifiedName[exp.packageNameVersion] = objectValue; - - if (wasCreated) - *wasCreated = true; - return objectValue; + return objectByQualifiedName(qualifiedName(cppPackage, cppName, ComponentVersion())); } -void CppQmlTypes::setPrototypes(QmlObjectValue *object) -{ - if (!object) - return; - - FakeMetaObject::ConstPtr fmo = object->metaObject(); - - // resolve attached type - // don't do it if the attached type name is the object itself (happens for QDeclarativeKeysAttached) - if (!fmo->attachedTypeName().isEmpty() - && fmo->className() != fmo->attachedTypeName()) { - QmlObjectValue *attachedObject = typeByCppName(fmo->attachedTypeName()); - if (attachedObject && attachedObject != object) - object->setAttachedType(attachedObject); - } - - const QString targetPackage = object->packageName(); - - // set prototypes for whole chain, creating new QmlObjectValues if necessary - // for instance, if an type isn't exported in the package of the super type - // Example: QObject (Qt, QtQuick) -> Positioner (not exported) -> Column (Qt, QtQuick) - // needs to create Positioner (Qt) and Positioner (QtQuick) - QmlObjectValue *v = object; - while (!v->prototype() && !fmo->superclassName().isEmpty()) { - QmlObjectValue *superValue = getOrCreateForPackage(targetPackage, fmo->superclassName()); - if (!superValue) - return; - v->setPrototype(superValue); - v = superValue; - fmo = v->metaObject(); - } -} - -QmlObjectValue *CppQmlTypes::getOrCreateForPackage(const QString &package, const QString &cppName) -{ - // first get the cpp object value - QmlObjectValue *cppObject = typeByCppName(cppName); - if (!cppObject) { - // ### disabled for now, should be communicated to the user somehow. - //qWarning() << "QML type system: could not find '" << cppName << "'"; - return 0; - } - - FakeMetaObject::ConstPtr metaObject = cppObject->metaObject(); - FakeMetaObject::Export exp = metaObject->exportInPackage(package); - QmlObjectValue *object = 0; - if (exp.isValid()) { - object = getOrCreate(cppObject->valueOwner(), metaObject, exp); - } else { - // make a convenience object that does not get added to _typesByPackage - const QString qname = qualifiedName(package, cppName, ComponentVersion()); - object = typeByQualifiedName(qname); - if (!object) { - object = new QmlObjectValue( - metaObject, cppName, package, ComponentVersion(), cppObject->valueOwner()); - _typesByFullyQualifiedName[qname] = object; - } - } - - return object; -} ConvertToNumber::ConvertToNumber(ValueOwner *valueOwner) : _valueOwner(valueOwner), _result(0) diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 18e0e36b74..fb7526ce21 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -418,7 +418,8 @@ class QMLJS_EXPORT QmlObjectValue: public ObjectValue { public: QmlObjectValue(LanguageUtils::FakeMetaObject::ConstPtr metaObject, const QString &className, - const QString &packageName, const LanguageUtils::ComponentVersion version, + const QString &moduleName, const LanguageUtils::ComponentVersion &componentVersion, + const LanguageUtils::ComponentVersion &importVersion, ValueOwner *valueOwner); virtual ~QmlObjectValue(); @@ -433,8 +434,9 @@ public: LanguageUtils::FakeMetaObject::ConstPtr metaObject() const; - QString packageName() const; - LanguageUtils::ComponentVersion version() const; + QString moduleName() const; + LanguageUtils::ComponentVersion componentVersion() const; + LanguageUtils::ComponentVersion importVersion() const; QString defaultPropertyName() const; QString propertyType(const QString &propertyName) const; @@ -443,7 +445,6 @@ public: bool isPointer(const QString &propertyName) const; bool hasLocalProperty(const QString &typeName) const; bool hasProperty(const QString &typeName) const; - bool hasChildInPackage() const; LanguageUtils::FakeMetaEnum getEnum(const QString &typeName, const QmlObjectValue **foundInScope = 0) const; const QmlEnumValue *getEnumValue(const QString &typeName, const QmlObjectValue **foundInScope = 0) const; @@ -455,8 +456,12 @@ protected: private: QmlObjectValue *_attachedType; LanguageUtils::FakeMetaObject::ConstPtr _metaObject; - const QString _packageName; + const QString _moduleName; + // _componentVersion is the version of the export + // _importVersion is the version it's imported as, used to find correct prototypes + // needed in cases when B 1.0 has A 1.1 as prototype when imported as 1.1 const LanguageUtils::ComponentVersion _componentVersion; + const LanguageUtils::ComponentVersion _importVersion; mutable QHash _metaSignature; QHash _enums; }; @@ -571,38 +576,32 @@ public: class QMLJS_EXPORT CppQmlTypes { public: + CppQmlTypes(ValueOwner *valueOwner); + // package name for objects that should be always available static const QLatin1String defaultPackage; // package name for objects with their raw cpp name static const QLatin1String cppPackage; template - QList load(ValueOwner *interpreter, const T &objects); - - QList typesForImport(const QString &prefix, LanguageUtils::ComponentVersion version) const; - QmlObjectValue *typeByCppName(const QString &cppName) const; - - bool hasPackage(const QString &package) const; + void load(const T &fakeMetaObjects, const QString &overridePackage = QString()); - QHash types() const - { return _typesByFullyQualifiedName; } + QList createObjectsForImport(const QString &package, LanguageUtils::ComponentVersion version); + bool hasModule(const QString &module) const; - static QString qualifiedName(const QString &package, const QString &type, LanguageUtils::ComponentVersion version); - QmlObjectValue *typeByQualifiedName(const QString &fullyQualifiedName) const; - QmlObjectValue *typeByQualifiedName(const QString &package, const QString &type, - LanguageUtils::ComponentVersion version) const; + static QString qualifiedName(const QString &module, const QString &type, + LanguageUtils::ComponentVersion version); + const QmlObjectValue *objectByQualifiedName(const QString &fullyQualifiedName) const; + const QmlObjectValue *objectByQualifiedName( + const QString &package, const QString &type, + LanguageUtils::ComponentVersion version) const; + const QmlObjectValue *objectByCppName(const QString &cppName) const; private: - void setPrototypes(QmlObjectValue *object); - QmlObjectValue *getOrCreate(ValueOwner *valueOwner, - LanguageUtils::FakeMetaObject::ConstPtr metaObject, - const LanguageUtils::FakeMetaObject::Export &exp, - bool *wasCreated = 0); - QmlObjectValue *getOrCreateForPackage(const QString &package, const QString &cppName); - - - QHash > _typesByPackage; - QHash _typesByFullyQualifiedName; + // "Package.CppName ImportVersion" -> QmlObjectValue + QHash _objectsByQualifiedName; + QHash > _fakeMetaObjectsByPackage; + ValueOwner *_valueOwner; }; class ConvertToNumber: protected ValueVisitor // ECMAScript ToInt() diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp index e4064eabf5..92c17276b4 100644 --- a/src/libs/qmljs/qmljslink.cpp +++ b/src/libs/qmljs/qmljslink.cpp @@ -153,7 +153,7 @@ Link::Link(const Snapshot &snapshot, const QStringList &importPaths, const Libra // populate engine with types from C++ foreach (const ModelManagerInterface::CppData &cppData, cppDataHash) { - d->valueOwner->cppQmlTypes().load(d->valueOwner, cppData.exportedTypes); + d->valueOwner->cppQmlTypes().load(cppData.exportedTypes); } // populate global object with context properties from C++ @@ -165,7 +165,7 @@ Link::Link(const Snapshot &snapshot, const QStringList &importPaths, const Libra const Value *value = 0; const QString cppTypeName = it.value(); if (!cppTypeName.isEmpty()) - value = d->valueOwner->cppQmlTypes().typeByCppName(cppTypeName); + value = d->valueOwner->cppQmlTypes().objectByCppName(cppTypeName); if (!value) value = d->valueOwner->undefinedValue(); global->setMember(it.key(), value); @@ -199,18 +199,18 @@ Context::ImportsPerDocument LinkPrivate::linkImports() // load builtin objects if (builtins.pluginTypeInfoStatus() == LibraryInfo::DumpDone || builtins.pluginTypeInfoStatus() == LibraryInfo::TypeInfoFileDone) { - valueOwner->cppQmlTypes().load(valueOwner, builtins.metaObjects()); + valueOwner->cppQmlTypes().load(builtins.metaObjects()); } else { - valueOwner->cppQmlTypes().load(valueOwner, CppQmlTypesLoader::defaultQtObjects); + valueOwner->cppQmlTypes().load(CppQmlTypesLoader::defaultQtObjects); } // load library objects shipped with Creator - valueOwner->cppQmlTypes().load(valueOwner, CppQmlTypesLoader::defaultLibraryObjects); + valueOwner->cppQmlTypes().load(CppQmlTypesLoader::defaultLibraryObjects); // the 'Qt' object is dumped even though it is not exported // it contains useful information, in particular on enums - add the // object as a prototype to our custom Qt object to offer these for completion - const_cast(valueOwner->qtObject())->setPrototype(valueOwner->cppQmlTypes().typeByCppName(QLatin1String("Qt"))); + const_cast(valueOwner->qtObject())->setPrototype(valueOwner->cppQmlTypes().objectByCppName(QLatin1String("Qt"))); if (document) { // do it on document first, to make sure import errors are shown @@ -363,10 +363,10 @@ Import LinkPrivate::importNonFile(Document::Ptr doc, const ImportInfo &importInf } // if there are cpp-based types for this package, use them too - if (valueOwner->cppQmlTypes().hasPackage(packageName)) { + if (valueOwner->cppQmlTypes().hasModule(packageName)) { importFound = true; - foreach (QmlObjectValue *object, - valueOwner->cppQmlTypes().typesForImport(packageName, version)) { + foreach (const QmlObjectValue *object, + valueOwner->cppQmlTypes().createObjectsForImport(packageName, version)) { import.object->setMember(object->className(), object); } } @@ -432,16 +432,14 @@ bool LinkPrivate::importLibrary(Document::Ptr doc, QString packageName; if (ast && ast->importUri) packageName = Bind::toString(importInfo.ast()->importUri, '.'); - if (errorLoc.isValid() && (packageName.isEmpty() || !valueOwner->cppQmlTypes().hasPackage(packageName))) { + if (errorLoc.isValid() && (packageName.isEmpty() || !valueOwner->cppQmlTypes().hasModule(packageName))) { error(doc, errorLoc, libraryInfo.pluginTypeInfoError()); } - } else { - QList loadedObjects = - valueOwner->cppQmlTypes().load(valueOwner, libraryInfo.metaObjects()); - foreach (QmlObjectValue *object, loadedObjects) { - if (object->packageName().isEmpty()) { - import->object->setMember(object->className(), object); - } + } else if (ast && ast->importUri) { + const QString packageName = Bind::toString(importInfo.ast()->importUri, '.'); + valueOwner->cppQmlTypes().load(libraryInfo.metaObjects(), packageName); + foreach (const QmlObjectValue *object, valueOwner->cppQmlTypes().createObjectsForImport(packageName, version)) { + import->object->setMember(object->className(), object); } } } @@ -526,14 +524,14 @@ void LinkPrivate::loadImplicitDirectoryImports(Imports *imports, Document::Ptr d void LinkPrivate::loadImplicitDefaultImports(Imports *imports) { const QString defaultPackage = CppQmlTypes::defaultPackage; - if (valueOwner->cppQmlTypes().hasPackage(defaultPackage)) { + if (valueOwner->cppQmlTypes().hasModule(defaultPackage)) { ImportInfo info(ImportInfo::LibraryImport, defaultPackage); Import import = importCache.value(ImportCacheKey(info)); if (!import.object) { import.info = info; import.object = new ObjectValue(valueOwner); - foreach (QmlObjectValue *object, - valueOwner->cppQmlTypes().typesForImport( + foreach (const QmlObjectValue *object, + valueOwner->cppQmlTypes().createObjectsForImport( defaultPackage, ComponentVersion(ComponentVersion::MaxVersion, ComponentVersion::MaxVersion))) { import.object->setMember(object->className(), object); diff --git a/src/libs/qmljs/qmljsscopebuilder.cpp b/src/libs/qmljs/qmljsscopebuilder.cpp index 0e455da1d7..3d0ac107ed 100644 --- a/src/libs/qmljs/qmljsscopebuilder.cpp +++ b/src/libs/qmljs/qmljsscopebuilder.cpp @@ -154,8 +154,8 @@ void ScopeBuilder::setQmlScopeObject(Node *node) if (const QmlObjectValue *qmlMetaObject = dynamic_cast(prototype)) { if ((qmlMetaObject->className() == QLatin1String("ListElement") || qmlMetaObject->className() == QLatin1String("Connections") - ) && (qmlMetaObject->packageName() == QLatin1String("Qt") - || qmlMetaObject->packageName() == QLatin1String("QtQuick"))) { + ) && (qmlMetaObject->moduleName() == QLatin1String("Qt") + || qmlMetaObject->moduleName() == QLatin1String("QtQuick"))) { qmlScopeObjects.clear(); break; } @@ -231,8 +231,8 @@ const ObjectValue *ScopeBuilder::isPropertyChangesObject(const ContextPtr &conte const ObjectValue *prototype = iter.next(); if (const QmlObjectValue *qmlMetaObject = dynamic_cast(prototype)) { if (qmlMetaObject->className() == QLatin1String("PropertyChanges") - && (qmlMetaObject->packageName() == QLatin1String("Qt") - || qmlMetaObject->packageName() == QLatin1String("QtQuick"))) + && (qmlMetaObject->moduleName() == QLatin1String("Qt") + || qmlMetaObject->moduleName() == QLatin1String("QtQuick"))) return prototype; } } diff --git a/src/libs/qmljs/qmljsvalueowner.cpp b/src/libs/qmljs/qmljsvalueowner.cpp index 2f0764c0d7..c6ef8fd52c 100644 --- a/src/libs/qmljs/qmljsvalueowner.cpp +++ b/src/libs/qmljs/qmljsvalueowner.cpp @@ -271,7 +271,8 @@ ValueOwner::ValueOwner() _qmlVector3DObject(0), _convertToNumber(this), _convertToString(this), - _convertToObject(this) + _convertToObject(this), + _cppQmlTypes(this) { initializePrototypes(); } diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index 5afb1a343e..d7db630154 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -104,7 +104,7 @@ public: m_properties.append(qMakePair(name, type)); } else { if (const QmlObjectValue * ov = dynamic_cast(value)) { - QString qualifiedTypeName = ov->packageName().isEmpty() ? ov->className() : ov->packageName() + '.' + ov->className(); + QString qualifiedTypeName = ov->moduleName().isEmpty() ? ov->className() : ov->moduleName() + '.' + ov->className(); m_properties.append(qMakePair(name, qualifiedTypeName)); } else { TypeId typeId; @@ -157,11 +157,11 @@ QStringList prototypes(const ObjectValue *ov, const ContextPtr &context, bool ve const QmlObjectValue * qmlValue = dynamic_cast(ov); if (qmlValue) { if (versions) { - list << qmlValue->packageName() + '.' + qmlValue->className() + - ' ' + QString::number(qmlValue->version().majorVersion()) + - '.' + QString::number(qmlValue->version().minorVersion()); + list << qmlValue->moduleName() + '.' + qmlValue->className() + + ' ' + QString::number(qmlValue->componentVersion().majorVersion()) + + '.' + QString::number(qmlValue->componentVersion().minorVersion()); } else { - list << qmlValue->packageName() + QLatin1Char('.') + qmlValue->className(); + list << qmlValue->moduleName() + QLatin1Char('.') + qmlValue->className(); } } else { if (versions) { @@ -436,9 +436,9 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, QString type, int maj, in if (objectValue) { const QmlObjectValue *qmlValue = dynamic_cast(objectValue); if (qmlValue) { - m_majorVersion = qmlValue->version().majorVersion(); - m_minorVersion = qmlValue->version().minorVersion(); - m_qualfiedTypeName = qmlValue->packageName() + '.' + qmlValue->className(); + m_majorVersion = qmlValue->componentVersion().majorVersion(); + m_minorVersion = qmlValue->componentVersion().minorVersion(); + m_qualfiedTypeName = qmlValue->moduleName() + '.' + qmlValue->className(); } else { m_isComponent = true; } @@ -452,73 +452,35 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, QString type, int maj, in } } -static inline QString getUrlFromType(const QString& typeName) -{ - QStringList nameComponents = typeName.split('.'); - QString result; - - for (int i = 0; i < (nameComponents.count() - 1); i++) { - result += nameComponents.at(i); - } - - return result; -} - const QmlJS::QmlObjectValue *NodeMetaInfoPrivate::getQmlObjectValue() const { - QmlJS::QmlObjectValue * value = context()->valueOwner()->cppQmlTypes().typeByQualifiedName(lookupName()); - if (value) - return value; - - //If no version was specified (-1,-1) the approach above does not work. - //But we can look up the value "manually" - //This is usefull to make something like QtQuick.Item -1 -1 work in all cases - //and fix ambiguities with Qt 4.7. - - if (m_majorVersion != -1 || m_minorVersion != -1) - return 0; - - const QString old_qualfiedTypeName = m_qualfiedTypeName; - - //This makes only sense if a package was specified. - if (m_qualfiedTypeName.split(".").count() < 2) + const QStringList nameComponents = m_qualfiedTypeName.split('.'); + if (nameComponents.size() < 2) return 0; + const QString type = nameComponents.last(); - const QString package = getUrlFromType(m_qualfiedTypeName); - const QString type = m_qualfiedTypeName.split('.').last(); - - - LanguageUtils::ComponentVersion version(9999, 9999); - //get the correct version - ImportInfo importInfo = context()->imports(document())->info(fullQualifiedImportAliasType(), context().data()); - - if (importInfo.isValid()) - version = importInfo.version(); + // maybe 'type' is a cpp name + const QmlJS::QmlObjectValue *value = context()->valueOwner()->cppQmlTypes().objectByCppName(type); + if (value) + return value; - QList qmlObjectValues = context()->valueOwner()->cppQmlTypes().typesForImport(package, version); - const QmlObjectValue *qmlValue = 0; - foreach (QmlObjectValue *value, qmlObjectValues) { - if (value->className() == type) - qmlValue = value; + QString module; + for (int i = 0; i < nameComponents.size() - 1; ++i) { + if (i != 0) + module += QLatin1Char('/'); + module += nameComponents.at(i); } - if (!qmlValue) - return 0; - - //Now we have to check the different packages. - const LanguageUtils::FakeMetaObject::Export exp = - qmlValue->metaObject()->exportInPackage(package); - const QString convertedName = exp.type; - - //Not available in the requested package - if (convertedName.isNull()) - return 0; - - //Different name for requested package - if (type != convertedName) - return 0; + // otherwise get the qml object value that's available in the document + foreach (const QmlJS::Import &import, context()->imports(document())->all()) { + if (import.info.name() != module) + continue; + const Value *lookupResult = import.object->lookupMember(type, context()); + if ((value = dynamic_cast(lookupResult))) + return value; + } - return qmlValue; + return 0; } const QmlJS::ObjectValue *NodeMetaInfoPrivate::getObjectValue() const @@ -775,7 +737,7 @@ QStringList NodeMetaInfoPrivate::keysForEnum(const QString &enumName) const QString NodeMetaInfoPrivate::packageName() const { if (!isComponent()) - return getQmlObjectValue()->packageName(); + return getQmlObjectValue()->moduleName(); return QString(); } @@ -855,10 +817,10 @@ void NodeMetaInfoPrivate::setupPrototypes() description.minorVersion = -1; description.majorVersion = -1; if (const QmlObjectValue * qmlValue = dynamic_cast(ov)) { - description.minorVersion = qmlValue->version().minorVersion(); - description.majorVersion = qmlValue->version().majorVersion(); - if (!qmlValue->packageName().isEmpty()) - description.className = qmlValue->packageName() + '.' + description.className; + description.minorVersion = qmlValue->componentVersion().minorVersion(); + description.majorVersion = qmlValue->componentVersion().majorVersion(); + if (!qmlValue->moduleName().isEmpty()) + description.className = qmlValue->moduleName() + '.' + description.className; m_prototypes.append(description); } else { if (context()->lookupType(document(), QStringList() << ov->className())) diff --git a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp index b636fd83ce..bab7cf2acf 100644 --- a/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp @@ -362,11 +362,11 @@ public: const QmlObjectValue * qmlValue = dynamic_cast(value); if (qmlValue) { - typeName = fixUpPackeNameForQt(qmlValue->packageName()) + QLatin1String(".") + qmlValue->className(); + typeName = fixUpPackeNameForQt(qmlValue->moduleName()) + QLatin1String(".") + qmlValue->className(); //### todo this is just a hack to support QtQuick 1.0 - majorVersion = fixUpMajorVersionForQt(qmlValue->packageName(), qmlValue->version().majorVersion()); - minorVersion = fixUpMinorVersionForQt(qmlValue->packageName(), qmlValue->version().minorVersion()); + majorVersion = fixUpMajorVersionForQt(qmlValue->moduleName(), qmlValue->componentVersion().majorVersion()); + minorVersion = fixUpMinorVersionForQt(qmlValue->moduleName(), qmlValue->componentVersion().minorVersion()); } else { for (UiQualifiedId *iter = astTypeNode; iter; iter = iter->next) if (!iter->next && !iter->name.isEmpty()) diff --git a/src/plugins/qmljseditor/qmljscompletionassist.cpp b/src/plugins/qmljseditor/qmljscompletionassist.cpp index eaf4c48d2d..4f0ac4187e 100644 --- a/src/plugins/qmljseditor/qmljscompletionassist.cpp +++ b/src/plugins/qmljseditor/qmljscompletionassist.cpp @@ -79,23 +79,114 @@ enum CompletionOrder { TypeOrder = -30 }; -class EnumerateProperties: private MemberProcessor +static void addCompletion(QList *completions, + const QString &text, + const QIcon &icon, + int order, + const QVariant &data = QVariant()) +{ + if (text.isEmpty()) + return; + + BasicProposalItem *item = new QmlJSAssistProposalItem; + item->setText(text); + item->setIcon(icon); + item->setOrder(order); + item->setData(data); + completions->append(item); +} + +static void addCompletions(QList *completions, + const QStringList &newCompletions, + const QIcon &icon, + int order) +{ + foreach (const QString &text, newCompletions) + addCompletion(completions, text, icon, order); +} + +class PropertyProcessor +{ +public: + virtual void operator()(const Value *base, const QString &name, const Value *value) = 0; +}; + +class CompletionAdder : public PropertyProcessor +{ +protected: + QList *completions; + +public: + CompletionAdder(QList *completions, + const QIcon &icon, int order) + : completions(completions) + , icon(icon) + , order(order) + {} + + virtual void operator()(const Value *base, const QString &name, const Value *value) + { + Q_UNUSED(base) + Q_UNUSED(value) + addCompletion(completions, name, icon, order); + } + + QIcon icon; + int order; +}; + +class LhsCompletionAdder : public CompletionAdder +{ +public: + LhsCompletionAdder(QList *completions, + const QIcon &icon, + int order, + bool afterOn) + : CompletionAdder(completions, icon, order) + , afterOn(afterOn) + {} + + virtual void operator ()(const Value *base, const QString &name, const Value *) + { + const QmlObjectValue *qmlBase = dynamic_cast(base); + + QString itemText = name; + QString postfix; + if (!itemText.isEmpty() && itemText.at(0).isLower()) + postfix = QLatin1String(": "); + if (afterOn) + postfix = QLatin1String(" {"); + + // readonly pointer properties (anchors, ...) always get a . + if (qmlBase && !qmlBase->isWritable(name) && qmlBase->isPointer(name)) + postfix = QLatin1Char('.'); + + itemText.append(postfix); + + addCompletion(completions, itemText, icon, order); + } + + bool afterOn; +}; + +class ProcessProperties: private MemberProcessor { QSet _processed; - QHash _properties; bool _globalCompletion; bool _enumerateGeneratedSlots; bool _enumerateSlots; const ScopeChain *_scopeChain; const ObjectValue *_currentObject; + PropertyProcessor *_propertyProcessor; public: - EnumerateProperties(const ScopeChain *scopeChain) + ProcessProperties(const ScopeChain *scopeChain) : _globalCompletion(false), _enumerateGeneratedSlots(false), _enumerateSlots(true), _scopeChain(scopeChain), - _currentObject(0) + _currentObject(0), + _propertyProcessor(0) { } @@ -114,59 +205,53 @@ public: _enumerateSlots = enumerate; } - QHash operator ()(const Value *value) + void operator ()(const Value *value, PropertyProcessor *processor) { _processed.clear(); - _properties.clear(); - _currentObject = value_cast(value); - - enumerateProperties(value); + _propertyProcessor = processor; - return _properties; + processProperties(value); } - QHash operator ()() + void operator ()(PropertyProcessor *processor) { _processed.clear(); - _properties.clear(); - _currentObject = 0; + _propertyProcessor = processor; foreach (const ObjectValue *scope, _scopeChain->all()) - enumerateProperties(scope); - - return _properties; + processProperties(scope); } private: - void insertProperty(const QString &name, const Value *value) + void process(const QString &name, const Value *value) { - _properties.insert(name, value); + (*_propertyProcessor)(_currentObject, name, value); } virtual bool processProperty(const QString &name, const Value *value) { - insertProperty(name, value); + process(name, value); return true; } virtual bool processEnumerator(const QString &name, const Value *value) { if (! _globalCompletion) - insertProperty(name, value); + process(name, value); return true; } virtual bool processSignal(const QString &name, const Value *value) { if (_globalCompletion) - insertProperty(name, value); + process(name, value); return true; } virtual bool processSlot(const QString &name, const Value *value) { if (_enumerateSlots) - insertProperty(name, value); + process(name, value); return true; } @@ -174,29 +259,31 @@ private: { if (_enumerateGeneratedSlots || (_currentObject && _currentObject->className().endsWith(QLatin1String("Keys")))) { // ### FIXME: add support for attached properties. - insertProperty(name, value); + process(name, value); } return true; } - void enumerateProperties(const Value *value) + void processProperties(const Value *value) { if (! value) return; else if (const ObjectValue *object = value->asObjectValue()) { - enumerateProperties(object); + processProperties(object); } } - void enumerateProperties(const ObjectValue *object) + void processProperties(const ObjectValue *object) { if (! object || _processed.contains(object)) return; _processed.insert(object); - enumerateProperties(object->prototype(_scopeChain->context())); + processProperties(object->prototype(_scopeChain->context())); + _currentObject = object; object->processMembers(this); + _currentObject = 0; } }; @@ -523,10 +610,10 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface doJsKeywordCompletion = false; doQmlTypeCompletion = true; - EnumerateProperties enumerateProperties(&scopeChain); - enumerateProperties.setGlobalCompletion(true); - enumerateProperties.setEnumerateGeneratedSlots(true); - enumerateProperties.setEnumerateSlots(false); + ProcessProperties processProperties(&scopeChain); + processProperties.setGlobalCompletion(true); + processProperties.setEnumerateGeneratedSlots(true); + processProperties.setEnumerateSlots(false); // id: is special BasicProposalItem *idProposalItem = new QmlJSAssistProposalItem; @@ -535,16 +622,16 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface idProposalItem->setOrder(PropertyOrder); m_completions.append(idProposalItem); - addCompletionsPropertyLhs(enumerateProperties(qmlScopeType), - m_interface->symbolIcon(), - PropertyOrder, - contextFinder.isAfterOnInLhsOfBinding()); + { + LhsCompletionAdder completionAdder(&m_completions, m_interface->symbolIcon(), + PropertyOrder, contextFinder.isAfterOnInLhsOfBinding()); + processProperties(qmlScopeType, &completionAdder); + } if (ScopeBuilder::isPropertyChangesObject(context, qmlScopeType) && scopeChain.qmlScopeObjects().size() == 2) { - addCompletions(enumerateProperties(scopeChain.qmlScopeObjects().first()), - m_interface->symbolIcon(), - SymbolOrder); + CompletionAdder completionAdder(&m_completions, m_interface->symbolIcon(), SymbolOrder); + processProperties(scopeChain.qmlScopeObjects().first(), &completionAdder); } } @@ -557,7 +644,7 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface if (const QmlEnumValue *enumValue = dynamic_cast(value)) { foreach (const QString &key, enumValue->keys()) - addCompletion(key, m_interface->symbolIcon(), + addCompletion(&m_completions, key, m_interface->symbolIcon(), EnumValueOrder, QString("%1.%2").arg(enumValue->owner()->className(), key)); } } @@ -567,21 +654,23 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface if (doQmlTypeCompletion) { if (const ObjectValue *qmlTypes = scopeChain.qmlTypes()) { - EnumerateProperties enumerateProperties(&scopeChain); - addCompletions(enumerateProperties(qmlTypes), m_interface->symbolIcon(), TypeOrder); + ProcessProperties processProperties(&scopeChain); + CompletionAdder completionAdder(&m_completions, m_interface->symbolIcon(), TypeOrder); + processProperties(qmlTypes, &completionAdder); } } if (doGlobalCompletion) { // It's a global completion. - EnumerateProperties enumerateProperties(&scopeChain); - enumerateProperties.setGlobalCompletion(true); - addCompletions(enumerateProperties(), m_interface->symbolIcon(), SymbolOrder); + ProcessProperties processProperties(&scopeChain); + processProperties.setGlobalCompletion(true); + CompletionAdder completionAdder(&m_completions, m_interface->symbolIcon(), SymbolOrder); + processProperties(&completionAdder); } if (doJsKeywordCompletion) { // add js keywords - addCompletions(Scanner::keywords(), m_interface->keywordIcon(), KeywordOrder); + addCompletions(&m_completions, Scanner::keywords(), m_interface->keywordIcon(), KeywordOrder); } // add qml extra words @@ -598,9 +687,9 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface if (qmlWordsAlsoInJs.isEmpty()) qmlWordsAlsoInJs << QLatin1String("default") << QLatin1String("function"); - addCompletions(qmlWords, m_interface->keywordIcon(), KeywordOrder); + addCompletions(&m_completions, qmlWords, m_interface->keywordIcon(), KeywordOrder); if (!doJsKeywordCompletion) - addCompletions(qmlWordsAlsoInJs, m_interface->keywordIcon(), KeywordOrder); + addCompletions(&m_completions, qmlWordsAlsoInJs, m_interface->keywordIcon(), KeywordOrder); } } @@ -621,15 +710,16 @@ IAssistProposal *QmlJSCompletionAssistProcessor::perform(const IAssistInterface //qDebug() << "type:" << interp->typeId(value); if (value && completionOperator == QLatin1Char('.')) { // member completion - EnumerateProperties enumerateProperties(&scopeChain); + ProcessProperties processProperties(&scopeChain); if (contextFinder.isInLhsOfBinding() && qmlScopeType) { - enumerateProperties.setEnumerateGeneratedSlots(true); - addCompletionsPropertyLhs(enumerateProperties(value), - m_interface->symbolIcon(), - PropertyOrder, - contextFinder.isAfterOnInLhsOfBinding()); - } else - addCompletions(enumerateProperties(value), m_interface->symbolIcon(), SymbolOrder); + LhsCompletionAdder completionAdder(&m_completions, m_interface->symbolIcon(), + PropertyOrder, contextFinder.isAfterOnInLhsOfBinding()); + processProperties.setEnumerateGeneratedSlots(true); + processProperties(value, &completionAdder); + } else { + CompletionAdder completionAdder(&m_completions, m_interface->symbolIcon(), SymbolOrder); + processProperties(value, &completionAdder); + } } else if (value && completionOperator == QLatin1Char('(') && m_startPosition == m_interface->position()) { @@ -768,74 +858,6 @@ bool QmlJSCompletionAssistProcessor::completeUrl(const QString &relativeBasePath return completeFileName(relativeBasePath, fileName); } -void QmlJSCompletionAssistProcessor::addCompletionsPropertyLhs(const QHash &newCompletions, - const QIcon &icon, - int order, - bool afterOn) -{ - QHashIterator it(newCompletions); - while (it.hasNext()) { - it.next(); - - QString itemText = it.key(); - QString postfix; - if (!itemText.isEmpty() && itemText.at(0).isLower()) - postfix = QLatin1String(": "); - if (afterOn) - postfix = QLatin1String(" {"); - if (const QmlObjectValue *qmlValue = - dynamic_cast(it.value())) { - // to distinguish "anchors." from "gradient:" we check if the right hand side - // type is instantiatable or is the prototype of an instantiatable object - if (qmlValue->hasChildInPackage()) - itemText.append(postfix); - else - itemText.append(QLatin1Char('.')); - } else { - itemText.append(postfix); - } - - addCompletion(itemText, icon, order); - } -} - -void QmlJSCompletionAssistProcessor::addCompletion(const QString &text, - const QIcon &icon, - int order, - const QVariant &data) -{ - if (text.isEmpty()) - return; - - BasicProposalItem *item = new QmlJSAssistProposalItem; - item->setText(text); - item->setIcon(icon); - item->setOrder(order); - item->setData(data); - m_completions.append(item); -} - -void QmlJSCompletionAssistProcessor::addCompletions(const QHash &newCompletions, - const QIcon &icon, - int order) -{ - QHashIterator it(newCompletions); - while (it.hasNext()) { - it.next(); - addCompletion(it.key(), icon, order); - } -} - -void QmlJSCompletionAssistProcessor::addCompletions(const QStringList &newCompletions, - const QIcon &icon, - int order) -{ - foreach (const QString &text, newCompletions) - addCompletion(text, icon, order); -} - // ------------------------------ // QmlJSCompletionAssistInterface // ------------------------------ diff --git a/src/plugins/qmljseditor/qmljscompletionassist.h b/src/plugins/qmljseditor/qmljscompletionassist.h index bf7ed02bda..3d63948fe3 100644 --- a/src/plugins/qmljseditor/qmljscompletionassist.h +++ b/src/plugins/qmljseditor/qmljscompletionassist.h @@ -109,20 +109,6 @@ private: const QString &fileName, const QStringList &patterns = QStringList()); - void addCompletion(const QString &text, - const QIcon &icon, - int order, - const QVariant &data = QVariant()); - void addCompletions(const QHash &newCompletions, - const QIcon &icon, - int order); - void addCompletions(const QStringList &newCompletions, const QIcon &icon, int order); - void addCompletionsPropertyLhs(const QHash &newCompletions, - const QIcon &icon, - int order, - bool afterOn); - int m_startPosition; QScopedPointer m_interface; QList m_completions; diff --git a/src/plugins/qmljseditor/qmljssemantichighlighter.cpp b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp index c0ba42675b..229ecc0eb2 100644 --- a/src/plugins/qmljseditor/qmljssemantichighlighter.cpp +++ b/src/plugins/qmljseditor/qmljssemantichighlighter.cpp @@ -100,7 +100,7 @@ public: CollectStateNames(const ScopeChain &scopeChain) : m_scopeChain(scopeChain) { - m_statePrototype = scopeChain.context()->valueOwner()->cppQmlTypes().typeByCppName(QLatin1String("QDeclarativeState")); + m_statePrototype = scopeChain.context()->valueOwner()->cppQmlTypes().objectByCppName(QLatin1String("QDeclarativeState")); } QStringList operator()(Node *ast) -- cgit v1.2.1