Debugger: add python debugger setting in run configuration

Change-Id: Ifa5d72566007e0bb006523433dcef97689677fbf
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
David Schulz
2023-11-29 15:08:48 +01:00
committed by hjk
parent 5034936333
commit eb740bdd95
11 changed files with 143 additions and 131 deletions

View File

@@ -395,6 +395,12 @@ bool allOf(const T &container, F predicate)
return std::all_of(std::begin(container), std::end(container), predicate); return std::all_of(std::begin(container), std::end(container), predicate);
} }
template<typename T, typename F>
bool allOf(const std::initializer_list<T> &initializerList, F predicate)
{
return std::all_of(std::begin(initializerList), std::end(initializerList), predicate);
}
// allOf taking a member function pointer // allOf taking a member function pointer
template<typename T, typename R, typename S> template<typename T, typename R, typename S>
bool allOf(const T &container, R (S::*predicate)() const) bool allOf(const T &container, R (S::*predicate)() const)

View File

@@ -97,7 +97,6 @@ enum DebuggerEngineType
NoEngineType = 0, NoEngineType = 0,
GdbEngineType = 0x001, GdbEngineType = 0x001,
CdbEngineType = 0x004, CdbEngineType = 0x004,
PdbEngineType = 0x008,
LldbEngineType = 0x100, LldbEngineType = 0x100,
UvscEngineType = 0x1000 UvscEngineType = 0x1000
}; };

View File

@@ -267,8 +267,8 @@ public:
connect(&settings().enableReverseDebugging, &BaseAspect::changed, this, [this] { connect(&settings().enableReverseDebugging, &BaseAspect::changed, this, [this] {
updateState(); updateState();
if (m_companionEngine) for (const QPointer<DebuggerEngine> &companion : std::as_const(m_companionEngines))
m_companionEngine->d->updateState(); companion->d->updateState();
}); });
static int contextCount = 0; static int contextCount = 0;
m_context = Context(Id("Debugger.Engine.").withSuffix(++contextCount)); m_context = Context(Id("Debugger.Engine.").withSuffix(++contextCount));
@@ -445,7 +445,7 @@ public:
DebuggerRunParameters m_runParameters; DebuggerRunParameters m_runParameters;
IDevice::ConstPtr m_device; IDevice::ConstPtr m_device;
QPointer<DebuggerEngine> m_companionEngine; QList<QPointer<DebuggerEngine>> m_companionEngines;
bool m_isPrimaryEngine = true; bool m_isPrimaryEngine = true;
// The current state. // The current state.
@@ -1134,9 +1134,9 @@ IDevice::ConstPtr DebuggerEngine::device() const
return d->m_device; return d->m_device;
} }
DebuggerEngine *DebuggerEngine::companionEngine() const QList<DebuggerEngine *> DebuggerEngine::companionEngines() const
{ {
return d->m_companionEngine; return Utils::transform(d->m_companionEngines, &QPointer<DebuggerEngine>::get);
} }
DebuggerState DebuggerEngine::state() const DebuggerState DebuggerEngine::state() const
@@ -1849,8 +1849,8 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
showMessage(msg, LogDebug); showMessage(msg, LogDebug);
d->updateState(); d->updateState();
if (d->m_companionEngine) for (const QPointer<DebuggerEngine> &companion : std::as_const(d->m_companionEngines))
d->m_companionEngine->d->updateState(); companion->d->updateState();
if (oldState != d->m_state) if (oldState != d->m_state)
emit EngineManager::instance()->engineStateChanged(this); emit EngineManager::instance()->engineStateChanged(this);
@@ -2037,9 +2037,9 @@ void DebuggerEngine::progressPing()
d->m_progress.setProgressValue(progress); d->m_progress.setProgressValue(progress);
} }
void DebuggerEngine::setCompanionEngine(DebuggerEngine *engine) void DebuggerEngine::addCompanionEngine(DebuggerEngine *engine)
{ {
d->m_companionEngine = engine; d->m_companionEngines << engine;
} }
void DebuggerEngine::setSecondaryEngine() void DebuggerEngine::setSecondaryEngine()

View File

@@ -149,6 +149,7 @@ public:
QString version; QString version;
bool isQmlDebugging = false; bool isQmlDebugging = false;
bool isPythonDebugging = false;
bool breakOnMain = false; bool breakOnMain = false;
bool multiProcess = false; // Whether to set detach-on-fork off. bool multiProcess = false; // Whether to set detach-on-fork off.
bool useTerminal = false; bool useTerminal = false;
@@ -269,7 +270,7 @@ public:
QString runId() const; QString runId() const;
const DebuggerRunParameters &runParameters() const; const DebuggerRunParameters &runParameters() const;
void setCompanionEngine(DebuggerEngine *engine); void addCompanionEngine(DebuggerEngine *engine);
void setSecondaryEngine(); void setSecondaryEngine();
void start(); void start();
@@ -553,7 +554,7 @@ protected:
void startDying() const; void startDying() const;
ProjectExplorer::IDeviceConstPtr device() const; ProjectExplorer::IDeviceConstPtr device() const;
DebuggerEngine *companionEngine() const; QList<DebuggerEngine *> companionEngines() const;
private: private:
friend class DebuggerPluginPrivate; friend class DebuggerPluginPrivate;

View File

@@ -243,10 +243,6 @@ void DebuggerItem::reinitializeFromFile(QString *error, Utils::Environment *cust
m_version = output.section(' ', 2); m_version = output.section(' ', 2);
return; return;
} }
if (output.startsWith("Python")) {
m_engineType = PdbEngineType;
return;
}
if (error) if (error)
*error = output; *error = output;
m_engineType = NoEngineType; m_engineType = NoEngineType;

View File

@@ -40,6 +40,12 @@ namespace Debugger {
\class Debugger::DebuggerRunConfigurationAspect \class Debugger::DebuggerRunConfigurationAspect
*/ */
static bool isDisabled(TriStateAspect *aspect)
{
QTC_ASSERT(aspect, return false);
return aspect->value() == TriState::Disabled;
}
DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target) DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target)
: m_target(target) : m_target(target)
{ {
@@ -49,6 +55,7 @@ DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target)
setConfigWidgetCreator([this] { setConfigWidgetCreator([this] {
Layouting::Grid builder; Layouting::Grid builder;
builder.addRow({m_cppAspect}); builder.addRow({m_cppAspect});
builder.addRow({m_pythonAspect});
auto info = new QLabel( auto info = new QLabel(
Tr::tr("<a href=\"" Tr::tr("<a href=\""
"qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html" "qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html"
@@ -98,6 +105,7 @@ DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target)
addDataExtractor(this, &DebuggerRunConfigurationAspect::useCppDebugger, &Data::useCppDebugger); addDataExtractor(this, &DebuggerRunConfigurationAspect::useCppDebugger, &Data::useCppDebugger);
addDataExtractor(this, &DebuggerRunConfigurationAspect::useQmlDebugger, &Data::useQmlDebugger); addDataExtractor(this, &DebuggerRunConfigurationAspect::useQmlDebugger, &Data::useQmlDebugger);
addDataExtractor(this, &DebuggerRunConfigurationAspect::usePythonDebugger, &Data::usePythonDebugger);
addDataExtractor(this, &DebuggerRunConfigurationAspect::useMultiProcess, &Data::useMultiProcess); addDataExtractor(this, &DebuggerRunConfigurationAspect::useMultiProcess, &Data::useMultiProcess);
addDataExtractor(this, &DebuggerRunConfigurationAspect::overrideStartup, &Data::overrideStartup); addDataExtractor(this, &DebuggerRunConfigurationAspect::overrideStartup, &Data::overrideStartup);
@@ -109,16 +117,23 @@ DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(Target *target)
m_qmlAspect->setLabelText(Tr::tr("QML debugger:")); m_qmlAspect->setLabelText(Tr::tr("QML debugger:"));
m_qmlAspect->setSettingsKey("RunConfiguration.UseQmlDebugger"); m_qmlAspect->setSettingsKey("RunConfiguration.UseQmlDebugger");
m_pythonAspect = new TriStateAspect(nullptr, Tr::tr("Enabled"), Tr::tr("Disabled"), Tr::tr("Automatic"));
m_pythonAspect->setLabelText(Tr::tr("Python debugger:"));
m_pythonAspect->setSettingsKey("RunConfiguration.UsePythonDebugger");
// Make sure at least one of the debuggers is set to be active. // Make sure at least one of the debuggers is set to be active.
connect(m_cppAspect, &TriStateAspect::changed, this, [this]{ connect(m_cppAspect, &TriStateAspect::changed, this, [this]{
if (m_cppAspect->value() == TriState::Disabled && m_qmlAspect->value() == TriState::Disabled) if (Utils::allOf({m_cppAspect, m_qmlAspect, m_pythonAspect}, &isDisabled))
m_qmlAspect->setValue(TriState::Default); m_qmlAspect->setValue(TriState::Default);
}); });
connect(m_qmlAspect, &TriStateAspect::changed, this, [this]{ connect(m_qmlAspect, &TriStateAspect::changed, this, [this]{
if (m_qmlAspect->value() == TriState::Disabled && m_cppAspect->value() == TriState::Disabled) if (Utils::allOf({m_cppAspect, m_qmlAspect, m_pythonAspect}, &isDisabled))
m_cppAspect->setValue(TriState::Default);
});
connect(m_qmlAspect, &TriStateAspect::changed, this, [this] {
if (Utils::allOf({m_cppAspect, m_qmlAspect, m_pythonAspect}, &isDisabled))
m_cppAspect->setValue(TriState::Default); m_cppAspect->setValue(TriState::Default);
}); });
m_multiProcessAspect = new BoolAspect; m_multiProcessAspect = new BoolAspect;
m_multiProcessAspect->setSettingsKey("RunConfiguration.UseMultiProcess"); m_multiProcessAspect->setSettingsKey("RunConfiguration.UseMultiProcess");
@@ -177,8 +192,8 @@ bool DebuggerRunConfigurationAspect::useQmlDebugger() const
// //
// Try to find a build configuration to check whether qml debugging is enabled there // Try to find a build configuration to check whether qml debugging is enabled there
if (BuildConfiguration *bc = m_target->activeBuildConfiguration()) { if (BuildConfiguration *bc = m_target->activeBuildConfiguration()) {
const auto aspect = bc->aspect<QtSupport::QmlDebuggingAspect>(); if (const auto aspect = bc->aspect<QtSupport::QmlDebuggingAspect>())
return aspect && aspect->value() == TriState::Enabled; return aspect->value() == TriState::Enabled;
} }
return !languages.contains(ProjectExplorer::Constants::CXX_LANGUAGE_ID); return !languages.contains(ProjectExplorer::Constants::CXX_LANGUAGE_ID);
@@ -186,6 +201,15 @@ bool DebuggerRunConfigurationAspect::useQmlDebugger() const
return m_qmlAspect->value() == TriState::Enabled; return m_qmlAspect->value() == TriState::Enabled;
} }
bool DebuggerRunConfigurationAspect::usePythonDebugger() const
{
if (m_pythonAspect->value() == TriState::Default) {
const Core::Context languages = m_target->project()->projectLanguages();
return languages.contains(ProjectExplorer::Constants::PYTHON_LANGUAGE_ID);
}
return m_pythonAspect->value() == TriState::Enabled;
}
bool DebuggerRunConfigurationAspect::useMultiProcess() const bool DebuggerRunConfigurationAspect::useMultiProcess() const
{ {
return m_multiProcessAspect->value(); return m_multiProcessAspect->value();
@@ -215,6 +239,7 @@ void DebuggerRunConfigurationAspect::toMap(Store &map) const
{ {
m_cppAspect->toMap(map); m_cppAspect->toMap(map);
m_qmlAspect->toMap(map); m_qmlAspect->toMap(map);
m_pythonAspect->toMap(map);
m_multiProcessAspect->toMap(map); m_multiProcessAspect->toMap(map);
m_overrideStartupAspect->toMap(map); m_overrideStartupAspect->toMap(map);
@@ -227,6 +252,7 @@ void DebuggerRunConfigurationAspect::fromMap(const Store &map)
{ {
m_cppAspect->fromMap(map); m_cppAspect->fromMap(map);
m_qmlAspect->fromMap(map); m_qmlAspect->fromMap(map);
m_pythonAspect->fromMap(map);
// respect old project settings // respect old project settings
if (map.value("RunConfiguration.UseCppDebuggerAuto", false).toBool()) if (map.value("RunConfiguration.UseCppDebuggerAuto", false).toBool())

View File

@@ -22,6 +22,7 @@ public:
bool useCppDebugger() const; bool useCppDebugger() const;
bool useQmlDebugger() const; bool useQmlDebugger() const;
bool usePythonDebugger() const;
void setUseQmlDebugger(bool value); void setUseQmlDebugger(bool value);
bool useMultiProcess() const; bool useMultiProcess() const;
void setUseMultiProcess(bool on); void setUseMultiProcess(bool on);
@@ -33,6 +34,7 @@ public:
{ {
bool useCppDebugger; bool useCppDebugger;
bool useQmlDebugger; bool useQmlDebugger;
bool usePythonDebugger;
bool useMultiProcess; bool useMultiProcess;
QString overrideStartup; QString overrideStartup;
}; };
@@ -40,6 +42,7 @@ public:
private: private:
Utils::TriStateAspect *m_cppAspect; Utils::TriStateAspect *m_cppAspect;
Utils::TriStateAspect *m_qmlAspect; Utils::TriStateAspect *m_qmlAspect;
Utils::TriStateAspect *m_pythonAspect;
Utils::BoolAspect *m_multiProcessAspect; Utils::BoolAspect *m_multiProcessAspect;
Utils::StringAspect *m_overrideStartupAspect; Utils::StringAspect *m_overrideStartupAspect;
ProjectExplorer::Target *m_target; ProjectExplorer::Target *m_target;

View File

@@ -481,31 +481,27 @@ void DebuggerRunTool::start()
runControl()->setDisplayName(m_runParameters.displayName); runControl()->setDisplayName(m_runParameters.displayName);
if (!m_engine) if (auto dapEngine = createDapEngine(runControl()->runMode()))
m_engine = createDapEngine(runControl()->runMode()); m_engines << dapEngine;
if (!m_engine) { if (m_engines.isEmpty()) {
if (m_runParameters.isCppDebugging()) { if (m_runParameters.isCppDebugging()) {
switch (m_runParameters.cppEngineType) { switch (m_runParameters.cppEngineType) {
case GdbEngineType: case GdbEngineType:
m_engine = createGdbEngine(); m_engines << createGdbEngine();
break; break;
case CdbEngineType: case CdbEngineType:
if (!HostOsInfo::isWindowsHost()) { if (!HostOsInfo::isWindowsHost()) {
reportFailure(Tr::tr("Unsupported CDB host system.")); reportFailure(Tr::tr("Unsupported CDB host system."));
return; return;
} }
m_engine = createCdbEngine(); m_engines << createCdbEngine();
break; break;
case LldbEngineType: case LldbEngineType:
m_engine = createLldbEngine(); m_engines << createLldbEngine();
break;
case PdbEngineType: // FIXME: Yes, Python counts as C++...
QTC_CHECK(false); // Called from DebuggerRunTool constructor already.
// m_engine = createPdbEngine();
break; break;
case UvscEngineType: case UvscEngineType:
m_engine = createUvscEngine(); m_engines << createUvscEngine();
break; break;
default: default:
if (!m_runParameters.isQmlDebugging) { if (!m_runParameters.isQmlDebugging) {
@@ -518,16 +514,14 @@ void DebuggerRunTool::start()
} }
} }
if (m_runParameters.isQmlDebugging) { if (m_runParameters.isPythonDebugging)
if (m_engine) { m_engines << createPdbEngine();
m_engine2 = createQmlEngine();
} else { if (m_runParameters.isQmlDebugging)
m_engine = createQmlEngine(); m_engines << createQmlEngine();
}
}
} }
if (!m_engine) { if (m_engines.isEmpty()) {
QString msg = noEngineMessage(); QString msg = noEngineMessage();
if (!DebuggerKitAspect::debugger(runControl()->kit())) if (!DebuggerKitAspect::debugger(runControl()->kit()))
msg += '\n' + noDebuggerInKitMessage(); msg += '\n' + noDebuggerInKitMessage();
@@ -535,55 +529,59 @@ void DebuggerRunTool::start()
return; return;
} }
m_engine->setRunParameters(m_runParameters); if (auto interpreterAspect = runControl()->aspect<FilePathAspect>()) {
m_engine->setRunId(d->runId); if (auto mainScriptAspect = runControl()->aspect<MainScriptAspect>()) {
m_engine->setRunTool(this); const FilePath mainScript = mainScriptAspect->filePath;
m_engine->setCompanionEngine(m_engine2); const FilePath interpreter = interpreterAspect->filePath;
auto rc = runControl(); if (!interpreter.isEmpty() && mainScript.endsWith(".py")) {
connect(m_engine, &DebuggerEngine::requestRunControlFinish, rc, [rc] { m_runParameters.mainScript = mainScript;
rc->setAutoDeleteOnStop(true); m_runParameters.interpreter = interpreter;
rc->initiateStop(); if (auto args = runControl()->aspect<ArgumentsAspect>())
}, Qt::QueuedConnection); m_runParameters.inferior.command.addArgs(args->arguments, CommandLine::Raw);
connect(m_engine, &DebuggerEngine::requestRunControlStop, rc, &RunControl::initiateStop); }
connect(m_engine, &DebuggerEngine::engineStarted, }
this, [this] { handleEngineStarted(m_engine); }); }
connect(m_engine, &DebuggerEngine::engineFinished,
this, [this] { handleEngineFinished(m_engine); });
connect(m_engine, &DebuggerEngine::appendMessageRequested,
this, &DebuggerRunTool::appendMessage);
++d->engineStartsNeeded;
++d->engineStopsNeeded;
connect(m_engine, &DebuggerEngine::attachToCoreRequested, this, [this](const QString &coreFile) { bool first = true;
auto rc = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE); for (auto engine : m_engines) {
rc->copyDataFromRunControl(runControl()); engine->setRunParameters(m_runParameters);
auto name = QString(Tr::tr("%1 - Snapshot %2").arg(runControl()->displayName()).arg(++d->snapshotCounter)); engine->setRunId(d->runId);
auto debugger = new DebuggerRunTool(rc); engine->setRunTool(this);
debugger->setStartMode(AttachToCore); for (auto companion : m_engines) {
debugger->setRunControlName(name); if (companion != engine)
debugger->setCoreFilePath(FilePath::fromString(coreFile), true); engine->addCompanionEngine(companion);
debugger->startRunControl(); }
}); if (!first)
engine->setSecondaryEngine();
if (m_engine2) { auto rc = runControl();
m_engine2->setRunParameters(m_runParameters); connect(engine, &DebuggerEngine::requestRunControlFinish, rc, [rc] {
m_engine2->setRunId(d->runId); rc->setAutoDeleteOnStop(true);
m_engine2->setRunTool(this); rc->initiateStop();
m_engine2->setCompanionEngine(m_engine); }, Qt::QueuedConnection);
m_engine2->setSecondaryEngine(); connect(engine, &DebuggerEngine::requestRunControlStop, rc, &RunControl::initiateStop);
connect(m_engine2, &DebuggerEngine::requestRunControlFinish, rc, [rc] { connect(engine, &DebuggerEngine::engineStarted,
rc->setAutoDeleteOnStop(true); this, [this, engine] { handleEngineStarted(engine); });
rc->initiateStop(); connect(engine, &DebuggerEngine::engineFinished,
}, Qt::QueuedConnection); this, [this, engine] { handleEngineFinished(engine); });
connect(m_engine2, &DebuggerEngine::requestRunControlStop, rc, &RunControl::initiateStop); connect(engine, &DebuggerEngine::appendMessageRequested,
connect(m_engine2, &DebuggerEngine::engineStarted,
this, [this] { handleEngineStarted(m_engine2); });
connect(m_engine2, &DebuggerEngine::engineFinished,
this, [this] { handleEngineFinished(m_engine2); });
connect(m_engine2, &DebuggerEngine::appendMessageRequested,
this, &DebuggerRunTool::appendMessage); this, &DebuggerRunTool::appendMessage);
++d->engineStartsNeeded; ++d->engineStartsNeeded;
++d->engineStopsNeeded; ++d->engineStopsNeeded;
if (first) {
connect(engine, &DebuggerEngine::attachToCoreRequested, this, [this](const QString &coreFile) {
auto rc = new RunControl(ProjectExplorer::Constants::DEBUG_RUN_MODE);
rc->copyDataFromRunControl(runControl());
auto name = QString(Tr::tr("%1 - Snapshot %2").arg(runControl()->displayName()).arg(++d->snapshotCounter));
auto debugger = new DebuggerRunTool(rc);
debugger->setStartMode(AttachToCore);
debugger->setRunControlName(name);
debugger->setCoreFilePath(FilePath::fromString(coreFile), true);
debugger->startRunControl();
});
first = false;
}
} }
if (m_runParameters.startMode != AttachToCore) { if (m_runParameters.startMode != AttachToCore) {
@@ -593,10 +591,11 @@ void DebuggerRunTool::start()
if (gbp->isEnabled()) { if (gbp->isEnabled()) {
const BreakpointParameters &bp = gbp->requestedParameters(); const BreakpointParameters &bp = gbp->requestedParameters();
hasQmlBreakpoints = hasQmlBreakpoints || bp.isQmlFileAndLineBreakpoint(); hasQmlBreakpoints = hasQmlBreakpoints || bp.isQmlFileAndLineBreakpoint();
if (!m_engine->acceptsBreakpoint(bp)) { auto engineAcceptsBp = [bp](const DebuggerEngine *engine) {
if (!m_engine2 || !m_engine2->acceptsBreakpoint(bp)) return engine->acceptsBreakpoint(bp);
unhandledIds.append(gbp->displayName()); };
} if (!Utils::anyOf(m_engines, engineAcceptsBp))
unhandledIds.append(gbp->displayName());
} }
} }
if (!unhandledIds.isEmpty()) { if (!unhandledIds.isEmpty()) {
@@ -624,28 +623,22 @@ void DebuggerRunTool::start()
appendMessage(Tr::tr("Debugging %1 ...").arg(m_runParameters.inferior.command.toUserOutput()), appendMessage(Tr::tr("Debugging %1 ...").arg(m_runParameters.inferior.command.toUserOutput()),
NormalMessageFormat); NormalMessageFormat);
QString debuggerName = m_engine->objectName(); const QString debuggerName = Utils::transform<QStringList>(m_engines, &DebuggerEngine::objectName).join(" ");
if (m_engine2)
debuggerName += ' ' + m_engine2->objectName();
const QString message = Tr::tr("Starting debugger \"%1\" for ABI \"%2\"...") const QString message = Tr::tr("Starting debugger \"%1\" for ABI \"%2\"...")
.arg(debuggerName).arg(m_runParameters.toolChainAbi.toString()); .arg(debuggerName).arg(m_runParameters.toolChainAbi.toString());
DebuggerMainWindow::showStatusMessage(message, 10000); DebuggerMainWindow::showStatusMessage(message, 10000);
showMessage(m_engine->formatStartParameters(), LogDebug); showMessage(m_engines.first()->formatStartParameters(), LogDebug);
showMessage(DebuggerSettings::dump(), LogDebug); showMessage(DebuggerSettings::dump(), LogDebug);
if (m_engine2) Utils::reverseForeach(m_engines, [](DebuggerEngine *engine) { engine->start(); });
m_engine2->start();
m_engine->start();
} }
void DebuggerRunTool::stop() void DebuggerRunTool::stop()
{ {
QTC_ASSERT(m_engine, reportStopped(); return); QTC_ASSERT(!m_engines.isEmpty(), reportStopped(); return);
if (m_engine2) Utils::reverseForeach(m_engines, [](DebuggerEngine *engine) { engine->quitDebugger(); });
m_engine2->quitDebugger();
m_engine->quitDebugger();
} }
void DebuggerRunTool::handleEngineStarted(DebuggerEngine *engine) void DebuggerRunTool::handleEngineStarted(DebuggerEngine *engine)
@@ -657,7 +650,7 @@ void DebuggerRunTool::handleEngineStarted(DebuggerEngine *engine)
// } // }
// Feels better, as the QML Engine might attach late or not at all. // Feels better, as the QML Engine might attach late or not at all.
if (engine == m_engine) { if (engine == m_engines.first()) {
EngineManager::activateDebugMode(); EngineManager::activateDebugMode();
reportStarted(); reportStarted();
} }
@@ -865,6 +858,7 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm
if (!aspect->useCppDebugger) if (!aspect->useCppDebugger)
m_runParameters.cppEngineType = NoEngineType; m_runParameters.cppEngineType = NoEngineType;
m_runParameters.isQmlDebugging = aspect->useQmlDebugger; m_runParameters.isQmlDebugging = aspect->useQmlDebugger;
m_runParameters.isPythonDebugging = aspect->usePythonDebugger;
m_runParameters.multiProcess = aspect->useMultiProcess; m_runParameters.multiProcess = aspect->useMultiProcess;
m_runParameters.additionalStartupCommands = aspect->overrideStartup; m_runParameters.additionalStartupCommands = aspect->overrideStartup;
@@ -907,22 +901,6 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, AllowTerminal allowTerm
if (ok) if (ok)
m_runParameters.nativeMixedEnabled = bool(nativeMixedOverride); m_runParameters.nativeMixedEnabled = bool(nativeMixedOverride);
if (auto interpreterAspect = runControl->aspect<FilePathAspect>()) {
if (auto mainScriptAspect = runControl->aspect<MainScriptAspect>()) {
const FilePath mainScript = mainScriptAspect->filePath;
const FilePath interpreter = interpreterAspect->filePath;
if (!interpreter.isEmpty() && mainScript.endsWith(".py")) {
m_runParameters.mainScript = mainScript;
m_runParameters.interpreter = interpreter;
if (auto args = runControl->aspect<ArgumentsAspect>())
m_runParameters.inferior.command.addArgs(args->arguments, CommandLine::Raw);
if (runControl->runMode() == ProjectExplorer::Constants::DEBUG_RUN_MODE)
m_engine = createPdbEngine();
}
}
}
if (QtSupport::QtVersion *baseQtVersion = QtSupport::QtKitAspect::qtVersion(kit)) { if (QtSupport::QtVersion *baseQtVersion = QtSupport::QtKitAspect::qtVersion(kit)) {
const QVersionNumber qtVersion = baseQtVersion->qtVersion(); const QVersionNumber qtVersion = baseQtVersion->qtVersion();
m_runParameters.fallbackQtVersion = 0x10000 * qtVersion.majorVersion() m_runParameters.fallbackQtVersion = 0x10000 * qtVersion.majorVersion()
@@ -948,10 +926,8 @@ DebuggerRunTool::~DebuggerRunTool()
if (m_runParameters.isSnapshot && !m_runParameters.coreFile.isEmpty()) if (m_runParameters.isSnapshot && !m_runParameters.coreFile.isEmpty())
m_runParameters.coreFile.removeFile(); m_runParameters.coreFile.removeFile();
delete m_engine2; qDeleteAll(m_engines);
m_engine2 = nullptr; m_engines.clear();
delete m_engine;
m_engine = nullptr;
delete d; delete d;
} }
@@ -961,11 +937,10 @@ void DebuggerRunTool::showMessage(const QString &msg, int channel, int timeout)
if (channel == ConsoleOutput) if (channel == ConsoleOutput)
debuggerConsole()->printItem(ConsoleItem::DefaultType, msg); debuggerConsole()->printItem(ConsoleItem::DefaultType, msg);
QTC_ASSERT(m_engine, qDebug() << msg; return); QTC_ASSERT(!m_engines.isEmpty(), qDebug() << msg; return);
m_engine->showMessage(msg, channel, timeout); for (auto engine : m_engines)
if (m_engine2) engine->showMessage(msg, channel, timeout);
m_engine->showMessage(msg, channel, timeout);
switch (channel) { switch (channel) {
case AppOutput: case AppOutput:
appendMessage(msg, StdOutFormat); appendMessage(msg, StdOutFormat);

View File

@@ -115,8 +115,7 @@ private:
void handleEngineFinished(Internal::DebuggerEngine *engine); void handleEngineFinished(Internal::DebuggerEngine *engine);
Internal::DebuggerRunToolPrivate *d; Internal::DebuggerRunToolPrivate *d;
QPointer<Internal::DebuggerEngine> m_engine; QList<QPointer<Internal::DebuggerEngine>> m_engines;
QPointer<Internal::DebuggerEngine> m_engine2;
Internal::DebuggerRunParameters m_runParameters; Internal::DebuggerRunParameters m_runParameters;
}; };

View File

@@ -405,7 +405,9 @@ void QmlEngine::appStartupFailed(const QString &errorMessage)
{ {
QString error = Tr::tr("Could not connect to the in-process QML debugger. %1").arg(errorMessage); QString error = Tr::tr("Could not connect to the in-process QML debugger. %1").arg(errorMessage);
if (companionEngine()) { if (companionEngines().isEmpty()) {
debuggerConsole()->printItem(ConsoleItem::WarningType, error);
} else {
auto infoBox = new QMessageBox(ICore::dialogParent()); auto infoBox = new QMessageBox(ICore::dialogParent());
infoBox->setIcon(QMessageBox::Critical); infoBox->setIcon(QMessageBox::Critical);
infoBox->setWindowTitle(QGuiApplication::applicationDisplayName()); infoBox->setWindowTitle(QGuiApplication::applicationDisplayName());
@@ -415,8 +417,6 @@ void QmlEngine::appStartupFailed(const QString &errorMessage)
connect(infoBox, &QDialog::finished, connect(infoBox, &QDialog::finished,
this, &QmlEngine::errorMessageBoxFinished); this, &QmlEngine::errorMessageBoxFinished);
infoBox->show(); infoBox->show();
} else {
debuggerConsole()->printItem(ConsoleItem::WarningType, error);
} }
notifyEngineRunFailed(); notifyEngineRunFailed();
@@ -1029,7 +1029,7 @@ bool QmlEngine::companionPreventsActions() const
{ {
// We need a C++ Engine in a Running state to do anything sensible // We need a C++ Engine in a Running state to do anything sensible
// as otherwise the debugger services in the debuggee are unresponsive. // as otherwise the debugger services in the debuggee are unresponsive.
if (DebuggerEngine *companion = companionEngine()) if (DebuggerEngine *companion = companionEngines().value(0))
return companion->state() != InferiorRunOk; return companion->state() != InferiorRunOk;
return false; return false;

View File

@@ -13,6 +13,7 @@
#include <coreplugin/messagemanager.h> #include <coreplugin/messagemanager.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <qmljs/qmljsmodelmanagerinterface.h> #include <qmljs/qmljsmodelmanagerinterface.h>
@@ -186,10 +187,14 @@ void PythonBuildSystem::triggerParsing()
newRoot->addNestedNode( newRoot->addNestedNode(
std::make_unique<PythonFileNode>(projectFile, displayName, FileType::Project)); std::make_unique<PythonFileNode>(projectFile, displayName, FileType::Project));
bool hasQmlFiles = false;
for (const FileEntry &entry : std::as_const(m_files)) { for (const FileEntry &entry : std::as_const(m_files)) {
const QString displayName = entry.filePath.relativePathFrom(projectDirectory()).toUserOutput(); const QString displayName = entry.filePath.relativePathFrom(projectDirectory()).toUserOutput();
const FileType fileType = getFileType(entry.filePath); const FileType fileType = getFileType(entry.filePath);
hasQmlFiles |= fileType == FileType::QML;
newRoot->addNestedNode(std::make_unique<PythonFileNode>(entry.filePath, displayName, fileType)); newRoot->addNestedNode(std::make_unique<PythonFileNode>(entry.filePath, displayName, fileType));
const MimeType mt = mimeTypeForFile(entry.filePath, MimeMatchMode::MatchExtension); const MimeType mt = mimeTypeForFile(entry.filePath, MimeMatchMode::MatchExtension);
if (mt.matchesName(Constants::C_PY_MIMETYPE) || mt.matchesName(Constants::C_PY3_MIMETYPE) if (mt.matchesName(Constants::C_PY_MIMETYPE) || mt.matchesName(Constants::C_PY3_MIMETYPE)
@@ -204,6 +209,8 @@ void PythonBuildSystem::triggerParsing()
appTargets.append(bti); appTargets.append(bti);
} }
} }
project()->setProjectLanguage(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID, hasQmlFiles);
setRootProjectNode(std::move(newRoot)); setRootProjectNode(std::move(newRoot));
setApplicationTargets(appTargets); setApplicationTargets(appTargets);