From c0185305877eb9c00a679b16e7e60bb7cec5a416 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Fri, 1 Apr 2016 16:19:55 +0200 Subject: [PATCH] ProjectExplorer: Handle imperfect build systems Handle buildsystems with imperfect knowledge about what they build more gracefully. Leave RunConfigurations around if the build system can not tell whether or not the relevant target was configured out of the current build or completely removed from the build system. This patch should not change the observable behavior of the code. Change-Id: I0ddb4bd3966d184a4b5c9818e68adb107047ed1f Reviewed-by: Eike Ziller Reviewed-by: Tim Jenssen --- src/plugins/projectexplorer/project.cpp | 5 +++ src/plugins/projectexplorer/project.h | 3 ++ src/plugins/projectexplorer/target.cpp | 50 ++++++++++++------------- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 930060f47cc..d20c324c392 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -684,6 +684,11 @@ bool Project::needsSpecialDeployment() const return false; } +bool Project::knowsAllBuildExecutables() const +{ + return true; +} + void Project::setup(QList infoList) { QList toRegister; diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index aa28e8ed146..7fd785279f7 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -139,6 +139,9 @@ public: void setPreferredKitMatcher(const KitMatcher &matcher); virtual bool needsSpecialDeployment() const; + // The build system is able to report all executables that can be built, independent + // of configuration. + virtual bool knowsAllBuildExecutables() const; void setup(QList infoList); Utils::MacroExpander *macroExpander() const; diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp index 2840cc878ed..e42a76ec1d2 100644 --- a/src/plugins/projectexplorer/target.cpp +++ b/src/plugins/projectexplorer/target.cpp @@ -590,14 +590,10 @@ void Target::updateDefaultRunConfigurations() QList newConfigured; // NEW configured Rcs QList newUnconfigured; // NEW unconfigured RCs - // sort existing RCs into configured/unconfigured. - foreach (RunConfiguration *rc, runConfigurations()) { - if (!rc->isConfigured()) - existingUnconfigured << rc; - else - existingConfigured << rc; - } + std::tie(existingConfigured, existingUnconfigured) + = Utils::partition(runConfigurations(), + [](const RunConfiguration *rc) { return rc->isConfigured(); }); int configuredCount = existingConfigured.count(); // find all RC ids that can get created: @@ -617,7 +613,7 @@ void Target::updateDefaultRunConfigurations() foreach (RunConfiguration *rc, existingConfigured) { if (availableFactoryIds.contains(rc->id())) toIgnore.append(rc->id()); // Already there - else + else if (project()->knowsAllBuildExecutables()) toRemove << rc; } foreach (Core::Id i, toIgnore) @@ -679,25 +675,27 @@ void Target::updateDefaultRunConfigurations() // Make sure a configured RC will be active after we delete the RCs: RunConfiguration *active = activeRunConfiguration(); - if (removalList.contains(active)) { - if (!existingConfigured.isEmpty()) { - setActiveRunConfiguration(existingConfigured.at(0)); - } else if (!newConfigured.isEmpty()) { - RunConfiguration *selected = newConfigured.at(0); - // Try to find a runconfiguration that matches the project name. That is a good - // candidate for something to run initially. - selected = Utils::findOr(newConfigured, selected, - Utils::equal(&RunConfiguration::displayName, project()->displayName())); - setActiveRunConfiguration(selected); - } else if (!newUnconfigured.isEmpty()){ - setActiveRunConfiguration(newUnconfigured.at(0)); - } else { - if (!removalList.isEmpty()) - setActiveRunConfiguration(removalList.last()); - // Nothing will be left after removal: We set this to the last of in the removal list - // since that gives us the minimum number of signals (one signal for the change here and - // one more when the last RC is removed and the active RC becomes 0). + if (removalList.contains(active) || !active->isEnabled()) { + RunConfiguration *newConfiguredDefault = newConfigured.isEmpty() ? nullptr : newConfigured.at(0); + + RunConfiguration *rc + = Utils::findOrDefault(existingConfigured, + [](RunConfiguration *rc) { return rc->isEnabled(); }); + if (!rc) { + rc = Utils::findOr(newConfigured, newConfiguredDefault, + Utils::equal(&RunConfiguration::displayName, project()->displayName())); } + if (!rc) + rc = newUnconfigured.isEmpty() ? nullptr : newUnconfigured.at(0); + if (!rc) { + // No RCs will be deleted, so use the one that will emit the minimum number of signals. + // One signal will be emitted from the next setActiveRunConfiguration, another one + // when the RC gets removed (and the activeRunConfiguration turns into a nullptr). + rc = removalList.isEmpty() ? nullptr : removalList.last(); + } + + if (rc) + setActiveRunConfiguration(rc); } // Remove the RCs that are no longer needed: