CMake: Pass const QList<const FileNode *> to Directory Readers

This makes sure they need to copy whatever they need.

Change-Id: I767ac0c5f54ca1f9f46acdefe4bd7fea35657312
Reviewed-by: Alexander Drozdov <adrozdoff@gmail.com>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Tobias Hunger
2016-12-15 12:53:37 +01:00
parent a347768488
commit 1b2fc1c815
14 changed files with 59 additions and 73 deletions

View File

@@ -276,40 +276,25 @@ bool BuildDirManager::persistCMakeState()
return true;
}
void BuildDirManager::generateProjectTree(CMakeListsNode *root, const QList<FileNode *> &allFiles)
void BuildDirManager::generateProjectTree(CMakeListsNode *root, const QList<const FileNode *> &allFiles)
{
QTC_ASSERT(m_reader, return);
const Utils::FileName projectFile = m_buildConfiguration->target()->project()->projectFilePath();
// input files only a reference, it persistent between calls
// make copy of them for concrete configuration
auto tmp = Utils::transform(allFiles, [](const FileNode* fn) {
return new FileNode(*fn);
});
m_reader->generateProjectTree(root, tmp);
QSet<FileNode *> usedNodes;
foreach (FileNode *fn, root->recursiveFileNodes())
usedNodes.insert(fn);
m_reader->generateProjectTree(root, allFiles);
// Make sure the top level CMakeLists.txt is always visible:
if (root->fileNodes().isEmpty()
&& root->folderNodes().isEmpty()
&& root->projectNodes().isEmpty()) {
FileNode *cm = Utils::findOrDefault(tmp, [&projectFile](const FileNode *fn) {
const FileNode *cm = Utils::findOrDefault(allFiles, [&projectFile](const FileNode *fn) {
return fn->filePath() == projectFile;
});
if (cm) {
root->addFileNodes({ cm });
usedNodes.insert(cm);
root->addFileNodes({ new FileNode(*cm) });
}
}
QList<FileNode *> leftOvers = Utils::filtered(tmp, [&usedNodes](FileNode *fn) {
return !usedNodes.contains(fn);
});
qDeleteAll(leftOvers);
}
QSet<Core::Id> BuildDirManager::updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder)

View File

@@ -71,7 +71,8 @@ public:
bool updateCMakeStateBeforeBuild();
bool persistCMakeState();
void generateProjectTree(CMakeListsNode *root, const QList<ProjectExplorer::FileNode *> &allFiles);
void generateProjectTree(CMakeListsNode *root,
const QList<const ProjectExplorer::FileNode *> &allFiles);
QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder);
QList<CMakeBuildTarget> buildTargets() const;

View File

@@ -103,7 +103,7 @@ public:
virtual CMakeConfig takeParsedConfiguration() = 0;
virtual QList<CMakeBuildTarget> buildTargets() const = 0;
virtual void generateProjectTree(CMakeListsNode *root,
const QList<ProjectExplorer::FileNode *> &allFiles) = 0;
const QList<const ProjectExplorer::FileNode *> &allFiles) = 0;
virtual QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder) = 0;
signals:

View File

@@ -210,7 +210,8 @@ QList<CMakeBuildTarget> CMakeBuildConfiguration::buildTargets() const
return m_buildDirManager->buildTargets();
}
void CMakeBuildConfiguration::generateProjectTree(CMakeListsNode *root, const QList<FileNode*> &allFiles) const
void CMakeBuildConfiguration::generateProjectTree(CMakeListsNode *root,
const QList<const FileNode*> &allFiles) const
{
if (!m_buildDirManager || m_buildDirManager->isParsing())
return;

View File

@@ -85,7 +85,7 @@ public:
void clearCache();
QList<CMakeBuildTarget> buildTargets() const;
void generateProjectTree(CMakeListsNode *root, const QList<ProjectExplorer::FileNode *> &allFiles) const;
void generateProjectTree(CMakeListsNode *root, const QList<const ProjectExplorer::FileNode *> &allFiles) const;
QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder);
static Utils::FileName

View File

@@ -392,7 +392,7 @@ void CMakeProject::handleParsingStarted()
void CMakeProject::handleTreeScanningFinished()
{
qDeleteAll(m_allFiles);
m_allFiles = m_treeScanner.release();
m_allFiles = Utils::transform(m_treeScanner.release(), [](const FileNode *fn) { return fn; });
auto t = activeTarget();
if (!t)

View File

@@ -134,7 +134,7 @@ private:
Internal::TreeScanner m_treeScanner;
QHash<QString, bool> m_mimeBinaryCache;
QList<ProjectExplorer::FileNode *> m_allFiles;
QList<const ProjectExplorer::FileNode *> m_allFiles;
friend class Internal::CMakeBuildConfiguration;
friend class Internal::CMakeBuildSettingsWidget;

View File

@@ -283,7 +283,8 @@ static ProjectNode *updateCMakeInputs(CMakeListsNode *root,
return cmakeVFolder;
}
void ServerModeReader::generateProjectTree(CMakeListsNode *root, const QList<FileNode *> &allFiles)
void ServerModeReader::generateProjectTree(CMakeListsNode *root,
const QList<const FileNode *> &allFiles)
{
// Split up cmake inputs into useful chunks:
QList<FileNode *> cmakeFilesSource;
@@ -648,12 +649,12 @@ static CMakeProjectNode *findOrCreateProjectNode(CMakeListsNode *root, const Uti
QSet<Node *> ServerModeReader::updateProjects(CMakeListsNode *root,
const QList<Project *> &projects,
const QList<FileNode *> &allFiles)
const QList<const FileNode *> &allFiles)
{
QSet<Node *> usedNodes;
QHash<Utils::FileName, QList<FileNode *>> includeFiles;
for (FileNode *f : allFiles) {
QHash<Utils::FileName, QList<const FileNode *>> includeFiles;
for (const FileNode *f : allFiles) {
if (f->fileType() != FileType::Header)
continue;
includeFiles[f->filePath().parentDir()].append(f);
@@ -689,7 +690,7 @@ static CMakeTargetNode *findOrCreateTargetNode(CMakeListsNode *root, const Utils
QSet<Node *> ServerModeReader::updateTargets(CMakeListsNode *root,
const QList<ServerModeReader::Target *> &targets,
const QHash<FileName, QList<FileNode *> > &headers)
const QHash<FileName, QList<const FileNode *> > &headers)
{
QSet<Node *> usedNodes;
for (const Target *t : targets) {
@@ -706,7 +707,7 @@ void ServerModeReader::updateFileGroups(ProjectNode *targetRoot,
const Utils::FileName &sourceDirectory,
const Utils::FileName &buildDirectory,
const QList<ServerModeReader::FileGroup *> &fileGroups,
const QHash<FileName, QList<FileNode *> > &headers)
const QHash<FileName, QList<const FileNode *> > &headers)
{
QList<FileNode *> toList;
QSet<Utils::FileName> alreadyListed;
@@ -723,13 +724,13 @@ void ServerModeReader::updateFileGroups(ProjectNode *targetRoot,
// Add scanned header files:
for (const IncludePath *i : f->includePaths) {
const QList<FileNode *> &headerFiles = headers.value(i->path);
const QList<FileNode *> unseenHeaders = Utils::filtered(headerFiles, [&alreadyListed](const FileNode *fn) {
const QList<const FileNode *> &headerFiles = headers.value(i->path);
const QList<const FileNode *> unseenHeaders = Utils::filtered(headerFiles, [&alreadyListed](const FileNode *fn) {
const int count = alreadyListed.count();
alreadyListed.insert(fn->filePath());
return count != alreadyListed.count();
});
toList.append(Utils::transform(unseenHeaders, [](FileNode *fn) -> FileNode * {
toList.append(Utils::transform(unseenHeaders, [](const FileNode *fn) -> FileNode * {
auto copy = new FileNode(fn->filePath(), fn->fileType(), fn->isGenerated());
copy->setEnabled(false);
return copy;

View File

@@ -64,7 +64,8 @@ public:
QList<CMakeBuildTarget> buildTargets() const final;
CMakeConfig takeParsedConfiguration() final;
void generateProjectTree(CMakeListsNode *root, const QList<ProjectExplorer::FileNode *> &allFiles) final;
void generateProjectTree(CMakeListsNode *root,
const QList<const ProjectExplorer::FileNode *> &allFiles) final;
QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder) final;
private:
@@ -123,15 +124,15 @@ private:
const QList<ProjectExplorer::FileNode *> &cmakeLists);
QSet<ProjectExplorer::Node *> updateProjects(CMakeListsNode *root,
const QList<Project *> &projects,
const QList<ProjectExplorer::FileNode *> &allFiles);
const QList<const ProjectExplorer::FileNode *> &allFiles);
QSet<ProjectExplorer::Node *> updateTargets(CMakeListsNode *root,
const QList<Target *> &targets,
const QHash<Utils::FileName, QList<ProjectExplorer::FileNode *>> &headers);
const QHash<Utils::FileName, QList<const ProjectExplorer::FileNode *> > &headers);
void updateFileGroups(ProjectExplorer::ProjectNode *targetRoot,
const Utils::FileName &sourceDirectory,
const Utils::FileName &buildDirectory,
const QList<FileGroup *> &fileGroups,
const QHash<Utils::FileName, QList<ProjectExplorer::FileNode *>> &headers);
const QHash<Utils::FileName, QList<const ProjectExplorer::FileNode *>> &headers);
bool m_hasData = false;

View File

@@ -243,7 +243,21 @@ CMakeConfig TeaLeafReader::takeParsedConfiguration()
return result;
}
void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList<FileNode *> &allFiles)
static void sanitizeTree(CMakeListsNode *root)
{
QSet<FileName> uniqueFileNames;
QSet<Node *> uniqueNodes;
foreach (FileNode *fn, root->recursiveFileNodes()) {
const int count = uniqueFileNames.count();
uniqueFileNames.insert(fn->filePath());
if (count != uniqueFileNames.count())
uniqueNodes.insert(static_cast<Node *>(fn));
}
root->trim(uniqueNodes);
root->removeProjectNodes(root->projectNodes()); // Remove all project nodes
}
void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList<const FileNode *> &allFiles)
{
root->setDisplayName(m_projectName);
@@ -270,9 +284,8 @@ void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList<FileNo
m_watchedFiles.insert(cm);
}
QList<FileNode *> added;
QList<FileNode *> deleted;
QList<const FileNode *> added;
QList<FileNode *> deleted; // Unused!
ProjectExplorer::compareSortedLists(m_files, allFiles, deleted, added, Node::sortByPath);
QSet<FileName> allIncludePathSet;
@@ -285,37 +298,17 @@ void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList<FileNo
}
const QList<FileName> allIncludePaths = allIncludePathSet.toList();
const QList<FileNode *> includedHeaderFiles
= Utils::filtered(allFiles, [&allIncludePaths](const FileNode *fn) -> bool {
const QList<const FileNode *> missingHeaders
= Utils::filtered(added, [&allIncludePaths](const FileNode *fn) -> bool {
if (fn->fileType() != FileType::Header)
return false;
return Utils::contains(allIncludePaths, [fn](const FileName &inc) { return fn->filePath().isChildOf(inc); });
});
const auto knownFiles = QSet<FileName>::fromList(Utils::transform(m_files, [](const FileNode *fn) { return fn->filePath(); }));
QList<FileNode *> uniqueHeaders;
foreach (FileNode *ifn, includedHeaderFiles) {
if (!knownFiles.contains(ifn->filePath())) {
uniqueHeaders.append(ifn);
ifn->setEnabled(false);
}
}
QList<FileNode *> fileNodes = m_files + uniqueHeaders;
// Filter out duplicate nodes that e.g. the servermode reader introduces:
QSet<FileName> uniqueFileNames;
QSet<Node *> uniqueNodes;
foreach (FileNode *fn, root->recursiveFileNodes()) {
const int count = uniqueFileNames.count();
uniqueFileNames.insert(fn->filePath());
if (count != uniqueFileNames.count())
uniqueNodes.insert(static_cast<Node *>(fn));
}
root->trim(uniqueNodes);
root->removeProjectNodes(root->projectNodes()); // Remove all project nodes
QList<FileNode *> fileNodes = m_files + Utils::transform(missingHeaders, [](const FileNode *fn) { return new FileNode(*fn); });
sanitizeTree(root); // Filter out duplicate nodes that e.g. the servermode reader introduces:
root->buildTree(fileNodes, m_parameters.sourceDirectory);
m_files.clear(); // Some of the FileNodes in files() were deleted!
}

View File

@@ -57,7 +57,7 @@ public:
QList<CMakeBuildTarget> buildTargets() const final;
CMakeConfig takeParsedConfiguration() final;
void generateProjectTree(CMakeListsNode *root,
const QList<ProjectExplorer::FileNode *> &allFiles) final;
const QList<const ProjectExplorer::FileNode *> &allFiles) final;
QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder) final;
private:

View File

@@ -84,7 +84,8 @@ signals:
void finished();
private:
static void scanForFiles(FutureInterface *fi, const Utils::FileName &directory, const FileFilter &filter, const FileTypeFactory &factory);
static void scanForFiles(FutureInterface *fi, const Utils::FileName &directory,
const FileFilter &filter, const FileTypeFactory &factory);
private:
FileFilter m_filter;

View File

@@ -194,7 +194,7 @@ Node *Node::trim(const QSet<Node *> &keepers)
return keepers.contains(this) ? nullptr : this;
}
bool Node::sortByPath(Node *a, Node *b)
bool Node::sortByPath(const Node *a, const Node *b)
{
return a->filePath() < b->filePath();
}
@@ -266,10 +266,13 @@ static QList<FileNode *> scanForFilesRecursively(const Utils::FileName &director
const Utils::FileName entryName = Utils::FileName::fromString(entry.absoluteFilePath());
if (!vcsControl || !vcsControl->isVcsFileOrDirectory(entryName)) {
if (entry.isDir())
if (entry.isDir()) {
result.append(scanForFilesRecursively(entryName, factory, visited, future, progress, progressIncrement));
else
result.append(factory(entryName));
} else {
FileNode *node = factory(entryName);
if (node)
result.append(node);
}
}
if (future) {
progress += progressIncrement;

View File

@@ -153,7 +153,7 @@ public:
virtual SessionNode *asSessionNode() { return nullptr; }
virtual const SessionNode *asSessionNode() const { return nullptr; }
static bool sortByPath(Node *a, Node *b);
static bool sortByPath(const Node *a, const Node *b);
protected:
Node(NodeType nodeType, const Utils::FileName &filePath, int line = -1);