forked from qt-creator/qt-creator
QmlJS: Return owning object from lookupMember.
This commit is contained in:
@@ -1871,27 +1871,36 @@ 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) {
|
||||
PrototypeIterator iter(this, context);
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user