diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index f33ecf164a8..78f11b0b27d 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -218,7 +218,7 @@ QList CMakeBuildConfiguration::buildTargets() const CMakeListsNode * CMakeBuildConfiguration::generateProjectTree(const QList &allFiles) const { - auto root = new CMakeListsNode(target()->project()->projectFilePath()); + auto root = new CMakeListsNode(target()->project()->projectDirectory()); if (!m_buildDirManager || m_buildDirManager->isParsing()) return nullptr; diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index bcc809e295f..19ec690ba06 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -531,87 +531,31 @@ void ServerModeReader::addCMakeLists(CMakeListsNode *root, const QList nodeHash; - for (FileNode *cm : cmakeLists) { - const QString relPath = baseDir.relativeFilePath(cm->filePath().parentDir().toString()); - QTC_CHECK(!nodeHash.contains(relPath)); - nodeHash[(relPath == ".") ? QString() : relPath ] = cm; - } - QStringList tmp = nodeHash.keys(); - Utils::sort(tmp, [](const QString &a, const QString &b) { return a.count() < b.count(); }); - const QStringList keys = tmp; - - QHash knownNodes; - knownNodes[QString()] = root; - - for (const QString &k : keys) { - FileNode *fn = nodeHash[k]; - CMakeListsNode *parentNode = nullptr; - QString prefix = k; - forever { - if (knownNodes.contains(prefix)) { - parentNode = knownNodes.value(prefix); - break; - } - const int pos = prefix.lastIndexOf('/'); - prefix = (pos < 0) ? QString() : prefix.left(prefix.lastIndexOf('/')); - } - - // Find or create CMakeListsNode: - CMakeListsNode *cmln = nullptr; - if (parentNode->filePath() == fn->filePath()) - cmln = parentNode; // Top level! + root->addNestedNodes(cmakeLists, Utils::FileName(), + [&cmakeLists](const Utils::FileName &fp) -> ProjectExplorer::FolderNode * { + if (Utils::contains(cmakeLists, [&fp](const FileNode *fn) { return fn->filePath().parentDir() == fp; })) + return new CMakeListsNode(fp); else - cmln = static_cast(parentNode->projectNode(fn->filePath())); - if (!cmln) { - cmln = new CMakeListsNode(fn->filePath()); - parentNode->addNode(cmln); - } - - // Find or create CMakeLists.txt filenode below CMakeListsNode: - FileNode *cmFn = cmln->fileNode(fn->filePath()); - if (!cmFn) { - cmFn = fn; - cmln->addNode(cmFn); - } - // Update displayName of CMakeListsNode: - const QString dn = prefix.isEmpty() ? k : k.mid(prefix.count() + 1); - if (!dn.isEmpty()) - cmln->setDisplayName(dn); // Set partial path as display name - - knownNodes.insert(k, cmln); - } + return new FolderNode(fp); + }); } static CMakeListsNode *findCMakeNode(CMakeListsNode *root, const Utils::FileName &dir) { const Utils::FileName stepDir = dir; - const Utils::FileName topDir = root->filePath().parentDir(); + const Utils::FileName topDir = root->filePath(); QStringList relative = stepDir.relativeChildPath(topDir).toString().split('/', QString::SkipEmptyParts); - CMakeListsNode *result = root; - - QString relativePathElement; + FolderNode *result = root; while (!relative.isEmpty()) { - const QString nextDirPath = result->filePath().parentDir().toString(); - Utils::FileName nextFullPath; - // Some directory may not contain CMakeLists.txt file, skip it: - do { - relativePathElement += '/' + relative.takeFirst(); - nextFullPath = Utils::FileName::fromString(nextDirPath + relativePathElement + "/CMakeLists.txt"); - } while (!nextFullPath.exists() && !relative.isEmpty()); - result = static_cast(result->projectNode(nextFullPath)); - // Intermediate directory can contain CMakeLists.txt file - // that is not a part of the root node, skip it: - if (!result && !relative.isEmpty()) { - result = root; - } else { - relativePathElement.clear(); - } - QTC_ASSERT(result, return nullptr); + Utils::FileName nextFullPath = result->filePath(); + nextFullPath.appendPath(relative.takeFirst()); + result = findOrDefault(result->folderNodes(), Utils::equal(&FolderNode::filePath, nextFullPath)); + if (!result) + return nullptr; } - return result; + return dynamic_cast(result); } static CMakeProjectNode *findOrCreateProjectNode(CMakeListsNode *root, const Utils::FileName &dir, diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 8067795304f..099ff9b76ad 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -60,7 +60,8 @@ static FolderNode *folderNode(const FolderNode *folder, const Utils::FileName &d static FolderNode *recursiveFindOrCreateFolderNode(FolderNode *folder, const Utils::FileName &directory, - const Utils::FileName &overrideBaseDir) + const Utils::FileName &overrideBaseDir, + const FolderNode::FolderNodeFactory &factory) { Utils::FileName path = overrideBaseDir.isEmpty() ? folder->filePath() : overrideBaseDir; @@ -90,7 +91,7 @@ static FolderNode *recursiveFindOrCreateFolderNode(FolderNode *folder, FolderNode *next = folderNode(parent, path); if (!next) { // No FolderNode yet, so create it - auto tmp = new ProjectExplorer::FolderNode(path); + auto tmp = factory(path); tmp->setDisplayName(part); parent->addNode(tmp); next = tmp; @@ -460,20 +461,22 @@ QList FolderNode::folderNodes() const return result; } -void FolderNode::addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir) +void FolderNode::addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir, + const FolderNodeFactory &factory) { // Get relative path to rootNode QString parentDir = fileNode->filePath().toFileInfo().absolutePath(); FolderNode *folder = recursiveFindOrCreateFolderNode(this, Utils::FileName::fromString(parentDir), - overrideBaseDir); + overrideBaseDir, factory); folder->addNode(fileNode); } -void FolderNode::addNestedNodes(QList &files, const Utils::FileName &overrideBaseDir) +void FolderNode::addNestedNodes(const QList &files, const Utils::FileName &overrideBaseDir, + const FolderNodeFactory &factory) { for (FileNode *fn : files) - addNestedNode(fn, overrideBaseDir); + addNestedNode(fn, overrideBaseDir, factory); } // "Compress" a tree of foldernodes such that foldernodes with exactly one foldernode as a child diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index aa5b9e397f2..9ac9d678cce 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -200,8 +200,11 @@ public: QList fileNodes() const; FileNode *fileNode(const Utils::FileName &file) const; QList folderNodes() const; - void addNestedNodes(QList &files, const Utils::FileName &overrideBaseDir = Utils::FileName()); - void addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir = Utils::FileName()); + using FolderNodeFactory = std::function; + void addNestedNodes(const QList &files, const Utils::FileName &overrideBaseDir = Utils::FileName(), + const FolderNodeFactory &factory = [](const Utils::FileName &fn) { return new FolderNode(fn); }); + void addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir = Utils::FileName(), + const FolderNodeFactory &factory = [](const Utils::FileName &fn) { return new FolderNode(fn); }); void compress(); bool isAncesterOf(Node *n);