forked from qt-creator/qt-creator
Debugger: Introduce a "Native Mixed" switch
This paves the the way to mixed QML/C++ debugging through the native backends. Currently this requires QTC_DEBUGGER_NATIVE_MIXED to be set in the environment. Change-Id: I126ad945e84806f3b548408318007351628c912f Reviewed-by: Leena Miettinen <riitta-leena.miettinen@theqtcompany.com> Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
#include "registerpostmortemaction.h"
|
||||
#endif
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <utils/savedaction.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -183,6 +184,18 @@ DebuggerSettings::DebuggerSettings()
|
||||
item->setIconVisibleInMenu(false);
|
||||
insertItem(OperateByInstruction, item);
|
||||
|
||||
item = new SavedAction(this);
|
||||
item->setText(tr("Native Mixed Mode"));
|
||||
item->setCheckable(true);
|
||||
item->setDefaultValue(true);
|
||||
item->setIcon(QIcon(QLatin1String(Core::Constants::ICON_LINK)));
|
||||
item->setToolTip(tr("This switches the debugger to native-mixed "
|
||||
"operation mode. In this mode, stepping and data display will "
|
||||
"be handled by the native debugger backend (GDB, LLDB or CDB) "
|
||||
"for C++, QML and JS sources."));
|
||||
item->setIconVisibleInMenu(false);
|
||||
insertItem(OperateNativeMixed, item);
|
||||
|
||||
item = new SavedAction(this);
|
||||
item->setText(tr("Dereference Pointers Automatically"));
|
||||
item->setCheckable(true);
|
||||
|
||||
@@ -99,6 +99,7 @@ enum DebuggerActionCode
|
||||
LogTimeStamps,
|
||||
VerboseLog,
|
||||
OperateByInstruction,
|
||||
OperateNativeMixed,
|
||||
CloseSourceBuffersOnExit,
|
||||
CloseMemoryBuffersOnExit,
|
||||
SwitchModeOnExit,
|
||||
|
||||
@@ -61,6 +61,7 @@ const char NEXT[] = "Debugger.NextLine";
|
||||
const char REVERSE[] = "Debugger.ReverseDirection";
|
||||
const char RESET[] = "Debugger.Reset";
|
||||
const char OPERATE_BY_INSTRUCTION[] = "Debugger.OperateByInstruction";
|
||||
const char OPERATE_NATIVE_MIXED[] = "Debugger.OperateNativeMixed";
|
||||
const char QML_SHOW_APP_ON_TOP[] = "Debugger.QmlShowAppOnTop";
|
||||
const char QML_UPDATE_ON_SAVE[] = "Debugger.QmlUpdateOnSave";
|
||||
const char QML_SELECTTOOL[] = "Debugger.QmlSelectTool";
|
||||
@@ -163,7 +164,8 @@ enum DebuggerCapabilities
|
||||
ShowModuleSectionsCapability = 0x200000,
|
||||
WatchComplexExpressionsCapability = 0x400000, // Used to filter out challenges for cdb.
|
||||
AdditionalQmlStackCapability = 0x800000, // C++ debugger engine is able to retrieve QML stack as well.
|
||||
ResetInferiorCapability = 0x1000000 //!< restart program while debugging
|
||||
ResetInferiorCapability = 0x1000000, //!< restart program while debugging
|
||||
NativeMixedCapability = 0x2000000
|
||||
};
|
||||
|
||||
enum LogChannel
|
||||
|
||||
@@ -112,6 +112,9 @@ DebuggerEngine *currentEngine();
|
||||
QMessageBox *showMessageBox(int icon, const QString &title,
|
||||
const QString &text, int buttons = 0);
|
||||
|
||||
bool isNativeMixedActive();
|
||||
bool isNativeMixedEnabled();
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
|
||||
@@ -496,6 +496,7 @@ bool DummyEngine::hasCapability(unsigned cap) const
|
||||
return cap & (WatchpointByAddressCapability
|
||||
| BreakConditionCapability
|
||||
| TracePointCapability
|
||||
| OperateNativeMixed
|
||||
| OperateByInstructionCapability);
|
||||
|
||||
// This is a Qml or unknown engine.
|
||||
@@ -2071,7 +2072,6 @@ void DebuggerPluginPrivate::setInitialState()
|
||||
|
||||
action(AutoDerefPointers)->setEnabled(true);
|
||||
action(ExpandStack)->setEnabled(false);
|
||||
|
||||
}
|
||||
|
||||
void DebuggerPluginPrivate::updateWatchersWindow(bool showWatch, bool showReturn)
|
||||
@@ -2528,6 +2528,17 @@ QMessageBox *showMessageBox(int icon, const QString &title,
|
||||
return mb;
|
||||
}
|
||||
|
||||
bool isNativeMixedEnabled()
|
||||
{
|
||||
static bool enabled = qEnvironmentVariableIsSet("QTC_DEBUGGER_NATIVE_MIXED");
|
||||
return enabled;
|
||||
}
|
||||
|
||||
bool isNativeMixedActive()
|
||||
{
|
||||
return isNativeMixedEnabled() && boolSetting(OperateNativeMixed);
|
||||
}
|
||||
|
||||
void DebuggerPluginPrivate::extensionsInitialized()
|
||||
{
|
||||
const QKeySequence debugKey = QKeySequence(UseMacShortcuts ? tr("Ctrl+Y") : tr("F5"));
|
||||
@@ -2966,6 +2977,17 @@ void DebuggerPluginPrivate::extensionsInitialized()
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
debugMenu->addAction(cmd);
|
||||
|
||||
if (isNativeMixedEnabled()) {
|
||||
SavedAction *act = action(OperateNativeMixed);
|
||||
act->setValue(true);
|
||||
cmd = ActionManager::registerAction(act,
|
||||
Constants::OPERATE_NATIVE_MIXED, globalcontext);
|
||||
cmd->setAttribute(Command::CA_Hide);
|
||||
debugMenu->addAction(cmd);
|
||||
connect(cmd->action(), &QAction::triggered,
|
||||
[this] { currentEngine()->updateAll(); });
|
||||
}
|
||||
|
||||
cmd = ActionManager::registerAction(m_breakAction,
|
||||
"Debugger.ToggleBreak", globalcontext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("F8") : tr("F9")));
|
||||
@@ -3114,6 +3136,8 @@ void DebuggerPluginPrivate::extensionsInitialized()
|
||||
hbox->addWidget(toolButton(Constants::STEPOUT));
|
||||
hbox->addWidget(toolButton(Constants::RESET));
|
||||
hbox->addWidget(toolButton(Constants::OPERATE_BY_INSTRUCTION));
|
||||
if (isNativeMixedEnabled())
|
||||
hbox->addWidget(toolButton(Constants::OPERATE_NATIVE_MIXED));
|
||||
|
||||
//hbox->addWidget(new StyledSeparator);
|
||||
m_reverseToolButton = toolButton(Constants::REVERSE);
|
||||
|
||||
@@ -2040,6 +2040,7 @@ bool GdbEngine::hasCapability(unsigned cap) const
|
||||
| WatchComplexExpressionsCapability
|
||||
| MemoryAddressCapability
|
||||
| AdditionalQmlStackCapability
|
||||
| NativeMixedCapability
|
||||
| ResetInferiorCapability))
|
||||
return true;
|
||||
|
||||
@@ -2759,8 +2760,12 @@ bool GdbEngine::stateAcceptsBreakpointChanges() const
|
||||
|
||||
bool GdbEngine::acceptsBreakpoint(BreakpointModelId id) const
|
||||
{
|
||||
return breakHandler()->breakpointData(id).isCppBreakpoint()
|
||||
&& startParameters().startMode != AttachCore;
|
||||
if (startParameters().startMode == AttachCore)
|
||||
return false;
|
||||
// We handle QML breakpoint unless specifically
|
||||
if (isNativeMixedEnabled() && !(startParameters().languages & QmlLanguage))
|
||||
return true;
|
||||
return breakHandler()->breakpointData(id).isCppBreakpoint();
|
||||
}
|
||||
|
||||
void GdbEngine::insertBreakpoint(BreakpointModelId id)
|
||||
@@ -2770,6 +2775,15 @@ void GdbEngine::insertBreakpoint(BreakpointModelId id)
|
||||
BreakHandler *handler = breakHandler();
|
||||
QTC_CHECK(handler->state(id) == BreakpointInsertRequested);
|
||||
handler->notifyBreakpointInsertProceeding(id);
|
||||
|
||||
if (!handler->breakpointData(id).isCppBreakpoint()) {
|
||||
const BreakpointParameters &data = handler->breakpointData(id);
|
||||
postCommand("insertQmlBreakpoint " + data.fileName.toUtf8() + ' '
|
||||
+ QByteArray::number(data.lineNumber));
|
||||
handler->notifyBreakpointInsertOk(id);
|
||||
return;
|
||||
}
|
||||
|
||||
BreakpointType type = handler->type(id);
|
||||
QVariant vid = QVariant::fromValue(id);
|
||||
if (type == WatchpointAtAddress) {
|
||||
|
||||
@@ -64,8 +64,12 @@ StackHandler::StackHandler()
|
||||
m_contentsValid = false;
|
||||
m_currentIndex = -1;
|
||||
m_canExpand = false;
|
||||
connect(action(OperateByInstruction), SIGNAL(triggered()),
|
||||
this, SLOT(resetModel()));
|
||||
connect(action(OperateByInstruction), &QAction::triggered,
|
||||
this, &StackHandler::resetModel);
|
||||
|
||||
if (isNativeMixedEnabled())
|
||||
connect(action(OperateNativeMixed), &QAction::triggered,
|
||||
this, &StackHandler::resetModel);
|
||||
}
|
||||
|
||||
StackHandler::~StackHandler()
|
||||
|
||||
Reference in New Issue
Block a user