diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2016-08-30 14:18:08 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2016-11-10 13:32:51 +0000 |
commit | 171a104ec567d660fd3ac44cfc2031ac748f6d56 (patch) | |
tree | c0a77ea99efe21e080264d472127c0101f208bda /src | |
parent | e518441cf636a2839d58d23f9853dbcdeeaad85a (diff) |
Make list properties overridable
Users should be able to "opt out" of values inserted by modules outside
their control.
Change-Id: I4f641b50ea203054759453402fa1e1795f6df4dd
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/corelib/language/astpropertiesitemhandler.cpp | 54 | ||||
-rw-r--r-- | src/lib/corelib/language/evaluatorscriptclass.cpp | 8 | ||||
-rw-r--r-- | src/lib/corelib/language/testdata/moduleproperties.qbs | 10 | ||||
-rw-r--r-- | src/lib/corelib/language/tst_language.cpp | 1 | ||||
-rw-r--r-- | src/lib/corelib/language/value.h | 6 |
5 files changed, 66 insertions, 13 deletions
diff --git a/src/lib/corelib/language/astpropertiesitemhandler.cpp b/src/lib/corelib/language/astpropertiesitemhandler.cpp index c358d658c..faa040604 100644 --- a/src/lib/corelib/language/astpropertiesitemhandler.cpp +++ b/src/lib/corelib/language/astpropertiesitemhandler.cpp @@ -76,12 +76,13 @@ void ASTPropertiesItemHandler::setupAlternatives() class PropertiesBlockConverter { public: - PropertiesBlockConverter(const QString &condition, Item *propertiesBlockContainer, - const Item *propertiesBlock) + PropertiesBlockConverter(const QString &condition, const QString &overrideListProperties, + Item *propertiesBlockContainer, const Item *propertiesBlock) : m_propertiesBlockContainer(propertiesBlockContainer) , m_propertiesBlock(propertiesBlock) { m_alternative.condition = condition; + m_alternative.overrideListProperties = overrideListProperties; } void apply() @@ -98,8 +99,11 @@ private: { for (auto it = inner->properties().constBegin(); it != inner->properties().constEnd(); ++it) { - if (inner == m_propertiesBlock && it.key() == QLatin1String("condition")) + if (inner == m_propertiesBlock + && (it.key() == QLatin1String("condition") + || it.key() == QLatin1String("overrideListProperties"))) { continue; + } if (it.value()->type() == Value::ItemValueType) { ItemValuePtr outerVal = outer->itemProperty(it.key()); if (!outerVal) { @@ -138,18 +142,44 @@ private: } }; -void ASTPropertiesItemHandler::handlePropertiesBlock(const Item *propertiesItem) +static QString getPropertyString(const Item *propertiesItem, const QString &name) { - const ValuePtr value = propertiesItem->property(QLatin1String("condition")); - if (Q_UNLIKELY(!value)) - throw ErrorInfo(Tr::tr("Properties.condition must be provided."), - propertiesItem->location()); - if (Q_UNLIKELY(value->type() != Value::JSSourceValueType)) - throw ErrorInfo(Tr::tr("Properties.condition must be a value binding."), + const ValuePtr value = propertiesItem->property(name); + if (!value) { + if (name == QLatin1String("condition")) { + throw ErrorInfo(Tr::tr("Properties.condition must be provided."), + propertiesItem->location()); + } + return QLatin1String("false"); + } + if (Q_UNLIKELY(value->type() != Value::JSSourceValueType)) { + throw ErrorInfo(Tr::tr("Properties.%1 must be a value binding.").arg(name), propertiesItem->location()); + } + if (name == QLatin1String("overrideListProperties")) { + const Item *parent = propertiesItem->parent(); + while (parent) { + if (parent->type() == ItemType::Product) + break; + parent = parent->parent(); + } + if (!parent) { + throw ErrorInfo(Tr::tr("Properties.overrideListProperties can only be set " + "in a Product item.")); + } + + } const JSSourceValuePtr srcval = value.staticCast<JSSourceValue>(); - const QString condition = srcval->sourceCodeForEvaluation(); - PropertiesBlockConverter(condition, m_parentItem, propertiesItem).apply(); + return srcval->sourceCodeForEvaluation(); +} + +void ASTPropertiesItemHandler::handlePropertiesBlock(const Item *propertiesItem) +{ + const QString condition = getPropertyString(propertiesItem, QLatin1String("condition")); + const QString overrideListProperties = getPropertyString(propertiesItem, + QLatin1String("overrideListProperties")); + PropertiesBlockConverter(condition, overrideListProperties, m_parentItem, + propertiesItem).apply(); } } // namespace Internal diff --git a/src/lib/corelib/language/evaluatorscriptclass.cpp b/src/lib/corelib/language/evaluatorscriptclass.cpp index d7f51f4bf..71818915f 100644 --- a/src/lib/corelib/language/evaluatorscriptclass.cpp +++ b/src/lib/corelib/language/evaluatorscriptclass.cpp @@ -195,6 +195,7 @@ private: pushItemScopes(alternative->value->definingItem()); engine->currentContext()->pushScope(conditionScope); const QScriptValue cr = engine->evaluate(alternative->condition); + const QScriptValue overrides = engine->evaluate(alternative->overrideListProperties); engine->currentContext()->popScope(); engine->currentContext()->popScope(); popScopes(); @@ -217,6 +218,8 @@ private: outerItem = Item::create(data->item->pool()); outerItem->setProperty(propertyName->toString(), outerValue); } + if (overrides.toBool()) + value->setIsExclusiveListValue(); value = alternative->value.data(); break; } @@ -387,6 +390,11 @@ void EvaluatorScriptClass::collectValuesFromNextChain(const EvaluationData *data if (v.isUndefined()) continue; lst << v; + if (next->type() == Value::JSSourceValueType + && next.staticCast<JSSourceValue>()->isExclusiveListValue()) { + lst = lst.mid(lst.length() - 2); + break; + } } m_currentNextChain = oldNextChain; diff --git a/src/lib/corelib/language/testdata/moduleproperties.qbs b/src/lib/corelib/language/testdata/moduleproperties.qbs index b74daf810..16fe2ea74 100644 --- a/src/lib/corelib/language/testdata/moduleproperties.qbs +++ b/src/lib/corelib/language/testdata/moduleproperties.qbs @@ -37,4 +37,14 @@ Project { dummy.listProp2: ["PRODUCT_STUFF"] dummy.controllingProp: true } + + Product { + name: "overridden_list_property" + Depends { name: "dummy" } + Properties { + condition: true + overrideListProperties: true + dummy.listProp: ["PRODUCT_STUFF"] + } + } } diff --git a/src/lib/corelib/language/tst_language.cpp b/src/lib/corelib/language/tst_language.cpp index 934f16a3f..e23869567 100644 --- a/src/lib/corelib/language/tst_language.cpp +++ b/src/lib/corelib/language/tst_language.cpp @@ -1097,6 +1097,7 @@ void TestLanguage::moduleProperties_data() QTest::newRow("list_property_depending_on_overridden_property") << "listProp2" << (QStringList() << "PRODUCT_STUFF" << "DEFAULT_STUFF" << "EXTRA_STUFF"); + QTest::newRow("overridden_list_property") << "listProp" << (QStringList() << "PRODUCT_STUFF"); QTest::newRow("cleanup") << QString() << QStringList(); } diff --git a/src/lib/corelib/language/value.h b/src/lib/corelib/language/value.h index 3f003275b..74cc3f35c 100644 --- a/src/lib/corelib/language/value.h +++ b/src/lib/corelib/language/value.h @@ -102,7 +102,8 @@ class JSSourceValue : public Value SourceUsesBase = 0x01, SourceUsesOuter = 0x02, SourceUsesOriginal = 0x04, - HasFunctionForm = 0x08 + HasFunctionForm = 0x08, + ExclusiveListValue = 0x10, }; Q_DECLARE_FLAGS(Flags, Flag) @@ -132,6 +133,8 @@ public: bool isInExportItem() const { return m_exportScope; } bool hasFunctionForm() const { return m_flags.testFlag(HasFunctionForm); } void setHasFunctionForm(bool b); + void setIsExclusiveListValue() { m_flags |= ExclusiveListValue; } + bool isExclusiveListValue() { return m_flags.testFlag(ExclusiveListValue); } const JSSourceValuePtr &baseValue() const { return m_baseValue; } void setBaseValue(const JSSourceValuePtr &v) { m_baseValue = v; } @@ -139,6 +142,7 @@ public: struct Alternative { QString condition; + QString overrideListProperties; JSSourceValuePtr value; }; |