forked from qt-creator/qt-creator
ProjectExplorer: Use visitor-by-lambda for project tree
And inline it into user code. Less code in total and no intermediate node lists. Change-Id: I3724883408bfaa868266110aee27bbffd4d96bd8 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -28,7 +28,6 @@
|
||||
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/projectnodes.h>
|
||||
#include <projectexplorer/nodesvisitor.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <resourceeditor/resourcenode.h>
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "nodesvisitor.h"
|
||||
#include "projectnodes.h"
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
/*!
|
||||
\class NodesVisitor
|
||||
|
||||
\brief Base class for visitors that can be used to traverse a node hierarchy.
|
||||
|
||||
The class follows the visitor pattern as described in Gamma et al. Pass
|
||||
an instance of NodesVisitor to FolderNode::accept(): The visit functions
|
||||
will be called for each node in the subtree, except for file nodes:
|
||||
Access these through FolderNode::fileNodes() in visitProjectNode()
|
||||
and visitoFolderNode().
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn NodesVisitor::visitSessionNode(SessionNode *)
|
||||
|
||||
Called for the root session node.
|
||||
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn NodesVisitor::visitProjectNode(SessionNode *)
|
||||
|
||||
Called for a project node.
|
||||
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn NodesVisitor::visitFolderNode(SessionNode *)
|
||||
|
||||
Called for a folder node that is _not_ a SessionNode or a ProjectNode.
|
||||
|
||||
The default implementation does nothing.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\class FindNodeForFileVisitor
|
||||
|
||||
Searches the first node that has the given file as its path.
|
||||
*/
|
||||
|
||||
FindNodesForFileVisitor::FindNodesForFileVisitor(const Utils::FileName &fileToSearch)
|
||||
: m_path(fileToSearch)
|
||||
{
|
||||
}
|
||||
|
||||
QList<Node*> FindNodesForFileVisitor::nodes() const
|
||||
{
|
||||
return m_nodes;
|
||||
}
|
||||
|
||||
void FindNodesForFileVisitor::visitFolderNode(FolderNode *node)
|
||||
{
|
||||
if (node->filePath() == m_path)
|
||||
m_nodes << node;
|
||||
foreach (FileNode *fileNode, node->fileNodes()) {
|
||||
if (fileNode->filePath() == m_path)
|
||||
m_nodes << fileNode;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\class FindAllFilesVisitor
|
||||
|
||||
Collects file information from all sub file nodes.
|
||||
*/
|
||||
|
||||
Utils::FileNameList FindAllFilesVisitor::filePaths() const
|
||||
{
|
||||
return m_filePaths;
|
||||
}
|
||||
|
||||
void FindAllFilesVisitor::visitFolderNode(FolderNode *folderNode)
|
||||
{
|
||||
m_filePaths.append(folderNode->filePath());
|
||||
foreach (const FileNode *fileNode, folderNode->fileNodes())
|
||||
m_filePaths.append(fileNode->filePath());
|
||||
}
|
||||
|
||||
NodesVisitor::~NodesVisitor()
|
||||
{
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "projectexplorer_export.h"
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
class Node;
|
||||
class FileNode;
|
||||
class SessionNode;
|
||||
class FolderNode;
|
||||
|
||||
class PROJECTEXPLORER_EXPORT NodesVisitor
|
||||
{
|
||||
public:
|
||||
virtual ~NodesVisitor();
|
||||
|
||||
virtual void visitFolderNode(FolderNode *) { }
|
||||
|
||||
protected:
|
||||
NodesVisitor() {}
|
||||
};
|
||||
|
||||
/* useful visitors */
|
||||
|
||||
class PROJECTEXPLORER_EXPORT FindNodesForFileVisitor : public NodesVisitor
|
||||
{
|
||||
public:
|
||||
explicit FindNodesForFileVisitor(const Utils::FileName &fileToSearch);
|
||||
|
||||
QList<Node*> nodes() const;
|
||||
|
||||
void visitFolderNode(FolderNode *node) override;
|
||||
|
||||
private:
|
||||
Utils::FileName m_path;
|
||||
QList<Node *> m_nodes;
|
||||
};
|
||||
|
||||
class PROJECTEXPLORER_EXPORT FindAllFilesVisitor : public NodesVisitor
|
||||
{
|
||||
public:
|
||||
Utils::FileNameList filePaths() const;
|
||||
|
||||
void visitFolderNode(FolderNode *folderNode) override;
|
||||
|
||||
private:
|
||||
Utils::FileNameList m_filePaths;
|
||||
};
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
@@ -63,7 +63,6 @@
|
||||
#include "dependenciespanel.h"
|
||||
#include "foldernavigationwidget.h"
|
||||
#include "iprojectmanager.h"
|
||||
#include "nodesvisitor.h"
|
||||
#include "appoutputpane.h"
|
||||
#include "processstep.h"
|
||||
#include "kitinformation.h"
|
||||
|
||||
@@ -80,7 +80,6 @@ HEADERS += projectexplorer.h \
|
||||
sessionview.h \
|
||||
projectwizardpage.h \
|
||||
buildstepspage.h \
|
||||
nodesvisitor.h \
|
||||
projectmodels.h \
|
||||
currentprojectfind.h \
|
||||
toolchain.h \
|
||||
@@ -227,7 +226,6 @@ SOURCES += projectexplorer.cpp \
|
||||
sessionview.cpp \
|
||||
projectwizardpage.cpp \
|
||||
buildstepspage.cpp \
|
||||
nodesvisitor.cpp \
|
||||
projectmodels.cpp \
|
||||
currentprojectfind.cpp \
|
||||
toolchain.cpp \
|
||||
|
||||
@@ -100,7 +100,6 @@ Project {
|
||||
"localenvironmentaspect.cpp", "localenvironmentaspect.h",
|
||||
"miniprojecttargetselector.cpp", "miniprojecttargetselector.h",
|
||||
"namedwidget.cpp", "namedwidget.h",
|
||||
"nodesvisitor.cpp", "nodesvisitor.h",
|
||||
"osparser.cpp", "osparser.h",
|
||||
"panelswidget.cpp", "panelswidget.h",
|
||||
"processparameters.cpp", "processparameters.h",
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include "projectnodes.h"
|
||||
|
||||
#include "nodesvisitor.h"
|
||||
#include "projectexplorerconstants.h"
|
||||
#include "projecttree.h"
|
||||
|
||||
@@ -58,7 +57,7 @@ namespace ProjectExplorer {
|
||||
A Visitor can be used to traverse all Projects and other Folders.
|
||||
|
||||
\sa ProjectExplorer::FileNode, ProjectExplorer::FolderNode, ProjectExplorer::ProjectNode
|
||||
\sa ProjectExplorer::NodesWatcher, ProjectExplorer::NodesVisitor
|
||||
\sa ProjectExplorer::NodesWatcher
|
||||
*/
|
||||
|
||||
Node::Node(NodeType nodeType, const Utils::FileName &filePath, int line) :
|
||||
@@ -516,15 +515,6 @@ void FolderNode::compress()
|
||||
}
|
||||
}
|
||||
|
||||
void FolderNode::accept(NodesVisitor *visitor)
|
||||
{
|
||||
visitor->visitFolderNode(this);
|
||||
for (Node *n : m_nodes) {
|
||||
if (FolderNode *subFolder = n->asFolderNode())
|
||||
subFolder->accept(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
void FolderNode::setDisplayName(const QString &name)
|
||||
{
|
||||
if (m_displayName == name)
|
||||
|
||||
@@ -88,11 +88,9 @@ enum ProjectAction {
|
||||
HasSubProjectRunConfigurations
|
||||
};
|
||||
|
||||
class Node;
|
||||
class FileNode;
|
||||
class FolderNode;
|
||||
class ProjectNode;
|
||||
class NodesVisitor;
|
||||
|
||||
// Documentation inside.
|
||||
class PROJECTEXPLORER_EXPORT Node : public QObject
|
||||
@@ -207,8 +205,6 @@ public:
|
||||
void buildTree(QList<FileNode *> &files, const Utils::FileName &overrideBaseDir = Utils::FileName());
|
||||
void compress();
|
||||
|
||||
virtual void accept(NodesVisitor *visitor);
|
||||
|
||||
void setDisplayName(const QString &name);
|
||||
void setIcon(const QIcon &icon);
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "project.h"
|
||||
#include "projectnodes.h"
|
||||
#include "projectexplorerconstants.h"
|
||||
#include "nodesvisitor.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
@@ -272,15 +272,11 @@ void ProjectTreeWidget::rowsInserted(const QModelIndex &parent, int start, int e
|
||||
|
||||
Node *ProjectTreeWidget::nodeForFile(const Utils::FileName &fileName)
|
||||
{
|
||||
return mostExpandedNode(SessionManager::nodesForFile(fileName));
|
||||
}
|
||||
|
||||
Node *ProjectTreeWidget::mostExpandedNode(const QList<Node *> &nodes)
|
||||
{
|
||||
Node *bestNode = 0;
|
||||
Node *bestNode = nullptr;
|
||||
int bestNodeExpandCount = INT_MAX;
|
||||
|
||||
foreach (Node *node, nodes) {
|
||||
SessionManager::sessionNode()->forEachGenericNode([&](Node *node) {
|
||||
if (node->filePath() == fileName) {
|
||||
if (!bestNode) {
|
||||
bestNode = node;
|
||||
bestNodeExpandCount = ProjectTreeWidget::expandedCount(node);
|
||||
@@ -295,6 +291,8 @@ Node *ProjectTreeWidget::mostExpandedNode(const QList<Node *> &nodes)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return bestNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ public:
|
||||
void showMessage(ProjectExplorer::Node *node, const QString &message);
|
||||
|
||||
static Node *nodeForFile(const Utils::FileName &fileName);
|
||||
static Node *mostExpandedNode(const QList<Node*> &nodes);
|
||||
|
||||
void toggleAutoSynchronization();
|
||||
void editCurrentItem();
|
||||
|
||||
@@ -31,9 +31,8 @@
|
||||
#include "buildconfiguration.h"
|
||||
#include "deployconfiguration.h"
|
||||
#include "projectexplorer.h"
|
||||
#include "nodesvisitor.h"
|
||||
#include "editorconfiguration.h"
|
||||
#include "projectnodes.h"
|
||||
#include "editorconfiguration.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
@@ -624,23 +623,18 @@ QList<Project *> SessionManager::projectOrder(const Project *project)
|
||||
return result;
|
||||
}
|
||||
|
||||
QList<Node *> SessionManager::nodesForFile(const Utils::FileName &fileName)
|
||||
{
|
||||
FindNodesForFileVisitor findNodes(fileName);
|
||||
sessionNode()->accept(&findNodes);
|
||||
return findNodes.nodes();
|
||||
}
|
||||
|
||||
// node for file returns a randomly selected node if there are multiple
|
||||
// prefer to use nodesForFile and figure out which node you want
|
||||
Node *SessionManager::nodeForFile(const Utils::FileName &fileName)
|
||||
{
|
||||
Node *node = nullptr;
|
||||
foreach (Node *n, nodesForFile(fileName)) {
|
||||
sessionNode()->forEachGenericNode([&](Node *n) {
|
||||
if (n->filePath() == fileName) {
|
||||
// prefer file nodes
|
||||
if (!node || (node->nodeType() != NodeType::File && n->nodeType() == NodeType::File))
|
||||
node = n;
|
||||
}
|
||||
});
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,6 @@ public:
|
||||
static SessionNode *sessionNode();
|
||||
|
||||
static Project *projectForNode(Node *node);
|
||||
static QList<Node *> nodesForFile(const Utils::FileName &fileName);
|
||||
static Node *nodeForFile(const Utils::FileName &fileName);
|
||||
static Project *projectForFile(const Utils::FileName &fileName);
|
||||
|
||||
|
||||
@@ -48,12 +48,11 @@
|
||||
#include <projectexplorer/buildmanager.h>
|
||||
#include <projectexplorer/buildtargetinfo.h>
|
||||
#include <projectexplorer/deploymentdata.h>
|
||||
#include <projectexplorer/nodesvisitor.h>
|
||||
#include <projectexplorer/toolchain.h>
|
||||
#include <projectexplorer/headerpath.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <projectexplorer/taskhub.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/toolchain.h>
|
||||
#include <proparser/qmakevfs.h>
|
||||
#include <qtsupport/profilereader.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
@@ -157,66 +156,8 @@ QDebug operator<<(QDebug d, const QmakeProjectFiles &f)
|
||||
return d;
|
||||
}
|
||||
|
||||
// A visitor to collect all files of a project in a QmakeProjectFiles struct
|
||||
class ProjectFilesVisitor : public NodesVisitor
|
||||
{
|
||||
ProjectFilesVisitor(QmakeProjectFiles *files);
|
||||
|
||||
public:
|
||||
static void findProjectFiles(QmakeProFileNode *rootNode, QmakeProjectFiles *files);
|
||||
|
||||
void visitFolderNode(FolderNode *folderNode) final;
|
||||
|
||||
private:
|
||||
QmakeProjectFiles *m_files;
|
||||
};
|
||||
|
||||
ProjectFilesVisitor::ProjectFilesVisitor(QmakeProjectFiles *files) :
|
||||
m_files(files)
|
||||
{
|
||||
}
|
||||
|
||||
namespace {
|
||||
// uses std::unique, so takes a sorted list
|
||||
void unique(QStringList &list)
|
||||
{
|
||||
list.erase(std::unique(list.begin(), list.end()), list.end());
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectFilesVisitor::findProjectFiles(QmakeProFileNode *rootNode, QmakeProjectFiles *files)
|
||||
{
|
||||
files->clear();
|
||||
ProjectFilesVisitor visitor(files);
|
||||
rootNode->accept(&visitor);
|
||||
for (int i = 0; i < static_cast<int>(FileType::FileTypeSize); ++i) {
|
||||
Utils::sort(files->files[i]);
|
||||
unique(files->files[i]);
|
||||
Utils::sort(files->generatedFiles[i]);
|
||||
unique(files->generatedFiles[i]);
|
||||
}
|
||||
Utils::sort(files->proFiles);
|
||||
unique(files->proFiles);
|
||||
}
|
||||
|
||||
void ProjectFilesVisitor::visitFolderNode(FolderNode *folderNode)
|
||||
{
|
||||
if (ProjectNode *projectNode = folderNode->asProjectNode())
|
||||
m_files->proFiles.append(projectNode->filePath().toString());
|
||||
if (dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(folderNode))
|
||||
m_files->files[static_cast<int>(FileType::Resource)].push_back(folderNode->filePath().toString());
|
||||
|
||||
foreach (FileNode *fileNode, folderNode->fileNodes()) {
|
||||
const int type = static_cast<int>(fileNode->fileType());
|
||||
QStringList &targetList = fileNode->isGenerated() ? m_files->generatedFiles[type] : m_files->files[type];
|
||||
targetList.push_back(fileNode->filePath().toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------- QmakeProjectFile
|
||||
namespace Internal {
|
||||
|
||||
QmakeProjectFile::QmakeProjectFile(const QString &filePath)
|
||||
{
|
||||
setId("Qmake.ProFile");
|
||||
@@ -303,10 +244,26 @@ QmakeProFile *QmakeProject::rootProFile() const
|
||||
|
||||
void QmakeProject::updateFileList()
|
||||
{
|
||||
QmakeProjectFiles newFiles;
|
||||
ProjectFilesVisitor::findProjectFiles(rootProjectNode(), &newFiles);
|
||||
if (newFiles != *m_projectFiles) {
|
||||
*m_projectFiles = newFiles;
|
||||
QmakeProjectFiles files;
|
||||
rootProjectNode()->forEachNode([&](FileNode *fileNode) {
|
||||
const int type = static_cast<int>(fileNode->fileType());
|
||||
QStringList &targetList = fileNode->isGenerated() ? files.generatedFiles[type] : files.files[type];
|
||||
targetList.push_back(fileNode->filePath().toString());
|
||||
}, [&](FolderNode *folderNode) {
|
||||
if (ProjectNode *projectNode = folderNode->asProjectNode())
|
||||
files.proFiles.append(projectNode->filePath().toString());
|
||||
if (dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(folderNode))
|
||||
files.files[static_cast<int>(FileType::Resource)].push_back(folderNode->filePath().toString());
|
||||
});
|
||||
|
||||
for (QStringList &f : files.files)
|
||||
f.removeDuplicates();
|
||||
for (QStringList &f : files.generatedFiles)
|
||||
f.removeDuplicates();
|
||||
files.proFiles.removeDuplicates();
|
||||
|
||||
if (files != *m_projectFiles) {
|
||||
*m_projectFiles = files;
|
||||
emit fileListChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
#include "todoitemsmodel.h"
|
||||
#include "todoitemsscanner.h"
|
||||
|
||||
#include <projectexplorer/nodesvisitor.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/projectnodes.h>
|
||||
#include <projectexplorer/projecttree.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
#include <projectexplorer/session.h>
|
||||
|
||||
#include <QTimer>
|
||||
@@ -148,13 +148,13 @@ void TodoItemsProvider::setItemsListWithinSubproject()
|
||||
if (node) {
|
||||
ProjectNode *projectNode = node->parentProjectNode();
|
||||
if (projectNode) {
|
||||
|
||||
FindAllFilesVisitor filesVisitor;
|
||||
projectNode->accept(&filesVisitor);
|
||||
// FIXME: The name doesn't match the implementation that lists all files.
|
||||
QSet<Utils::FileName> subprojectFileNames;
|
||||
projectNode->forEachGenericNode([&](Node *node) {
|
||||
subprojectFileNames.insert(node->filePath());
|
||||
});
|
||||
|
||||
// files must be both in the current subproject and the startup-project.
|
||||
QSet<Utils::FileName> subprojectFileNames =
|
||||
QSet<Utils::FileName>::fromList(filesVisitor.filePaths());
|
||||
QSet<QString> fileNames = QSet<QString>::fromList(
|
||||
m_startupProject->files(ProjectExplorer::Project::SourceFiles));
|
||||
QHashIterator<QString, QList<TodoItem> > it(m_itemsHash);
|
||||
|
||||
Reference in New Issue
Block a user