diff options
| author | Joerg Bornemann <joerg.bornemann@digia.com> | 2013-07-22 16:46:34 +0200 |
|---|---|---|
| committer | Christian Kandeler <christian.kandeler@digia.com> | 2013-07-23 13:54:49 +0200 |
| commit | 1670c3af43c7af113b9f6eadc1d30d1e271cfc6c (patch) | |
| tree | b496a752f7156d57a8c310a8664d460f1073bf09 | |
| parent | 03590bb1ca6bd6fb84d7e23af3a39d419f869ddf (diff) | |
| download | qbs-1670c3af43c7af113b9f6eadc1d30d1e271cfc6c.tar.gz | |
yield error for cycles in project references and subprojects
Task-number: QBS-368
Change-Id: Ie260827fd2df2d211146958b4d8cafe8b3011ad0
Reviewed-by: Christian Kandeler <christian.kandeler@digia.com>
9 files changed, 70 insertions, 11 deletions
diff --git a/src/lib/language/moduleloader.cpp b/src/lib/language/moduleloader.cpp index 20e611d9b..7f51bc422 100644 --- a/src/lib/language/moduleloader.cpp +++ b/src/lib/language/moduleloader.cpp @@ -111,13 +111,14 @@ ModuleLoaderResult ModuleLoader::load(const QString &filePath, if (wrapWithProjectItem && root->typeName() != QLatin1String("Project")) root = wrapWithProject(root); - handleProject(&result, root); + handleProject(&result, root, QSet<QString>() << QDir::cleanPath(filePath)); result.root = root; result.qbsFiles = m_reader->filesRead(); return result; } -void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item) +void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item, + const QSet<QString> &referencedFilePaths) { if (!checkItemCondition(item)) return; @@ -141,10 +142,10 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item) if (child->typeName() == QLatin1String("Product")) { handleProduct(&projectContext, child); } else if (child->typeName() == QLatin1String("SubProject")) { - handleSubProject(&projectContext, child); + handleSubProject(&projectContext, child, referencedFilePaths); } else if (child->typeName() == QLatin1String("Project")) { copyProperties(item, child); - handleProject(loadResult, child); + handleProject(loadResult, child, referencedFilePaths); } } @@ -152,6 +153,9 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item) const QStringList refs = toStringList(m_evaluator->property(item, "references")); foreach (const QString &filePath, refs) { const QString absReferencePath = FileInfo::resolvePath(projectFileDirPath, filePath); + if (referencedFilePaths.contains(absReferencePath)) + throw ErrorInfo(Tr::tr("Cycle detected while referencing file '%1'.").arg(filePath), + item->property(QLatin1String("references"))->location()); Item *subItem = m_reader->readFile(absReferencePath); subItem->setScope(projectContext.scope); subItem->setParent(projectContext.item); @@ -162,7 +166,8 @@ void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, Item *item) handleProduct(&projectContext, subItem); } else if (subItem->typeName() == "Project") { copyProperties(item, subItem); - handleProject(loadResult, subItem); + handleProject(loadResult, subItem, + QSet<QString>(referencedFilePaths) << absReferencePath); } else { throw ErrorInfo(Tr::tr("The top-level item of a file in a \"references\" list must be " "a Product or a Project, but it is \"%1\".").arg(subItem->typeName()), @@ -208,7 +213,8 @@ void ModuleLoader::handleProduct(ProjectContext *projectContext, Item *item) projectContext->result->productInfos.insert(item, productContext.info); } -void ModuleLoader::handleSubProject(ModuleLoader::ProjectContext *projectContext, Item *item) +void ModuleLoader::handleSubProject(ModuleLoader::ProjectContext *projectContext, Item *item, + const QSet<QString> &referencedFilePaths) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] handleSubProject " << item->file()->filePath(); @@ -221,8 +227,12 @@ void ModuleLoader::handleSubProject(ModuleLoader::ProjectContext *projectContext return; const QString projectFileDirPath = FileInfo::path(item->file()->filePath()); - QString subProjectFilePath = m_evaluator->property(item, "filePath").toString(); - subProjectFilePath = FileInfo::resolvePath(projectFileDirPath, subProjectFilePath); + const QString relativeFilePath = m_evaluator->property(item, + QLatin1String("filePath")).toString(); + QString subProjectFilePath = FileInfo::resolvePath(projectFileDirPath, relativeFilePath); + if (referencedFilePaths.contains(subProjectFilePath)) + throw ErrorInfo(Tr::tr("Cycle detected while loading subproject file '%1'.") + .arg(relativeFilePath), item->location()); Item *loadedItem = m_reader->readFile(subProjectFilePath); if (loadedItem->typeName() == QLatin1String("Product")) loadedItem = wrapWithProject(loadedItem); @@ -251,7 +261,8 @@ void ModuleLoader::handleSubProject(ModuleLoader::ProjectContext *projectContext Item::addChild(item, loadedItem); item->setScope(projectContext->scope); - handleProject(projectContext->result, loadedItem); + handleProject(projectContext->result, loadedItem, + QSet<QString>(referencedFilePaths) << subProjectFilePath); } void ModuleLoader::createAdditionalModuleInstancesInProduct(ProductContext *productContext) diff --git a/src/lib/language/moduleloader.h b/src/lib/language/moduleloader.h index 6c196c414..e30d6bd4f 100644 --- a/src/lib/language/moduleloader.h +++ b/src/lib/language/moduleloader.h @@ -145,9 +145,11 @@ private: typedef QPair<Item *, ModuleLoaderResult::ProductInfo::Dependency> ProductDependencyResult; typedef QList<ProductDependencyResult> ProductDependencyResults; - void handleProject(ModuleLoaderResult *loadResult, Item *item); + void handleProject(ModuleLoaderResult *loadResult, Item *item, + const QSet<QString> &referencedFilePaths); void handleProduct(ProjectContext *projectContext, Item *item); - void handleSubProject(ProjectContext *projectContext, Item *item); + void handleSubProject(ProjectContext *projectContext, Item *item, + const QSet<QString> &referencedFilePaths); void createAdditionalModuleInstancesInProduct(ProductContext *productContext); void handleGroup(ProductContext *productContext, Item *group); void handleArtifact(ProductContext *productContext, Item *item); diff --git a/src/lib/language/testdata/erroneous/references_cycle.qbs b/src/lib/language/testdata/erroneous/references_cycle.qbs new file mode 100644 index 000000000..6d0960f09 --- /dev/null +++ b/src/lib/language/testdata/erroneous/references_cycle.qbs @@ -0,0 +1,6 @@ +import qbs 1.0 + +Project { + references: ["references_cycle2.qbs"] +} + diff --git a/src/lib/language/testdata/erroneous/references_cycle2.qbs b/src/lib/language/testdata/erroneous/references_cycle2.qbs new file mode 100644 index 000000000..0b0d2734d --- /dev/null +++ b/src/lib/language/testdata/erroneous/references_cycle2.qbs @@ -0,0 +1,6 @@ +import qbs 1.0 + +Project { + references: ["references_cycle3.qbs"] +} + diff --git a/src/lib/language/testdata/erroneous/references_cycle3.qbs b/src/lib/language/testdata/erroneous/references_cycle3.qbs new file mode 100644 index 000000000..2a237d154 --- /dev/null +++ b/src/lib/language/testdata/erroneous/references_cycle3.qbs @@ -0,0 +1,6 @@ +import qbs 1.0 + +Project { + references: ["references_cycle.qbs"] +} + diff --git a/src/lib/language/testdata/erroneous/subproject_cycle.qbs b/src/lib/language/testdata/erroneous/subproject_cycle.qbs new file mode 100644 index 000000000..0a9cd289f --- /dev/null +++ b/src/lib/language/testdata/erroneous/subproject_cycle.qbs @@ -0,0 +1,8 @@ +import qbs 1.0 + +Project { + SubProject { + filePath: "subproject_cycle2.qbs" + } +} + diff --git a/src/lib/language/testdata/erroneous/subproject_cycle2.qbs b/src/lib/language/testdata/erroneous/subproject_cycle2.qbs new file mode 100644 index 000000000..ab92d76dd --- /dev/null +++ b/src/lib/language/testdata/erroneous/subproject_cycle2.qbs @@ -0,0 +1,8 @@ +import qbs 1.0 + +Project { + SubProject { + filePath: "subproject_cycle3.qbs" + } +} + diff --git a/src/lib/language/testdata/erroneous/subproject_cycle3.qbs b/src/lib/language/testdata/erroneous/subproject_cycle3.qbs new file mode 100644 index 000000000..af1e50f5a --- /dev/null +++ b/src/lib/language/testdata/erroneous/subproject_cycle3.qbs @@ -0,0 +1,8 @@ +import qbs 1.0 + +Project { + SubProject { + filePath: "subproject_cycle.qbs" + } +} + diff --git a/src/lib/language/tst_language.cpp b/src/lib/language/tst_language.cpp index 5d75ac339..4f953de2f 100644 --- a/src/lib/language/tst_language.cpp +++ b/src/lib/language/tst_language.cpp @@ -318,6 +318,10 @@ void TestLanguage::erroneousFiles_data() << "Cannot reuse the name of built-in extension 'TextFile'."; QTest::newRow("throw_in_property_binding") << "something is wrong"; + QTest::newRow("references_cycle") + << "Cycle detected while referencing file 'references_cycle.qbs'."; + QTest::newRow("subproject_cycle") + << "Cycle detected while loading subproject file 'subproject_cycle.qbs'."; } void TestLanguage::erroneousFiles() |
