aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/utils/datafromprocess.h4
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketool.cpp139
-rw-r--r--src/plugins/cmakeprojectmanager/cmaketool.h6
-rw-r--r--src/plugins/python/pyside.cpp2
-rw-r--r--src/plugins/python/pythonlanguageclient.cpp4
-rw-r--r--src/plugins/python/pythonsettings.cpp8
-rw-r--r--src/plugins/python/pythonutils.cpp47
-rw-r--r--src/plugins/python/pythonutils.h1
-rw-r--r--src/plugins/qtsupport/qtoptionspage.cpp3
9 files changed, 127 insertions, 87 deletions
diff --git a/src/libs/utils/datafromprocess.h b/src/libs/utils/datafromprocess.h
index b87b7f7d133..00a105e8acf 100644
--- a/src/libs/utils/datafromprocess.h
+++ b/src/libs/utils/datafromprocess.h
@@ -53,6 +53,7 @@ public:
Callback cachedValueChangedCallback;
bool persistValue = true;
QList<ProcessResult> allowedResults{ProcessResult::FinishedWithSuccess};
+ bool disableUnixTerminal = false;
};
// Use the first variant whenever possible.
@@ -109,6 +110,9 @@ inline std::optional<Data> DataFromProcess<Data>::getOrProvideData(const Paramet
const auto outputRetriever = std::make_shared<Process>();
outputRetriever->setCommand(params.commandLine);
+ outputRetriever->setEnvironment(params.environment);
+ if (params.disableUnixTerminal)
+ outputRetriever->setDisableUnixTerminal();
if (params.persistValue && !params.callback) {
const QChar separator = params.commandLine.executable().pathListSeparator();
diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp
index 1f53f797213..66fda223b3b 100644
--- a/src/plugins/cmakeprojectmanager/cmaketool.cpp
+++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp
@@ -9,6 +9,7 @@
#include <coreplugin/icore.h>
#include <projectexplorer/devicesupport/devicemanager.h>
#include <utils/algorithm.h>
+#include <utils/datafromprocess.h>
#include <utils/environment.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -40,11 +41,35 @@ const char CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY[] = "AutoCreateBuildDir
const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected";
const char CMAKE_INFORMATION_DETECTIONSOURCE[] = "DetectionSource";
+bool operator==(const CMakeTool::Version &v1, const CMakeTool::Version &v2)
+{
+ return v1.major == v2.major && v1.minor == v2.minor && v1.patch == v2.patch
+ && v1.fullVersion == v2.fullVersion;
+}
+
+bool operator!=(const CMakeTool::Version &v1, const CMakeTool::Version &v2)
+{
+ return !(v1 == v2);
+}
+
bool CMakeTool::Generator::matches(const QString &n) const
{
return n == name;
}
+bool operator==(const CMakeTool::Generator &g1, const CMakeTool::Generator &g2)
+{
+ return g1.name == g2.name
+ && g1.extraGenerators == g2.extraGenerators
+ && g1.supportsPlatform == g2.supportsPlatform
+ && g1.supportsToolset == g2.supportsToolset;
+}
+
+bool operator!=(const CMakeTool::Generator &g1, const CMakeTool::Generator &g2)
+{
+ return !(g1 == g2);
+}
+
namespace Internal {
// --------------------------------------------------------------------
@@ -57,6 +82,37 @@ public:
std::pair<int, int> version;
};
+bool operator==(const FileApi &f1, const FileApi &f2)
+{
+ return f1.kind == f2.kind && f1.version == f2.version;
+}
+
+bool operator!=(const FileApi &f1, const FileApi &f2)
+{
+ return !(f1 == f2);
+}
+
+class Capabilities {
+public:
+ static Capabilities fromJson(const QString &input);
+
+ QList<CMakeTool::Generator> generators;
+ QList<FileApi> fileApis;
+ CMakeTool::Version version;
+};
+
+bool operator==(const Capabilities &c1, const Capabilities &c2)
+{
+ return c1.generators == c2.generators
+ && c1.fileApis == c2.fileApis
+ && c1.version == c2.version;
+}
+
+bool operator!=(const Capabilities &c1, const Capabilities &c2)
+{
+ return !(c1 == c2);
+}
+
class IntrospectionData
{
public:
@@ -64,13 +120,9 @@ public:
bool m_haveCapabilitites = true;
bool m_haveKeywords = false;
- QList<CMakeTool::Generator> m_generators;
+ Capabilities m_capabilities;
CMakeKeywords m_keywords;
QMutex m_keywordsMutex;
- QList<FileApi> m_fileApis;
- CMakeTool::Version m_version;
-
- void parseFromCapabilities(const QString &input);
};
} // namespace Internal
@@ -145,7 +197,8 @@ bool CMakeTool::isValid() const
if (!m_introspection->m_didAttemptToRun)
readInformation();
- return m_introspection->m_haveCapabilitites && !m_introspection->m_fileApis.isEmpty();
+ return m_introspection->m_haveCapabilitites
+ && !m_introspection->m_capabilities.fileApis.isEmpty();
}
void CMakeTool::runCMake(Process &cmake, const QStringList &args, int timeoutS) const
@@ -214,7 +267,7 @@ FilePath CMakeTool::cmakeExecutable(const FilePath &path)
QList<CMakeTool::Generator> CMakeTool::supportedGenerators() const
{
- return isValid() ? m_introspection->m_generators : QList<CMakeTool::Generator>();
+ return isValid() ? m_introspection->m_capabilities.generators : QList<CMakeTool::Generator>();
}
CMakeKeywords CMakeTool::keywords()
@@ -233,14 +286,18 @@ CMakeKeywords CMakeTool::keywords()
/ "find-root.cmake";
findCMakeRoot.writeFileContents("message(${CMAKE_ROOT})");
- FilePath cmakeRoot;
- runCMake(proc, {"-P", findCMakeRoot.nativePath()});
- if (proc.result() == ProcessResult::FinishedWithSuccess) {
- QStringList output = filtered(proc.allOutput().split('\n'),
- std::not_fn(&QString::isEmpty));
+ CommandLine command(cmakeExecutable(), {"-P", findCMakeRoot.nativePath()});
+ auto outputParser = [](const QString &stdOut, const QString &) -> std::optional<FilePath> {
+ QStringList output = filtered(stdOut.split('\n'), std::not_fn(&QString::isEmpty));
if (output.size() > 0)
- cmakeRoot = FilePath::fromString(output[0]);
- }
+ return FilePath::fromString(output[0]);
+ return {};
+ };
+ DataFromProcess<FilePath>::Parameters params(command, outputParser);
+ params.environment = command.executable().deviceEnvironment();
+ params.environment.setupEnglishOutput();
+ params.disableUnixTerminal = true;
+ const FilePath cmakeRoot = DataFromProcess<FilePath>::getData(params).value_or(FilePath());
const struct
{
@@ -299,12 +356,12 @@ CMakeKeywords CMakeTool::keywords()
bool CMakeTool::hasFileApi() const
{
- return isValid() ? !m_introspection->m_fileApis.isEmpty() : false;
+ return isValid() ? !m_introspection->m_capabilities.fileApis.isEmpty() : false;
}
CMakeTool::Version CMakeTool::version() const
{
- return isValid() ? m_introspection->m_version : CMakeTool::Version();
+ return isValid() ? m_introspection->m_capabilities.version : CMakeTool::Version();
}
QString CMakeTool::versionDisplay() const
@@ -315,7 +372,7 @@ QString CMakeTool::versionDisplay() const
if (!isValid())
return Tr::tr("Version not parseable");
- const Version &version = m_introspection->m_version;
+ const Version &version = m_introspection->m_capabilities.version;
if (version.fullVersion.isEmpty())
return QString::fromUtf8(version.fullVersion);
@@ -450,15 +507,25 @@ void CMakeTool::fetchFromCapabilities() const
if (device
&& (device->deviceState() == IDevice::DeviceReadyToUse
|| device->deviceState() == IDevice::DeviceConnected)) {
- Process cmake;
- runCMake(cmake, {"-E", "capabilities"});
- if (cmake.result() == ProcessResult::FinishedWithSuccess) {
+ CommandLine command(cmakeExecutable(), {"-E", "capabilities"});
+ auto outputParser = [](const QString &stdOut, const QString &) {
+ return Internal::Capabilities::fromJson(stdOut);
+ };
+ DataFromProcess<Internal::Capabilities>::Parameters params(command, outputParser);
+ params.environment = command.executable().deviceEnvironment();
+ params.environment.setupEnglishOutput();
+ params.disableUnixTerminal = true;
+ params.errorHandler = [](const Process &p) {
+ qCCritical(cmakeToolLog) << "Fetching capabilities failed: " << p.verboseExitMessage();
+ };
+ const auto capabilities = DataFromProcess<Internal::Capabilities>::getData(params);
+
+ if (const auto capabilities = DataFromProcess<Internal::Capabilities>::getData(params)) {
m_introspection->m_haveCapabilitites = true;
- m_introspection->parseFromCapabilities(cmake.cleanedStdOut());
+ m_introspection->m_capabilities = *capabilities;
return;
}
- qCCritical(cmakeToolLog) << "Fetching capabilities failed: " << cmake.verboseExitMessage();
} else {
qCDebug(cmakeToolLog) << "Device for" << cmakeExecutable().toUserOutput()
<< "is not connected";
@@ -479,22 +546,22 @@ static int getVersion(const QVariantMap &obj, const QString &value)
return result;
}
-void Internal::IntrospectionData::parseFromCapabilities(const QString &input)
+Internal::Capabilities Internal::Capabilities::fromJson(const QString &input)
{
+ Capabilities result;
auto doc = QJsonDocument::fromJson(input.toUtf8());
if (!doc.isObject())
- return;
+ return result;
const QVariantMap data = doc.object().toVariantMap();
const QVariantList generatorList = data.value("generators").toList();
for (const QVariant &v : generatorList) {
const QVariantMap gen = v.toMap();
- m_generators.append(
- CMakeTool::Generator(
- gen.value("name").toString(),
- gen.value("extraGenerators").toStringList(),
- gen.value("platformSupport").toBool(),
- gen.value("toolsetSupport").toBool()));
+ result.generators.append(CMakeTool::Generator(
+ gen.value("name").toString(),
+ gen.value("extraGenerators").toStringList(),
+ gen.value("platformSupport").toBool(),
+ gen.value("toolsetSupport").toBool()));
}
const QVariantMap fileApis = data.value("fileApi").toMap();
@@ -513,14 +580,16 @@ void Internal::IntrospectionData::parseFromCapabilities(const QString &input)
highestVersion = version;
}
if (!kind.isNull() && highestVersion.first != -1 && highestVersion.second != -1)
- m_fileApis.append({kind, highestVersion});
+ result.fileApis.append({kind, highestVersion});
}
const QVariantMap versionInfo = data.value("version").toMap();
- m_version.major = versionInfo.value("major").toInt();
- m_version.minor = versionInfo.value("minor").toInt();
- m_version.patch = versionInfo.value("patch").toInt();
- m_version.fullVersion = versionInfo.value("string").toByteArray();
+ result.version.major = versionInfo.value("major").toInt();
+ result.version.minor = versionInfo.value("minor").toInt();
+ result.version.patch = versionInfo.value("patch").toInt();
+ result.version.fullVersion = versionInfo.value("string").toByteArray();
+
+ return result;
}
void CMakeTool::setDetectionSource(const DetectionSource &source)
diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h
index 4dfeb265926..7b071d19790 100644
--- a/src/plugins/cmakeprojectmanager/cmaketool.h
+++ b/src/plugins/cmakeprojectmanager/cmaketool.h
@@ -46,6 +46,9 @@ public:
int minor = 0;
int patch = 0;
QByteArray fullVersion;
+
+ friend bool operator==(const Version &v1, const Version &v2);
+ friend bool operator!=(const Version &v1, const Version &v2);
};
class Generator
@@ -61,6 +64,9 @@ public:
bool supportsToolset = true;
bool matches(const QString &n) const;
+
+ friend bool operator==(const CMakeTool::Generator &g1, const CMakeTool::Generator &g2);
+ friend bool operator!=(const CMakeTool::Generator &g1, const CMakeTool::Generator &g2);
};
explicit CMakeTool(const Utils::Store &map, bool fromSdk);
diff --git a/src/plugins/python/pyside.cpp b/src/plugins/python/pyside.cpp
index 79cb6949ee2..8e74e71b1f6 100644
--- a/src/plugins/python/pyside.cpp
+++ b/src/plugins/python/pyside.cpp
@@ -211,7 +211,7 @@ void PySideInstaller::handlePySideMissing(const FilePath &python,
if (!document || !document->infoBar()->canInfoBeAdded(installPySideInfoBarId))
return;
const QString message = Tr::tr("%1 installation missing for %2 (%3)")
- .arg(pySide, pythonName(python), python.toUserOutput());
+ .arg(pySide, pythonVersion(python), python.toUserOutput());
InfoBarEntry info(installPySideInfoBarId, message, InfoBarEntry::GlobalSuppression::Enabled);
auto installCallback = [this, python, pySide] { installPySide(python, pySide, true); };
const QString installTooltip = Tr::tr("Install %1 for %2 using pip package installer.")
diff --git a/src/plugins/python/pythonlanguageclient.cpp b/src/plugins/python/pythonlanguageclient.cpp
index 052ebe1d388..4a2ed9ec23b 100644
--- a/src/plugins/python/pythonlanguageclient.cpp
+++ b/src/plugins/python/pythonlanguageclient.cpp
@@ -390,7 +390,7 @@ void PyLSConfigureAssistant::handlePyLSState(const FilePath &python,
&& infoBar->canInfoBeAdded(installPylsInfoBarId)) {
auto message = Tr::tr("Install Python language server (PyLS) for %1 (%2). "
"The language server provides Python specific completion and annotation.")
- .arg(pythonName(python), python.toUserOutput());
+ .arg(pythonVersion(python), python.toUserOutput());
InfoBarEntry info(installPylsInfoBarId, message, InfoBarEntry::GlobalSuppression::Enabled);
info.addCustomButton(Tr::tr("Install"), [this, python, document, state] {
installPythonLanguageServer(python, document, state.pylsModulePath, false, false);
@@ -400,7 +400,7 @@ void PyLSConfigureAssistant::handlePyLSState(const FilePath &python,
} else if (state.state == PythonLanguageServerState::Updatable) {
if (infoBar->canInfoBeAdded(updatePylsInfoBarId)) {
auto message = Tr::tr("Update Python language server (PyLS) for %1 (%2).")
- .arg(pythonName(python), python.toUserOutput());
+ .arg(pythonVersion(python), python.toUserOutput());
InfoBarEntry info(updatePylsInfoBarId, message);
info.addCustomButton(
Tr::tr("Always Update"),
diff --git a/src/plugins/python/pythonsettings.cpp b/src/plugins/python/pythonsettings.cpp
index 6c257aa2c90..fde31e692f1 100644
--- a/src/plugins/python/pythonsettings.cpp
+++ b/src/plugins/python/pythonsettings.cpp
@@ -129,13 +129,7 @@ Interpreter PythonSettings::createInterpreter(
result.command = python;
result.detectionSource = detectionSource;
- Process pythonProcess;
- pythonProcess.setProcessChannelMode(QProcess::MergedChannels);
- pythonProcess.setCommand({python, {"--version"}});
- using namespace std::chrono_literals;
- pythonProcess.runBlocking(1s);
- if (pythonProcess.result() == ProcessResult::FinishedWithSuccess)
- result.name = pythonProcess.cleanedStdOut().trimmed();
+ result.name = pythonVersion(python);
if (result.name.isEmpty())
result.name = defaultName;
QDir pythonDir(python.parentDir().toUrlishString());
diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp
index 2936d4f4c5d..178f66108e1 100644
--- a/src/plugins/python/pythonutils.cpp
+++ b/src/plugins/python/pythonutils.cpp
@@ -18,6 +18,7 @@
#include <projectexplorer/target.h>
#include <utils/algorithm.h>
+#include <utils/datafromprocess.h>
#include <utils/mimeutils.h>
#include <utils/qtcprocess.h>
#include <utils/synchronizedvalue.h>
@@ -137,25 +138,6 @@ void openPythonRepl(QObject *parent, const FilePath &file, ReplType type)
}
}
-QString pythonName(const FilePath &pythonPath)
-{
- static QHash<FilePath, QString> nameForPython;
- if (!pythonPath.exists())
- return {};
- QString name = nameForPython.value(pythonPath);
- if (name.isEmpty()) {
- Process pythonProcess;
- pythonProcess.setCommand({pythonPath, {"--version"}});
- using namespace std::chrono_literals;
- pythonProcess.runBlocking(2s);
- if (pythonProcess.result() != ProcessResult::FinishedWithSuccess)
- return {};
- name = pythonProcess.allOutput().trimmed();
- nameForPython[pythonPath] = name;
- }
- return name;
-}
-
PythonProject *pythonProjectForFile(const FilePath &file)
{
for (Project *project : ProjectManager::projects()) {
@@ -207,26 +189,13 @@ bool pipIsUsable(const FilePath &python)
QString pythonVersion(const FilePath &python)
{
- static QReadWriteLock lock;
- static QMap<FilePath, QString> versionCache;
-
- {
- QReadLocker locker(&lock);
- auto it = versionCache.constFind(python);
- if (it != versionCache.constEnd())
- return *it;
- }
-
- Process p;
- p.setCommand({python, {"--version"}});
- p.runBlocking();
- if (p.result() == ProcessResult::FinishedWithSuccess) {
- const QString version = p.readAllStandardOutput().trimmed();
- QWriteLocker locker(&lock);
- versionCache.insert(python, version);
- return version;
- }
- return QString();
+ DataFromProcess<QString>::Parameters
+ params({python, {"--version"}}, [](const QString &stdOut, const QString &) {
+ return stdOut.trimmed();
+ });
+ if (const std::optional<QString> version = DataFromProcess<QString>::getData(params))
+ return *version;
+ return {};
}
} // namespace Python::Internal
diff --git a/src/plugins/python/pythonutils.h b/src/plugins/python/pythonutils.h
index 7aa5a575f56..4d4b0bd8cc1 100644
--- a/src/plugins/python/pythonutils.h
+++ b/src/plugins/python/pythonutils.h
@@ -11,7 +11,6 @@ enum class ReplType { Unmodified, Import, ImportToplevel };
void openPythonRepl(QObject *parent, const Utils::FilePath &file, ReplType type);
Utils::FilePath detectPython(const Utils::FilePath &documentPath);
void definePythonForDocument(const Utils::FilePath &documentPath, const Utils::FilePath &python);
-QString pythonName(const Utils::FilePath &pythonPath);
class PythonProject;
PythonProject *pythonProjectForFile(const Utils::FilePath &pythonFile);
diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp
index 06403105f04..44477828eb8 100644
--- a/src/plugins/qtsupport/qtoptionspage.cpp
+++ b/src/plugins/qtsupport/qtoptionspage.cpp
@@ -801,8 +801,7 @@ void QtSettingsPageWidget::redetect()
if (!QTC_GUARD(dev))
return;
- const FilePaths qMakes
- = BuildableHelperLibrary::findQtsInEnvironment(dev->systemEnvironment(), dev->rootPath());
+ const FilePaths qMakes = BuildableHelperLibrary::findQtsInPaths(dev->toolSearchPaths());
for (const FilePath &qmakePath : qMakes) {
if (BuildableHelperLibrary::isQtChooser(qmakePath))
continue;