CMake: Project tree for server mode data

Change-Id: Ief884a76c1b4211501dd6515b17b6e88a8e881e5
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Tobias Hunger
2016-11-07 18:20:47 +01:00
parent 38f30e733f
commit 4b4dc9d06c
13 changed files with 484 additions and 39 deletions

View File

@@ -298,9 +298,10 @@ void BuildDirManager::resetData()
m_reader->resetData(); m_reader->resetData();
m_cmakeCache.clear(); m_cmakeCache.clear();
QTC_ASSERT(!m_futureInterface || m_futureInterface->isFinished(), return);
m_futureInterface.reset(); m_futureInterface.reset();
m_reader.reset(nullptr); m_reader.reset();
} }
bool BuildDirManager::updateCMakeStateBeforeBuild() bool BuildDirManager::updateCMakeStateBeforeBuild()
@@ -323,7 +324,7 @@ bool BuildDirManager::persistCMakeState()
return true; return true;
} }
void BuildDirManager::generateProjectTree(CMakeProjectNode *root) void BuildDirManager::generateProjectTree(CMakeListsNode *root)
{ {
QTC_ASSERT(m_reader, return); QTC_ASSERT(m_reader, return);
QTC_ASSERT(m_futureInterface, return); QTC_ASSERT(m_futureInterface, return);

View File

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

View File

@@ -49,6 +49,7 @@ namespace CMakeProjectManager {
namespace Internal { namespace Internal {
class CMakeBuildConfiguration; class CMakeBuildConfiguration;
class CMakeListsNode;
class BuildDirReader : public QObject class BuildDirReader : public QObject
{ {
@@ -100,7 +101,7 @@ public:
virtual CMakeConfig parsedConfiguration() const = 0; virtual CMakeConfig parsedConfiguration() const = 0;
virtual QList<CMakeBuildTarget> buildTargets() const = 0; virtual QList<CMakeBuildTarget> buildTargets() const = 0;
virtual void generateProjectTree(CMakeProjectNode *root, virtual void generateProjectTree(CMakeListsNode *root,
const QList<ProjectExplorer::FileNode *> &allFiles) = 0; const QList<ProjectExplorer::FileNode *> &allFiles) = 0;
virtual QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder) = 0; virtual QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder) = 0;

View File

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

View File

@@ -46,6 +46,7 @@ namespace Internal {
class BuildDirManager; class BuildDirManager;
class CMakeBuildConfigurationFactory; class CMakeBuildConfigurationFactory;
class CMakeBuildSettingsWidget; class CMakeBuildSettingsWidget;
class CMakeListsNode;
class CMakeBuildConfiguration : public ProjectExplorer::BuildConfiguration class CMakeBuildConfiguration : public ProjectExplorer::BuildConfiguration
{ {
@@ -84,7 +85,7 @@ public:
void clearCache(); void clearCache();
QList<CMakeBuildTarget> buildTargets() const; QList<CMakeBuildTarget> buildTargets() const;
void generateProjectTree(CMakeProjectNode *root) const; void generateProjectTree(CMakeListsNode *root) const;
QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder); QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder);
static Utils::FileName static Utils::FileName

View File

@@ -78,7 +78,7 @@ CMakeProject::CMakeProject(CMakeManager *manager, const FileName &fileName)
setDocument(new TextEditor::TextDocument); setDocument(new TextEditor::TextDocument);
document()->setFilePath(fileName); document()->setFilePath(fileName);
setRootProjectNode(new CMakeProjectNode(FileName::fromString(fileName.toFileInfo().absolutePath()))); setRootProjectNode(new CMakeListsNode(fileName));
setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT)); setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT));
setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX)); setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX));
@@ -104,7 +104,7 @@ void CMakeProject::updateProjectData()
return; return;
Kit *k = t->kit(); Kit *k = t->kit();
cmakeBc->generateProjectTree(static_cast<CMakeProjectNode *>(rootProjectNode())); cmakeBc->generateProjectTree(static_cast<CMakeListsNode *>(rootProjectNode()));
updateApplicationAndDeploymentTargets(); updateApplicationAndDeploymentTargets();
updateTargetRunConfigurations(t); updateTargetRunConfigurations(t);

View File

@@ -41,9 +41,8 @@ QT_END_NAMESPACE
namespace CMakeProjectManager { namespace CMakeProjectManager {
namespace Internal { namespace Internal {
class CMakeBuildSettingsWidget;
class CMakeBuildConfiguration; class CMakeBuildConfiguration;
class CMakeProjectNode; class CMakeBuildSettingsWidget;
class CMakeManager; class CMakeManager;
} // namespace Internal } // namespace Internal
@@ -76,8 +75,7 @@ public:
class CMAKE_EXPORT CMakeProject : public ProjectExplorer::Project class CMAKE_EXPORT CMakeProject : public ProjectExplorer::Project
{ {
Q_OBJECT Q_OBJECT
// for changeBuildDirectory
friend class Internal::CMakeBuildSettingsWidget;
public: public:
CMakeProject(Internal::CMakeManager *manager, const Utils::FileName &filename); CMakeProject(Internal::CMakeManager *manager, const Utils::FileName &filename);
~CMakeProject() final; ~CMakeProject() final;
@@ -128,6 +126,7 @@ private:
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers; QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
friend class Internal::CMakeBuildConfiguration; friend class Internal::CMakeBuildConfiguration;
friend class Internal::CMakeBuildSettingsWidget;
}; };
} // namespace CMakeProjectManager } // namespace CMakeProjectManager

View File

@@ -25,22 +25,122 @@
#include "cmakeprojectnodes.h" #include "cmakeprojectnodes.h"
#include "cmakeprojectconstants.h"
#include <coreplugin/fileiconprovider.h>
#include <utils/algorithm.h>
#include <QApplication>
using namespace CMakeProjectManager; using namespace CMakeProjectManager;
using namespace CMakeProjectManager::Internal; using namespace CMakeProjectManager::Internal;
CMakeProjectNode::CMakeProjectNode(const Utils::FileName &dirName) CMakeInputsNode::CMakeInputsNode(const Utils::FileName &cmakeLists) :
: ProjectExplorer::ProjectNode(dirName) ProjectExplorer::ProjectNode(CMakeInputsNode::inputsPathFromCMakeListsPath(cmakeLists))
{ {
setPriority(Node::DefaultPriority - 10); // Bottom most!
setDisplayName(QCoreApplication::translate("CMakeFilesProjectNode", "CMake Modules"));
setIcon(QIcon(":/projectexplorer/images/session.png")); // TODO: Use a better icon!
} }
bool CMakeProjectNode::showInSimpleTree() const Utils::FileName CMakeInputsNode::inputsPathFromCMakeListsPath(const Utils::FileName &cmakeLists)
{ {
// TODO Utils::FileName result = cmakeLists;
return true; result.appendPath("cmakeInputs"); // cmakeLists is a file, so this can not exist on disk
return result;
} }
QList<ProjectExplorer::ProjectAction> CMakeProjectNode::supportedActions(Node *node) const bool CMakeInputsNode::showInSimpleTree() const
{
return false;
}
QList<ProjectExplorer::ProjectAction> CMakeInputsNode::supportedActions(ProjectExplorer::Node *node) const
{ {
Q_UNUSED(node); Q_UNUSED(node);
return QList<ProjectExplorer::ProjectAction>(); return QList<ProjectExplorer::ProjectAction>();
} }
CMakeListsNode::CMakeListsNode(const Utils::FileName &cmakeListPath) :
ProjectExplorer::ProjectNode(cmakeListPath)
{
static QIcon folderIcon;
if (folderIcon.isNull()) {
const QIcon overlayIcon(Constants::FILEOVERLAY_CMAKE);
QPixmap dirPixmap = qApp->style()->standardIcon(QStyle::SP_DirIcon).pixmap(QSize(16, 16));
folderIcon.addPixmap(Core::FileIconProvider::overlayIcon(dirPixmap, overlayIcon));
}
setIcon(folderIcon);
}
bool CMakeListsNode::showInSimpleTree() const
{
return false;
}
QList<ProjectExplorer::ProjectAction> CMakeListsNode::supportedActions(ProjectExplorer::Node *node) const
{
Q_UNUSED(node);
return QList<ProjectExplorer::ProjectAction>();
}
CMakeProjectNode::CMakeProjectNode(const Utils::FileName &directory) :
ProjectExplorer::ProjectNode(directory)
{
setPriority(Node::DefaultProjectPriority + 1000);
setIcon(QIcon(":/projectexplorer/images/projectexplorer.png")); // TODO: Use proper icon!
}
bool CMakeProjectNode::showInSimpleTree() const
{
return true;
}
QString CMakeProjectNode::tooltip() const
{
return QString();
}
QList<ProjectExplorer::ProjectAction> CMakeProjectNode::supportedActions(ProjectExplorer::Node *node) const
{
Q_UNUSED(node);
return QList<ProjectExplorer::ProjectAction>();
}
CMakeTargetNode::CMakeTargetNode(const Utils::FileName &directory) :
ProjectExplorer::ProjectNode(directory)
{
setPriority(Node::DefaultProjectPriority + 900);
setIcon(QIcon(":/projectexplorer/images/build.png")); // TODO: Use proper icon!
}
bool CMakeTargetNode::showInSimpleTree() const
{
return true;
}
QString CMakeTargetNode::tooltip() const
{
return m_tooltip;
}
QList<ProjectExplorer::ProjectAction> CMakeTargetNode::supportedActions(ProjectExplorer::Node *node) const
{
Q_UNUSED(node);
return QList<ProjectExplorer::ProjectAction>();
}
void CMakeTargetNode::setTargetInformation(const QList<Utils::FileName> &artifacts,
const QString &type)
{
m_tooltip = QCoreApplication::translate("CMakeTargetNode", "Target type: ") + type + "<br>";
if (artifacts.count() == 0) {
m_tooltip += QCoreApplication::translate("CMakeTargetNode", "No build artifacts");
} else {
const QStringList tmp = Utils::transform(artifacts, &Utils::FileName::toUserOutput);
m_tooltip += QCoreApplication::translate("CMakeTargetNode", "Build artifacts:<br>")
+ tmp.join("<br>");
}
}

View File

@@ -32,12 +32,49 @@ class CMakeProject;
namespace Internal { namespace Internal {
class CMakeInputsNode : public ProjectExplorer::ProjectNode
{
public:
CMakeInputsNode(const Utils::FileName &cmakeLists);
static Utils::FileName inputsPathFromCMakeListsPath(const Utils::FileName &cmakeLists);
bool showInSimpleTree() const final;
QList<ProjectExplorer::ProjectAction> supportedActions(Node *node) const final;
};
class CMakeListsNode : public ProjectExplorer::ProjectNode
{
public:
CMakeListsNode(const Utils::FileName &cmakeListPath);
bool showInSimpleTree() const final;
QList<ProjectExplorer::ProjectAction> supportedActions(Node *node) const final;
};
class CMakeProjectNode : public ProjectExplorer::ProjectNode class CMakeProjectNode : public ProjectExplorer::ProjectNode
{ {
public: public:
CMakeProjectNode(const Utils::FileName &dirName); CMakeProjectNode(const Utils::FileName &directory);
bool showInSimpleTree() const override;
QList<ProjectExplorer::ProjectAction> supportedActions(Node *node) const override; bool showInSimpleTree() const final;
QString tooltip() const final;
QList<ProjectExplorer::ProjectAction> supportedActions(Node *node) const final;
};
class CMakeTargetNode : public ProjectExplorer::ProjectNode
{
public:
CMakeTargetNode(const Utils::FileName &directory);
void setTargetInformation(const QList<Utils::FileName> &artifacts, const QString &type);
bool showInSimpleTree() const final;
QString tooltip() const final;
QList<ProjectExplorer::ProjectAction> supportedActions(Node *node) const final;
private:
QString m_tooltip;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -211,24 +211,90 @@ CMakeConfig ServerModeReader::parsedConfiguration() const
return m_cmakeCache; return m_cmakeCache;
} }
void ServerModeReader::generateProjectTree(CMakeProjectNode *root, const QList<FileNode *> &allFiles) FolderNode *setupCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, int priority,
const QString &displayName, QList<FileNode *> &files)
{ {
Q_UNUSED(allFiles); FolderNode *folder
QSet<Utils::FileName> knownFiles; = findOrDefault(base->folderNodes(), [basePath](const FolderNode *fn) {
for (auto it = m_cmakeInputsFileNodes.constBegin(); it != m_cmakeInputsFileNodes.constEnd(); ++it) return fn->filePath() == basePath;
knownFiles.insert((*it)->filePath()); });
if (files.isEmpty()) {
QList<FileNode *> fileGroupNodes = m_cmakeInputsFileNodes; return folder;
m_cmakeInputsFileNodes.clear(); // Clean out, they are not going to be used anymore! } else {
foreach (const FileGroup *fg, m_fileGroups) { if (!folder) {
for (const FileName &s : fg->sources) { folder = new VirtualFolderNode(basePath, priority);
const int oldCount = knownFiles.count(); folder->setDisplayName(displayName);
knownFiles.insert(s); base->addFolderNodes({ folder });
if (oldCount != knownFiles.count())
fileGroupNodes.append(new FileNode(s, FileType::Source, fg->isGenerated));
} }
folder->buildTree(files);
} }
root->buildTree(fileGroupNodes); return nullptr;
}
static ProjectNode *updateCMakeInputs(CMakeListsNode *root,
const Utils::FileName &sourceDir,
const Utils::FileName &buildDir,
QList<FileNode *> &sourceInputs,
QList<FileNode *> &buildInputs,
QList<FileNode *> &rootInputs)
{
ProjectNode *cmakeVFolder
= root->projectNode(CMakeInputsNode::inputsPathFromCMakeListsPath(root->filePath()));
if (!cmakeVFolder) {
cmakeVFolder = new CMakeInputsNode(root->filePath());
root->addProjectNodes({ cmakeVFolder });
}
QList<FolderNode *> foldersToDelete;
foldersToDelete.append(setupCMakeVFolder(cmakeVFolder, sourceDir, 1000,
QCoreApplication::translate("CMakeProjectManager::Internal", "Source Directory"),
sourceInputs));
foldersToDelete.append(setupCMakeVFolder(cmakeVFolder, buildDir, 100,
QCoreApplication::translate("CMakeProjectManager::Internal", "Build Directory"),
buildInputs));
foldersToDelete.append(setupCMakeVFolder(cmakeVFolder, Utils::FileName(), 10,
QCoreApplication::translate("CMakeProjectManager::Internal", "Other Locations"),
rootInputs));
// Clean out unused nodes in "CMake Files":
const QList<FolderNode *> tmp = filtered(foldersToDelete, [](const FolderNode *fn) { return fn; });
cmakeVFolder->removeFolderNodes(tmp);
return cmakeVFolder;
}
void ServerModeReader::generateProjectTree(CMakeListsNode *root, const QList<FileNode *> &allFiles)
{
// Split up cmake inputs into useful chunks:
QList<FileNode *> cmakeFilesSource;
QList<FileNode *> cmakeFilesBuild;
QList<FileNode *> cmakeFilesOther;
QList<FileNode *> cmakeLists;
foreach (FileNode *fn, m_cmakeInputsFileNodes) {
const FileName path = fn->filePath();
if (path.fileName().compare("CMakeLists.txt", HostOsInfo::fileNameCaseSensitivity()) == 0)
cmakeLists.append(fn);
else if (path.isChildOf(m_parameters.sourceDirectory))
cmakeFilesSource.append(fn);
else if (path.isChildOf(m_parameters.buildDirectory))
cmakeFilesBuild.append(fn);
else
cmakeFilesOther.append(fn);
}
m_cmakeInputsFileNodes.clear(); // Clean out, they are not going to be used anymore!
if (!m_projects.isEmpty())
root->setDisplayName(m_projects.at(0)->name);
QSet<Node *> usedNodes;
usedNodes.insert(updateCMakeInputs(root, m_parameters.sourceDirectory, m_parameters.buildDirectory,
cmakeFilesSource, cmakeFilesBuild, cmakeFilesOther));
usedNodes.unite(updateCMakeLists(root, cmakeLists));
usedNodes.unite(updateProjects(root, m_projects, allFiles));
// Trim out unused nodes:
root->trim(usedNodes);
} }
QSet<Core::Id> ServerModeReader::updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder) QSet<Core::Id> ServerModeReader::updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder)
@@ -448,5 +514,231 @@ void ServerModeReader::extractCacheData(const QVariantMap &data)
m_cmakeCache = config; m_cmakeCache = config;
} }
QSet<Node *> ServerModeReader::updateCMakeLists(CMakeListsNode *root,
const QList<FileNode *> &cmakeLists)
{
QSet<Node *> usedNodes;
const QDir baseDir = QDir(root->filePath().parentDir().toString());
QHash<QString, FileNode *> 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<QString, CMakeListsNode *> 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!
else
cmln = static_cast<CMakeListsNode *>(parentNode->projectNode(fn->filePath()));
if (!cmln) {
cmln = new CMakeListsNode(fn->filePath());
parentNode->addProjectNodes({ cmln });
}
// Find or create CMakeLists.txt filenode below CMakeListsNode:
FileNode *cmFn = cmln->fileNode(fn->filePath());
if (!cmFn) {
cmFn = fn;
cmln->addFileNodes({ cmFn });
}
usedNodes.insert(cmFn); // register existing CMakeLists.txt filenode
// 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 usedNodes;
}
static CMakeListsNode *findCMakeNode(CMakeListsNode *root, const Utils::FileName &dir)
{
Utils::FileName stepDir = dir;
CMakeListsNode *base = root;
forever {
Utils::FileName stepLists = stepDir;
stepLists.appendPath("CMakeLists.txt");
CMakeListsNode *cmln = nullptr;
if (base->filePath() == stepLists) {
cmln = base;
} else {
ProjectNode *pcmln = base->projectNode(stepLists);
cmln = static_cast<CMakeListsNode *>(pcmln);
}
if (!cmln) {
stepDir = stepDir.parentDir();
if (stepDir.isEmpty())
return nullptr;
} else {
if (cmln->filePath().parentDir() == dir)
return cmln;
stepDir = dir;
base = cmln;
}
}
}
static CMakeProjectNode *findOrCreateProjectNode(CMakeListsNode *root, const Utils::FileName &dir,
const QString &displayName)
{
CMakeListsNode *cmln = findCMakeNode(root, dir);
QTC_ASSERT(cmln, return nullptr);
Utils::FileName projectName = dir;
projectName.appendPath(".project::" + displayName);
CMakeProjectNode *pn = static_cast<CMakeProjectNode *>(cmln->projectNode(projectName));
if (!pn) {
pn = new CMakeProjectNode(projectName);
cmln->addProjectNodes({ pn });
}
pn->setDisplayName(displayName);
return pn;
}
QSet<Node *> ServerModeReader::updateProjects(CMakeListsNode *root,
const QList<Project *> &projects,
const QList<FileNode *> &allFiles)
{
QSet<Node *> usedNodes;
QHash<Utils::FileName, QList<FileNode *>> includeFiles;
for (FileNode *f : allFiles) {
if (f->fileType() != FileType::Header)
continue;
includeFiles[f->filePath().parentDir()].append(f);
}
for (const Project *p : projects) {
CMakeProjectNode *pNode = findOrCreateProjectNode(root, p->sourceDirectory, p->name);
QTC_ASSERT(pNode, continue);
usedNodes.insert(pNode); // Mark as leaf to keep.
usedNodes.unite(updateTargets(root, p->targets, includeFiles));
}
return usedNodes;
}
static CMakeTargetNode *findOrCreateTargetNode(CMakeListsNode *root, const Utils::FileName &dir,
const QString &displayName)
{
CMakeListsNode *cmln = findCMakeNode(root, dir);
QTC_ASSERT(cmln, return nullptr);
Utils::FileName targetName = dir;
targetName.appendPath(".target::" + displayName);
CMakeTargetNode *tn = static_cast<CMakeTargetNode *>(cmln->projectNode(targetName));
if (!tn) {
tn = new CMakeTargetNode(targetName);
cmln->addProjectNodes({ tn });
}
tn->setDisplayName(displayName);
return tn;
}
QSet<Node *> ServerModeReader::updateTargets(CMakeListsNode *root,
const QList<ServerModeReader::Target *> &targets,
const QHash<FileName, QList<FileNode *> > &headers)
{
QSet<Node *> usedNodes;
for (const Target *t : targets) {
CMakeTargetNode *tNode = findOrCreateTargetNode(root, t->sourceDirectory, t->name);
tNode->setTargetInformation(t->artifacts, t->type);
usedNodes.unite(updateFileGroups(tNode, t->sourceDirectory, t->buildDirectory,
t->fileGroups, headers));
}
return usedNodes;
}
static Utils::FileName mapFileName(const Utils::FileName &fn, const Utils::FileName &sourceDirectory,
const Utils::FileName &buildDirectory)
{
if (fn.isChildOf(buildDirectory)) {
Utils::FileName mapped = sourceDirectory;
mapped.appendPath(QCoreApplication::translate("CMakeProjectManager::Internal", "<Build Directory>"));
QDir bd = QDir(buildDirectory.toString());
mapped.appendPath(bd.relativeFilePath(fn.toString()));
return mapped;
}
return fn;
}
QSet<Node *> ServerModeReader::updateFileGroups(ProjectNode *targetRoot,
const Utils::FileName &sourceDirectory,
const Utils::FileName &buildDirectory,
const QList<ServerModeReader::FileGroup *> &fileGroups,
const QHash<FileName, QList<FileNode *> > &headers)
{
QSet<Node *> usedNodes;
QList<FileNode *> toList;
QSet<Utils::FileName> alreadyListed;
for (const FileGroup *f : fileGroups) {
const QList<FileName> newSources = Utils::filtered(f->sources, [&alreadyListed](const Utils::FileName &fn) {
const int count = alreadyListed.count();
alreadyListed.insert(fn);
return count != alreadyListed.count();
});
const QList<FileNode *> newFileNodes = Utils::transform(newSources, [f, &sourceDirectory, &buildDirectory](const Utils::FileName &fn) {
return new FileNode(mapFileName(fn, sourceDirectory, buildDirectory), FileType::Source, f->isGenerated);
});
toList.append(newFileNodes);
// 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 int count = alreadyListed.count();
alreadyListed.insert(fn->filePath());
return count != alreadyListed.count();
});
toList.append(Utils::transform(unseenHeaders, [&sourceDirectory, &buildDirectory](FileNode *fn) -> FileNode * {
const Utils::FileName mappedPath = mapFileName(fn->filePath(), sourceDirectory, buildDirectory);
auto copy = new FileNode(mappedPath, fn->fileType(), fn->isGenerated());
copy->setEnabled(false);
return copy;
}));
}
}
targetRoot->buildTree(toList, sourceDirectory);
foreach (FileNode *fn, toList)
usedNodes.insert(static_cast<Node *>(fn)); // Mark all leaves as keeper!
return usedNodes;
}
} // namespace Internal } // namespace Internal
} // namespace CMakeProjectManager } // namespace CMakeProjectManager

View File

@@ -64,7 +64,7 @@ public:
QList<CMakeBuildTarget> buildTargets() const final; QList<CMakeBuildTarget> buildTargets() const final;
CMakeConfig parsedConfiguration() const final; CMakeConfig parsedConfiguration() const final;
void generateProjectTree(CMakeProjectNode *root, const QList<ProjectExplorer::FileNode *> &allFiles) final; void generateProjectTree(CMakeListsNode *root, const QList<ProjectExplorer::FileNode *> &allFiles) final;
QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder) final; QSet<Core::Id> updateCodeModel(CppTools::ProjectPartBuilder &ppBuilder) final;
private: private:
@@ -119,6 +119,20 @@ private:
void extractCMakeInputsData(const QVariantMap &data); void extractCMakeInputsData(const QVariantMap &data);
void extractCacheData(const QVariantMap &data); void extractCacheData(const QVariantMap &data);
QSet<ProjectExplorer::Node *> updateCMakeLists(CMakeListsNode *root,
const QList<ProjectExplorer::FileNode *> &cmakeLists);
QSet<ProjectExplorer::Node *> updateProjects(CMakeListsNode *root,
const QList<Project *> &projects,
const QList<ProjectExplorer::FileNode *> &allFiles);
QSet<ProjectExplorer::Node *> updateTargets(CMakeListsNode *root,
const QList<Target *> &targets,
const QHash<Utils::FileName, QList<ProjectExplorer::FileNode *>> &headers);
QSet<ProjectExplorer::Node *> updateFileGroups(ProjectExplorer::ProjectNode *targetRoot,
const Utils::FileName &sourceDirectory,
const Utils::FileName &buildDirectory,
const QList<FileGroup *> &fileGroups,
const QHash<Utils::FileName, QList<ProjectExplorer::FileNode *>> &headers);
bool m_hasData = false; bool m_hasData = false;
std::unique_ptr<ServerMode> m_cmakeServer; std::unique_ptr<ServerMode> m_cmakeServer;

View File

@@ -318,7 +318,7 @@ CMakeConfig TeaLeafReader::parseConfiguration(const FileName &cacheFile, QString
return result; return result;
} }
void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QList<FileNode *> &allFiles) void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList<FileNode *> &allFiles)
{ {
root->setDisplayName(m_projectName); root->setDisplayName(m_projectName);

View File

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