diff options
author | Ivan Komissarov <[email protected]> | 2025-06-14 13:19:37 +0300 |
---|---|---|
committer | Ivan Komissarov <[email protected]> | 2025-06-25 11:48:47 +0000 |
commit | 27cc61e6693670054c11e669ade4697baf350ecd (patch) | |
tree | 236e0ce99635da61c6a3cac7156a6e6093b36181 | |
parent | 314765f95436b399fa251d92af32eaab9d87795a (diff) |
generators: add artifacts to graphviz generator
Change-Id: Id494b304a29c04ea74a4dbdb40bf6ef50baf6993
Reviewed-by: Christian Kandeler <[email protected]>
-rw-r--r-- | src/lib/corelib/api/project.cpp | 13 | ||||
-rw-r--r-- | src/lib/corelib/api/projectdata.cpp | 5 | ||||
-rw-r--r-- | src/lib/corelib/api/projectdata.h | 1 | ||||
-rw-r--r-- | src/lib/corelib/api/projectdata_p.h | 1 | ||||
-rw-r--r-- | src/plugins/generator/graphviz/dotgraph.h | 6 | ||||
-rw-r--r-- | src/plugins/generator/graphviz/graphvizgenerator.cpp | 55 |
6 files changed, 80 insertions, 1 deletions
diff --git a/src/lib/corelib/api/project.cpp b/src/lib/corelib/api/project.cpp index 658e04814..abab9c94c 100644 --- a/src/lib/corelib/api/project.cpp +++ b/src/lib/corelib/api/project.cpp @@ -285,6 +285,11 @@ ArtifactData ProjectPrivate::createArtifactData(const Artifact *artifact, ta.d->filePath = artifact->filePath(); ta.d->fileTags = artifact->fileTags().toStringList(); ta.d->properties.d->m_map = artifact->properties; + for (const Artifact *a : filterByType<Artifact>(artifact->children)) { + ta.d->childPaths << a->filePath(); + for (const auto *f : a->fileDependencies) + ta.d->childPaths << f->filePath(); + } ta.d->isGenerated = artifact->artifactType == Artifact::Generated; ta.d->isTargetArtifact = targetArtifacts.contains(const_cast<Artifact *>(artifact)); ta.d->isValid = true; @@ -678,6 +683,14 @@ void ProjectPrivate::retrieveProjectData(ProjectData &projectData, ta.d->filePath = it.key(); ta.d->fileTags = it.value().fileTags.toStringList(); ta.d->properties.d->m_map = it.value().properties; + Artifact * const child = lookupArtifact(resolvedProduct, it.key(), true); + if (child) { + for (const Artifact *a : filterByType<Artifact>(child->children)) { + ta.d->childPaths << a->filePath(); + for (const auto *f : a->fileDependencies) + ta.d->childPaths << f->filePath(); + } + } ta.d->isGenerated = true; ta.d->isTargetArtifact = resolvedProduct->fileTags.intersects(it.value().fileTags); ta.d->isValid = true; diff --git a/src/lib/corelib/api/projectdata.cpp b/src/lib/corelib/api/projectdata.cpp index 0a4fe5486..cc4a9ea60 100644 --- a/src/lib/corelib/api/projectdata.cpp +++ b/src/lib/corelib/api/projectdata.cpp @@ -354,6 +354,11 @@ InstallData ArtifactData::installData() const return d->installData; } +QStringList ArtifactData::childPaths() const +{ + return d->childPaths; +} + bool operator==(const ArtifactData &ad1, const ArtifactData &ad2) { return ad1.filePath() == ad2.filePath() diff --git a/src/lib/corelib/api/projectdata.h b/src/lib/corelib/api/projectdata.h index 4b7bc2803..5b4dde686 100644 --- a/src/lib/corelib/api/projectdata.h +++ b/src/lib/corelib/api/projectdata.h @@ -129,6 +129,7 @@ public: bool isTargetArtifact() const; PropertyMap properties() const; InstallData installData() const; + QStringList childPaths() const; private: QExplicitlySharedDataPointer<Internal::ArtifactDataPrivate> d; diff --git a/src/lib/corelib/api/projectdata_p.h b/src/lib/corelib/api/projectdata_p.h index e241ea92c..5b6a8c037 100644 --- a/src/lib/corelib/api/projectdata_p.h +++ b/src/lib/corelib/api/projectdata_p.h @@ -63,6 +63,7 @@ public: QStringList fileTags; PropertyMap properties; InstallData installData; + QStringList childPaths; bool isValid = false; bool isGenerated = false; bool isTargetArtifact = false; diff --git a/src/plugins/generator/graphviz/dotgraph.h b/src/plugins/generator/graphviz/dotgraph.h index ed449c92f..ddd28795a 100644 --- a/src/plugins/generator/graphviz/dotgraph.h +++ b/src/plugins/generator/graphviz/dotgraph.h @@ -53,7 +53,7 @@ struct DotGraphNode QString label; bool enabled{true}; - enum class Type { Product, Project, Module }; + enum class Type { Product, Project, Module, Artifact, File }; Type type; static QByteArray typeToString(Type type) @@ -64,6 +64,10 @@ struct DotGraphNode return QByteArray("box"); if (type == Type::Module) return QByteArray("diamond"); + if (type == Type::Artifact) + return QByteArray("pentagon"); + if (type == Type::File) + return QByteArray("note"); return QByteArray("box"); } diff --git a/src/plugins/generator/graphviz/graphvizgenerator.cpp b/src/plugins/generator/graphviz/graphvizgenerator.cpp index f8041d0a8..c142cd682 100644 --- a/src/plugins/generator/graphviz/graphvizgenerator.cpp +++ b/src/plugins/generator/graphviz/graphvizgenerator.cpp @@ -219,6 +219,61 @@ void GraphvizGenerator::writeProductGraph( dotGraph.addRelation({productNode, childNode}); } + const auto fileTagsString = [](const ArtifactData &artifact) { + return QStringLiteral("[%1]").arg(artifact.fileTags().join(QLatin1String(", "))); + }; + + const auto productNode2 = dotGraph.addNode( + makeProductNode(dotGraph.createNodeId(), productMap.at(product.name()))); + + std::unordered_map<QString, size_t> artifactToNode; + std::unordered_map<QString, ArtifactData> artifactMap; + + for (const auto &group : product.groups()) { + for (const auto &artifact : group.allSourceArtifacts()) { + artifactMap[artifact.filePath()] = artifact; + } + } + + std::deque<std::pair<ArtifactData, size_t /*node*/>> artifactQueue; + for (const auto &artifact : product.generatedArtifacts()) { + artifactMap[artifact.filePath()] = artifact; + if (artifact.isTargetArtifact()) + artifactQueue.push_back({artifact, productNode2}); + } + + // Traverse artifacts starting from target artifacts down to their dependencies. + // This way we create nodes only for artifacts reachable from the top of the graph. + // Otherwise, graph becomes too complicated. + while (!artifactQueue.empty()) { + const auto &[artifact, parentNodeId] = artifactQueue.front(); + const auto currentPath = artifact.filePath(); + + auto &nodeId = artifactToNode[currentPath]; + if (nodeId) { + dotGraph.addRelation({parentNodeId, nodeId}); + artifactQueue.pop_front(); + continue; + } + DotGraphNode node; + node.id = dotGraph.createNodeId(); + node.label = QFileInfo(currentPath).fileName() + QLatin1String("\n") + + fileTagsString(artifact); + node.type = artifact.isGenerated() ? DotGraphNode::Type::Artifact + : DotGraphNode::Type::File; + nodeId = dotGraph.addNode(std::move(node)); + + dotGraph.addRelation({parentNodeId, nodeId}); + + for (const auto &childPath : artifact.childPaths()) { + auto it = artifactMap.find(childPath); + if (it != artifactMap.end()) { + artifactQueue.push_back({it->second, nodeId}); + } + } + artifactQueue.pop_front(); + } + const QString graphFilePath = getFileName( projectData, QLatin1String(".products/") + product.name()); dotGraph.write(graphFilePath); |