diff options
-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 | 97 | ||||
-rw-r--r-- | src/lib/corelib/language/projectresolver.h | 13 | ||||
-rw-r--r-- | src/lib/corelib/language/tst_language.cpp | 1 | ||||
-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.qbs | 1 | ||||
-rw-r--r-- | tests/auto/api/tst_api.cpp | 2 |
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); } |