summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/language/moduleloader.cpp29
-rw-r--r--src/lib/language/moduleloader.h6
-rw-r--r--src/lib/language/testdata/erroneous/references_cycle.qbs6
-rw-r--r--src/lib/language/testdata/erroneous/references_cycle2.qbs6
-rw-r--r--src/lib/language/testdata/erroneous/references_cycle3.qbs6
-rw-r--r--src/lib/language/testdata/erroneous/subproject_cycle.qbs8
-rw-r--r--src/lib/language/testdata/erroneous/subproject_cycle2.qbs8
-rw-r--r--src/lib/language/testdata/erroneous/subproject_cycle3.qbs8
-rw-r--r--src/lib/language/tst_language.cpp4
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()