summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2011-09-16 13:55:10 +0200
committerChristian Kamm <christian.d.kamm@nokia.com>2011-09-19 13:52:26 +0200
commit6c925cf0fc4f0c6494e5e5639e84970d67ea248b (patch)
tree81d2e75cd1567bf08f8cd0eadbeea8bb91e63739 /src
parent793031c7ba64ca7ba67c6a555bbab49ae2ec0b85 (diff)
downloadqt-creator-6c925cf0fc4f0c6494e5e5639e84970d67ea248b.tar.gz
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 <Thomas.Hartmann@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/libs/qmljs/qmljsinterpreter.cpp298
-rw-r--r--src/libs/qmljs/qmljsinterpreter.h53
-rw-r--r--src/libs/qmljs/qmljslink.cpp38
-rw-r--r--src/libs/qmljs/qmljsscopebuilder.cpp8
-rw-r--r--src/libs/qmljs/qmljsvalueowner.cpp3
-rw-r--r--src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp106
-rw-r--r--src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp6
-rw-r--r--src/plugins/qmljseditor/qmljscompletionassist.cpp268
-rw-r--r--src/plugins/qmljseditor/qmljscompletionassist.h14
-rw-r--r--src/plugins/qmljseditor/qmljssemantichighlighter.cpp2
10 files changed, 363 insertions, 433 deletions
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 <languageutils/fakemetaobject.h>
+#include <utils/qtcassert.h>
#include <QtCore/QFile>
#include <QtCore/QDir>
@@ -54,6 +55,8 @@
#include <QtCore/QProcess>
#include <QtCore/QDebug>
+#include <algorithm>
+
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<QString, QmlObjectValue *> 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("<default>");
const QLatin1String CppQmlTypes::cppPackage("<cpp>");
template <typename T>
-QList<QmlObjectValue *> CppQmlTypes::load(ValueOwner *valueOwner, const T &objects)
-{
- // load
- QList<QmlObjectValue *> loadedObjects;
- QList<QmlObjectValue *> 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<QmlObjectValue *> 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<QmlObjectValue *> CppQmlTypes::load< QList<FakeMetaObject::ConstPtr> >(ValueOwner *, const QList<FakeMetaObject::ConstPtr> &);
-template QList<QmlObjectValue *> CppQmlTypes::load< QHash<QString, FakeMetaObject::ConstPtr> >(ValueOwner *, const QHash<QString, FakeMetaObject::ConstPtr> &);
-
-QList<QmlObjectValue *> CppQmlTypes::typesForImport(const QString &packageName, ComponentVersion version) const
-{
- QHash<QString, QmlObjectValue *> 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<FakeMetaObject::ConstPtr> >(const QList<FakeMetaObject::ConstPtr> &, const QString &);
+template void CppQmlTypes::load< QHash<QString, FakeMetaObject::ConstPtr> >(const QHash<QString, FakeMetaObject::ConstPtr> &, const QString &);
+
+QList<const QmlObjectValue *> CppQmlTypes::createObjectsForImport(const QString &package, ComponentVersion version)
+{
+ QList<const QmlObjectValue *> 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<QmlObjectValue *>(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<int, const Value *> _metaSignature;
QHash<QString, const QmlEnumValue * > _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 <typename T>
- QList<QmlObjectValue *> load(ValueOwner *interpreter, const T &objects);
-
- QList<QmlObjectValue *> 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<QString, QmlObjectValue *> types() const
- { return _typesByFullyQualifiedName; }
+ QList<const QmlObjectValue *> 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<QString, QList<QmlObjectValue *> > _typesByPackage;
- QHash<QString, QmlObjectValue *> _typesByFullyQualifiedName;
+ // "Package.CppName ImportVersion" -> QmlObjectValue
+ QHash<QString, const QmlObjectValue *> _objectsByQualifiedName;
+ QHash<QString, QSet<LanguageUtils::FakeMetaObject::ConstPtr> > _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<ObjectValue *>(valueOwner->qtObject())->setPrototype(valueOwner->cppQmlTypes().typeByCppName(QLatin1String("Qt")));
+ const_cast<ObjectValue *>(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<QmlObjectValue *> 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<const QmlObjectValue *>(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<const QmlObjectValue *>(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<const QmlObjectValue *>(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<const QmlObjectValue *>(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<const QmlObjectValue *>(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<QmlObjectValue *> 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<const QmlObjectValue *>(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<const QmlObjectValue *>(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<const QmlObjectValue *>(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<TextEditor::BasicProposalItem *> *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<TextEditor::BasicProposalItem *> *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<TextEditor::BasicProposalItem *> *completions;
+
+public:
+ CompletionAdder(QList<TextEditor::BasicProposalItem *> *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<TextEditor::BasicProposalItem *> *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<const QmlObjectValue *>(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<const ObjectValue *> _processed;
- QHash<QString, const Value *> _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<QString, const Value *> operator ()(const Value *value)
+ void operator ()(const Value *value, PropertyProcessor *processor)
{
_processed.clear();
- _properties.clear();
- _currentObject = value_cast<const ObjectValue *>(value);
-
- enumerateProperties(value);
+ _propertyProcessor = processor;
- return _properties;
+ processProperties(value);
}
- QHash<QString, const Value *> 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<const QmlEnumValue *>(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<QString,
- const QmlJS::Value *> &newCompletions,
- const QIcon &icon,
- int order,
- bool afterOn)
-{
- QHashIterator<QString, const Value *> 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<const QmlObjectValue *>(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<QString,
- const QmlJS::Value *> &newCompletions,
- const QIcon &icon,
- int order)
-{
- QHashIterator<QString, const Value *> 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<QString, const QmlJS::Value *> &newCompletions,
- const QIcon &icon,
- int order);
- void addCompletions(const QStringList &newCompletions, const QIcon &icon, int order);
- void addCompletionsPropertyLhs(const QHash<QString,
- const QmlJS::Value *> &newCompletions,
- const QIcon &icon,
- int order,
- bool afterOn);
-
int m_startPosition;
QScopedPointer<const QmlJSCompletionAssistInterface> m_interface;
QList<TextEditor::BasicProposalItem *> 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)