diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index 182c6fc2e93..34011b5118a 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -28,9 +28,11 @@ #include "cmakekitinformation.h" #include "cmakeparser.h" #include "cmakeprojectmanager.h" +#include "cmakeprojectnodes.h" #include "cmaketool.h" #include +#include #include #include #include @@ -54,6 +56,8 @@ #include #include +using namespace ProjectExplorer; + // -------------------------------------------------------------------- // Helper: // -------------------------------------------------------------------- @@ -61,7 +65,7 @@ namespace CMakeProjectManager { namespace Internal { -static QStringList toArguments(const CMakeConfig &config, const ProjectExplorer::Kit *k) { +static QStringList toArguments(const CMakeConfig &config, const Kit *k) { return Utils::transform(config, [k](const CMakeConfigItem &i) -> QString { QString a = QString::fromLatin1("-D"); a.append(QString::fromUtf8(i.key)); @@ -110,10 +114,11 @@ BuildDirManager::~BuildDirManager() { stopProcess(); resetData(); + qDeleteAll(m_watchedFiles); delete m_tempDir; } -const ProjectExplorer::Kit *BuildDirManager::kit() const +const Kit *BuildDirManager::kit() const { return m_buildConfiguration->target()->kit(); } @@ -202,6 +207,38 @@ bool BuildDirManager::persistCMakeState() return true; } +void BuildDirManager::generateProjectTree(CMakeProjectNode *root) +{ + root->setDisplayName(m_projectName); + + // Delete no longer necessary file watcher: + const QSet currentWatched + = Utils::transform(m_watchedFiles, [](CMakeFile *cmf) { return cmf->filePath(); }); + const QSet toWatch = m_cmakeFiles; + QSet toDelete = currentWatched; + toDelete.subtract(toWatch); + m_watchedFiles = Utils::filtered(m_watchedFiles, [&toDelete](Internal::CMakeFile *cmf) { + if (toDelete.contains(cmf->filePath())) { + delete cmf; + return false; + } + return true; + }); + + // Add new file watchers: + QSet toAdd = toWatch; + toAdd.subtract(currentWatched); + foreach (const Utils::FileName &fn, toAdd) { + CMakeFile *cm = new CMakeFile(this, fn); + Core::DocumentManager::addDocument(cm); + m_watchedFiles.insert(cm); + } + + QList fileNodes = m_files; + root->buildTree(fileNodes); + m_files.clear(); // Some of the FileNodes in files() were deleted! +} + void BuildDirManager::parse() { checkConfiguration(); @@ -247,31 +284,11 @@ void BuildDirManager::clearCache() forceReparse(); } -QString BuildDirManager::projectName() const -{ - return m_projectName; -} - QList BuildDirManager::buildTargets() const { return m_buildTargets; } -QList BuildDirManager::files() -{ - return m_files; -} - -QSet BuildDirManager::cmakeFiles() -{ - return m_cmakeFiles; -} - -void BuildDirManager::clearFiles() -{ - m_files.clear(); -} - CMakeConfig BuildDirManager::parsedConfiguration() const { if (m_cmakeCache.isEmpty()) { @@ -350,7 +367,7 @@ void BuildDirManager::extractData() resetData(); m_projectName = sourceDirectory().fileName(); - m_files.append(new ProjectExplorer::FileNode(topCMake, ProjectExplorer::ProjectFileType, false)); + m_files.append(new FileNode(topCMake, ProjectFileType, false)); // Do not insert topCMake into m_cmakeFiles: The project already watches that! // Find cbp file @@ -376,13 +393,13 @@ void BuildDirManager::extractData() m_files = cbpparser.fileList(); if (cbpparser.hasCMakeFiles()) { m_files.append(cbpparser.cmakeFileList()); - foreach (const ProjectExplorer::FileNode *node, cbpparser.cmakeFileList()) + foreach (const FileNode *node, cbpparser.cmakeFileList()) m_cmakeFiles.insert(node->filePath()); } // Make sure the top cmakelists.txt file is always listed: - if (!Utils::contains(m_files, [topCMake](ProjectExplorer::FileNode *fn) { return fn->filePath() == topCMake; })) { - m_files.append(new ProjectExplorer::FileNode(topCMake, ProjectExplorer::ProjectFileType, false)); + if (!Utils::contains(m_files, [topCMake](FileNode *fn) { return fn->filePath() == topCMake; })) { + m_files.append(new FileNode(topCMake, ProjectFileType, false)); } m_buildTargets = cbpparser.buildTargets(); @@ -409,14 +426,14 @@ void BuildDirManager::startCMake(CMakeTool *tool, const QStringList &generatorAr m_parser = new CMakeParser; QDir source = QDir(sourceDirectory().toString()); - connect(m_parser, &ProjectExplorer::IOutputParser::addTask, m_parser, - [source](const ProjectExplorer::Task &task) { + connect(m_parser, &IOutputParser::addTask, m_parser, + [source](const Task &task) { if (task.file.isEmpty() || task.file.toFileInfo().isAbsolute()) { - ProjectExplorer::TaskHub::addTask(task); + TaskHub::addTask(task); } else { - ProjectExplorer::Task t = task; + Task t = task; t.file = Utils::FileName::fromString(source.absoluteFilePath(task.file.toString())); - ProjectExplorer::TaskHub::addTask(t); + TaskHub::addTask(t); } }); @@ -440,7 +457,7 @@ void BuildDirManager::startCMake(CMakeTool *tool, const QStringList &generatorAr Utils::QtcProcess::addArgs(&args, generatorArgs); Utils::QtcProcess::addArgs(&args, toArguments(config, kit())); - ProjectExplorer::TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); + TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); Core::MessageManager::write(tr("Running \"%1 %2\" in %3.") .arg(tool->cmakeExecutable().toUserOutput()) @@ -478,8 +495,7 @@ void BuildDirManager::cmakeFinished(int code, QProcess::ExitStatus status) if (!msg.isEmpty()) { Core::MessageManager::write(msg); - ProjectExplorer::TaskHub::addTask(ProjectExplorer::Task::Error, msg, - ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); + TaskHub::addTask(Task::Error, msg, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); m_future->reportCanceled(); } else { m_future->setProgressValue(1); @@ -526,7 +542,7 @@ void BuildDirManager::checkConfiguration() if (m_tempDir) // always throw away changes in the tmpdir! return; - ProjectExplorer::Kit *k = m_buildConfiguration->target()->kit(); + Kit *k = m_buildConfiguration->target()->kit(); const CMakeConfig cache = parsedConfiguration(); if (cache.isEmpty()) return; // No cache file yet. @@ -664,6 +680,15 @@ CMakeConfig BuildDirManager::parseConfiguration(const Utils::FileName &cacheFile return result; } +void BuildDirManager::handleCmakeFileChange() +{ + Target *t = m_buildConfiguration->target()->project()->activeTarget(); + BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr; + + if (m_buildConfiguration->target() == t && m_buildConfiguration == bc) + cmakeFilesChanged(); +} + void BuildDirManager::maybeForceReparse() { checkConfiguration(); diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.h b/src/plugins/cmakeprojectmanager/builddirmanager.h index 0e860f03ce3..cadb88a9e2e 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.h +++ b/src/plugins/cmakeprojectmanager/builddirmanager.h @@ -27,6 +27,7 @@ #include "cmakecbpparser.h" #include "cmakeconfigitem.h" +#include "cmakefile.h" #include @@ -66,15 +67,8 @@ public: BuildDirManager(CMakeBuildConfiguration *bc); ~BuildDirManager() override; - const ProjectExplorer::Kit *kit() const; - const Utils::FileName buildDirectory() const; - const Utils::FileName workDirectory() const; - const Utils::FileName sourceDirectory() const; - const CMakeConfig intendedConfiguration() const; bool isParsing() const; - void cmakeFilesChanged(); - void parse(); void clearCache(); void forceReparse(); @@ -82,24 +76,33 @@ public: void resetData(); bool persistCMakeState(); - QString projectName() const; + void generateProjectTree(CMakeProjectNode *root); + QList buildTargets() const; - QList files(); - QSet cmakeFiles(); - void clearFiles(); CMakeConfig parsedConfiguration() const; void checkConfiguration(); - static CMakeConfig parseConfiguration(const Utils::FileName &cacheFile, - QString *errorMessage); + void handleCmakeFileChange(); signals: void configurationStarted() const; void dataAvailable() const; void errorOccured(const QString &err) const; +protected: + static CMakeConfig parseConfiguration(const Utils::FileName &cacheFile, + QString *errorMessage); + + const ProjectExplorer::Kit *kit() const; + const Utils::FileName buildDirectory() const; + const Utils::FileName workDirectory() const; + const Utils::FileName sourceDirectory() const; + const CMakeConfig intendedConfiguration() const; + private: + void cmakeFilesChanged(); + void stopProcess(); void cleanUpProcess(); void extractData(); @@ -127,6 +130,8 @@ private: QFutureInterface *m_future = nullptr; QTimer m_reparseTimer; + + QSet m_watchedFiles; }; } // namespace Internal diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 441c03abb15..79d3ed6d747 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -71,11 +71,6 @@ CMakeBuildConfiguration::~CMakeBuildConfiguration() m_buildDirManager->deleteLater(); // Do not block while waiting for cmake... } -void CMakeBuildConfiguration::cmakeFilesChanged() -{ - m_buildDirManager->cmakeFilesChanged(); -} - bool CMakeBuildConfiguration::isEnabled() const { return m_error.isEmpty(); diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h index d56965ffb6c..37ec1aa4275 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h @@ -52,8 +52,6 @@ public: CMakeBuildConfiguration(ProjectExplorer::Target *parent); ~CMakeBuildConfiguration(); - void cmakeFilesChanged(); - bool isEnabled() const override; QString disabledReason() const override; diff --git a/src/plugins/cmakeprojectmanager/cmakefile.cpp b/src/plugins/cmakeprojectmanager/cmakefile.cpp index 30a1db0e153..612e48ec8d1 100644 --- a/src/plugins/cmakeprojectmanager/cmakefile.cpp +++ b/src/plugins/cmakeprojectmanager/cmakefile.cpp @@ -24,7 +24,8 @@ ****************************************************************************/ #include "cmakefile.h" -#include "cmakeproject.h" + +#include "builddirmanager.h" #include "cmakeprojectconstants.h" #include @@ -36,7 +37,7 @@ using namespace Utils; namespace CMakeProjectManager { namespace Internal { -CMakeFile::CMakeFile(CMakeProject *project, const FileName &fileName) : m_project(project) +CMakeFile::CMakeFile(BuildDirManager *bdm, const FileName &fileName) : m_buildDirManager(bdm) { setId("Cmake.ProjectFile"); setMimeType(QLatin1String(Constants::CMAKEPROJECTMIMETYPE)); @@ -56,7 +57,7 @@ bool CMakeFile::reload(QString *errorString, Core::IDocument::ReloadFlag flag, C Q_UNUSED(flag); if (type != TypePermissions) - m_project->handleCmakeFileChanged(); + m_buildDirManager->handleCmakeFileChange(); return true; } diff --git a/src/plugins/cmakeprojectmanager/cmakefile.h b/src/plugins/cmakeprojectmanager/cmakefile.h index 606012ea244..4f3376b640c 100644 --- a/src/plugins/cmakeprojectmanager/cmakefile.h +++ b/src/plugins/cmakeprojectmanager/cmakefile.h @@ -28,20 +28,20 @@ #include namespace CMakeProjectManager { -class CMakeProject; - namespace Internal { +class BuildDirManager; + class CMakeFile : public Core::IDocument { public: - CMakeFile(CMakeProject *project, const Utils::FileName &fileName); + CMakeFile(BuildDirManager *bdm, const Utils::FileName &fileName); ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override; bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override; private: - CMakeProject *m_project; + BuildDirManager *m_buildDirManager; }; } // namespace Internal diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 1f2d1f42124..9e6555d64b1 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -89,13 +90,13 @@ CMakeProject::CMakeProject(CMakeManager *manager, const FileName &fileName) { setId(Constants::CMAKEPROJECT_ID); setProjectManager(manager); - setDocument(new Internal::CMakeFile(this, fileName)); + setDocument(new TextEditor::TextDocument); + document()->setFilePath(fileName); setRootProjectNode(new CMakeProjectNode(Utils::FileName::fromString(fileName.toFileInfo().absolutePath()))); setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT)); setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX)); - Core::DocumentManager::addDocument(document()); rootProjectNode()->setDisplayName(fileName.parentDir().fileName()); connect(this, &CMakeProject::activeTargetChanged, this, &CMakeProject::handleActiveTargetChanged); @@ -105,7 +106,6 @@ CMakeProject::~CMakeProject() { setRootProjectNode(nullptr); m_codeModelFuture.cancel(); - qDeleteAll(m_watchedFiles); qDeleteAll(m_extraCompilers); } @@ -219,34 +219,7 @@ void CMakeProject::updateProjectData() BuildDirManager *bdm = cmakeBc->buildDirManager(); QTC_ASSERT(bdm, return); - rootProjectNode()->setDisplayName(bdm->projectName()); - - // Delete no longer necessary file watcher: - const QSet currentWatched - = Utils::transform(m_watchedFiles, [](CMakeFile *cmf) { return cmf->filePath(); }); - const QSet toWatch = bdm->cmakeFiles(); - QSet toDelete = currentWatched; - toDelete.subtract(toWatch); - m_watchedFiles = Utils::filtered(m_watchedFiles, [&toDelete](Internal::CMakeFile *cmf) { - if (toDelete.contains(cmf->filePath())) { - delete cmf; - return false; - } - return true; - }); - - // Add new file watchers: - QSet toAdd = toWatch; - toAdd.subtract(currentWatched); - foreach (const Utils::FileName &fn, toAdd) { - CMakeFile *cm = new CMakeFile(this, fn); - Core::DocumentManager::addDocument(cm); - m_watchedFiles.insert(cm); - } - - QList fileNodes = bdm->files(); - rootProjectNode()->buildTree(fileNodes); - bdm->clearFiles(); // Some of the FileNodes in files() were deleted! + bdm->generateProjectTree(static_cast(rootProjectNode())); updateApplicationAndDeploymentTargets(); updateTargetRunConfigurations(t); @@ -459,15 +432,6 @@ bool CMakeProject::setupTarget(Target *t) return true; } -void CMakeProject::handleCmakeFileChanged() -{ - if (Target *t = activeTarget()) { - if (auto bc = qobject_cast(t->activeBuildConfiguration())) { - bc->cmakeFilesChanged(); - } - } -} - void CMakeProject::handleActiveTargetChanged() { if (m_connectedTarget) { diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index 334cca4f6c7..5e9fa7e159e 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -110,8 +110,6 @@ protected: bool setupTarget(ProjectExplorer::Target *t) final; private: - void handleCmakeFileChanged(); - void handleActiveTargetChanged(); void handleActiveBuildConfigurationChanged(); void handleParsingStarted(); @@ -133,8 +131,6 @@ private: QFuture m_codeModelFuture; QList m_extraCompilers; - QSet m_watchedFiles; - friend class Internal::CMakeBuildConfiguration; friend class Internal::CMakeFile; };