CompilationDatabase: Add folders to Project view

Change-Id: I4cd480535c203aa923b27596ea4ca74f83c12a9e
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Ivan Donchevskii
2018-10-30 14:21:34 +01:00
parent 595824d17b
commit 7f67e987ea
3 changed files with 92 additions and 26 deletions

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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<FolderNode>(
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<Node> 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<DBProjectNode>(projectDirectory());
root->addNode(std::make_unique<FileNode>(
projectFile,
FileType::Project,
false));
auto headers = std::make_unique<VirtualFolderNode>(
Utils::FileName::fromString("Headers"), 0);
auto sources = std::make_unique<VirtualFolderNode>(
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<FileNode>(fileName, type, false));
commonPath = rpps.empty()
? fileName.parentDir()
: Utils::FileUtils::commonPath(commonPath, fileName);
ProjectExplorer::FileType type = ProjectExplorer::FileType::Unknown;
root->addNode(std::make_unique<FileNode>(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<FileNode>(
projectFile,
FileType::Project,
false));
setRootProjectNode(std::move(root));