From 496e9fafd0a321a923e96bdddd03617feb18f2ad Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Thu, 12 Jan 2012 20:28:17 +0100
Subject: [PATCH] debugger: replace static capability check by something
 potentially dynamic

This does not yet use the potential.

Change-Id: I087311fb7d59b46e49f65a84c4420c72a1227ebb
Reviewed-by: Aurindam Jana <aurindam.jana@nokia.com>
---
 src/plugins/debugger/breakhandler.cpp         |  6 ---
 src/plugins/debugger/breakwindow.cpp          | 40 +++++++++----------
 src/plugins/debugger/debuggerconstants.h      |  3 +-
 src/plugins/debugger/debuggerengine.cpp       |  8 +---
 src/plugins/debugger/debuggerengine.h         |  2 +-
 .../debugger/debuggerinternalconstants.h      |  1 -
 src/plugins/debugger/debuggerplugin.cpp       | 27 ++++++-------
 src/plugins/debugger/gdb/gdbengine.cpp        | 13 +++---
 src/plugins/debugger/gdb/gdbengine.h          |  2 +-
 src/plugins/debugger/lldb/ipcenginehost.h     |  1 +
 src/plugins/debugger/moduleswindow.cpp        | 21 ++++------
 src/plugins/debugger/pdb/pdbengine.cpp        |  4 +-
 src/plugins/debugger/pdb/pdbengine.h          |  2 +-
 src/plugins/debugger/qml/qmlcppengine.cpp     | 16 ++++----
 src/plugins/debugger/qml/qmlcppengine.h       |  2 +-
 src/plugins/debugger/qml/qmlengine.cpp        |  6 +--
 src/plugins/debugger/qml/qmlengine.h          |  2 +-
 src/plugins/debugger/registerwindow.cpp       |  9 ++---
 src/plugins/debugger/script/scriptengine.h    |  2 +-
 src/plugins/debugger/snapshothandler.cpp      |  2 +-
 src/plugins/debugger/stackwindow.cpp          | 13 +++---
 src/plugins/debugger/watchhandler.cpp         |  2 +-
 src/plugins/debugger/watchwindow.cpp          | 13 +++---
 23 files changed, 86 insertions(+), 111 deletions(-)

diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index 2149de4469a..d7ebf6f10f3 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -683,12 +683,6 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
         if (debuggerCore()->boolSetting(UseToolTipsInBreakpointsView))
                 return QVariant(it->toToolTip());
         break;
-    case EngineCapabilitiesRole:  {
-        const unsigned caps = it.value().engine ?
-                              it.value().engine->debuggerCapabilities() :
-                              unsigned(AllDebuggerCapabilities);
-        return QVariant(caps);
-    }
     }
     return QVariant();
 }
diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp
index c4618a94c01..9f57b876b83 100644
--- a/src/plugins/debugger/breakwindow.cpp
+++ b/src/plugins/debugger/breakwindow.cpp
@@ -70,7 +70,7 @@ class BreakpointDialog : public QDialog
 {
     Q_OBJECT
 public:
-    explicit BreakpointDialog(unsigned engineCapabilities, QWidget *parent = 0);
+    explicit BreakpointDialog(BreakpointModelId id, QWidget *parent = 0);
     bool showDialog(BreakpointParameters *data, BreakpointParts *parts);
 
     void setParameters(const BreakpointParameters &data);
@@ -95,18 +95,20 @@ private:
     bool m_firstTypeChange;
 };
 
-BreakpointDialog::BreakpointDialog(unsigned engineCapabilities, QWidget *parent)
+BreakpointDialog::BreakpointDialog(BreakpointModelId id, QWidget *parent)
     : QDialog(parent), m_enabledParts(-1), m_previousType(UnknownType),
       m_firstTypeChange(true)
 {
     m_ui.setupUi(this);
     m_ui.comboBoxType->setMaxVisibleItems(20);
-    if (!(engineCapabilities & BreakConditionCapability))
-        m_enabledParts &= ~ConditionPart;
-    if (!(engineCapabilities & BreakModuleCapability))
-        m_enabledParts &= ~ModulePart;
-    if (!(engineCapabilities & TracePointCapability))
-        m_enabledParts &= ~TracePointPart;
+    if (DebuggerEngine *engine = breakHandler()->engine(id)) {
+        if (!engine->hasCapability(BreakConditionCapability))
+            m_enabledParts &= ~ConditionPart;
+        if (!engine->hasCapability(BreakModuleCapability))
+            m_enabledParts &= ~ModulePart;
+        if (!engine->hasCapability(TracePointCapability))
+            m_enabledParts &= ~TracePointPart;
+    }
     // Match BreakpointType (omitting unknown type).
     QStringList types;
     types << tr("File name and line number")
@@ -123,7 +125,7 @@ BreakpointDialog::BreakpointDialog(unsigned engineCapabilities, QWidget *parent)
           << tr("Break on QML signal handler")
           << tr("Break when JavaScript exception is thrown");
 
-    QTC_ASSERT(types.size() == BreakpointAtJavaScriptThrow, return; )
+    QTC_ASSERT(types.size() == BreakpointAtJavaScriptThrow, return);
     m_ui.comboBoxType->addItems(types);
     m_ui.pathChooserFileName->setExpectedKind(Utils::PathChooser::File);
     connect(m_ui.comboBoxType, SIGNAL(activated(int)), SLOT(typeChanged(int)));
@@ -448,7 +450,7 @@ class MultiBreakPointsDialog : public QDialog
 {
     Q_OBJECT
 public:
-    MultiBreakPointsDialog(unsigned engineCapabilities, QWidget *parent = 0);
+    MultiBreakPointsDialog(QWidget *parent = 0);
 
     QString condition() const { return m_ui.lineEditCondition->text(); }
     int ignoreCount() const { return m_ui.spinBoxIgnoreCount->value(); }
@@ -464,7 +466,7 @@ private:
     Ui::BreakCondition m_ui;
 };
 
-MultiBreakPointsDialog::MultiBreakPointsDialog(unsigned engineCapabilities, QWidget *parent) :
+MultiBreakPointsDialog::MultiBreakPointsDialog(QWidget *parent) :
     QDialog(parent)
 {
     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
@@ -472,7 +474,7 @@ MultiBreakPointsDialog::MultiBreakPointsDialog(unsigned engineCapabilities, QWid
     setWindowTitle(tr("Edit Breakpoint Properties"));
     m_ui.spinBoxIgnoreCount->setMinimum(0);
     m_ui.spinBoxIgnoreCount->setMaximum(2147483647);
-    if (!(engineCapabilities & BreakConditionCapability)) {
+    if (!debuggerCore()->currentEngine()->hasCapability(BreakConditionCapability)) {
         m_ui.labelCondition->setEnabled(false);
         m_ui.lineEditCondition->setEnabled(false);
     }
@@ -624,7 +626,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
     menu.addAction(synchronizeAction);
     menu.addSeparator();
     menu.addAction(debuggerCore()->action(UseToolTipsInBreakpointsView));
-    if (debuggerCore()->currentEngine()->debuggerCapabilities() & MemoryAddressCapability)
+    if (debuggerCore()->currentEngine()->hasCapability(MemoryAddressCapability))
         menu.addAction(debuggerCore()->action(UseAddressInBreakpointsView));
     addBaseContextActions(&menu);
 
@@ -669,11 +671,8 @@ void BreakWindow::deleteBreakpoints(const BreakpointModelIds &ids)
 void BreakWindow::editBreakpoint(BreakpointModelId id, QWidget *parent)
 {
     BreakpointParameters data = breakHandler()->breakpointData(id);
-    unsigned engineCapabilities = AllDebuggerCapabilities;
-    if (const DebuggerEngine *engine = breakHandler()->engine(id))
-        engineCapabilities = engine->debuggerCapabilities();
     BreakpointParts parts = NoParts;
-    BreakpointDialog dialog(engineCapabilities, parent);
+    BreakpointDialog dialog(id, parent);
     if (dialog.showDialog(&data, &parts))
         breakHandler()->changeBreakpointData(id, data, parts);
 }
@@ -682,7 +681,7 @@ void BreakWindow::addBreakpoint()
 {
     BreakpointParameters data(BreakpointByFileAndLine);
     BreakpointParts parts = NoParts;
-    BreakpointDialog dialog(AllDebuggerCapabilities, this);
+    BreakpointDialog dialog(BreakpointModelId(), this);
     dialog.setWindowTitle(tr("Add Breakpoint"));
     if (dialog.showDialog(&data, &parts))
         breakHandler()->appendBreakpoint(data);
@@ -701,10 +700,7 @@ void BreakWindow::editBreakpoints(const BreakpointModelIds &ids)
 
     // This allows to change properties of multiple breakpoints at a time.
     BreakHandler *handler = breakHandler();
-    unsigned engineCapabilities = AllDebuggerCapabilities;
-    if (const DebuggerEngine *engine = breakHandler()->engine(id))
-        engineCapabilities = engine->debuggerCapabilities();
-    MultiBreakPointsDialog dialog(engineCapabilities);
+    MultiBreakPointsDialog dialog;
     const QString oldCondition = QString::fromLatin1(handler->condition(id));
     dialog.setCondition(oldCondition);
     const int oldIgnoreCount = handler->ignoreCount(id);
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index ad1eb9c05d9..29da510015c 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -161,8 +161,7 @@ enum DebuggerCapabilities
     CatchCapability = 0x200000, //!< fork, vfork, syscall
     OperateByInstructionCapability = 0x400000,
     RunToLineCapability = 0x800000,
-    MemoryAddressCapability = 0x1000000,
-    AllDebuggerCapabilities = 0xFFFFFFFF
+    MemoryAddressCapability = 0x1000000
 };
 
 enum LogChannel
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index 1b2f7b27ca0..c0b5f16a890 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -547,9 +547,8 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
     if (!d->m_startParameters.environment.size())
         d->m_startParameters.environment = Utils::Environment();
 
-    const unsigned engineCapabilities = debuggerCapabilities();
     debuggerCore()->action(OperateByInstruction)
-        ->setEnabled(engineCapabilities & DisassemblerCapability);
+        ->setEnabled(hasCapability(DisassemblerCapability));
 
     QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
          qDebug() << state());
@@ -1346,11 +1345,6 @@ void DebuggerEngine::addOptionPages(QList<Core::IOptionsPage*> *) const
 {
 }
 
-unsigned DebuggerEngine::debuggerCapabilities() const
-{
-    return 0;
-}
-
 bool DebuggerEngine::isSynchronous() const
 {
     return false;
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index 25e4625f595..c0ddae4890c 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -193,7 +193,7 @@ public:
 
     virtual void setRegisterValue(int regnr, const QString &value);
     virtual void addOptionPages(QList<Core::IOptionsPage*> *) const;
-    virtual unsigned debuggerCapabilities() const;
+    virtual bool hasCapability(unsigned cap) const = 0;
 
     virtual bool isSynchronous() const;
     virtual QByteArray qtNamespace() const;
diff --git a/src/plugins/debugger/debuggerinternalconstants.h b/src/plugins/debugger/debuggerinternalconstants.h
index 0ef3b93193c..0d569e4f917 100644
--- a/src/plugins/debugger/debuggerinternalconstants.h
+++ b/src/plugins/debugger/debuggerinternalconstants.h
@@ -67,7 +67,6 @@ enum ModelRoles
     DisplaySourceRole = 32,  // Qt::UserRole
 
     EngineStateRole,
-    EngineCapabilitiesRole,
     EngineActionsEnabledRole,
     RequestActivationRole,
     RequestContextMenuRole,
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index c799e09f6e2..45aef0b5a0d 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -483,12 +483,12 @@ public:
     void runEngine() {}
     void shutdownEngine() {}
     void shutdownInferior() {}
-    unsigned debuggerCapabilities() const;
+    bool hasCapability(unsigned cap) const;
     bool acceptsBreakpoint(BreakpointModelId) const { return false; }
     bool acceptsDebuggerCommands() const { return false; }
 };
 
-unsigned DummyEngine::debuggerCapabilities() const
+bool DummyEngine::hasCapability(unsigned cap) const
 {
     // This can only be a first approximation of what to expect when running.
     Project *project = ProjectExplorerPlugin::instance()->currentProject();
@@ -501,13 +501,13 @@ unsigned DummyEngine::debuggerCapabilities() const
 
     // This is a non-started Cdb or Gdb engine:
     if (activeRc->useCppDebugger())
-        return WatchpointByAddressCapability
+        return cap & (WatchpointByAddressCapability
                | BreakConditionCapability
                | TracePointCapability
-               | OperateByInstructionCapability;
+               | OperateByInstructionCapability);
 
     // This is a Qml or unknown engine.
-    return AddWatcherCapability;
+    return cap & AddWatcherCapability;
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -1955,7 +1955,7 @@ void DebuggerPluginPrivate::requestContextMenu(ITextEditor *editor,
     // Run to, jump to line below in stopped state.
     if (currentEngine()->state() == InferiorStopOk && contextUsable) {
         menu->addSeparator();
-        if (currentEngine()->debuggerCapabilities() & RunToLineCapability) {
+        if (currentEngine()->hasCapability(RunToLineCapability)) {
             const QString runText = args.address
                 ? DebuggerEngine::tr("Run to Address 0x%1").arg(args.address, 0, 16)
                 : DebuggerEngine::tr("Run to Line %1").arg(args.lineNumber);
@@ -1964,7 +1964,7 @@ void DebuggerPluginPrivate::requestContextMenu(ITextEditor *editor,
             connect(runToLineAction, SIGNAL(triggered()), SLOT(slotRunToLine()));
             menu->addAction(runToLineAction);
         }
-        if (currentEngine()->debuggerCapabilities() & JumpToLineCapability) {
+        if (currentEngine()->hasCapability(JumpToLineCapability)) {
             const QString jumpText = args.address
                 ? DebuggerEngine::tr("Jump to Address 0x%1").arg(args.address, 0, 16)
                 : DebuggerEngine::tr("Jump to Line %1").arg(args.lineNumber);
@@ -2326,8 +2326,7 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
     if (stopped)
         QApplication::alert(mainWindow(), 3000);
 
-    const uint caps = engine->debuggerCapabilities();
-    const bool canReverse = (caps & ReverseSteppingCapability)
+    const bool canReverse = engine->hasCapability(ReverseSteppingCapability)
                 && boolSetting(EnableReverseDebugging);
     m_reverseDirectionAction->setEnabled(canReverse);
 
@@ -2335,7 +2334,7 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
     m_watchAction2->setEnabled(true);
     m_breakAction->setEnabled(true);
 
-    const bool canOperateByInstruction = (caps & OperateByInstructionCapability)
+    const bool canOperateByInstruction = engine->hasCapability(OperateByInstructionCapability)
             && (stopped || isCore);
     action(OperateByInstruction)->setEnabled(canOperateByInstruction);
 
@@ -2348,15 +2347,15 @@ void DebuggerPluginPrivate::updateState(DebuggerEngine *engine)
     m_nextAction->setToolTip(QString());
 
     m_stepOutAction->setEnabled(stopped);
-    m_runToLineAction->setEnabled(stopped && (caps & RunToLineCapability));
+    m_runToLineAction->setEnabled(stopped && engine->hasCapability(RunToLineCapability));
     m_runToSelectedFunctionAction->setEnabled(stopped);
     m_returnFromFunctionAction->
-        setEnabled(stopped && (caps & ReturnFromFunctionCapability));
+        setEnabled(stopped && engine->hasCapability(ReturnFromFunctionCapability));
 
-    const bool canJump = stopped && (caps & JumpToLineCapability);
+    const bool canJump = stopped && engine->hasCapability(JumpToLineCapability);
     m_jumpToLineAction->setEnabled(canJump);
 
-    const bool canDeref = actionsEnabled && (caps & AutoDerefPointersCapability);
+    const bool canDeref = actionsEnabled && engine->hasCapability(AutoDerefPointersCapability);
     action(AutoDerefPointers)->setEnabled(canDeref);
     action(AutoDerefPointers)->setEnabled(true);
     action(ExpandStack)->setEnabled(actionsEnabled);
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index f5e37399626..76a8bb73c35 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1969,9 +1969,9 @@ void GdbEngine::setupEngine()
     m_gdbAdapter->startAdapter();
 }
 
-unsigned GdbEngine::debuggerCapabilities() const
+bool GdbEngine::hasCapability(unsigned cap) const
 {
-    unsigned caps = ReverseSteppingCapability
+    if (cap & (ReverseSteppingCapability
         | AutoDerefPointersCapability
         | DisassemblerCapability
         | RegisterCapability
@@ -1992,16 +1992,17 @@ unsigned GdbEngine::debuggerCapabilities() const
         | CatchCapability
         | OperateByInstructionCapability
         | RunToLineCapability
-        | MemoryAddressCapability;
+        | MemoryAddressCapability))
+        return true;
 
     if (startParameters().startMode == AttachCore)
-        return caps;
+        return false;
 
     // FIXME: Remove in case we have gdb 7.x on Mac.
     if (startParameters().toolChainAbi.os() == Abi::MacOS)
-        return caps;
+        return false;
 
-    return caps | SnapshotCapability;
+    return cap == SnapshotCapability;
 }
 
 
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 1f90d0d5e31..4bab3df399d 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -238,7 +238,7 @@ private: ////////// General Interface //////////
     virtual void setupInferior();
     virtual void runEngine();
 
-    virtual unsigned debuggerCapabilities() const;
+    virtual bool hasCapability(unsigned) const;
     virtual void detachDebugger();
     virtual void shutdownEngine();
     virtual void shutdownInferior();
diff --git a/src/plugins/debugger/lldb/ipcenginehost.h b/src/plugins/debugger/lldb/ipcenginehost.h
index 25fde63b824..9fc5b77d4e1 100644
--- a/src/plugins/debugger/lldb/ipcenginehost.h
+++ b/src/plugins/debugger/lldb/ipcenginehost.h
@@ -116,6 +116,7 @@ public:
     void updateWatchData(const WatchData &data,
             const WatchUpdateFlags &flags = WatchUpdateFlags());
     void fetchFrameSource(qint64 id);
+    bool hasCapability(unsigned) const { return false; }
 
     void rpcCall(Function f, QByteArray payload = QByteArray());
 protected:
diff --git a/src/plugins/debugger/moduleswindow.cpp b/src/plugins/debugger/moduleswindow.cpp
index 185f0c2cf41..7b4f8d09550 100644
--- a/src/plugins/debugger/moduleswindow.cpp
+++ b/src/plugins/debugger/moduleswindow.cpp
@@ -90,29 +90,26 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
     DebuggerEngine *engine = debuggerCore()->currentEngine();
     QTC_ASSERT(engine, return);
     const bool enabled = engine->debuggerActionsEnabled();
-    const unsigned capabilities = engine->debuggerCapabilities();
+    const bool canReload = engine->hasCapability(ReloadModuleCapability);
+    const bool canLoadSymbols = engine->hasCapability(ReloadModuleSymbolsCapability);
 
     QMenu menu;
 
     QAction *actUpdateModuleList
         = new QAction(tr("Update Module List"), &menu);
-    actUpdateModuleList
-        ->setEnabled(enabled && (capabilities & ReloadModuleCapability));
+    actUpdateModuleList->setEnabled(enabled && canReload);
 
     QAction *actShowModuleSources
         = new QAction(tr("Show Source Files for Module \"%1\"").arg(name), &menu);
-    actShowModuleSources
-        ->setEnabled(enabled && (capabilities & ReloadModuleCapability));
+    actShowModuleSources->setEnabled(enabled && canReload);
 
     QAction *actLoadSymbolsForAllModules
         = new QAction(tr("Load Symbols for All Modules"), &menu);
-    actLoadSymbolsForAllModules
-        -> setEnabled(enabled && (capabilities & ReloadModuleSymbolsCapability));
+    actLoadSymbolsForAllModules->setEnabled(enabled && canLoadSymbols);
 
     QAction *actExamineAllModules
         = new QAction(tr("Examine All Modules"), &menu);
-    actExamineAllModules
-        -> setEnabled(enabled && (capabilities & ReloadModuleSymbolsCapability));
+    actExamineAllModules->setEnabled(enabled && canLoadSymbols);
 
     QAction *actLoadSymbolsForModule = 0;
     QAction *actEditFile = 0;
@@ -130,14 +127,12 @@ void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
     } else {
         actLoadSymbolsForModule
             = new QAction(tr("Load Symbols for Module \"%1\"").arg(name), &menu);
-        actLoadSymbolsForModule
-            ->setEnabled(capabilities & ReloadModuleSymbolsCapability);
+        actLoadSymbolsForModule->setEnabled(canLoadSymbols);
         actEditFile
             = new QAction(tr("Edit File \"%1\"").arg(name), &menu);
         actShowModuleSymbols
             = new QAction(tr("Show Symbols in File \"%1\"").arg(name), &menu);
-        actShowModuleSymbols
-            ->setEnabled(capabilities & ShowModuleSymbolsCapability);
+        actShowModuleSymbols->setEnabled(engine->hasCapability(ShowModuleSymbolsCapability));
         actShowDependencies = new QAction(tr("Show Dependencies of \"%1\"").arg(name), &menu);
         actShowDependencies->setEnabled(!fileName.isEmpty());
 #ifndef Q_OS_WIN
diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp
index 16791fdbac0..94ec5f05332 100644
--- a/src/plugins/debugger/pdb/pdbengine.cpp
+++ b/src/plugins/debugger/pdb/pdbengine.cpp
@@ -828,9 +828,9 @@ void PdbEngine::handleListLocals(const PdbResponse &response)
     handler->insertBulkData(list);
 }
 
-unsigned PdbEngine::debuggerCapabilities() const
+bool PdbEngine::hasCapability(unsigned cap) const
 {
-    return ReloadModuleCapability|BreakConditionCapability;
+    return cap & (ReloadModuleCapability|BreakConditionCapability);
 }
 
 DebuggerEngine *createPdbEngine(const DebuggerStartParameters &startParameters)
diff --git a/src/plugins/debugger/pdb/pdbengine.h b/src/plugins/debugger/pdb/pdbengine.h
index 8a79a252d34..ede6c8b84e0 100644
--- a/src/plugins/debugger/pdb/pdbengine.h
+++ b/src/plugins/debugger/pdb/pdbengine.h
@@ -116,7 +116,7 @@ signals:
 
 private:
     QString errorMessage(QProcess::ProcessError error) const;
-    unsigned debuggerCapabilities() const;
+    bool hasCapability(unsigned cap) const;
 
     Q_SLOT void handlePdbFinished(int, QProcess::ExitStatus status);
     Q_SLOT void handlePdbError(QProcess::ProcessError error);
diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp
index d72b80c5b0d..f8913f40491 100644
--- a/src/plugins/debugger/qml/qmlcppengine.cpp
+++ b/src/plugins/debugger/qml/qmlcppengine.cpp
@@ -250,18 +250,18 @@ void QmlCppEngine::setRegisterValue(int regnr, const QString &value)
     d->m_cppEngine->setRegisterValue(regnr, value);
 }
 
-unsigned QmlCppEngine::debuggerCapabilities() const
+
+bool QmlCppEngine::hasCapability(unsigned cap) const
 {
     // ### this could also be an OR of both engines' capabilities
-    unsigned result = d->m_cppEngine->debuggerCapabilities();
+    bool hasCap = d->m_cppEngine->hasCapability(cap);
     if (d->m_activeEngine != d->m_cppEngine) {
-        const unsigned qmlCapabilities = d->m_qmlEngine->debuggerCapabilities();
-        if (qmlCapabilities & AddWatcherWhileRunningCapability)
-            result |= AddWatcherWhileRunningCapability;
-        if (!(qmlCapabilities & WatchWidgetsCapability))
-            result &= ~WatchWidgetsCapability;
+        if (cap == AddWatcherWhileRunningCapability)
+            hasCap = hasCap || d->m_qmlEngine->hasCapability(cap);
+        if (cap == WatchWidgetsCapability)
+            hasCap = hasCap && d->m_qmlEngine->hasCapability(cap);
     }
-    return result;
+    return hasCap;
 }
 
 bool QmlCppEngine::isSynchronous() const
diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h
index b0ede13318f..a01ac4ef655 100644
--- a/src/plugins/debugger/qml/qmlcppengine.h
+++ b/src/plugins/debugger/qml/qmlcppengine.h
@@ -71,7 +71,7 @@ public:
     void reloadFullStack();
 
     void setRegisterValue(int regnr, const QString &value);
-    unsigned debuggerCapabilities() const;
+    bool hasCapability(unsigned cap) const;
 
     bool isSynchronous() const;
     QByteArray qtNamespace() const;
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 4cad9eba62f..2f2d05efbe5 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -780,11 +780,11 @@ void QmlEngine::synchronizeWatchers()
     }
 }
 
-unsigned QmlEngine::debuggerCapabilities() const
+bool QmlEngine::hasCapability(unsigned cap) const
 {
-    return AddWatcherCapability
+    return cap & (AddWatcherCapability
             | AddWatcherWhileRunningCapability
-            | RunToLineCapability;
+            | RunToLineCapability);
     /*ReverseSteppingCapability | SnapshotCapability
         | AutoDerefPointersCapability | DisassemblerCapability
         | RegisterCapability | ShowMemoryCapability
diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h
index 00768ae689f..07ef33559b1 100644
--- a/src/plugins/debugger/qml/qmlengine.h
+++ b/src/plugins/debugger/qml/qmlengine.h
@@ -148,7 +148,7 @@ private:
         const WatchUpdateFlags &flags);
     void executeDebuggerCommand(const QString &command);
 
-    unsigned int debuggerCapabilities() const;
+    bool hasCapability(unsigned) const;
 
 signals:
     void tooltipRequested(const QPoint &mousePos,
diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp
index 635ed6f3655..72d0ea16a3d 100644
--- a/src/plugins/debugger/registerwindow.cpp
+++ b/src/plugins/debugger/registerwindow.cpp
@@ -179,12 +179,11 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
     DebuggerEngine *engine = currentEngine();
     QTC_ASSERT(engine, return);
     RegisterHandler *handler = currentHandler();
-    const unsigned engineCapabilities = engine->debuggerCapabilities();
     const bool actionsEnabled = engine->debuggerActionsEnabled();
     const int state = engine->state();
 
     QAction *actReload = menu.addAction(tr("Reload Register Listing"));
-    actReload->setEnabled((engineCapabilities & RegisterCapability)
+    actReload->setEnabled(engine->hasCapability(RegisterCapability)
         && (state == InferiorStopOk || state == InferiorUnrunnable));
 
     menu.addSeparator();
@@ -201,17 +200,17 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
 
     QAction *actShowDisassemblerAt = menu.addAction(QString());
     QAction *actShowDisassembler = menu.addAction(tr("Open Disassembler..."));
-    actShowDisassembler->setEnabled(engineCapabilities & DisassemblerCapability);
+    actShowDisassembler->setEnabled(engine->hasCapability(DisassemblerCapability));
 
     if (address) {
-        const bool canShow = actionsEnabled && (engineCapabilities & ShowMemoryCapability);
+        const bool canShow = actionsEnabled && engine->hasCapability(ShowMemoryCapability);
         actEditMemory->setText(tr("Open Memory Editor at 0x%1").arg(address, 0, 16));
         actEditMemory->setEnabled(canShow);
         actViewMemory->setText(tr("Open Memory View at Value of Register %1 0x%2")
             .arg(QString::fromAscii(aRegister.name)).arg(address, 0, 16));
         actShowDisassemblerAt->setText(tr("Open Disassembler at 0x%1")
             .arg(address, 0, 16));
-        actShowDisassemblerAt->setEnabled(engineCapabilities & DisassemblerCapability);
+        actShowDisassemblerAt->setEnabled(engine->hasCapability(DisassemblerCapability));
     } else {
         actEditMemory->setText(tr("Open Memory Editor"));
         actViewMemory->setText(tr("Open Memory View at Value of Register"));
diff --git a/src/plugins/debugger/script/scriptengine.h b/src/plugins/debugger/script/scriptengine.h
index 0f3a780c306..be90ea8322e 100644
--- a/src/plugins/debugger/script/scriptengine.h
+++ b/src/plugins/debugger/script/scriptengine.h
@@ -105,11 +105,11 @@ private:
     void reloadSourceFiles() {}
     void reloadFullStack() {}
 
-    bool supportsThreads() const { return true; }
     bool checkForBreakCondition(bool byFunction);
     void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags);
     void updateLocals();
     void updateSubItem(const WatchData &data);
+    bool hasCapability(unsigned) const { return false; }
 
 private:
     friend class ScriptAgent;
diff --git a/src/plugins/debugger/snapshothandler.cpp b/src/plugins/debugger/snapshothandler.cpp
index cdff0e81e01..7be50a7cb16 100644
--- a/src/plugins/debugger/snapshothandler.cpp
+++ b/src/plugins/debugger/snapshothandler.cpp
@@ -162,7 +162,7 @@ QVariant SnapshotHandler::data(const QModelIndex &index, int role) const
     const DebuggerEngine *engine = at(index.row());
 
     if (role == SnapshotCapabilityRole)
-        return engine && (engine->debuggerCapabilities() & SnapshotCapability);
+        return engine && engine->hasCapability(SnapshotCapability);
 
     if (!engine)
         return QLatin1String("<finished>");
diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp
index a4109493157..b2f5d6a38de 100644
--- a/src/plugins/debugger/stackwindow.cpp
+++ b/src/plugins/debugger/stackwindow.cpp
@@ -97,7 +97,6 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
     StackHandler *handler = engine->stackHandler();
     const QModelIndex index = indexAt(ev->pos());
     const int row = index.row();
-    const unsigned engineCapabilities = engine->debuggerCapabilities();
     StackFrame frame;
     if (row >= 0 && row < handler->stackSize())
         frame = handler->frameAt(row);
@@ -109,25 +108,25 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
     QAction *actCopyContents = menu.addAction(tr("Copy Contents to Clipboard"));
     actCopyContents->setEnabled(model() != 0);
 
-    if (engineCapabilities & CreateFullBacktraceCapability)
+    if (engine->hasCapability(CreateFullBacktraceCapability))
         menu.addAction(debuggerCore()->action(CreateFullBacktrace));
 
     QAction *actShowMemory = 0;
-    if (engineCapabilities & ShowMemoryCapability) {
+    if (engine->hasCapability(ShowMemoryCapability)) {
         actShowMemory = menu.addAction(QString());
         if (address == 0) {
             actShowMemory->setText(tr("Open Memory Editor"));
             actShowMemory->setEnabled(false);
         } else {
             actShowMemory->setText(tr("Open Memory Editor at 0x%1").arg(address, 0, 16));
-            actShowMemory->setEnabled(engineCapabilities & ShowMemoryCapability);
+            actShowMemory->setEnabled(engine->hasCapability(ShowMemoryCapability));
         }
     }
 
     QAction *actShowDisassemblerAt = 0;
     QAction *actShowDisassembler = 0;
 
-    if (engineCapabilities & DisassemblerCapability) {
+    if (engine->hasCapability(DisassemblerCapability)) {
         actShowDisassemblerAt = menu.addAction(QString());
         actShowDisassembler = menu.addAction(tr("Open Disassembler..."));
         if (address == 0) {
@@ -140,13 +139,13 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
 
 
     QAction *actLoadSymbols = 0;
-    if (engineCapabilities & ShowModuleSymbolsCapability)
+    if (engine->hasCapability(ShowModuleSymbolsCapability))
         actLoadSymbols = menu.addAction(tr("Try to Load Unknown Symbols"));
 
 #if 0 // @TODO: not implemented
     menu.addAction(debuggerCore()->action(UseToolTipsInStackView));
 #endif
-    if (engineCapabilities & MemoryAddressCapability)
+    if (engine->hasCapability(MemoryAddressCapability))
         menu.addAction(debuggerCore()->action(UseAddressInStackView));
 
     menu.addSeparator();
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 366877071c4..b744e1765d2 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -919,7 +919,7 @@ Qt::ItemFlags WatchModel::flags(const QModelIndex &idx) const
 
     // Disable editing if debuggee is positively running.
     const bool isRunning = engine() && engine()->state() == InferiorRunOk;
-    if (isRunning && engine() && !(engine()->debuggerCapabilities() & AddWatcherWhileRunningCapability))
+    if (isRunning && engine() && !engine()->hasCapability(AddWatcherWhileRunningCapability))
         return notEditable;
 
     const WatchData &data = *watchItem(idx);
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index 16921f155d1..4f464188ff8 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -707,19 +707,18 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
     }
 
     const bool actionsEnabled = engine->debuggerActionsEnabled();
-    const unsigned engineCapabilities = engine->debuggerCapabilities();
-    const bool canHandleWatches = engineCapabilities & AddWatcherCapability;
+    const bool canHandleWatches = engine->hasCapability(AddWatcherCapability);
     const DebuggerState state = engine->state();
     const bool canInsertWatches = state == InferiorStopOk
         || state == DebuggerNotReady
         || state == InferiorUnrunnable
-        || (state == InferiorRunOk && (engineCapabilities & AddWatcherWhileRunningCapability));
+        || (state == InferiorRunOk && engine->hasCapability(AddWatcherWhileRunningCapability));
 
     QMenu breakpointMenu;
     breakpointMenu.setTitle(tr("Add Data Breakpoint..."));
     QAction *actSetWatchpointAtVariableAddress = 0;
     QAction *actSetWatchpointAtPointerValue = 0;
-    const bool canSetWatchpoint = engineCapabilities & WatchpointByAddressCapability;
+    const bool canSetWatchpoint = engine->hasCapability(WatchpointByAddressCapability);
     if (canSetWatchpoint && address) {
         actSetWatchpointAtVariableAddress =
             new QAction(tr("Add Data Breakpoint at Object's Address (0x%1)")
@@ -744,7 +743,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
            "to stop when the data at the address is modified."));
 
     QAction *actSetWatchpointAtExpression = 0;
-    const bool canSetWatchpointAtExpression = engineCapabilities & WatchpointByExpressionCapability;
+    const bool canSetWatchpointAtExpression = engine->hasCapability(WatchpointByExpressionCapability);
     if (name.isEmpty() || !canSetWatchpointAtExpression) {
         actSetWatchpointAtExpression =
             new QAction(tr("Add Data Breakpoint at Expression"),
@@ -771,7 +770,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
     actInsertNewWatchItem->setEnabled(canHandleWatches && canInsertWatches);
     QAction *actSelectWidgetToWatch = menu.addAction(tr("Select Widget to Watch"));
     actSelectWidgetToWatch->setEnabled(canHandleWatches
-           && (engine->debuggerCapabilities() & WatchWidgetsCapability));
+           && engine->hasCapability(WatchWidgetsCapability));
     QAction *actEditTypeFormats = menu.addAction(tr("Change Global Display Formats..."));
     actEditTypeFormats->setEnabled(true);
     menu.addSeparator();
@@ -806,7 +805,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
     QAction *actOpenMemoryEditorStackLayout = new QAction(&memoryMenu);
     QAction *actOpenMemoryViewAtVariableAddress = new QAction(&memoryMenu);
     QAction *actOpenMemoryViewAtPointerValue = new QAction(&memoryMenu);
-    if (engineCapabilities & ShowMemoryCapability) {
+    if (engine->hasCapability(ShowMemoryCapability)) {
         actOpenMemoryEditor->setText(tr("Open Memory Editor..."));
         if (address) {
             actOpenMemoryEditAtVariableAddress->setText(
-- 
GitLab