aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2016-08-30 14:18:08 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2016-11-10 13:32:51 +0000
commit171a104ec567d660fd3ac44cfc2031ac748f6d56 (patch)
treec0a77ea99efe21e080264d472127c0101f208bda /src
parente518441cf636a2839d58d23f9853dbcdeeaad85a (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.cpp54
-rw-r--r--src/lib/corelib/language/evaluatorscriptclass.cpp8
-rw-r--r--src/lib/corelib/language/testdata/moduleproperties.qbs10
-rw-r--r--src/lib/corelib/language/tst_language.cpp1
-rw-r--r--src/lib/corelib/language/value.h6
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;
};