From a5c93306557cfd69f6e6d7181eb4c7d884af4d41 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 12 Jun 2014 15:37:35 +0200 Subject: fix scope chain of conditions of Properties items Conditions of Properties items that were used to set non-module properties were evaluated in the wrong scope. Task-number: QBS-613 Change-Id: Ia28070c4352bcca4c153f3cdfb3b66586ea5f3e5 Reviewed-by: Christian Kandeler --- src/lib/corelib/language/evaluatorscriptclass.cpp | 32 +++++++++- .../corelib/language/testdata/propertiesblocks.qbs | 4 ++ src/lib/corelib/language/tst_language.cpp | 73 ++++++++++++++++------ 3 files changed, 88 insertions(+), 21 deletions(-) diff --git a/src/lib/corelib/language/evaluatorscriptclass.cpp b/src/lib/corelib/language/evaluatorscriptclass.cpp index a5f03b81c..8fcd785eb 100644 --- a/src/lib/corelib/language/evaluatorscriptclass.cpp +++ b/src/lib/corelib/language/evaluatorscriptclass.cpp @@ -128,9 +128,35 @@ private: const JSSourceValue::Alternative *alternative = 0; alternative = &value->alternatives().at(i); if (!conditionScopeItem) { - conditionScopeItem = data->item->scope(); - if (!conditionScopeItem) - conditionScopeItem = data->item; + // We have to differentiate between module instances and normal items here. + // + // The module instance case: + // Product { + // property bool something: true + // Properties { + // condition: something + // cpp.defines: ["ABC"] + // } + // } + // + // data->item points to cpp and the condition's scope chain must contain cpp's + // scope, which is the item where cpp is instantiated. The scope chain must not + // contain data->item itself. + // + // The normal item case: + // Product { + // property bool something: true + // property string value: "ABC" + // Properties { + // condition: something + // value: "DEF" + // } + // } + // + // data->item points to the product and the condition's scope chain must contain + // the product item. + conditionScopeItem = data->item->isModuleInstance() + ? data->item->scope() : data->item; conditionScope = data->evaluator->scriptValue(conditionScopeItem); QBS_ASSERT(conditionScope.isObject(), return); conditionFileScope = data->evaluator->fileScope(conditionScopeItem->file()); diff --git a/src/lib/corelib/language/testdata/propertiesblocks.qbs b/src/lib/corelib/language/testdata/propertiesblocks.qbs index d61f0dd86..2480e9e7b 100644 --- a/src/lib/corelib/language/testdata/propertiesblocks.qbs +++ b/src/lib/corelib/language/testdata/propertiesblocks.qbs @@ -86,19 +86,23 @@ Project { Product { name: "condition_refers_to_product_property" property string narf: true + property string someString: "SOMETHING" Depends { name: "dummy" } Properties { condition: narf dummy.defines: ["OVERWRITTEN"] + someString: "OVERWRITTEN" } } property string zort: true Product { name: "condition_refers_to_project_property" + property string someString: "SOMETHING" Depends { name: "dummy" } Properties { condition: project.zort dummy.defines: ["OVERWRITTEN"] + someString: "OVERWRITTEN" } } ProductBase { diff --git a/src/lib/corelib/language/tst_language.cpp b/src/lib/corelib/language/tst_language.cpp index ff19b8afe..eb77a2df1 100644 --- a/src/lib/corelib/language/tst_language.cpp +++ b/src/lib/corelib/language/tst_language.cpp @@ -1127,45 +1127,77 @@ void TestLanguage::propertiesBlocks_data() { QTest::addColumn("propertyName"); QTest::addColumn("expectedValues"); + QTest::addColumn("expectedStringValue"); - QTest::newRow("init") << QString() << QStringList(); - QTest::newRow("property_overwrite") << QString("dummy.defines") << QStringList("OVERWRITTEN"); - QTest::newRow("property_overwrite_no_outer") << QString("dummy.defines") << QStringList("OVERWRITTEN"); - QTest::newRow("property_append_to_outer") << QString("dummy.defines") << (QStringList() << QString("ONE") << QString("TWO")); + QTest::newRow("init") << QString() << QStringList() << QString(); + QTest::newRow("property_overwrite") + << QString("dummy.defines") + << QStringList("OVERWRITTEN") + << QString(); + QTest::newRow("property_overwrite_no_outer") + << QString("dummy.defines") + << QStringList("OVERWRITTEN") + << QString(); + QTest::newRow("property_append_to_outer") + << QString("dummy.defines") + << (QStringList() << QString("ONE") << QString("TWO")) + << QString(); + + QTest::newRow("multiple_exclusive_properties") + << QString("dummy.defines") + << QStringList("OVERWRITTEN") + << QString(); + QTest::newRow("multiple_exclusive_properties_no_outer") + << QString("dummy.defines") + << QStringList("OVERWRITTEN") + << QString(); + QTest::newRow("multiple_exclusive_properties_append_to_outer") + << QString("dummy.defines") + << (QStringList() << QString("ONE") << QString("TWO")) + << QString(); - QTest::newRow("multiple_exclusive_properties") << QString("dummy.defines") << QStringList("OVERWRITTEN"); - QTest::newRow("multiple_exclusive_properties_no_outer") << QString("dummy.defines") << QStringList("OVERWRITTEN"); - QTest::newRow("multiple_exclusive_properties_append_to_outer") << QString("dummy.defines") << (QStringList() << QString("ONE") << QString("TWO")); QTest::newRow("condition_refers_to_product_property") - << QString("dummy.defines") << QStringList("OVERWRITTEN"); + << QString("dummy.defines") + << QStringList("OVERWRITTEN") + << QString("OVERWRITTEN"); QTest::newRow("condition_refers_to_project_property") - << QString("dummy.defines") << QStringList("OVERWRITTEN"); + << QString("dummy.defines") + << QStringList("OVERWRITTEN") + << QString("OVERWRITTEN"); QTest::newRow("ambiguous_properties") << QString("dummy.defines") - << (QStringList() << QString("ONE") << QString("TWO")); + << (QStringList() << QString("ONE") << QString("TWO")) + << QString(); QTest::newRow("inheritance_overwrite_in_subitem") << QString("dummy.defines") - << (QStringList() << QString("OVERWRITTEN_IN_SUBITEM")); + << (QStringList() << QString("OVERWRITTEN_IN_SUBITEM")) + << QString(); QTest::newRow("inheritance_retain_base1") << QString("dummy.defines") - << (QStringList() << QString("BASE") << QString("SUB")); + << (QStringList() << QString("BASE") << QString("SUB")) + << QString(); QTest::newRow("inheritance_retain_base2") << QString("dummy.defines") - << (QStringList() << QString("BASE") << QString("SUB")); + << (QStringList() << QString("BASE") << QString("SUB")) + << QString(); QTest::newRow("inheritance_retain_base3") << QString("dummy.defines") - << (QStringList() << QString("BASE") << QString("SUB")); + << (QStringList() << QString("BASE") << QString("SUB")) + << QString(); QTest::newRow("inheritance_condition_in_subitem1") << QString("dummy.defines") - << (QStringList() << QString("SOMETHING") << QString("SUB")); + << (QStringList() << QString("SOMETHING") << QString("SUB")) + << QString(); QTest::newRow("inheritance_condition_in_subitem2") << QString("dummy.defines") - << (QStringList() << QString("SOMETHING")); + << (QStringList() << QString("SOMETHING")) + << QString(); QTest::newRow("condition_references_id") << QString("dummy.defines") - << (QStringList() << QString("OVERWRITTEN")); - QTest::newRow("cleanup") << QString() << QStringList(); + << (QStringList() << QString("OVERWRITTEN")) + << QString(); + QTest::newRow("cleanup") << QString() << QStringList() << QString(); } void TestLanguage::propertiesBlocks() @@ -1173,6 +1205,7 @@ void TestLanguage::propertiesBlocks() HANDLE_INIT_CLEANUP_DATATAGS("propertiesblocks.qbs"); QFETCH(QString, propertyName); QFETCH(QStringList, expectedValues); + QFETCH(QString, expectedStringValue); QVERIFY(project); QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); @@ -1181,6 +1214,10 @@ void TestLanguage::propertiesBlocks() QCOMPARE(product->name, productName); QVariant v = productPropertyValue(product, propertyName); QCOMPARE(v.toStringList(), expectedValues); + if (!expectedStringValue.isEmpty()) { + v = productPropertyValue(product, "someString"); + QCOMPARE(v.toString(), expectedStringValue); + } } void TestLanguage::fileTags_data() -- cgit v1.2.3