diff options
Diffstat (limited to 'src/lib/corelib/language/modulemerger.cpp')
-rw-r--r-- | src/lib/corelib/language/modulemerger.cpp | 267 |
1 files changed, 0 insertions, 267 deletions
diff --git a/src/lib/corelib/language/modulemerger.cpp b/src/lib/corelib/language/modulemerger.cpp deleted file mode 100644 index 6ad8e2259..000000000 --- a/src/lib/corelib/language/modulemerger.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qbs. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "modulemerger.h" - -#include "value.h" - -#include <logging/translator.h> -#include <tools/qbsassert.h> -#include <tools/qttools.h> -#include <tools/stlutils.h> -#include <tools/stringconstants.h> - -namespace qbs { -namespace Internal { - -ModuleMerger::ModuleMerger(Logger &logger, Item *productItem, const QString &productName, - const Item::Modules::iterator &modulesBegin, - const Item::Modules::iterator &modulesEnd) - : m_logger(logger) - , m_productItem(productItem) - , m_mergedModule(*modulesBegin) - , m_isBaseModule(m_mergedModule.name.first() == StringConstants::qbsModule()) - , m_isShadowProduct(productName.startsWith(StringConstants::shadowProductPrefix())) - , m_modulesBegin(std::next(modulesBegin)) - , m_modulesEnd(modulesEnd) -{ - QBS_CHECK(modulesBegin->item->type() == ItemType::ModuleInstance); -} - -void ModuleMerger::replaceItemInValues(QualifiedId moduleName, Item *containerItem, Item *toReplace) -{ - QBS_CHECK(!moduleName.empty()); - QBS_CHECK(containerItem != m_mergedModule.item); - const QString moduleNamePrefix = moduleName.takeFirst(); - const Item::PropertyMap &properties = containerItem->properties(); - for (auto it = properties.begin(); it != properties.end(); ++it) { - if (it.key() != moduleNamePrefix) - continue; - Value * const val = it.value().get(); - QBS_CHECK(val); - QBS_CHECK(val->type() == Value::ItemValueType); - const auto itemVal = static_cast<ItemValue *>(val); - if (moduleName.empty()) { - QBS_CHECK(itemVal->item() == toReplace); - itemVal->setItem(m_mergedModule.item); - } else { - replaceItemInValues(moduleName, itemVal->item(), toReplace); - } - } -} - -void ModuleMerger::start() -{ - // Iterate over any module that our product depends on. These modules - // may depend on m_mergedModule and contribute property assignments. - Item::PropertyMap props; - for (auto module = m_modulesBegin; module != m_modulesEnd; module++) - mergeModule(&props, *module); - - // Module property assignments in the product have the highest priority - // and are thus prepended. - Item::Module m; - m.item = m_productItem; - mergeModule(&props, m); - - // The module's prototype is the essential unmodified module as loaded - // from the cache. - Item *moduleProto = m_mergedModule.item->prototype(); - while (moduleProto->prototype()) - moduleProto = moduleProto->prototype(); - - // The prototype item might contain default values which get appended in - // case of list properties. Scalar properties will only be set if not - // already specified above. - Item::PropertyMap mergedProps = m_mergedModule.item->properties(); - for (auto it = props.constBegin(); it != props.constEnd(); ++it) { - appendPrototypeValueToNextChain(moduleProto, it.key(), it.value()); - mergedProps[it.key()] = it.value(); - } - - m_mergedModule.item->setProperties(mergedProps); - - // Update all sibling instances of the to-be-merged module to behave identical - // to the merged module. - for (Item *moduleInstanceContainer : qAsConst(m_moduleInstanceContainers)) { - Item::Modules modules; - for (const Item::Module &dep : moduleInstanceContainer->modules()) { - const bool isTheModule = dep.name == m_mergedModule.name; - Item::Module m = dep; - if (isTheModule && m.item != m_mergedModule.item) { - QBS_CHECK(m.item->type() == ItemType::ModuleInstance); - replaceItemInValues(m.name, moduleInstanceContainer, m.item); - m.item = m_mergedModule.item; - m.required = m_mergedModule.required; - m.versionRange = m_mergedModule.versionRange; - m.fallbackEnabled = m_mergedModule.fallbackEnabled; - } - modules << m; - } - moduleInstanceContainer->setModules(modules); - } -} - -void ModuleMerger::mergeModule(Item::PropertyMap *dstProps, const Item::Module &module) -{ - const Item::Module *dep = findModule(module.item, m_mergedModule.name); - if (!dep) - return; - - const bool mergingProductItem = (module.item == m_productItem); - Item *srcItem = dep->item; - Item *origSrcItem = srcItem; - do { - if (m_seenInstances.insert(srcItem).second) { - for (auto it = srcItem->properties().constBegin(); - it != srcItem->properties().constEnd(); ++it) { - const ValuePtr &srcVal = it.value(); - if (srcVal->type() == Value::ItemValueType) - continue; - if (it.key() == StringConstants::qbsSourceDirPropertyInternal()) - continue; - const PropertyDeclaration srcDecl = srcItem->propertyDeclaration(it.key()); - if (!srcDecl.isValid()) - continue; - - // Scalar variant values could stem from product multiplexing, in which case - // the merged qbs module instance needs to get that value. - if (srcVal->type() == Value::VariantValueType - && (!srcDecl.isScalar() || !m_isBaseModule)) { - continue; - } - - ValuePtr clonedSrcVal = srcVal->clone(); - clonedSrcVal->setDefiningItem(origSrcItem); - - ValuePtr &dstVal = (*dstProps)[it.key()]; - if (dstVal) { - if (srcDecl.isScalar()) { - // Scalar properties get replaced. - if ((dstVal->type() == Value::JSSourceValueType) - && (srcVal->type() == Value::JSSourceValueType)) { - // Warn only about conflicting source code values - const JSSourceValuePtr dstJsVal = - std::static_pointer_cast<JSSourceValue>(dstVal); - const JSSourceValuePtr srcJsVal = - std::static_pointer_cast<JSSourceValue>(srcVal); - const bool overriddenInProduct = - m_mergedModule.item->properties().contains(it.key()); - - if (dstJsVal->sourceCode() != srcJsVal->sourceCode() - && !mergingProductItem && !overriddenInProduct - && !m_isShadowProduct) { - m_logger.qbsWarning() - << Tr::tr("Conflicting scalar values at %1 and %2.").arg( - dstJsVal->location().toString(), - srcJsVal->location().toString()); - } - } - } else { - // List properties get prepended - QBS_CHECK(!clonedSrcVal->next()); - clonedSrcVal->setNext(dstVal); - } - } - dstVal = clonedSrcVal; - } - } - srcItem = srcItem->prototype(); - } while (srcItem && srcItem->type() == ItemType::ModuleInstance); - - // Update dependency constraints - if (dep->required) - m_mergedModule.required = true; - // if one dep has fallback disabled, disable it for the merged module - m_mergedModule.fallbackEnabled = m_mergedModule.fallbackEnabled && dep->fallbackEnabled; - m_mergedModule.versionRange.narrowDown(dep->versionRange); - - // We need to touch the unmerged module instances later once more - m_moduleInstanceContainers << module.item; -} - -void ModuleMerger::appendPrototypeValueToNextChain(Item *moduleProto, const QString &propertyName, - const ValuePtr &sv) -{ - const PropertyDeclaration pd = m_mergedModule.item->propertyDeclaration(propertyName); - if (pd.isScalar()) - return; - if (!m_clonedModulePrototype) { - m_clonedModulePrototype = Item::create(moduleProto->pool(), ItemType::Module); - m_clonedModulePrototype->setScope(m_mergedModule.item); - m_clonedModulePrototype->setLocation(moduleProto->location()); - moduleProto->copyProperty(StringConstants::nameProperty(), m_clonedModulePrototype); - } - const ValuePtr &protoValue = moduleProto->property(propertyName); - QBS_CHECK(protoValue); - const ValuePtr clonedValue = protoValue->clone(); - lastInNextChain(sv)->setNext(clonedValue); - clonedValue->setDefiningItem(m_clonedModulePrototype); - m_clonedModulePrototype->setPropertyDeclaration(propertyName, pd); - m_clonedModulePrototype->setProperty(propertyName, clonedValue); -} - -ValuePtr ModuleMerger::lastInNextChain(const ValuePtr &v) -{ - ValuePtr n = v; - while (n->next()) - n = n->next(); - return n; -} - -const Item::Module *ModuleMerger::findModule(const Item *item, const QualifiedId &name) -{ - for (const auto &module : item->modules()) { - if (module.name == name) - return &module; - } - return nullptr; -} - -void ModuleMerger::merge(Logger &logger, Item *product, const QString &productName, - Item::Modules *topSortedModules) -{ - for (auto it = topSortedModules->begin(); it != topSortedModules->end(); ++it) - ModuleMerger(logger, product, productName, it, topSortedModules->end()).start(); -} - - - -} // namespace Internal -} // namespace qbs |