diff --git a/src/libs/qmljs/qmljsdescribevalue.cpp b/src/libs/qmljs/qmljsdescribevalue.cpp index c0c8f2785f1..9213646a843 100644 --- a/src/libs/qmljs/qmljsdescribevalue.cpp +++ b/src/libs/qmljs/qmljsdescribevalue.cpp @@ -187,9 +187,18 @@ public: return true; } - bool processProperty(const QString &name, const Value *value) QTC_OVERRIDE + bool processProperty(const QString &name, const Value *value, const PropertyInfo &pInfo) QTC_OVERRIDE { - return dump(name, value); + d.dumpNewline(); + d.dump(name); + d.openContext(":"); + d.dump("<"); + d.dump(pInfo.toString()); + d.dump(">"); + d.dumpNewline(); // avoid? + value->accept(&d); + d.closeContext(""); + return true; } bool processEnumerator(const QString &name, const Value *value) QTC_OVERRIDE { diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index fbf5725a02b..b02fda890b3 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -107,7 +107,7 @@ public: const Value *value() const { return m_value; } - virtual bool processProperty(const QString &name, const Value *value) + virtual bool processProperty(const QString &name, const Value *value, const PropertyInfo &) { return process(name, value); } @@ -186,6 +186,45 @@ uint qHash(const FakeMetaObjectWithOrigin &fmoo) return qHash(fmoo.fakeMetaObject); } +PropertyInfo::PropertyInfo(uint flags) + : flags(flags) +{ } + +QString PropertyInfo::toString() const +{ + bool join = false; + QString res; + if (isReadable()) { + res += QLatin1String("Readable"); + join = true; + } + if (isWriteable()) { + if (join) + res += QLatin1String("|"); + res += QLatin1String("Writeable"); + join = true; + } + if (isList()) { + if (join) + res += QLatin1String("|"); + res += QLatin1String("ListType"); + join = true; + } + if (canBePointer()) { + if (join) + res += QLatin1String("|"); + res += QLatin1String("Pointer"); + join = true; + } + if (canBeValue()) { + if (join) + res += QLatin1String("|"); + res += QLatin1String("Value"); + join = true; + } + return res; +} + } // namespace QmlJS CppComponentValue::CppComponentValue(FakeMetaObject::ConstPtr metaObject, const QString &className, @@ -303,7 +342,17 @@ void CppComponentValue::processMembers(MemberProcessor *processor) const continue; const QString propertyName = prop.name(); - processor->processProperty(propertyName, valueForCppName(prop.typeName())); + uint propertyFlags = PropertyInfo::Readable; + if (isWritable(propertyName)) + propertyFlags |= PropertyInfo::Writeable; + if (isListProperty(propertyName)) + propertyFlags |= PropertyInfo::ListType; + if (isPointer(propertyName)) + propertyFlags |= PropertyInfo::PointerType; + else + propertyFlags |= PropertyInfo::ValueType; + processor->processProperty(propertyName, valueForCppName(prop.typeName()), + PropertyInfo(propertyFlags)); // every property always has a onXyzChanged slot, even if the NOTIFY // signal has a different name @@ -951,7 +1000,7 @@ MemberProcessor::~MemberProcessor() { } -bool MemberProcessor::processProperty(const QString &, const Value *) +bool MemberProcessor::processProperty(const QString &, const Value *, const PropertyInfo &) { return true; } @@ -1024,7 +1073,12 @@ void ObjectValue::setPrototype(const Value *prototype) void ObjectValue::setMember(const QString &name, const Value *value) { - m_members[name] = value; + m_members[name].value = value; +} + +void ObjectValue::setPropertyInfo(const QString &name, const PropertyInfo &propertyInfo) +{ + m_members[name].propertyInfo = propertyInfo; } void ObjectValue::removeMember(const QString &name) @@ -1063,12 +1117,12 @@ bool ObjectValue::checkPrototype(const ObjectValue *, QSet void ObjectValue::processMembers(MemberProcessor *processor) const { - QHashIterator it(m_members); + QHashIterator it(m_members); while (it.hasNext()) { it.next(); - if (! processor->processProperty(it.key(), it.value())) + if (! processor->processProperty(it.key(), it.value().value, it.value().propertyInfo)) break; } } @@ -1077,7 +1131,7 @@ const Value *ObjectValue::lookupMember(const QString &name, const Context *conte const ObjectValue **foundInObject, bool examinePrototypes) const { - if (const Value *m = m_members.value(name)) { + if (const Value *m = m_members.value(name).value) { if (foundInObject) *foundInObject = this; return m; @@ -1849,7 +1903,10 @@ bool ASTObjectValue::getSourceLocation(QString *fileName, int *line, int *column void ASTObjectValue::processMembers(MemberProcessor *processor) const { foreach (ASTPropertyReference *ref, m_properties) { - processor->processProperty(ref->ast()->name.toString(), ref); + uint pFlags = PropertyInfo::Readable; + if (!ref->ast()->isReadonlyMember) + pFlags |= PropertyInfo::Writeable; + processor->processProperty(ref->ast()->name.toString(), ref, PropertyInfo(pFlags)); // ### Should get a different value? processor->processGeneratedSlot(ref->onChangedSlotName(), ref); } @@ -2334,7 +2391,7 @@ void TypeScope::processMembers(MemberProcessor *processor) const continue; if (!info.as().isEmpty()) - processor->processProperty(info.as(), import); + processor->processProperty(info.as(), import, PropertyInfo(PropertyInfo::Readable)); else import->processMembers(processor); } @@ -2387,7 +2444,7 @@ void JSImportScope::processMembers(MemberProcessor *processor) const const ImportInfo &info = i.info; if (info.type() == ImportType::File || info.type() == ImportType::QrcFile) - processor->processProperty(info.as(), import); + processor->processProperty(info.as(), import, PropertyInfo(PropertyInfo::Readable)); } } @@ -2513,9 +2570,9 @@ class MemberDumper: public MemberProcessor public: MemberDumper() {} - virtual bool processProperty(const QString &name, const Value *) + virtual bool processProperty(const QString &name, const Value *, const PropertyInfo &pInfo) { - qCDebug(qmljsLog) << "property: " << name; + qCDebug(qmljsLog) << "property: " << name << " flags:" << pInfo.toString(); return true; } diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 230d9f03f0b..0a374ce7bb2 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -388,6 +388,44 @@ public: const UrlValue *asUrlValue() const QTC_OVERRIDE; }; +class PropertyInfo { +public: + enum PropertyFlag { + Readable = 1, + Writeable = 2, + ListType = 4, + PointerType= 8, + ValueType = 16, + PointerOrValue = PointerType|ValueType, + Default = Readable|Writeable|PointerOrValue + }; + + PropertyInfo(uint flags = Default); + uint flags; + bool isPointer() const { + return (flags & PointerOrValue) == PointerType; + } + bool isValue() const { + return (flags & PointerOrValue) == ValueType; + } + bool canBePointer() const { + return (flags & PointerType) != 0; + } + bool canBeValue() const { + return (flags & ValueType) != 0; + } + bool isReadable() const { + return (flags & Readable) != 0; + } + bool isWriteable() const { + return (flags & Writeable) != 0; + } + bool isList() const { + return (flags & ListType) != 0; + } + QString toString() const; +}; + class QMLJS_EXPORT MemberProcessor { MemberProcessor(const MemberProcessor &other); @@ -398,7 +436,8 @@ public: virtual ~MemberProcessor(); // Returns false to stop the processor. - virtual bool processProperty(const QString &name, const Value *value); + virtual bool processProperty(const QString &name, const Value *value, + const PropertyInfo &propertyInfo); virtual bool processEnumerator(const QString &name, const Value *value); virtual bool processSignal(const QString &name, const Value *value); virtual bool processSlot(const QString &name, const Value *value); @@ -440,6 +479,16 @@ public: void accept(ValueVisitor *) const QTC_OVERRIDE; }; +class QMLJS_EXPORT PropertyData { +public: + const Value *value; + PropertyInfo propertyInfo; + PropertyData(const Value *value = 0, + PropertyInfo propertyInfo = PropertyInfo(PropertyInfo::Default)) + : value(value), propertyInfo(propertyInfo) + { } +}; + class QMLJS_EXPORT ObjectValue: public Value { public: @@ -462,6 +511,7 @@ public: virtual void processMembers(MemberProcessor *processor) const; virtual void setMember(const QString &name, const Value *value); + virtual void setPropertyInfo(const QString &name, const PropertyInfo &propertyInfo); virtual void removeMember(const QString &name); virtual const Value *lookupMember(const QString &name, const Context *context, @@ -484,7 +534,7 @@ private: private: ValueOwner *m_valueOwner; - QHash m_members; + QHash m_members; QString m_className; QString m_originId; diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index 3eee5fe7c08..303376aea2e 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -278,7 +278,7 @@ class PropertyMemberProcessor : public MemberProcessor public: PropertyMemberProcessor(const ContextPtr &context) : m_context(context) {} - bool processProperty(const QString &name, const Value *value) + bool processProperty(const QString &name, const Value *value, const QmlJS::PropertyInfo &) { PropertyName propertyName = name.toUtf8(); const ASTPropertyReference *ref = value_cast(value); diff --git a/src/plugins/qmljseditor/qmljscompletionassist.cpp b/src/plugins/qmljseditor/qmljscompletionassist.cpp index 015ee485a25..a3eebd02dee 100644 --- a/src/plugins/qmljseditor/qmljscompletionassist.cpp +++ b/src/plugins/qmljseditor/qmljscompletionassist.cpp @@ -245,7 +245,7 @@ private: (*_propertyProcessor)(_currentObject, name, value); } - bool processProperty(const QString &name, const Value *value) QTC_OVERRIDE + bool processProperty(const QString &name, const Value *value, const PropertyInfo &) QTC_OVERRIDE { process(name, value); return true;