QmlJS: Return owning object from lookupMember.

This commit is contained in:
Christian Kamm
2010-11-17 14:20:06 +01:00
parent 4d5cdb3ed8
commit aa2d9e6dd6
4 changed files with 40 additions and 56 deletions

View File

@@ -1871,15 +1871,22 @@ void ObjectValue::processMembers(MemberProcessor *processor) const
} }
} }
const Value *ObjectValue::lookupMember(const QString &name, const Context *context, bool examinePrototypes) const const Value *ObjectValue::lookupMember(const QString &name, const Context *context,
const ObjectValue **foundInObject,
bool examinePrototypes) const
{ {
if (const Value *m = _members.value(name)) if (const Value *m = _members.value(name)) {
if (foundInObject)
*foundInObject = this;
return m; return m;
else { } else {
LookupMember slowLookup(name); LookupMember slowLookup(name);
processMembers(&slowLookup); processMembers(&slowLookup);
if (slowLookup.value()) if (slowLookup.value()) {
if (foundInObject)
*foundInObject = this;
return slowLookup.value(); return slowLookup.value();
}
} }
if (examinePrototypes) { if (examinePrototypes) {
@@ -1887,11 +1894,13 @@ const Value *ObjectValue::lookupMember(const QString &name, const Context *conte
iter.next(); // skip this iter.next(); // skip this
while (iter.hasNext()) { while (iter.hasNext()) {
const ObjectValue *prototypeObject = iter.next(); const ObjectValue *prototypeObject = iter.next();
if (const Value *m = prototypeObject->lookupMember(name, context, false)) if (const Value *m = prototypeObject->lookupMember(name, context, foundInObject, false))
return m; return m;
} }
} }
if (foundInObject)
*foundInObject = 0;
return 0; return 0;
} }
@@ -3501,7 +3510,8 @@ TypeEnvironment::TypeEnvironment(Engine *engine)
{ {
} }
const Value *TypeEnvironment::lookupMember(const QString &name, const Context *context, bool) const const Value *TypeEnvironment::lookupMember(const QString &name, const Context *context,
const ObjectValue **foundInObject, bool) const
{ {
QHashIterator<const ObjectValue *, ImportInfo> it(_imports); QHashIterator<const ObjectValue *, ImportInfo> it(_imports);
while (it.hasNext()) { while (it.hasNext()) {
@@ -3510,19 +3520,27 @@ const Value *TypeEnvironment::lookupMember(const QString &name, const Context *c
const ImportInfo &info = it.value(); const ImportInfo &info = it.value();
if (!info.id().isEmpty()) { if (!info.id().isEmpty()) {
if (info.id() == name) if (info.id() == name) {
if (foundInObject)
*foundInObject = this;
return import; return import;
}
continue; continue;
} }
if (info.type() == ImportInfo::FileImport) { if (info.type() == ImportInfo::FileImport) {
if (import->className() == name) if (import->className() == name) {
if (foundInObject)
*foundInObject = this;
return import; return import;
}
} else { } else {
if (const Value *v = import->property(name, context)) if (const Value *v = import->lookupMember(name, context, foundInObject))
return v; return v;
} }
} }
if (foundInObject)
*foundInObject = 0;
return 0; return 0;
} }

View File

@@ -407,7 +407,9 @@ public:
virtual void setProperty(const QString &name, const Value *value); virtual void setProperty(const QString &name, const Value *value);
virtual void removeProperty(const QString &name); virtual void removeProperty(const QString &name);
virtual const Value *lookupMember(const QString &name, const Context *context, bool examinePrototypes = true) const; virtual const Value *lookupMember(const QString &name, const Context *context,
const ObjectValue **foundInObject = 0,
bool examinePrototypes = true) const;
// Value interface // Value interface
virtual const ObjectValue *asObjectValue() const; virtual const ObjectValue *asObjectValue() const;
@@ -989,7 +991,9 @@ class QMLJS_EXPORT TypeEnvironment: public ObjectValue
public: public:
TypeEnvironment(Engine *engine); TypeEnvironment(Engine *engine);
virtual const Value *lookupMember(const QString &name, const Context *context, bool examinePrototypes) const; virtual const Value *lookupMember(const QString &name, const Context *context,
const ObjectValue **foundInObject = 0,
bool examinePrototypes = true) const;
virtual void processMembers(MemberProcessor *processor) const; virtual void processMembers(MemberProcessor *processor) const;
void addImport(const ObjectValue *import, const ImportInfo &info); void addImport(const ObjectValue *import, const ImportInfo &info);

View File

@@ -399,14 +399,7 @@ public:
return hasQuotes ? QVariant(cleanedValue) : cleverConvert(cleanedValue); return hasQuotes ? QVariant(cleanedValue) : cleverConvert(cleanedValue);
} }
Interpreter::PrototypeIterator iter(containingObject, m_context); containingObject->lookupMember(name, m_context, &containingObject);
while (iter.hasNext()) {
const Interpreter::ObjectValue *proto = iter.next();
if (proto->lookupMember(name, m_context, false)) {
containingObject = proto;
break;
}
}
if (const Interpreter::QmlObjectValue * qmlObject = dynamic_cast<const Interpreter::QmlObjectValue *>(containingObject)) { if (const Interpreter::QmlObjectValue * qmlObject = dynamic_cast<const Interpreter::QmlObjectValue *>(containingObject)) {
const QString typeName = qmlObject->propertyType(name); const QString typeName = qmlObject->propertyType(name);
@@ -450,14 +443,7 @@ public:
return QVariant(); return QVariant();
} }
Interpreter::PrototypeIterator iter(containingObject, m_context); containingObject->lookupMember(name, m_context, &containingObject);
while (iter.hasNext()) {
const Interpreter::ObjectValue *proto = iter.next();
if (proto->lookupMember(name, m_context, false)) {
containingObject = proto;
break;
}
}
const Interpreter::QmlObjectValue * lhsQmlObject = dynamic_cast<const Interpreter::QmlObjectValue *>(containingObject); const Interpreter::QmlObjectValue * lhsQmlObject = dynamic_cast<const Interpreter::QmlObjectValue *>(containingObject);
if (!lhsQmlObject) if (!lhsQmlObject)
return QVariant(); return QVariant();
@@ -479,14 +465,7 @@ public:
rhsValueName = memberExp->name->asString(); rhsValueName = memberExp->name->asString();
} }
iter = Interpreter::PrototypeIterator(rhsValueObject, m_context); rhsValueObject->lookupMember(rhsValueName, m_context, &rhsValueObject);
while (iter.hasNext()) {
const Interpreter::ObjectValue *proto = iter.next();
if (proto->lookupMember(rhsValueName, m_context, false)) {
rhsValueObject = proto;
break;
}
}
const Interpreter::QmlObjectValue *rhsQmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(rhsValueObject); const Interpreter::QmlObjectValue *rhsQmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(rhsValueObject);
if (!rhsQmlObjectValue) if (!rhsQmlObjectValue)

View File

@@ -64,25 +64,6 @@ using namespace QmlJS::Interpreter;
using namespace QmlJS::AST; using namespace QmlJS::AST;
using namespace QmlJSEditor; using namespace QmlJSEditor;
static const ObjectValue *prototypeWithMember(const Context *context, const ObjectValue *object, const QString &name)
{
if (!object)
return 0;
const Value *value = object->property(name, context);
if (!value)
return 0;
const ObjectValue *prev = object;
PrototypeIterator iter(object, context);
iter.next();
while (iter.hasNext()) {
const ObjectValue *prototype = iter.next();
if (prototype->property(name, context) != value)
return prev;
prev = prototype;
}
return prev;
}
namespace { namespace {
// ### These visitors could be useful in general // ### These visitors could be useful in general
@@ -265,7 +246,9 @@ private:
{ {
if (!s) if (!s)
return false; return false;
return prototypeWithMember(_context, s, _name) == _scope; const ObjectValue *definingObject;
s->lookupMember(_name, _context, &definingObject);
return definingObject == _scope;
} }
bool checkQmlScope() bool checkQmlScope()
@@ -610,7 +593,7 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
} }
if (!scope) if (!scope)
return; return;
scope = prototypeWithMember(&context, scope, name); scope->lookupMember(name, &context, &scope);
if (!scope) if (!scope)
return; return;