From 0665a9151c0423cc77aab12440114f852ac5aed0 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Mon, 27 Sep 2021 17:26:40 +0200 Subject: [PATCH] CMakePM: Scan files only on CMake configuration failure The file tree scanner will only be started on CMake configuration failure to generate the fall back project node. Change-Id: I873ef1189fd43dc9bffa03aeafabb00bb3b8b6af Reviewed-by: Qt CI Bot Reviewed-by: Eike Ziller --- .../cmakeprojectmanager/cmakebuildsystem.cpp | 118 +++++++++--------- .../cmakeprojectmanager/cmakebuildsystem.h | 16 +-- .../fileapidataextractor.cpp | 26 ---- .../fileapidataextractor.h | 4 - .../cmakeprojectmanager/fileapireader.cpp | 36 +++--- .../cmakeprojectmanager/fileapireader.h | 6 +- 6 files changed, 83 insertions(+), 123 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index d3a95645304..d1c9d9a22b4 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -35,6 +35,7 @@ #include "cmakeprojectnodes.h" #include "cmakeprojectplugin.h" #include "cmakespecificsettings.h" +#include "projecttreehelper.h" #include "utils/algorithm.h" #include @@ -158,8 +159,7 @@ CMakeBuildSystem::CMakeBuildSystem(CMakeBuildConfiguration *bc) m_treeScanner.setFilter([this](const MimeType &mimeType, const FilePath &fn) { // Mime checks requires more resources, so keep it last in check list - auto isIgnored = fn.toString().startsWith(projectFilePath().toString() + ".user") - || TreeScanner::isWellKnownBinary(mimeType, fn); + auto isIgnored = TreeScanner::isWellKnownBinary(mimeType, fn); // Cache mime check result for speed up if (!isIgnored) { @@ -213,7 +213,6 @@ CMakeBuildSystem::~CMakeBuildSystem() delete m_cppCodeModelUpdater; qDeleteAll(m_extraCompilers); - qDeleteAll(m_allFiles.allFiles); } void CMakeBuildSystem::triggerParsing() @@ -244,28 +243,11 @@ void CMakeBuildSystem::triggerParsing() qCDebug(cmakeBuildSystemLog) << "ParseGuard acquired."; - if (m_allFiles.allFiles.isEmpty()) { - qCDebug(cmakeBuildSystemLog) - << "No treescanner information available, forcing treescanner run."; - updateReparseParameters(REPARSE_SCAN); - } - int reparseParameters = takeReparseParameters(); - m_waitingForScan = (reparseParameters & REPARSE_SCAN) != 0; m_waitingForParse = true; m_combinedScanAndParseResult = true; - if (m_waitingForScan) { - qCDebug(cmakeBuildSystemLog) << "Starting TreeScanner"; - QTC_CHECK(m_treeScanner.isFinished()); - if (m_treeScanner.asyncScanForFiles(projectDirectory())) - Core::ProgressManager::addTask(m_treeScanner.future(), - tr("Scan \"%1\" project tree") - .arg(project()->displayName()), - "CMake.Scan.Tree"); - } - QTC_ASSERT(m_parameters.isValid(), return ); TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); @@ -365,8 +347,6 @@ QString CMakeBuildSystem::reparseParametersString(int reparseFlags) result += " FORCE_CMAKE_RUN"; if (reparseFlags & REPARSE_FORCE_INITIAL_CONFIGURATION) result += " FORCE_CONFIG"; - if (reparseFlags & REPARSE_SCAN) - result += " SCAN"; } return result.trimmed(); } @@ -442,7 +422,7 @@ void CMakeBuildSystem::runCMakeAndScanProjectTree() BuildDirParameters parameters(cmakeBuildConfiguration()); qCDebug(cmakeBuildSystemLog) << "Requesting parse due to \"Rescan Project\" command"; setParametersAndRequestParse(parameters, - REPARSE_FORCE_CMAKE_RUN | REPARSE_SCAN | REPARSE_URGENT); + REPARSE_FORCE_CMAKE_RUN | REPARSE_URGENT); } void CMakeBuildSystem::runCMakeWithExtraArguments() @@ -461,18 +441,6 @@ void CMakeBuildSystem::buildCMakeTarget(const QString &buildTarget) cmakeBuildConfiguration()->buildTarget(buildTarget); } -void CMakeBuildSystem::handleTreeScanningFinished() -{ - QTC_CHECK(m_waitingForScan); - - qDeleteAll(m_allFiles.allFiles); - m_allFiles = m_treeScanner.release(); - - m_waitingForScan = false; - - combineScanAndParse(m_reader.lastCMakeExitCode() != 0); -} - bool CMakeBuildSystem::persistCMakeState() { BuildDirParameters parameters(cmakeBuildConfiguration()); @@ -524,17 +492,10 @@ void CMakeBuildSystem::clearCMakeCache() path.removeRecursively(); } -std::unique_ptr CMakeBuildSystem::generateProjectTree( - const TreeScanner::Result &allFiles, bool failedToParse) -{ - auto root = m_reader.generateProjectTree(allFiles, failedToParse); - return root; -} - void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup) { if (cmakeBuildConfiguration()->isActive()) { - if (m_waitingForParse || m_waitingForScan) + if (m_waitingForParse) return; if (m_combinedScanAndParseResult) { @@ -548,6 +509,15 @@ void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup) "

The backup of the previous configuration has been restored.

" "

Have a look at the Issues pane or in the \"Projects > Build\" settings " "for more information about the failure.(m_parameters.sourceDirectory); + newRoot->setDisplayName(m_parameters.sourceDirectory.fileName()); + + if (!m_reader.topCmakeFile().isEmpty()) { + auto node = std::make_unique(m_reader.topCmakeFile(), FileType::Project); + node->setIsGenerated(false); + + std::vector> fileNodes; + fileNodes.emplace_back(std::move(node)); + + addCMakeLists(newRoot.get(), std::move(fileNodes)); + } + + addFileSystemNodes(newRoot.get(), m_allFiles); + setRootProjectNode(std::move(newRoot)); + + m_reader.resetData(); + + m_currentGuard = {}; + emitBuildSystemUpdated(); + + qCDebug(cmakeBuildSystemLog) << "All fallback CMake project data up to date."; +} + void CMakeBuildSystem::updateFallbackProjectData() { qCDebug(cmakeBuildSystemLog) << "Updating fallback CMake project data"; - - QTC_ASSERT(m_treeScanner.isFinished() && !m_reader.isParsing(), return ); - - auto newRoot = generateProjectTree(m_allFiles, true); - setRootProjectNode(std::move(newRoot)); - - qCDebug(cmakeBuildSystemLog) << "All fallback CMake project data up to date."; + qCDebug(cmakeBuildSystemLog) << "Starting TreeScanner"; + QTC_CHECK(m_treeScanner.isFinished()); + if (m_treeScanner.asyncScanForFiles(projectDirectory())) + Core::ProgressManager::addTask(m_treeScanner.future(), + tr("Scan \"%1\" project tree") + .arg(project()->displayName()), + "CMake.Scan.Tree"); } void CMakeBuildSystem::updateCMakeConfiguration(QString &errorMessage) @@ -899,7 +895,7 @@ void CMakeBuildSystem::becameDirty() if (isParsing()) return; - setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()), REPARSE_SCAN); + setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()), REPARSE_DEFAULT); } void CMakeBuildSystem::updateReparseParameters(const int parameters) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h index 4ed4342b01d..542568b5a77 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h @@ -37,7 +37,10 @@ #include namespace CppEditor { class CppProjectUpdater; } -namespace ProjectExplorer { class ExtraCompiler; } +namespace ProjectExplorer { + class ExtraCompiler; + class FolderNode; +} namespace CMakeProjectManager { @@ -113,8 +116,7 @@ private: REPARSE_FORCE_INITIAL_CONFIGURATION = (1 << 1), // Force initial configuration arguments to cmake REPARSE_FORCE_EXTRA_CONFIGURATION = (1 << 2), // Force extra configuration arguments to cmake - REPARSE_SCAN = (1 << 3), // Run filesystem scan - REPARSE_URGENT = (1 << 4), // Do not delay the parser run by 1s + REPARSE_URGENT = (1 << 3), // Do not delay the parser run by 1s }; QString reparseParametersString(int reparseFlags); void setParametersAndRequestParse(const BuildDirParameters ¶meters, @@ -132,9 +134,6 @@ private: // Combining Treescanner and Parser states: void combineScanAndParse(bool restoredFromBackup); - - std::unique_ptr generateProjectTree( - const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse); void checkAndReportError(QString &errorMessage); void updateCMakeConfiguration(QString &errorMessage); @@ -146,6 +145,8 @@ private: const QList &moduleMappings); void updateInitialCMakeExpandableVars(); + void updateFileSystemNodes(); + void handleParsingSucceeded(bool restoredFromBackup); void handleParsingFailed(const QString &msg); @@ -161,10 +162,9 @@ private: void runCTest(); ProjectExplorer::TreeScanner m_treeScanner; - ProjectExplorer::TreeScanner::Result m_allFiles; + std::shared_ptr m_allFiles; QHash m_mimeBinaryCache; - bool m_waitingForScan = false; bool m_waitingForParse = false; bool m_combinedScanAndParseResult = false; diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp index 5c50ce0c977..d893370028e 100644 --- a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp +++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp @@ -721,31 +721,5 @@ FileApiQtcData extractData(FileApiData &input, return result; } -FileApiQtcData generateFallbackData(const FilePath &topCmakeFile, - const FilePath &sourceDirectory, - const FilePath &buildDirectory, - QString errorMessage) -{ - Q_UNUSED(buildDirectory) - - FileApiQtcData result; - - result.rootProjectNode.reset(new CMakeProjectNode{sourceDirectory}); - result.rootProjectNode->setDisplayName(sourceDirectory.fileName()); - result.errorMessage = errorMessage; - - if (!topCmakeFile.isEmpty()) { - auto node = std::make_unique(topCmakeFile, FileType::Project); - node->setIsGenerated(false); - - std::vector> fileNodes; - fileNodes.emplace_back(std::move(node)); - - addCMakeLists(result.rootProjectNode.get(), std::move(fileNodes)); - } - - return result; -} - } // namespace Internal } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.h b/src/plugins/cmakeprojectmanager/fileapidataextractor.h index f0ba89d0428..2b65c76e079 100644 --- a/src/plugins/cmakeprojectmanager/fileapidataextractor.h +++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.h @@ -75,10 +75,6 @@ public: FileApiQtcData extractData(FileApiData &data, const Utils::FilePath &sourceDirectory, const Utils::FilePath &buildDirectory); -FileApiQtcData generateFallbackData(const Utils::FilePath &topCmakeFile, - const Utils::FilePath &sourceDirectory, - const Utils::FilePath &buildDirectory, - QString errorMessage); } // namespace Internal } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/fileapireader.cpp b/src/plugins/cmakeprojectmanager/fileapireader.cpp index 24c3c29fe47..faa1717e71c 100644 --- a/src/plugins/cmakeprojectmanager/fileapireader.cpp +++ b/src/plugins/cmakeprojectmanager/fileapireader.cpp @@ -27,7 +27,6 @@ #include "fileapidataextractor.h" #include "fileapiparser.h" -#include "projecttreehelper.h" #include @@ -214,15 +213,6 @@ bool FileApiReader::usesAllCapsTargets() const return m_usesAllCapsTargets; } -std::unique_ptr FileApiReader::generateProjectTree( - const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse) -{ - if (failedToParse) - addFileSystemNodes(m_rootProjectNode.get(), allFiles.folderNode); - - return std::exchange(m_rootProjectNode, {}); -} - RawProjectParts FileApiReader::createRawProjectParts(QString &errorMessage) { Q_UNUSED(errorMessage) @@ -250,37 +240,29 @@ void FileApiReader::endState(const FilePath &replyFilePath, bool restoredFromBac const FilePath sourceDirectory = m_parameters.sourceDirectory; const FilePath buildDirectory = m_parameters.buildDirectory; - const FilePath topCmakeFile = m_cmakeFiles.size() == 1 ? (*m_cmakeFiles.begin()).path : FilePath{}; const QString cmakeBuildType = m_parameters.cmakeBuildType == "Build" ? "" : m_parameters.cmakeBuildType; QTC_CHECK(!replyFilePath.needsDevice()); m_lastReplyTimestamp = replyFilePath.lastModified(); m_future = runAsync(ProjectExplorerPlugin::sharedThreadPool(), - [replyFilePath, sourceDirectory, buildDirectory, topCmakeFile, cmakeBuildType]( + [replyFilePath, sourceDirectory, buildDirectory, cmakeBuildType]( QFutureInterface> &fi) { auto result = std::make_shared(); FileApiData data = FileApiParser::parseData(fi, replyFilePath, cmakeBuildType, result->errorMessage); - if (!result->errorMessage.isEmpty()) { - *result = generateFallbackData(topCmakeFile, - sourceDirectory, - buildDirectory, - result->errorMessage); - } else { + if (result->errorMessage.isEmpty()) *result = extractData(data, sourceDirectory, buildDirectory); - } - if (!result->errorMessage.isEmpty()) { + else qWarning() << result->errorMessage; - } fi.reportResult(result); }); onResultReady(m_future.value(), this, - [this, topCmakeFile, sourceDirectory, buildDirectory, restoredFromBackup]( + [this, sourceDirectory, buildDirectory, restoredFromBackup]( const std::shared_ptr &value) { m_isParsing = false; m_cache = std::move(value->cache); @@ -348,6 +330,16 @@ void FileApiReader::writeConfigurationIntoBuildDirectory(const QStringList &conf QTC_CHECK(settingsFile.writeFileContents(contents)); } +std::unique_ptr FileApiReader::rootProjectNode() +{ + return std::exchange(m_rootProjectNode, {}); +} + +FilePath FileApiReader::topCmakeFile() const +{ + return m_cmakeFiles.size() == 1 ? (*m_cmakeFiles.begin()).path : FilePath{}; +} + int FileApiReader::lastCMakeExitCode() const { return m_lastCMakeExitCode; diff --git a/src/plugins/cmakeprojectmanager/fileapireader.h b/src/plugins/cmakeprojectmanager/fileapireader.h index a0fd38c491d..8e0c77278d2 100644 --- a/src/plugins/cmakeprojectmanager/fileapireader.h +++ b/src/plugins/cmakeprojectmanager/fileapireader.h @@ -71,8 +71,6 @@ public: QList takeBuildTargets(QString &errorMessage); CMakeConfig takeParsedConfiguration(QString &errorMessage); QString ctestPath() const; - std::unique_ptr generateProjectTree( - const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse); ProjectExplorer::RawProjectParts createRawProjectParts(QString &errorMessage); bool isMultiConfig() const; @@ -80,6 +78,10 @@ public: int lastCMakeExitCode() const; + std::unique_ptr rootProjectNode(); + + Utils::FilePath topCmakeFile() const; + signals: void configurationStarted() const; void dataAvailable(bool restoredFromBackup) const;