forked from qt-creator/qt-creator
QmlJS: Return owning object from lookupMember.
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user