diff options
author | Joerg Bornemann <joerg.bornemann@theqtcompany.com> | 2015-01-19 11:57:40 +0100 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@theqtcompany.com> | 2015-01-20 12:06:01 +0100 |
commit | 0d477159e67ef4e0dd665b8c5ba8850b11145afe (patch) | |
tree | b9d1163c7d63b46378011d1bc67b91dda94e9ced /src | |
parent | 1df130f1f1a1ae6b7d3782c1b5208c13d6274977 (diff) | |
download | qbs-0d477159e67ef4e0dd665b8c5ba8850b11145afe.tar.gz |
fix product variable in Export items
Consider a module M that's exported by Product B.
Product A depends on product B and thus depends on M.
This patch fixes the product variable in M that was referring to the
exporting product B, not the importing product A.
Task-number: QBS-729
Change-Id: Ia30b7159aa5d5ec37fe6257300e6c16205141f86
Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/corelib/language/evaluator.cpp | 5 | ||||
-rw-r--r-- | src/lib/corelib/language/evaluator.h | 2 | ||||
-rw-r--r-- | src/lib/corelib/language/evaluatorscriptclass.cpp | 21 | ||||
-rw-r--r-- | src/lib/corelib/language/evaluatorscriptclass.h | 2 | ||||
-rw-r--r-- | src/lib/corelib/language/projectresolver.cpp | 92 | ||||
-rw-r--r-- | src/lib/corelib/language/projectresolver.h | 12 | ||||
-rw-r--r-- | src/lib/corelib/language/tst_language.cpp | 1 |
7 files changed, 111 insertions, 24 deletions
diff --git a/src/lib/corelib/language/evaluator.cpp b/src/lib/corelib/language/evaluator.cpp index d0c5dceb1..4c5494aa3 100644 --- a/src/lib/corelib/language/evaluator.cpp +++ b/src/lib/corelib/language/evaluator.cpp @@ -224,5 +224,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 ec844af92..b1a598dce 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 d523ef75c..2f9063e97 100644 --- a/src/lib/corelib/language/evaluatorscriptclass.cpp +++ b/src/lib/corelib/language/evaluatorscriptclass.cpp @@ -395,11 +395,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); @@ -413,10 +416,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 ba56f5d5e..f8b77f89b 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; private: @@ -87,6 +88,7 @@ private: }; QueryResult m_queryResult; Logger m_logger; + bool m_valueCacheEnabled; QScriptValue m_getNativeSettingBuiltin; QScriptValue m_getEnvBuiltin; QScriptValue m_getHostOSBuiltin; diff --git a/src/lib/corelib/language/projectresolver.cpp b/src/lib/corelib/language/projectresolver.cpp index a353fa23a..ebd3a25db 100644 --- a/src/lib/corelib/language/projectresolver.cpp +++ b/src/lib/corelib/language/projectresolver.cpp @@ -859,7 +859,8 @@ void ProjectResolver::resolveExport(Item *item, ProjectContext *projectContext) Q_UNUSED(projectContext); checkCancelation(); const QString &productName = m_productContext->product->uniqueName(); - m_exports[productName] = evaluateModuleValues(item); + m_exports[productName] = item; + m_exportItemModules[item] = evaluateModuleValues(item, false); } static void insertExportedConfig(const QString &usedProductName, @@ -891,6 +892,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. @@ -927,6 +978,7 @@ void ProjectResolver::resolveProductDependencies(ProjectContext *projectContext) if (!rproduct->enabled) continue; Item *productItem = m_productItemMap.value(rproduct); + ItemValuePtr productItemValue = ItemValue::create(productItem); foreach (const ModuleLoaderResult::ProductInfo::Dependency &dependency, projectContext->loadResult->productInfos.value(productItem).usedProducts) { const QString &usedProductName = dependency.uniqueName(); @@ -936,8 +988,22 @@ void ProjectResolver::resolveProductDependencies(ProjectContext *projectContext) productItem->location()); rproduct->dependencies.insert(usedProduct); + // Evaluate properties of the Export item using the importing product. + Item *exportItem = m_exports.value(usedProductName); + ProductContext productContext; + productContext.product = usedProduct; + m_productContext = &productContext; + const ValuePerItem oldProducts = replaceProduct(exportItem, productItemValue); + m_evaluator->setCachingEnabled(false); + QVariantMap exportedConfig = evaluateModuleValues(exportItem); + m_evaluator->setCachingEnabled(true); + restoreOldProducts(oldProducts); + + // Re-evaluate direct properties of the Export item using the exporting product. + copyProperties(m_exportItemModules.value(exportItem), exportedConfig); + m_productContext = 0; + // insert the configuration of the Export item into the product's configuration - const QVariantMap exportedConfig = m_exports.value(usedProductName); if (exportedConfig.isEmpty()) continue; @@ -983,16 +1049,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(); @@ -1000,22 +1067,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(); @@ -1076,8 +1144,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 8fea4a1ff..05f326b2c 100644 --- a/src/lib/corelib/language/projectresolver.h +++ b/src/lib/corelib/language/projectresolver.h @@ -118,11 +118,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; @@ -138,7 +139,8 @@ private: QMap<QString, ResolvedProductPtr> m_productsByName; QHash<ResolvedProductPtr, Item *> m_productItemMap; mutable QHash<FileContextConstPtr, ResolvedFileContextPtr> m_fileContextMap; - QMap<QString, QVariantMap> m_exports; + QMap<QString, Item *> m_exports; + QHash<Item *, QVariantMap> m_exportItemModules; // ### merge with ExportContext in 1.4. SetupProjectParameters m_setupParams; typedef void (ProjectResolver::*ItemFuncPtr)(Item *item, ProjectContext *projectContext); diff --git a/src/lib/corelib/language/tst_language.cpp b/src/lib/corelib/language/tst_language.cpp index 3857e48e6..c38fa5876 100644 --- a/src/lib/corelib/language/tst_language.cpp +++ b/src/lib/corelib/language/tst_language.cpp @@ -420,7 +420,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")); |