From 7f67e987ead9677f8ca95414994ea3e0ae1ef92d Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Tue, 30 Oct 2018 14:21:34 +0100 Subject: [PATCH] CompilationDatabase: Add folders to Project view Change-Id: I4cd480535c203aa923b27596ea4ca74f83c12a9e Reviewed-by: Marco Bubke --- src/libs/utils/fileutils.cpp | 7 ++ src/libs/utils/fileutils.h | 1 + .../compilationdatabaseproject.cpp | 110 +++++++++++++----- 3 files changed, 92 insertions(+), 26 deletions(-) diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index 0110857790c..5d20b7b8cc1 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -346,6 +346,13 @@ QString FileUtils::resolvePath(const QString &baseDir, const QString &fileName) return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName); } +FileName FileUtils::commonPath(const FileName &oldCommonPath, const FileName &fileName) +{ + FileName newCommonPath = oldCommonPath; + while (!newCommonPath.isEmpty() && !fileName.isChildOf(newCommonPath)) + newCommonPath = newCommonPath.parentDir(); + return canonicalPath(newCommonPath); +} QByteArray FileReader::fetchQrc(const QString &fileName) { diff --git a/src/libs/utils/fileutils.h b/src/libs/utils/fileutils.h index f6b0032f611..aa6310c7601 100644 --- a/src/libs/utils/fileutils.h +++ b/src/libs/utils/fileutils.h @@ -129,6 +129,7 @@ public: static bool isRelativePath(const QString &fileName); static bool isAbsolutePath(const QString &fileName) { return !isRelativePath(fileName); } static QString resolvePath(const QString &baseDir, const QString &fileName); + static FileName commonPath(const FileName &oldCommonPath, const FileName &fileName); }; // for actually finding out if e.g. directories are writable on Windows diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp index 198cd7c62dd..9e724cb8252 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp @@ -163,7 +163,7 @@ ToolChain *toolchainFromFlags(const Kit *kit, const QStringList &flags, const Co Utils::FileName jsonObjectFilename(const QJsonObject &object) { - const QString workingDir = object["directory"].toString(); + const QString workingDir = QDir::fromNativeSeparators(object["directory"].toString()); Utils::FileName fileName = Utils::FileName::fromString( QDir::fromNativeSeparators(object["file"].toString())); if (fileName.toFileInfo().isRelative()) { @@ -232,6 +232,76 @@ CppTools::RawProjectPart makeRawProjectPart(const Utils::FileName &projectFile, return rpp; } +QStringList relativeDirsList(Utils::FileName currentPath, const Utils::FileName &rootPath) +{ + QStringList dirsList; + while (!currentPath.isEmpty() && currentPath != rootPath) { + QString dirName = currentPath.fileName(); + if (dirName.isEmpty()) + dirName = currentPath.toString(); + dirsList.prepend(dirName); + currentPath = currentPath.parentDir(); + } + return dirsList; +} + +FolderNode *addChildFolderNode(FolderNode *parent, const QString &childName) +{ + Utils::FileName parentPath = parent->filePath(); + auto node = std::make_unique( + parentPath.appendPath(childName), NodeType::Folder, childName); + FolderNode *childNode = node.get(); + parent->addNode(std::move(node)); + + return childNode; +} + +FolderNode *addOrGetChildFolderNode(FolderNode *parent, const QString &childName) +{ + Node *childNode = parent->findNode([childName](const Node *node) { + if (!node->asFolderNode()) + return false; + QString nodeDirName = node->filePath().fileName(); + if (nodeDirName.isEmpty()) + nodeDirName = node->filePath().toString(); + return nodeDirName == childName; + }); + if (childNode) + return childNode->asFolderNode(); + + return addChildFolderNode(parent, childName); +} + + // Return the node for folderPath. +FolderNode *createFoldersIfNeeded(FolderNode *root, const Utils::FileName &folderPath) +{ + const QStringList dirsList = relativeDirsList(folderPath, root->filePath()); + + FolderNode *parent = root; + for (const QString &dir : dirsList) + parent = addOrGetChildFolderNode(parent, dir); + + return parent; +} + +void createFolders(FolderNode *root, const Utils::FileName &rootPath) +{ + root->setAbsoluteFilePathAndLine(rootPath, -1); + + for (Node *child : root->nodes()) { + FileNode *fileNode = child->asFileNode(); + if (!fileNode) + continue; + + FolderNode *parentNode = createFoldersIfNeeded(root, + fileNode->filePath().parentDir()); + child->setParentFolderNode(nullptr); + std::unique_ptr childNode = root->takeNode(child); + if (!parentNode->fileNode(child->filePath())) + parentNode->addNode(std::move(childNode)); + } +} + } // anonymous namespace void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName &projectFile) @@ -245,38 +315,22 @@ void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName const QJsonArray array = QJsonDocument::fromJson(file.readAll()).array(); auto root = std::make_unique(projectDirectory()); - root->addNode(std::make_unique( - projectFile, - FileType::Project, - false)); - auto headers = std::make_unique( - Utils::FileName::fromString("Headers"), 0); - auto sources = std::make_unique( - Utils::FileName::fromString("Sources"), 0); CppTools::RawProjectParts rpps; + Utils::FileName commonPath; ToolChain *cToolchain = nullptr; ToolChain *cxxToolchain = nullptr; for (const QJsonValue &element : array) { const QJsonObject object = element.toObject(); - Utils::FileName fileName = jsonObjectFilename(object); const QStringList flags = jsonObjectFlags(object); - const QString filePath = fileName.toString(); - const CppTools::ProjectFile::Kind kind = CppTools::ProjectFile::classify(filePath); - FolderNode *parent = nullptr; - FileType type = FileType::Unknown; - if (CppTools::ProjectFile::isHeader(kind)) { - parent = headers.get(); - type = FileType::Header; - } else if (CppTools::ProjectFile::isSource(kind)) { - parent = sources.get(); - type = FileType::Source; - } else { - parent = root.get(); - } - parent->addNode(std::make_unique(fileName, type, false)); + commonPath = rpps.empty() + ? fileName.parentDir() + : Utils::FileUtils::commonPath(commonPath, fileName); + + ProjectExplorer::FileType type = ProjectExplorer::FileType::Unknown; + root->addNode(std::make_unique(fileName, type, false)); CppTools::RawProjectPart rpp = makeRawProjectPart(projectFile, m_kit.get(), @@ -297,8 +351,12 @@ void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName rpps[rppIndex].files.append(rpp.files); } - root->addNode(std::move(headers)); - root->addNode(std::move(sources)); + createFolders(root.get(), commonPath); + + root->addNode(std::make_unique( + projectFile, + FileType::Project, + false)); setRootProjectNode(std::move(root));