diff options
| author | Joerg Bornemann <joerg.bornemann@digia.com> | 2013-04-09 11:47:19 +0200 |
|---|---|---|
| committer | Christian Kandeler <christian.kandeler@digia.com> | 2013-04-10 12:30:23 +0200 |
| commit | 66068863ca647c5216b0fb7ee8ce933ef6aea077 (patch) | |
| tree | 26be59e5c747c4dcabecc5aec4c4de79227bb82b | |
| parent | 35710e2ebe7e3f0a2ada05bedb0868ed2edda14f (diff) | |
| download | qbs-66068863ca647c5216b0fb7ee8ce933ef6aea077.tar.gz | |
fix scope of own properties of module instances
Own properties of module instances must not have the instance itself in
the scope.
This fixes the following case:
Product {
name: "foo"
Depends { name: "cpp" }
cpp.defines: [name.toUpperCase()] // expected result: ["FOO"]
}
Task-number: QBS-252
Change-Id: Iac3d7153918132d01aec980a19502e9817f5e31d
Reviewed-by: Christian Kandeler <christian.kandeler@digia.com>
| -rw-r--r-- | src/lib/language/evaluatorscriptclass.cpp | 19 | ||||
| -rw-r--r-- | src/lib/language/evaluatorscriptclass.h | 3 | ||||
| -rw-r--r-- | src/lib/language/item.cpp | 1 | ||||
| -rw-r--r-- | src/lib/language/item.h | 13 | ||||
| -rw-r--r-- | src/lib/language/moduleloader.cpp | 1 | ||||
| -rw-r--r-- | src/lib/language/tst_language.cpp | 1 |
6 files changed, 31 insertions, 7 deletions
diff --git a/src/lib/language/evaluatorscriptclass.cpp b/src/lib/language/evaluatorscriptclass.cpp index 8404e5384..95c3df1da 100644 --- a/src/lib/language/evaluatorscriptclass.cpp +++ b/src/lib/language/evaluatorscriptclass.cpp @@ -50,6 +50,7 @@ class SVConverter : ValueHandler QScriptContext *const scriptContext; const QScriptValue *object; const ValuePtr &valuePtr; + const bool inPrototype; char pushedScopesCount; public: @@ -57,12 +58,14 @@ public: const EvaluationData *data; QScriptValue *result; - SVConverter(EvaluatorScriptClass *esc, const QScriptValue *obj, const ValuePtr &v) + SVConverter(EvaluatorScriptClass *esc, const QScriptValue *obj, const ValuePtr &v, + bool _inPrototype) : scriptClass(esc) , engine(esc->engine()) , scriptContext(esc->engine()->currentContext()) , object(obj) , valuePtr(v) + , inPrototype(_inPrototype) , pushedScopesCount(0) { } @@ -157,7 +160,7 @@ private: if (value->sourceUsesBase()) { QScriptValue baseValue; if (value->baseValue()) { - SVConverter converter(scriptClass, object, value->baseValue()); + SVConverter converter(scriptClass, object, value->baseValue(), inPrototype); converter.propertyName = propertyName; converter.data = data; converter.result = &baseValue; @@ -171,11 +174,13 @@ private: pushScope(data->evaluator->fileScope(value->file())); pushItemScopes(data->item); - scriptContext->pushScope(*object); + if (inPrototype || !data->item->isModuleInstance()) { + // Own properties of module instances must not have the instance itself in the scope. + pushScope(*object); + } pushScope(extraScope); *result = engine->evaluate(value->sourceCode()); popScopes(); - scriptContext->popScope(); } void handle(ItemValue *value) @@ -255,6 +260,8 @@ QScriptClass::QueryFlags EvaluatorScriptClass::queryItemProperty(const Evaluatio m_queryResult.value = item->properties().value(name); if (!m_queryResult.value.isNull()) { m_queryResult.data = data; + if (data->item != item) + m_queryResult.inPrototype = true; return HandlesReadAccess; } } @@ -297,7 +304,9 @@ QScriptValue EvaluatorScriptClass::property(const QScriptValue &object, const QS uint id) { const EvaluationData *data = m_queryResult.data; + const bool inPrototype = m_queryResult.inPrototype; m_queryResult.data = 0; + m_queryResult.inPrototype = false; QBS_ASSERT(data, return QScriptValue()); const QueryPropertyType qpt = static_cast<QueryPropertyType>(id); @@ -321,7 +330,7 @@ QScriptValue EvaluatorScriptClass::property(const QScriptValue &object, const QS return result; } - SVConverter converter(this, &object, value); + SVConverter converter(this, &object, value, inPrototype); converter.propertyName = &name; converter.data = data; converter.result = &result; diff --git a/src/lib/language/evaluatorscriptclass.h b/src/lib/language/evaluatorscriptclass.h index cfbabefa3..60da663d7 100644 --- a/src/lib/language/evaluatorscriptclass.h +++ b/src/lib/language/evaluatorscriptclass.h @@ -70,7 +70,7 @@ private: struct QueryResult { QueryResult() - : data(0) + : data(0), inPrototype(false) {} bool isNull() const @@ -79,6 +79,7 @@ private: } const EvaluationData *data; + bool inPrototype; ValuePtr value; }; QueryResult m_queryResult; diff --git a/src/lib/language/item.cpp b/src/lib/language/item.cpp index 1adc0a5c8..b0ec37db2 100644 --- a/src/lib/language/item.cpp +++ b/src/lib/language/item.cpp @@ -36,6 +36,7 @@ namespace Internal { Item::Item() : m_propertyObserver(0) + , m_moduleInstance(false) { } diff --git a/src/lib/language/item.h b/src/lib/language/item.h index cb1fcbe4e..233e5b1b7 100644 --- a/src/lib/language/item.h +++ b/src/lib/language/item.h @@ -72,6 +72,7 @@ public: const CodeLocation &location() const; const ItemPtr &prototype() const; ItemPtr scope() const; + bool isModuleInstance() const; WeakPointer<Item> outerItem() const; WeakPointer<Item> parent() const; const FileContextPtr file() const; @@ -93,6 +94,7 @@ public: void setPrototype(const ItemPtr &prototype); void setFile(const FileContextPtr &file); void setScope(const ItemPtr &item); + void setModuleInstanceFlag(bool b); void setOuterItem(const ItemPtr &item); void setChildren(const QList<ItemPtr> &children); void setParent(const ItemPtr &item); @@ -105,6 +107,7 @@ private: CodeLocation m_location; ItemPtr m_prototype; ItemPtr m_scope; + bool m_moduleInstance; WeakPointer<Item> m_outerItem; WeakPointer<Item> m_parent; QList<ItemPtr> m_children; @@ -140,6 +143,11 @@ inline ItemPtr Item::scope() const return m_scope; } +inline bool Item::isModuleInstance() const +{ + return m_moduleInstance; +} + inline WeakPointer<Item> Item::outerItem() const { return m_outerItem; @@ -202,6 +210,11 @@ inline void Item::setScope(const ItemPtr &item) m_scope = item; } +inline void Item::setModuleInstanceFlag(bool b) +{ + m_moduleInstance = b; +} + inline void Item::setOuterItem(const ItemPtr &item) { m_outerItem = item; diff --git a/src/lib/language/moduleloader.cpp b/src/lib/language/moduleloader.cpp index dc6655031..06a9fa59b 100644 --- a/src/lib/language/moduleloader.cpp +++ b/src/lib/language/moduleloader.cpp @@ -547,6 +547,7 @@ void ModuleLoader::instantiateModule(ProductContext *productContext, const ItemP copyProperty(QLatin1String("project"), productContext->project->scope, moduleScope); copyProperty(QLatin1String("product"), productContext->scope, moduleScope); moduleInstance->setScope(moduleScope); + moduleInstance->setModuleInstanceFlag(true); QHash<ItemPtr, ItemPtr> prototypeInstanceMap; prototypeInstanceMap[modulePrototype] = moduleInstance; diff --git a/src/lib/language/tst_language.cpp b/src/lib/language/tst_language.cpp index 4f34683bb..df7adb986 100644 --- a/src/lib/language/tst_language.cpp +++ b/src/lib/language/tst_language.cpp @@ -637,7 +637,6 @@ void TestLanguage::moduleScope() QCOMPARE(ipf.intValue("d"), 2); // genuine, dependent on genuine value QCOMPARE(ipf.intValue("e"), 1); // genuine QCOMPARE(ipf.intValue("f"), 2); // overridden - QEXPECT_FAIL("", "QBS-252", Abort); QCOMPARE(ipf.intValue("g"), 156); // overridden, dependent on product properties QCOMPARE(ipf.intValue("h"), 158); // overridden, base dependent on product properties } |
