Python: Centralize interpreter specific function in the aspect

... and expose that instead of the PythonRunConfiguration.

This makes the PythonRunConfiguration more the container of aspects,
similar to where the other runconfigs move.

Change-Id: Ibc76b706f2d4d334640ea8f3b91343f9e7c0f566
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
hjk
2023-07-05 09:30:51 +02:00
parent 7a28ed76b8
commit b3df9a4fcf
3 changed files with 59 additions and 37 deletions

View File

@@ -207,8 +207,9 @@ void PyLSClient::openDocument(TextEditor::TextDocument *document)
const FilePath documentPath = document->filePath(); const FilePath documentPath = document->filePath();
if (PythonProject *project = pythonProjectForFile(documentPath)) { if (PythonProject *project = pythonProjectForFile(documentPath)) {
if (Target *target = project->activeTarget()) { if (Target *target = project->activeTarget()) {
if (auto rc = qobject_cast<PythonRunConfiguration *>(target->activeRunConfiguration())) if (RunConfiguration *rc = target->activeRunConfiguration())
updateExtraCompilers(project, rc->extraCompilers()); if (auto aspect = rc->aspect<PythonInterpreterAspect>())
updateExtraCompilers(project, aspect->extraCompilers());
} }
} else if (isSupportedDocument(document)) { } else if (isSupportedDocument(document)) {
const FilePath workspacePath = documentPath.parentDir(); const FilePath workspacePath = documentPath.parentDir();

View File

@@ -119,28 +119,25 @@ private:
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
class PythonInterpreterAspect final : public InterpreterAspect class PythonInterpreterAspectPrivate : public QObject
{ {
public: public:
PythonInterpreterAspect(PythonRunConfiguration *rc) PythonInterpreterAspectPrivate(PythonInterpreterAspect *parent, PythonRunConfiguration *rc)
: q(rc) : q(parent), rc(rc)
{ {
connect(this, &InterpreterAspect::changed, connect(q, &InterpreterAspect::changed,
this, &PythonInterpreterAspect::currentInterpreterChanged); this, &PythonInterpreterAspectPrivate::currentInterpreterChanged);
currentInterpreterChanged(); currentInterpreterChanged();
connect(PySideInstaller::instance(), &PySideInstaller::pySideInstalled, this, connect(PySideInstaller::instance(), &PySideInstaller::pySideInstalled, this,
[this](const FilePath &python) { [this](const FilePath &python) {
if (python == currentInterpreter().command) if (python == q->currentInterpreter().command)
checkForPySide(python); checkForPySide(python);
} }
); );
} }
~PythonInterpreterAspect() ~PythonInterpreterAspectPrivate() { qDeleteAll(m_extraCompilers); }
{
qDeleteAll(m_extraCompilers);
}
void checkForPySide(const FilePath &python); void checkForPySide(const FilePath &python);
void checkForPySide(const FilePath &python, const QString &pySidePackageName); void checkForPySide(const FilePath &python, const QString &pySidePackageName);
@@ -152,12 +149,28 @@ public:
FilePath m_pySideUicPath; FilePath m_pySideUicPath;
PythonRunConfiguration *q; PythonInterpreterAspect *q;
PythonRunConfiguration *rc;
QList<PySideUicExtraCompiler *> m_extraCompilers; QList<PySideUicExtraCompiler *> m_extraCompilers;
QFutureWatcher<PipPackageInfo> m_watcher; QFutureWatcher<PipPackageInfo> m_watcher;
QMetaObject::Connection m_watcherConnection; QMetaObject::Connection m_watcherConnection;
}; };
PythonInterpreterAspect::PythonInterpreterAspect(PythonRunConfiguration *rc)
: d(new PythonInterpreterAspectPrivate(this, rc))
{}
PythonInterpreterAspect::~PythonInterpreterAspect()
{
delete d;
}
class PythonRunConfiguration : public ProjectExplorer::RunConfiguration
{
public:
PythonRunConfiguration(ProjectExplorer::Target *target, Utils::Id id);
};
PythonRunConfiguration::PythonRunConfiguration(Target *target, Id id) PythonRunConfiguration::PythonRunConfiguration(Target *target, Id id)
: RunConfiguration(target, id) : RunConfiguration(target, id)
{ {
@@ -232,17 +245,17 @@ PythonRunConfiguration::PythonRunConfiguration(Target *target, Id id)
}); });
connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update); connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update);
connect(target, &Target::buildSystemUpdated, this, [this, interpreterAspect] { interpreterAspect->updateExtraCompilers(); }); connect(target, &Target::buildSystemUpdated, this, [this, interpreterAspect] {
interpreterAspect->d->updateExtraCompilers();
});
} }
PythonRunConfiguration::~PythonRunConfiguration() = default; void PythonInterpreterAspectPrivate::checkForPySide(const FilePath &python)
void PythonInterpreterAspect::checkForPySide(const FilePath &python)
{ {
checkForPySide(python, "PySide6-Essentials"); checkForPySide(python, "PySide6-Essentials");
} }
void PythonInterpreterAspect::checkForPySide(const FilePath &python, void PythonInterpreterAspectPrivate::checkForPySide(const FilePath &python,
const QString &pySidePackageName) const QString &pySidePackageName)
{ {
const PipPackage package(pySidePackageName); const PipPackage package(pySidePackageName);
@@ -255,8 +268,8 @@ void PythonInterpreterAspect::checkForPySide(const FilePath &python,
ExtensionSystem::PluginManager::futureSynchronizer()->addFuture(future); ExtensionSystem::PluginManager::futureSynchronizer()->addFuture(future);
} }
void PythonInterpreterAspect::handlePySidePackageInfo(const PipPackageInfo &pySideInfo, void PythonInterpreterAspectPrivate::handlePySidePackageInfo(const PipPackageInfo &pySideInfo,
const Utils::FilePath &python, const FilePath &python,
const QString &requestedPackageName) const QString &requestedPackageName)
{ {
struct PythonTools struct PythonTools
@@ -266,7 +279,7 @@ void PythonInterpreterAspect::handlePySidePackageInfo(const PipPackageInfo &pySi
}; };
BuildStepList *buildSteps = nullptr; BuildStepList *buildSteps = nullptr;
if (Target *target = q->target()) { if (Target *target = rc->target()) {
if (auto buildConfiguration = target->activeBuildConfiguration()) if (auto buildConfiguration = target->activeBuildConfiguration())
buildSteps = buildConfiguration->buildSteps(); buildSteps = buildConfiguration->buildSteps();
} }
@@ -311,12 +324,12 @@ void PythonInterpreterAspect::handlePySidePackageInfo(const PipPackageInfo &pySi
pySideBuildStep->updatePySideProjectPath(pythonTools.pySideProjectPath); pySideBuildStep->updatePySideProjectPath(pythonTools.pySideProjectPath);
} }
void PythonInterpreterAspect::currentInterpreterChanged() void PythonInterpreterAspectPrivate::currentInterpreterChanged()
{ {
const FilePath python = currentInterpreter().command; const FilePath python = q->currentInterpreter().command;
checkForPySide(python); checkForPySide(python);
for (FilePath &file : q->project()->files(Project::AllFiles)) { for (FilePath &file : rc->project()->files(Project::AllFiles)) {
if (auto document = TextEditor::TextDocument::textDocumentForFilePath(file)) { if (auto document = TextEditor::TextDocument::textDocumentForFilePath(file)) {
if (document->mimeType() == Constants::C_PY_MIMETYPE if (document->mimeType() == Constants::C_PY_MIMETYPE
|| document->mimeType() == Constants::C_PY3_MIMETYPE) { || document->mimeType() == Constants::C_PY3_MIMETYPE) {
@@ -327,12 +340,12 @@ void PythonInterpreterAspect::currentInterpreterChanged()
} }
} }
QList<PySideUicExtraCompiler *> PythonRunConfiguration::extraCompilers() const QList<PySideUicExtraCompiler *> PythonInterpreterAspect::extraCompilers() const
{ {
return static_cast<PythonInterpreterAspect *>(aspect<InterpreterAspect>())->m_extraCompilers; return d->m_extraCompilers;
} }
void PythonInterpreterAspect::updateExtraCompilers() void PythonInterpreterAspectPrivate::updateExtraCompilers()
{ {
QList<PySideUicExtraCompiler *> oldCompilers = m_extraCompilers; QList<PySideUicExtraCompiler *> oldCompilers = m_extraCompilers;
m_extraCompilers.clear(); m_extraCompilers.clear();
@@ -343,21 +356,21 @@ void PythonInterpreterAspect::updateExtraCompilers()
return fileNode->fileType() == ProjectExplorer::FileType::Form; return fileNode->fileType() == ProjectExplorer::FileType::Form;
return false; return false;
}; };
const FilePaths uiFiles = q->project()->files(uiMatcher); const FilePaths uiFiles = rc->project()->files(uiMatcher);
for (const FilePath &uiFile : uiFiles) { for (const FilePath &uiFile : uiFiles) {
FilePath generated = uiFile.parentDir(); FilePath generated = uiFile.parentDir();
generated = generated.pathAppended("/ui_" + uiFile.baseName() + ".py"); generated = generated.pathAppended("/ui_" + uiFile.baseName() + ".py");
int index = Utils::indexOf(oldCompilers, [&](PySideUicExtraCompiler *oldCompiler) { int index = Utils::indexOf(oldCompilers, [&](PySideUicExtraCompiler *oldCompiler) {
return oldCompiler->pySideUicPath() == m_pySideUicPath return oldCompiler->pySideUicPath() == m_pySideUicPath
&& oldCompiler->project() == q->project() && oldCompiler->source() == uiFile && oldCompiler->project() == rc->project() && oldCompiler->source() == uiFile
&& oldCompiler->targets() == FilePaths{generated}; && oldCompiler->targets() == FilePaths{generated};
}); });
if (index < 0) { if (index < 0) {
m_extraCompilers << new PySideUicExtraCompiler(m_pySideUicPath, m_extraCompilers << new PySideUicExtraCompiler(m_pySideUicPath,
q->project(), rc->project(),
uiFile, uiFile,
{generated}, {generated},
q); this);
} else { } else {
m_extraCompilers << oldCompilers.takeAt(index); m_extraCompilers << oldCompilers.takeAt(index);
} }
@@ -365,11 +378,13 @@ void PythonInterpreterAspect::updateExtraCompilers()
} }
for (LanguageClient::Client *client : LanguageClient::LanguageClientManager::clients()) { for (LanguageClient::Client *client : LanguageClient::LanguageClientManager::clients()) {
if (auto pylsClient = qobject_cast<PyLSClient *>(client)) if (auto pylsClient = qobject_cast<PyLSClient *>(client))
pylsClient->updateExtraCompilers(q->project(), m_extraCompilers); pylsClient->updateExtraCompilers(rc->project(), m_extraCompilers);
} }
qDeleteAll(oldCompilers); qDeleteAll(oldCompilers);
} }
// Factories
PythonRunConfigurationFactory::PythonRunConfigurationFactory() PythonRunConfigurationFactory::PythonRunConfigurationFactory()
{ {
registerRunConfiguration<PythonRunConfiguration>(Constants::C_PYTHONRUNCONFIGURATION_ID); registerRunConfiguration<PythonRunConfiguration>(Constants::C_PYTHONRUNCONFIGURATION_ID);

View File

@@ -4,21 +4,27 @@
#pragma once #pragma once
#include <projectexplorer/runconfiguration.h> #include <projectexplorer/runconfiguration.h>
#include <projectexplorer/runconfigurationaspects.h>
#include <projectexplorer/runcontrol.h> #include <projectexplorer/runcontrol.h>
namespace Python::Internal { namespace Python::Internal {
class PySideUicExtraCompiler; class PySideUicExtraCompiler;
class PythonRunConfiguration;
class PythonRunConfiguration : public ProjectExplorer::RunConfiguration class PythonInterpreterAspect final : public ProjectExplorer::InterpreterAspect
{ {
Q_OBJECT Q_OBJECT
public: public:
PythonRunConfiguration(ProjectExplorer::Target *target, Utils::Id id); explicit PythonInterpreterAspect(PythonRunConfiguration *rc);
~PythonRunConfiguration() override; ~PythonInterpreterAspect() final;
QList<PySideUicExtraCompiler *> extraCompilers() const; QList<PySideUicExtraCompiler *> extraCompilers() const;
private:
friend class PythonRunConfiguration;
class PythonInterpreterAspectPrivate *d = nullptr;
}; };
class PythonRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory class PythonRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory