aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/corelib/language/evaluator.cpp5
-rw-r--r--src/lib/corelib/language/evaluator.h2
-rw-r--r--src/lib/corelib/language/evaluatorscriptclass.cpp21
-rw-r--r--src/lib/corelib/language/evaluatorscriptclass.h2
-rw-r--r--src/lib/corelib/language/projectresolver.cpp97
-rw-r--r--src/lib/corelib/language/projectresolver.h13
-rw-r--r--src/lib/corelib/language/tst_language.cpp1
-rw-r--r--tests/auto/api/testdata/export-with-recursive-depends/modules/module1/module1.qbs (renamed from tests/auto/api/testdata/export-with-recursive-depends/qbs/modules/module1/module1.qbs)0
-rw-r--r--tests/auto/api/testdata/export-with-recursive-depends/modules/module2/module2.qbs (renamed from tests/auto/api/testdata/export-with-recursive-depends/qbs/modules/module2/module2.qbs)0
-rw-r--r--tests/auto/api/testdata/export-with-recursive-depends/project.qbs1
-rw-r--r--tests/auto/api/tst_api.cpp2
11 files changed, 116 insertions, 28 deletions
diff --git a/src/lib/corelib/language/evaluator.cpp b/src/lib/corelib/language/evaluator.cpp
index 0fa2dd9bb..e9ecd73e0 100644
--- a/src/lib/corelib/language/evaluator.cpp
+++ b/src/lib/corelib/language/evaluator.cpp
@@ -219,5 +219,10 @@ QScriptValue Evaluator::fileScope(const FileContextConstPtr &file)
return result;
}
+void Evaluator::setCachingEnabled(bool enabled)
+{
+ m_scriptClass->setValueCacheEnabled(enabled);
+}
+
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/language/evaluator.h b/src/lib/corelib/language/evaluator.h
index 073417d85..686b973a9 100644
--- a/src/lib/corelib/language/evaluator.h
+++ b/src/lib/corelib/language/evaluator.h
@@ -66,6 +66,8 @@ public:
QScriptValue scriptValue(const Item *item);
QScriptValue fileScope(const FileContextConstPtr &file);
+ void setCachingEnabled(bool enabled);
+
private:
void onItemPropertyChanged(Item *item);
void onItemDestroyed(Item *item);
diff --git a/src/lib/corelib/language/evaluatorscriptclass.cpp b/src/lib/corelib/language/evaluatorscriptclass.cpp
index bf23330f1..b6eac6e36 100644
--- a/src/lib/corelib/language/evaluatorscriptclass.cpp
+++ b/src/lib/corelib/language/evaluatorscriptclass.cpp
@@ -400,11 +400,14 @@ QScriptValue EvaluatorScriptClass::property(const QScriptValue &object, const QS
if (debugProperties)
m_logger.qbsTrace() << "[SC] property " << name;
- QScriptValue result = data->valueCache.value(name);
- if (result.isValid()) {
- if (debugProperties)
- m_logger.qbsTrace() << "[SC] cache hit " << name << ": " << resultToString(result);
- return result;
+ QScriptValue result;
+ if (m_valueCacheEnabled) {
+ result = data->valueCache.value(name);
+ if (result.isValid()) {
+ if (debugProperties)
+ m_logger.qbsTrace() << "[SC] cache hit " << name << ": " << resultToString(result);
+ return result;
+ }
}
SVConverter converter(this, &object, value, itemOfProperty, &name, data, &result);
@@ -415,10 +418,16 @@ QScriptValue EvaluatorScriptClass::property(const QScriptValue &object, const QS
if (debugProperties)
m_logger.qbsTrace() << "[SC] cache miss " << name << ": " << resultToString(result);
- data->valueCache.insert(name, result);
+ if (m_valueCacheEnabled)
+ data->valueCache.insert(name, result);
return result;
}
+void EvaluatorScriptClass::setValueCacheEnabled(bool enabled)
+{
+ m_valueCacheEnabled = enabled;
+}
+
QScriptValue EvaluatorScriptClass::scriptValueForBuiltin(BuiltinValue::Builtin builtin) const
{
switch (builtin) {
diff --git a/src/lib/corelib/language/evaluatorscriptclass.h b/src/lib/corelib/language/evaluatorscriptclass.h
index 30537e7d5..adafe0785 100644
--- a/src/lib/corelib/language/evaluatorscriptclass.h
+++ b/src/lib/corelib/language/evaluatorscriptclass.h
@@ -57,6 +57,7 @@ public:
QScriptValue property(const QScriptValue &object,
const QScriptString &name, uint id);
+ void setValueCacheEnabled(bool enabled);
QScriptValue scriptValueForBuiltin(BuiltinValue::Builtin builtin) const;
static QScriptValue js_getNativeSetting(QScriptContext *context, QScriptEngine *engine);
@@ -89,6 +90,7 @@ private:
};
QueryResult m_queryResult;
Logger m_logger;
+ bool m_valueCacheEnabled;
QScriptValue m_getNativeSettingBuiltin;
QScriptValue m_getEnvBuiltin;
QScriptValue m_canonicalArchitectureBuiltin;
diff --git a/src/lib/corelib/language/projectresolver.cpp b/src/lib/corelib/language/projectresolver.cpp
index 0f4147f4f..c294303ca 100644
--- a/src/lib/corelib/language/projectresolver.cpp
+++ b/src/lib/corelib/language/projectresolver.cpp
@@ -828,7 +828,8 @@ void ProjectResolver::resolveExport(Item *item, ProjectContext *projectContext)
checkCancelation();
const QString &productName = m_productContext->product->uniqueName();
m_exportsContext = &m_exports[productName];
- m_exportsContext->moduleValues = evaluateModuleValues(item);
+ m_exportsContext->item = item;
+ m_exportsContext->moduleValues = evaluateModuleValues(item, false);
ItemFuncMap mapping;
mapping["Depends"] = &ProjectResolver::ignoreItem;
@@ -934,6 +935,56 @@ static void addUsedProducts(ModuleLoaderResult::ProductInfo *productInfo,
*productsAdded = (oldCount != productInfo->usedProducts.count());
}
+typedef QHash<Item *, ValuePtr> ValuePerItem;
+
+static void replaceProductRecursive(Item *item, const ItemValuePtr &productItemValue,
+ ValuePerItem *seen)
+{
+ if (seen->contains(item))
+ return;
+ ValuePtr oldProductValue = item->property(QLatin1String("product"));
+ seen->insert(item, oldProductValue);
+ if (oldProductValue)
+ item->setProperty(QLatin1String("product"), productItemValue);
+ if (item->scope())
+ replaceProductRecursive(item->scope(), productItemValue, seen);
+ foreach (const Item::Module &module, item->modules())
+ replaceProductRecursive(module.item, productItemValue, seen);
+ foreach (Item *child, item->children())
+ replaceProductRecursive(child, productItemValue, seen);
+}
+
+static ValuePerItem replaceProduct(Item *item, const ItemValuePtr &productItemValue)
+{
+ ValuePerItem seen;
+ replaceProductRecursive(item, productItemValue, &seen);
+ return seen;
+}
+
+static void restoreOldProducts(const ValuePerItem &vip)
+{
+ for (ValuePerItem::const_iterator it = vip.constBegin(); it != vip.constEnd(); ++it) {
+ const ValuePtr &oldProductValue = it.value();
+ if (oldProductValue)
+ it.key()->setProperty(QLatin1String("product"), oldProductValue);
+ }
+}
+
+static void copyProperties(const QVariantMap &src, QVariantMap &dst)
+{
+ for (QVariantMap::const_iterator it = src.constBegin(); it != src.constEnd(); ++it) {
+ const QVariant &v = it.value();
+ if (v.type() == QVariant::Map) {
+ QVariant &dstValue = dst[it.key()];
+ QVariantMap dstMap = dstValue.toMap();
+ copyProperties(v.toMap(), dstMap);
+ dstValue = dstMap;
+ } else {
+ dst[it.key()] = v;
+ }
+ }
+}
+
void ProjectResolver::resolveProductDependencies(ProjectContext *projectContext)
{
// Collect product dependencies from Export items.
@@ -965,6 +1016,7 @@ void ProjectResolver::resolveProductDependencies(ProjectContext *projectContext)
if (!rproduct->enabled)
continue;
Item *productItem = m_productItemMap.value(rproduct);
+ ItemValuePtr productItemValue = ItemValue::create(productItem);
ModuleLoaderResult::ProductInfo &productInfo
= projectContext->loadResult->productInfos[productItem];
foreach (const ResolvedProductPtr &usedProduct,
@@ -977,17 +1029,30 @@ void ProjectResolver::resolveProductDependencies(ProjectContext *projectContext)
foreach (const RulePtr &rule, ctx.rules)
rproduct->rules << rule;
+ // Evaluate properties of the Export item using the importing product.
+ ProductContext productContext;
+ productContext.product = usedProduct;
+ m_productContext = &productContext;
+ const ValuePerItem oldProducts = replaceProduct(ctx.item, productItemValue);
+ m_evaluator->setCachingEnabled(false);
+ QVariantMap exportedConfig = evaluateModuleValues(ctx.item);
+ m_evaluator->setCachingEnabled(true);
+ restoreOldProducts(oldProducts);
+
+ // Re-evaluate direct properties of the Export item using the exporting product.
+ copyProperties(ctx.moduleValues, exportedConfig);
+ m_productContext = 0;
+
// insert the configuration of the Export item into the product's configuration
- if (ctx.moduleValues.isEmpty())
+ if (exportedConfig.isEmpty())
continue;
- insertExportedConfig(usedProductName, ctx.moduleValues, rproduct->moduleProperties);
+ insertExportedConfig(usedProductName, exportedConfig, rproduct->moduleProperties);
// insert the configuration of the Export item into the artifact configurations
foreach (SourceArtifactPtr artifact, rproduct->allEnabledFiles()) {
if (artifact->properties != rproduct->moduleProperties)
- insertExportedConfig(usedProductName, ctx.moduleValues,
- artifact->properties);
+ insertExportedConfig(usedProductName, exportedConfig, artifact->properties);
}
}
}
@@ -1022,16 +1087,17 @@ void ProjectResolver::applyFileTaggers(const SourceArtifactPtr &artifact,
}
}
-QVariantMap ProjectResolver::evaluateModuleValues(Item *item) const
+QVariantMap ProjectResolver::evaluateModuleValues(Item *item, bool lookupPrototype) const
{
QVariantMap modules;
- evaluateModuleValues(item, &modules);
+ evaluateModuleValues(item, &modules, lookupPrototype);
QVariantMap result;
result[QLatin1String("modules")] = modules;
return result;
}
-void ProjectResolver::evaluateModuleValues(Item *item, QVariantMap *modulesMap) const
+void ProjectResolver::evaluateModuleValues(Item *item, QVariantMap *modulesMap,
+ bool lookupPrototype) const
{
checkCancelation();
for (Item::Modules::const_iterator it = item->modules().constBegin();
@@ -1039,22 +1105,23 @@ void ProjectResolver::evaluateModuleValues(Item *item, QVariantMap *modulesMap)
{
QVariantMap depmods;
const Item::Module &module = *it;
- evaluateModuleValues(module.item, &depmods);
- QVariantMap dep = evaluateProperties(module.item);
+ evaluateModuleValues(module.item, &depmods, lookupPrototype);
+ QVariantMap dep = evaluateProperties(module.item, lookupPrototype);
dep.insert(QLatin1String("modules"), depmods);
modulesMap->insert(ModuleLoader::fullModuleName(module.name), dep);
}
}
-QVariantMap ProjectResolver::evaluateProperties(Item *item) const
+QVariantMap ProjectResolver::evaluateProperties(Item *item, bool lookupPrototype) const
{
const QVariantMap tmplt;
- return evaluateProperties(item, item, tmplt);
+ return evaluateProperties(item, item, tmplt, lookupPrototype);
}
QVariantMap ProjectResolver::evaluateProperties(Item *item,
Item *propertiesContainer,
- const QVariantMap &tmplt) const
+ const QVariantMap &tmplt,
+ bool lookupPrototype) const
{
QVariantMap result = tmplt;
for (QMap<QString, ValuePtr>::const_iterator it = propertiesContainer->properties().begin();
@@ -1113,8 +1180,8 @@ QVariantMap ProjectResolver::evaluateProperties(Item *item,
break;
}
}
- return propertiesContainer->prototype()
- ? evaluateProperties(item, propertiesContainer->prototype(), result)
+ return lookupPrototype && propertiesContainer->prototype()
+ ? evaluateProperties(item, propertiesContainer->prototype(), result, true)
: result;
}
diff --git a/src/lib/corelib/language/projectresolver.h b/src/lib/corelib/language/projectresolver.h
index 6e9df9e1a..2b3bebbe5 100644
--- a/src/lib/corelib/language/projectresolver.h
+++ b/src/lib/corelib/language/projectresolver.h
@@ -97,6 +97,10 @@ private:
struct ExportsContext
{
+ ExportsContext()
+ : item(0) {}
+
+ Item *item;
QVariantMap moduleValues;
QList<FileTaggerConstPtr> fileTaggers;
QSet<RulePtr> rules;
@@ -126,11 +130,12 @@ private:
void resolveProductDependencies(ProjectContext *projectContext);
void postProcess(const ResolvedProductPtr &product, ProjectContext *projectContext) const;
void applyFileTaggers(const ResolvedProductPtr &product) const;
- QVariantMap evaluateModuleValues(Item *item) const;
- void evaluateModuleValues(Item *item, QVariantMap *modulesMap) const;
- QVariantMap evaluateProperties(Item *item) const;
+ QVariantMap evaluateModuleValues(Item *item, bool lookupPrototype = true) const;
+ void evaluateModuleValues(Item *item, QVariantMap *modulesMap,
+ bool lookupPrototype = true) const;
+ QVariantMap evaluateProperties(Item *item, bool lookupPrototype = true) const;
QVariantMap evaluateProperties(Item *item, Item *propertiesContainer,
- const QVariantMap &tmplt) const;
+ const QVariantMap &tmplt, bool lookupPrototype = true) const;
QVariantMap createProductConfig() const;
QString convertPathProperty(const QString &path, const QString &dirPath) const;
QStringList convertPathListProperty(const QStringList &paths, const QString &dirPath) const;
diff --git a/src/lib/corelib/language/tst_language.cpp b/src/lib/corelib/language/tst_language.cpp
index 67590e504..8e84c2560 100644
--- a/src/lib/corelib/language/tst_language.cpp
+++ b/src/lib/corelib/language/tst_language.cpp
@@ -463,7 +463,6 @@ void TestLanguage::exports()
QVariant propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName);
QCOMPARE(propertyValue.toStringList(), QStringList() << "USE_MYLIB");
- QEXPECT_FAIL(0, "QBS-729", Continue);
QCOMPARE(PropertyFinder().propertyValue(product->moduleProperties->value(), "dummy",
"productName").toString(), QString("myapp"));
diff --git a/tests/auto/api/testdata/export-with-recursive-depends/qbs/modules/module1/module1.qbs b/tests/auto/api/testdata/export-with-recursive-depends/modules/module1/module1.qbs
index c1c4ad358..c1c4ad358 100644
--- a/tests/auto/api/testdata/export-with-recursive-depends/qbs/modules/module1/module1.qbs
+++ b/tests/auto/api/testdata/export-with-recursive-depends/modules/module1/module1.qbs
diff --git a/tests/auto/api/testdata/export-with-recursive-depends/qbs/modules/module2/module2.qbs b/tests/auto/api/testdata/export-with-recursive-depends/modules/module2/module2.qbs
index 75a274631..75a274631 100644
--- a/tests/auto/api/testdata/export-with-recursive-depends/qbs/modules/module2/module2.qbs
+++ b/tests/auto/api/testdata/export-with-recursive-depends/modules/module2/module2.qbs
diff --git a/tests/auto/api/testdata/export-with-recursive-depends/project.qbs b/tests/auto/api/testdata/export-with-recursive-depends/project.qbs
index 045e65133..d5f5f79e5 100644
--- a/tests/auto/api/testdata/export-with-recursive-depends/project.qbs
+++ b/tests/auto/api/testdata/export-with-recursive-depends/project.qbs
@@ -12,5 +12,4 @@ Project {
Depends { name: "app1" }
files: "main2.cpp"
}
- qbsSearchPaths: "qbs"
}
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index 514a5c170..f889cfdcd 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -895,7 +895,7 @@ void TestApi::exportSimple()
void TestApi::exportWithRecursiveDepends()
{
const qbs::ErrorInfo errorInfo = doBuildProject("export-with-recursive-depends/project.qbs");
- QEXPECT_FAIL("", "currently broken", Abort);
+ QEXPECT_FAIL("", "QBS-706", Abort);
VERIFY_NO_ERROR(errorInfo);
}