Commit aa2d9e6d authored by Christian Kamm's avatar Christian Kamm
Browse files

QmlJS: Return owning object from lookupMember.

parent 4d5cdb3e
......@@ -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;
else {
} else {
LookupMember slowLookup(name);
processMembers(&slowLookup);
if (slowLookup.value())
if (slowLookup.value()) {
if (foundInObject)
*foundInObject = this;
return slowLookup.value();
}
}
if (examinePrototypes) {
......@@ -1887,11 +1894,13 @@ const Value *ObjectValue::lookupMember(const QString &name, const Context *conte
iter.next(); // skip this
while (iter.hasNext()) {
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;
}
}
if (foundInObject)
*foundInObject = 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);
while (it.hasNext()) {
......@@ -3510,19 +3520,27 @@ const Value *TypeEnvironment::lookupMember(const QString &name, const Context *c
const ImportInfo &info = it.value();
if (!info.id().isEmpty()) {
if (info.id() == name)
if (info.id() == name) {
if (foundInObject)
*foundInObject = this;
return import;
}
continue;
}
if (info.type() == ImportInfo::FileImport) {
if (import->className() == name)
if (import->className() == name) {
if (foundInObject)
*foundInObject = this;
return import;
}
} else {
if (const Value *v = import->property(name, context))
if (const Value *v = import->lookupMember(name, context, foundInObject))
return v;
}
}
if (foundInObject)
*foundInObject = 0;
return 0;
}
......
......@@ -407,7 +407,9 @@ public:
virtual void setProperty(const QString &name, const Value *value);
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
virtual const ObjectValue *asObjectValue() const;
......@@ -989,7 +991,9 @@ class QMLJS_EXPORT TypeEnvironment: public ObjectValue
public:
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;
void addImport(const ObjectValue *import, const ImportInfo &info);
......
......@@ -399,14 +399,7 @@ public:
return hasQuotes ? QVariant(cleanedValue) : cleverConvert(cleanedValue);
}
Interpreter::PrototypeIterator iter(containingObject, m_context);
while (iter.hasNext()) {
const Interpreter::ObjectValue *proto = iter.next();
if (proto->lookupMember(name, m_context, false)) {
containingObject = proto;
break;
}
}
containingObject->lookupMember(name, m_context, &containingObject);
if (const Interpreter::QmlObjectValue * qmlObject = dynamic_cast<const Interpreter::QmlObjectValue *>(containingObject)) {
const QString typeName = qmlObject->propertyType(name);
......@@ -450,14 +443,7 @@ public:
return QVariant();
}
Interpreter::PrototypeIterator iter(containingObject, m_context);
while (iter.hasNext()) {
const Interpreter::ObjectValue *proto = iter.next();
if (proto->lookupMember(name, m_context, false)) {
containingObject = proto;
break;
}
}
containingObject->lookupMember(name, m_context, &containingObject);
const Interpreter::QmlObjectValue * lhsQmlObject = dynamic_cast<const Interpreter::QmlObjectValue *>(containingObject);
if (!lhsQmlObject)
return QVariant();
......@@ -479,14 +465,7 @@ public:
rhsValueName = memberExp->name->asString();
}
iter = Interpreter::PrototypeIterator(rhsValueObject, m_context);
while (iter.hasNext()) {
const Interpreter::ObjectValue *proto = iter.next();
if (proto->lookupMember(rhsValueName, m_context, false)) {
rhsValueObject = proto;
break;
}
}
rhsValueObject->lookupMember(rhsValueName, m_context, &rhsValueObject);
const Interpreter::QmlObjectValue *rhsQmlObjectValue = dynamic_cast<const Interpreter::QmlObjectValue *>(rhsValueObject);
if (!rhsQmlObjectValue)
......
......@@ -64,25 +64,6 @@ using namespace QmlJS::Interpreter;
using namespace QmlJS::AST;
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 {
// ### These visitors could be useful in general
......@@ -265,7 +246,9 @@ private:
{
if (!s)
return false;
return prototypeWithMember(_context, s, _name) == _scope;
const ObjectValue *definingObject;
s->lookupMember(_name, _context, &definingObject);
return definingObject == _scope;
}
bool checkQmlScope()
......@@ -610,7 +593,7 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
}
if (!scope)
return;
scope = prototypeWithMember(&context, scope, name);
scope->lookupMember(name, &context, &scope);
if (!scope)
return;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment