summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@theqtcompany.com>2015-07-23 11:55:11 +0200
committerChristian Kandeler <christian.kandeler@theqtcompany.com>2015-08-04 14:47:02 +0000
commit8c5e63fae7509b6dcc8a3d4387e5d27093ede7fc (patch)
treef0a844ff4f927ea37f471c7108186d705da44c1e
parent6cc4b9d6af6ed169cdb05a3925e50d353ab8c8a9 (diff)
downloadqbs-8c5e63fae7509b6dcc8a3d4387e5d27093ede7fc.tar.gz
Make it possible to overwrite properties conditionally.
If a product or higher-level module wants to set the property of a (different) module only if some condition is fulfilled and leave it unchanged otherwise, it would currently need to duplicate the value from the module prototype. Obviously, this is not feasible for anything but the most trivial definitions, and even then it easily introduces maintenance problems. Change-Id: If33c93a25dc84603fe95704e8815aa6e3aa1e0e4 Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com> Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
-rw-r--r--doc/reference/items/module.qdoc15
-rw-r--r--src/lib/corelib/language/evaluatorscriptclass.cpp10
-rw-r--r--src/lib/corelib/language/itemreaderastvisitor.cpp5
-rw-r--r--src/lib/corelib/language/testdata/defaultvalue/egon.qbs14
-rw-r--r--src/lib/corelib/language/testdata/defaultvalue/modules/higher/higher.qbs7
-rw-r--r--src/lib/corelib/language/testdata/defaultvalue/modules/lower/lower.qbs7
-rw-r--r--src/lib/corelib/language/testdata/defaultvalue/test.txt0
-rw-r--r--src/lib/corelib/language/tst_language.cpp51
-rw-r--r--src/lib/corelib/language/tst_language.h2
-rw-r--r--src/lib/corelib/language/value.h2
-rw-r--r--src/lib/qtprofilesetup/templates/core.qbs1
11 files changed, 112 insertions, 2 deletions
diff --git a/doc/reference/items/module.qdoc b/doc/reference/items/module.qdoc
index 4a6e38678..343790f47 100644
--- a/doc/reference/items/module.qdoc
+++ b/doc/reference/items/module.qdoc
@@ -118,6 +118,20 @@
}
\endcode
+ \section2 \c original
+ This is the value of the property in the module itself (possibly overridden from a profile or
+ the command line). Use it to set a module property conditionally:
+ \code
+ Module { // This is mymodule
+ property string aProperty: "z"
+ }
+ ----------
+ Product {
+ Depends { name: "mymodule" }
+ Depends { name: "myothermodule" }
+ mymodule.aProperty: myothermodule.anotherProperty === "x" ? "y" : original // => "y" if myothermodule.anotherProperty is "x", "z" otherwise
+ \endcode
+
\section2 \c outer
This value is used in nested items, where it refers to the value of the respective property
in the surrounding item. It is often encountered in \l{Group Item}{groups}:
@@ -133,6 +147,7 @@
}
\endcode
+
\section1 Module Properties
\table
diff --git a/src/lib/corelib/language/evaluatorscriptclass.cpp b/src/lib/corelib/language/evaluatorscriptclass.cpp
index e9e6d8d36..e0dd5a525 100644
--- a/src/lib/corelib/language/evaluatorscriptclass.cpp
+++ b/src/lib/corelib/language/evaluatorscriptclass.cpp
@@ -215,6 +215,16 @@ private:
if (value->sourceUsesOuter() && outerItem)
setupConvenienceProperty(QLatin1String("outer"), &extraScope,
data->evaluator->property(outerItem, *propertyName));
+ if (value->sourceUsesOriginal()) {
+ const Item *item = itemOfProperty;
+ while (item->isModuleInstance())
+ item = item->prototype();
+ QScriptValue originalValue;
+ SVConverter converter(scriptClass, object, item->property(*propertyName), item,
+ propertyName, data, &originalValue, sourceValueStack);
+ converter.start();
+ setupConvenienceProperty(QLatin1String("original"), &extraScope, originalValue);
+ }
pushScope(data->evaluator->fileScope(value->file()));
pushItemScopes(data->item);
diff --git a/src/lib/corelib/language/itemreaderastvisitor.cpp b/src/lib/corelib/language/itemreaderastvisitor.cpp
index 0fc4696c8..0815ef01a 100644
--- a/src/lib/corelib/language/itemreaderastvisitor.cpp
+++ b/src/lib/corelib/language/itemreaderastvisitor.cpp
@@ -463,15 +463,18 @@ bool ItemReaderASTVisitor::visitStatement(AST::Statement *statement)
m_sourceValue->setLocation(statement->firstSourceLocation().startLine,
statement->firstSourceLocation().startColumn);
- bool usesBase, usesOuter;
+ bool usesBase, usesOuter, usesOriginal;
IdentifierSearch idsearch;
idsearch.add(QLatin1String("base"), &usesBase);
idsearch.add(QLatin1String("outer"), &usesOuter);
+ idsearch.add(QLatin1String("original"), &usesOriginal);
idsearch.start(statement);
if (usesBase)
m_sourceValue->m_flags |= JSSourceValue::SourceUsesBase;
if (usesOuter)
m_sourceValue->m_flags |= JSSourceValue::SourceUsesOuter;
+ if (usesOriginal)
+ m_sourceValue->m_flags |= JSSourceValue::SourceUsesOriginal;
return false;
}
diff --git a/src/lib/corelib/language/testdata/defaultvalue/egon.qbs b/src/lib/corelib/language/testdata/defaultvalue/egon.qbs
new file mode 100644
index 000000000..7b254b0c8
--- /dev/null
+++ b/src/lib/corelib/language/testdata/defaultvalue/egon.qbs
@@ -0,0 +1,14 @@
+import qbs
+
+Project {
+ Product {
+ name: "dep"
+ Export { Depends { name: "higher" } }
+ }
+
+ Product {
+ name: "egon"
+ Depends { name: "dep" }
+ lower.prop1: "blubb"
+ }
+}
diff --git a/src/lib/corelib/language/testdata/defaultvalue/modules/higher/higher.qbs b/src/lib/corelib/language/testdata/defaultvalue/modules/higher/higher.qbs
new file mode 100644
index 000000000..9894f80cf
--- /dev/null
+++ b/src/lib/corelib/language/testdata/defaultvalue/modules/higher/higher.qbs
@@ -0,0 +1,7 @@
+import qbs
+
+Module {
+ Depends { name: "lower" }
+ lower.prop2: lower.prop1 === "egon" ? "withEgon" : original
+ lower.listProp: lower.prop1 === "egon" ? ["egon"] : original
+}
diff --git a/src/lib/corelib/language/testdata/defaultvalue/modules/lower/lower.qbs b/src/lib/corelib/language/testdata/defaultvalue/modules/lower/lower.qbs
new file mode 100644
index 000000000..0540185e9
--- /dev/null
+++ b/src/lib/corelib/language/testdata/defaultvalue/modules/lower/lower.qbs
@@ -0,0 +1,7 @@
+import qbs
+
+Module {
+ property string prop1
+ property string prop2: prop1 === "blubb" ? "withBlubb" : "withoutBlubb"
+ property stringList listProp: prop1 === "blubb" ? ["blubb", "other"] : ["other"]
+}
diff --git a/src/lib/corelib/language/testdata/defaultvalue/test.txt b/src/lib/corelib/language/testdata/defaultvalue/test.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/lib/corelib/language/testdata/defaultvalue/test.txt
diff --git a/src/lib/corelib/language/tst_language.cpp b/src/lib/corelib/language/tst_language.cpp
index c227f1b83..8dd911ff3 100644
--- a/src/lib/corelib/language/tst_language.cpp
+++ b/src/lib/corelib/language/tst_language.cpp
@@ -354,6 +354,55 @@ void qbs::Internal::TestLanguage::dependencyOnAllProfiles()
QCOMPARE(exceptionCaught, false);
}
+void TestLanguage::defaultValue()
+{
+ bool exceptionCaught = false;
+ try {
+ SetupProjectParameters params = defaultParameters;
+ params.setProjectFilePath(testProject("defaultvalue/egon.qbs"));
+ QFETCH(QString, prop1Value);
+ QVariantMap overridden;
+ if (!prop1Value.isEmpty())
+ overridden.insert("lower.prop1", prop1Value);
+ params.setOverriddenValues(overridden);
+ TopLevelProjectPtr project = loader->loadProject(params);
+ QVERIFY(project);
+ QHash<QString, ResolvedProductPtr> products = productsFromProject(project);
+ QCOMPARE(products.count(), 2);
+ const ResolvedProductPtr product = products.value("egon");
+ QVERIFY(product);
+ QStringList propertyName = QStringList() << "modules" << "lower" << "prop2";
+ QVariant propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName);
+ QFETCH(QVariant, expectedProp2Value);
+ QCOMPARE(propertyValue, expectedProp2Value);
+ propertyName = QStringList() << "modules" << "lower" << "listProp";
+ propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName);
+ QFETCH(QVariant, expectedListPropValue);
+ QEXPECT_FAIL("controlling property not overwritten", "QBS-845", Continue);
+ QCOMPARE(propertyValue.toStringList(), expectedListPropValue.toStringList());
+ }
+ catch (const ErrorInfo &e) {
+ exceptionCaught = true;
+ qDebug() << e.toString();
+ }
+ QCOMPARE(exceptionCaught, false);
+}
+
+void TestLanguage::defaultValue_data()
+{
+ QTest::addColumn<QString>("prop1Value");
+ QTest::addColumn<QVariant>("expectedProp2Value");
+ QTest::addColumn<QVariant>("expectedListPropValue");
+ QTest::newRow("controlling property with random value") << "random" << QVariant("withoutBlubb")
+ << QVariant(QStringList({"other", "other"}));
+ QTest::newRow("controlling property with blubb value") << "blubb" << QVariant("withBlubb")
+ << QVariant(QStringList({"blubb", "other", "blubb", "other"}));
+ QTest::newRow("controlling property with egon value") << "egon" << QVariant("withEgon")
+ << QVariant(QStringList({"egon", "other"}));
+ QTest::newRow("controlling property not overwritten") << "" << QVariant("withBlubb")
+ << QVariant(QStringList({"blubb", "other", "blubb", "other"}));
+}
+
void TestLanguage::environmentVariable()
{
bool exceptionCaught = false;
@@ -998,7 +1047,7 @@ void TestLanguage::moduleProperties()
QStringList valueStrings;
foreach (const QVariant &v, values)
valueStrings += v.toString();
- QEXPECT_FAIL("list_property_depending_on_overridden_property", "QBS_845", Continue);
+ QEXPECT_FAIL("list_property_depending_on_overridden_property", "QBS-845", Continue);
QCOMPARE(valueStrings, expectedValues);
}
diff --git a/src/lib/corelib/language/tst_language.h b/src/lib/corelib/language/tst_language.h
index 624f5428b..863f2b7b4 100644
--- a/src/lib/corelib/language/tst_language.h
+++ b/src/lib/corelib/language/tst_language.h
@@ -106,6 +106,8 @@ private slots:
void profileValuesAndOverriddenValues();
void propertiesBlocks_data();
void propertiesBlocks();
+ void defaultValue();
+ void defaultValue_data();
void qualifiedId();
void recursiveProductDependencies();
void rfc1034Identifier();
diff --git a/src/lib/corelib/language/value.h b/src/lib/corelib/language/value.h
index 8f17f0be9..7dbbdd9bc 100644
--- a/src/lib/corelib/language/value.h
+++ b/src/lib/corelib/language/value.h
@@ -90,6 +90,7 @@ class JSSourceValue : public Value
NoFlags = 0x00,
SourceUsesBase = 0x01,
SourceUsesOuter = 0x02,
+ SourceUsesOriginal = 0x04,
HasFunctionForm = 0x08
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -116,6 +117,7 @@ public:
void setSourceUsesBaseFlag() { m_flags |= SourceUsesBase; }
bool sourceUsesBase() const { return m_flags.testFlag(SourceUsesBase); }
bool sourceUsesOuter() const { return m_flags.testFlag(SourceUsesOuter); }
+ bool sourceUsesOriginal() const { return m_flags.testFlag(SourceUsesOriginal); }
bool isInExportItem() const { return m_exportScope; }
bool hasFunctionForm() const { return m_flags.testFlag(HasFunctionForm); }
void setHasFunctionForm(bool b);
diff --git a/src/lib/qtprofilesetup/templates/core.qbs b/src/lib/qtprofilesetup/templates/core.qbs
index 844a58784..8bec90675 100644
--- a/src/lib/qtprofilesetup/templates/core.qbs
+++ b/src/lib/qtprofilesetup/templates/core.qbs
@@ -144,6 +144,7 @@ Module {
if (qbs.targetOS.contains('darwin') && qbs.toolchain.contains('clang')
&& config.contains('c++11'))
return "libc++";
+ return original;
}
additionalProductTypes: ["qm"]