aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2018-02-01 16:40:57 +0100
committerChristian Kandeler <christian.kandeler@qt.io>2018-02-15 12:17:06 +0000
commitcee7367f72c4c2321e6f324bb36be0b6923db640 (patch)
tree04404d02ed6177eb087fdc1a00e38f7793437c30 /src
parente82f6d702369876d9c44e50f45941a31f2a727d7 (diff)
Check product and project names in command-line property overrides
Users should get feedback if they mistyped a product name, for instance. Task-number: QBS-1288 Change-Id: Icb57490d896d21c5ff9ed3940b53d9b18fe00a30 Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/lib/corelib/language/moduleloader.cpp90
-rw-r--r--src/lib/corelib/language/moduleloader.h8
-rw-r--r--src/lib/corelib/tools/stringconstants.h3
3 files changed, 91 insertions, 10 deletions
diff --git a/src/lib/corelib/language/moduleloader.cpp b/src/lib/corelib/language/moduleloader.cpp
index 27c5f5dc8..f81e8d44f 100644
--- a/src/lib/corelib/language/moduleloader.cpp
+++ b/src/lib/corelib/language/moduleloader.cpp
@@ -298,8 +298,10 @@ ModuleLoaderResult ModuleLoader::load(const SetupProjectParameters &parameters)
break;
}
}
- if (ok)
+ if (ok) {
+ collectNameFromOverride(key);
continue;
+ }
ErrorInfo e(Tr::tr("Property override key '%1' not understood.").arg(key));
e.append(Tr::tr("Please use one of the following:"));
e.append(QLatin1Char('\t') + Tr::tr("projects.<project-name>.<property-name>:value"));
@@ -523,7 +525,10 @@ void ModuleLoader::handleTopLevelProject(ModuleLoaderResult *loadResult, Item *p
TopLevelProjectContext tlp;
tlp.buildDirectory = buildDirectory;
handleProject(loadResult, &tlp, projectItem, referencedFilePaths);
+ checkProjectNamesInOverrides(tlp);
collectProductsByName(tlp);
+ checkProductNamesInOverrides();
+
adjustDependenciesForMultiplexing(tlp);
for (ProjectContext * const projectContext : qAsConst(tlp.projects)) {
@@ -574,12 +579,15 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult,
projectItem->addModule(loadBaseModule(&dummyProductContext, projectItem));
overrideItemProperties(projectItem, StringConstants::projectPrefix(),
m_parameters.overriddenValuesTree());
- const QString projectName = m_evaluator->stringValue(projectItem,
- StringConstants::nameProperty());
- if (!projectName.isEmpty())
- overrideItemProperties(projectItem, QStringLiteral("projects.") + projectName,
- m_parameters.overriddenValuesTree());
+ projectContext.name = m_evaluator->stringValue(projectItem,
+ StringConstants::nameProperty());
+ if (projectContext.name.isEmpty())
+ projectContext.name = FileInfo::baseName(projectItem->location().filePath());
+ overrideItemProperties(projectItem,
+ StringConstants::projectsOverridePrefix() + projectContext.name,
+ m_parameters.overriddenValuesTree());
if (!checkItemCondition(projectItem)) {
+ m_disabledProjects.insert(projectContext.name);
delete p;
return;
}
@@ -786,7 +794,7 @@ QList<Item *> ModuleLoader::multiplexProductItem(ProductContext *dummyContext, I
productName = FileInfo::completeBaseName(productItem->file()->filePath());
productItem->setProperty(nameKey, VariantValue::create(productName));
}
- overrideItemProperties(productItem, QStringLiteral("products.") + productName,
+ overrideItemProperties(productItem, StringConstants::productsOverridePrefix() + productName,
m_parameters.overriddenValuesTree());
const MultiplexInfo &multiplexInfo = extractMultiplexInfo(productItem, qbsModule.item);
@@ -1753,6 +1761,70 @@ void ModuleLoader::handleProfile(Item *profileItem)
m_localProfiles.insert(profileName, values);
}
+void ModuleLoader::collectNameFromOverride(const QString &overrideString)
+{
+ static const auto extract = [](const QString &prefix, const QString &overrideString) {
+ if (!overrideString.startsWith(prefix))
+ return QString();
+ const int startPos = prefix.length();
+ const int endPos = overrideString.lastIndexOf(StringConstants::dot());
+ if (endPos == -1)
+ return QString();
+ return overrideString.mid(startPos, endPos - startPos);
+ };
+ const QString &projectName = extract(StringConstants::projectsOverridePrefix(), overrideString);
+ if (!projectName.isEmpty()) {
+ m_projectNamesUsedInOverrides.insert(projectName);
+ return;
+ }
+ const QString &productName = extract(StringConstants::productsOverridePrefix(), overrideString);
+ if (!productName.isEmpty()) {
+ m_productNamesUsedInOverrides.insert(productName.left(
+ productName.indexOf(StringConstants::dot())));
+ return;
+ }
+}
+
+void ModuleLoader::checkProjectNamesInOverrides(const ModuleLoader::TopLevelProjectContext &tlp)
+{
+ for (const QString &projectNameInOverride : m_projectNamesUsedInOverrides) {
+ if (m_disabledProjects.contains(projectNameInOverride))
+ continue;
+ bool found = false;
+ for (const ProjectContext * const p : tlp.projects) {
+ if (p->name == projectNameInOverride) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ handlePropertyError(Tr::tr("Unknown project '%1' in property override.")
+ .arg(projectNameInOverride), m_parameters, m_logger);
+ }
+ }
+}
+
+void ModuleLoader::checkProductNamesInOverrides()
+{
+ for (const QString &productNameInOverride : m_productNamesUsedInOverrides) {
+ bool found = false;
+ for (auto it = m_productsByName.cbegin(); it != m_productsByName.cend(); ++it) {
+ // In an override string such as "a.b.c:d, we cannot tell whether we have a product
+ // "a" and a module "b.c" or a product "a.b" and a module "c", so we need to take
+ // care not to emit false positives here.
+ if (it->first == productNameInOverride
+ || it->first.startsWith(productNameInOverride + StringConstants::dot())) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ handlePropertyError(Tr::tr("Unknown product '%1' in property override.")
+ .arg(productNameInOverride), m_parameters, m_logger);
+ }
+ }
+}
+
void ModuleLoader::collectProductsByName(const TopLevelProjectContext &topLevelProject)
{
for (ProjectContext * const project : topLevelProject.projects) {
@@ -2827,8 +2899,8 @@ void ModuleLoader::instantiateModule(ProductContext *productContext, Item *expor
deepestModuleInstance->setPrototype(modulePrototype);
const QString fullName = moduleName.toString();
const QString generalOverrideKey = QStringLiteral("modules.") + fullName;
- const QString perProductOverrideKey = QStringLiteral("products.") + productContext->name
- + QLatin1Char('.') + fullName;
+ const QString perProductOverrideKey = StringConstants::productsOverridePrefix()
+ + productContext->name + QLatin1Char('.') + fullName;
for (Item *instance = moduleInstance; instance; instance = instance->prototype()) {
overrideItemProperties(instance, generalOverrideKey, m_parameters.overriddenValuesTree());
if (fullName == QStringLiteral("qbs"))
diff --git a/src/lib/corelib/language/moduleloader.h b/src/lib/corelib/language/moduleloader.h
index 3dafd42de..8eafb54da 100644
--- a/src/lib/corelib/language/moduleloader.h
+++ b/src/lib/corelib/language/moduleloader.h
@@ -152,6 +152,7 @@ private:
Item *item;
Item *scope;
+ QString name;
};
class ProjectContext;
@@ -163,7 +164,6 @@ private:
public:
ProjectContext *project;
ModuleLoaderResult::ProductInfo info;
- QString name;
QString profileName;
QString multiplexConfigurationId;
QString multiplexConfigIdForModulePrototypes;
@@ -340,6 +340,9 @@ private:
void evaluateProfileValues(const QualifiedId &namePrefix, Item *item, Item *profileItem,
QVariantMap &values);
void handleProfile(Item *profileItem);
+ void collectNameFromOverride(const QString &overrideString);
+ void checkProjectNamesInOverrides(const TopLevelProjectContext &tlp);
+ void checkProductNamesInOverrides();
ItemPool *m_pool;
Logger &m_logger;
@@ -378,6 +381,9 @@ private:
Version m_qbsVersion;
Item *m_tempScopeItem = nullptr;
qint64 m_elapsedTimeProbes;
+ Set<QString> m_projectNamesUsedInOverrides;
+ Set<QString> m_productNamesUsedInOverrides;
+ Set<QString> m_disabledProjects;
};
} // namespace Internal
diff --git a/src/lib/corelib/tools/stringconstants.h b/src/lib/corelib/tools/stringconstants.h
index fca451b7f..004effb97 100644
--- a/src/lib/corelib/tools/stringconstants.h
+++ b/src/lib/corelib/tools/stringconstants.h
@@ -146,6 +146,9 @@ public:
static const QString &projectPrefix() { return project(); }
static const QString &productValue() { return product(); }
+ QBS_STRING_CONSTANT(projectsOverridePrefix, "projects.")
+ QBS_STRING_CONSTANT(productsOverridePrefix, "products.")
+
QBS_STRING_CONSTANT(baseVar, "base")
static const QString &explicitlyDependsOnVar() { return explicitlyDependsOn(); }
QBS_STRING_CONSTANT(inputVar, "input")