Commit 5a3f3dda authored by Peifeng Yu's avatar Peifeng Yu
Browse files

Associate MIVariable to MIDebugSession

parent bb9e7f81
......@@ -30,6 +30,7 @@
#include "debuglog.h"
#include "midebugger.h"
#include "mivariable.h"
#include "mi/mi.h"
#include "mi/micommand.h"
#include "mi/micommandqueue.h"
......@@ -114,6 +115,27 @@ IDebugSession::DebuggerState MIDebugSession::state() const
return m_sessionState;
}
QMap<QString, MIVariable*> & MIDebugSession::variableMapping()
{
return m_allVariables;
}
MIVariable* MIDebugSession::findVariableByVarobjName(const QString &varobjName)
{
if (m_allVariables.count(varobjName) == 0)
return nullptr;
return m_allVariables[varobjName];
}
void MIDebugSession::markAllVariableDead()
{
for (auto i = m_allVariables.begin(), e = m_allVariables.end(); i != e; ++i)
{
i.value()->markAsDead();
}
m_allVariables.clear();
}
bool MIDebugSession::restartAvaliable() const
{
if (debuggerStateIsOn(s_attached) || debuggerStateIsOn(s_core)) {
......
......@@ -35,6 +35,8 @@
#include "mi/mi.h"
#include "mi/micommand.h"
#include <QMap>
#include <memory>
class IExecutePlugin;
......@@ -50,6 +52,7 @@ class CommandQueue;
}
class MIDebugger;
class MIVariable;
class STTY;
class MIDebugSession : public KDevelop::IDebugSession
{
......@@ -211,6 +214,10 @@ public:
void (Handler::* handler_method)(const MI::ResultRecord&),
MI::CommandFlags flags = 0);
QMap<QString, MIVariable*> & variableMapping();
MIVariable* findVariableByVarobjName(const QString &varobjName);
void markAllVariableDead();
protected Q_SLOTS:
virtual void slotDebuggerReady();
virtual void slotDebuggerExited(bool abnormal, const QString &msg);
......@@ -328,6 +335,9 @@ protected:
bool m_hasCrashed;
bool m_sourceInitFile;
// Map from GDB varobj name to MIVariable.
QMap<QString, MIVariable*> m_allVariables;
};
template<class Handler>
......
......@@ -21,6 +21,7 @@
#include "mivariable.h"
#include "debuglog.h"
#include "midebugsession.h"
#include "mi/micommand.h"
......@@ -31,24 +32,20 @@ using namespace KDevelop;
using namespace KDevMI;
using namespace KDevMI::MI;
QMap<QString, MIVariable*> MIVariable::allVariables_;
static bool hasStartedSession()
bool MIVariable::sessionIsAlive() const
{
if (!ICore::self()->debugController()) return false; //happens on shutdown
IDebugSession *session = ICore::self()->debugController()->currentSession();
if (!session)
if (!debugSession)
return false;
IDebugSession::DebuggerState s = session->state();
IDebugSession::DebuggerState s = debugSession->state();
return s != IDebugSession::NotStartedState
&& s != IDebugSession::EndedState;
}
MIVariable::MIVariable(TreeModel* model, TreeItem* parent,
MIVariable::MIVariable(MIDebugSession *session, TreeModel* model, TreeItem* parent,
const QString& expression, const QString& display)
: Variable(model, parent, expression, display)
, debugSession(session)
{
}
......@@ -58,33 +55,29 @@ MIVariable::~MIVariable()
{
// Delete only top-level variable objects.
if (topLevel()) {
if (hasStartedSession()) {
IDebugSession* is = ICore::self()->debugController()->currentSession();
MIDebugSession * s = static_cast<MIDebugSession *>(is);
s->addCommand(VarDelete, QString("\"%1\"").arg(varobj_));
if (sessionIsAlive()) {
debugSession->addCommand(VarDelete, QString("\"%1\"").arg(varobj_));
}
}
allVariables_.remove(varobj_);
if (debugSession)
debugSession->variableMapping().remove(varobj_);
}
}
MIVariable* MIVariable::findByVarobjName(const QString& varobjName)
{
if (allVariables_.count(varobjName) == 0)
return 0;
return allVariables_[varobjName];
}
void MIVariable::setVarobj(const QString& v)
{
if (!debugSession) {
qCDebug(DEBUGGERCOMMON) << "WARNING: MIVariable::setVarobj called when its session died";
return;
}
if (!varobj_.isEmpty()) {
// this should not happen
// but apperently it does when attachMaybe is called a second time before
// the first -var-create call returned
allVariables_.remove(varobj_);
debugSession->variableMapping().remove(varobj_);
}
varobj_ = v;
allVariables_[varobj_] = this;
debugSession->variableMapping()[varobj_] = this;
}
......@@ -153,23 +146,20 @@ void MIVariable::attachMaybe(QObject *callback, const char *callbackMethod)
if (!varobj_.isEmpty())
return;
if (hasStartedSession()) {
IDebugSession* is = ICore::self()->debugController()->currentSession();
MIDebugSession * s = static_cast<MIDebugSession *>(is);
s->addCommand(VarCreate,
QString("var%1 @ %2").arg(nextId++).arg(enquotedExpression()),
new CreateVarobjHandler(this, callback, callbackMethod));
// Try find a current session and attach to it
if (!ICore::self()->debugController()) return; //happens on shutdown
debugSession = static_cast<MIDebugSession*>(ICore::self()->debugController()->currentSession());
if (sessionIsAlive()) {
debugSession->addCommand(VarCreate,
QString("var%1 @ %2").arg(nextId++).arg(enquotedExpression()),
new CreateVarobjHandler(this, callback, callbackMethod));
}
}
void MIVariable::markAllDead()
void MIVariable::markAsDead()
{
QMap<QString, MIVariable*>::iterator i, e;
for (i = allVariables_.begin(), e = allVariables_.end(); i != e; ++i)
{
i.value()->varobj_.clear();
}
allVariables_.clear();
varobj_.clear();
}
class FetchMoreChildrenHandler : public MICommandHandler
......@@ -247,13 +237,12 @@ void MIVariable::fetchMoreChildren()
int c = childItems.size();
// FIXME: should not even try this if app is not started.
// Probably need to disable open, or something
if (hasStartedSession()) {
IDebugSession* is = ICore::self()->debugController()->currentSession();
MIDebugSession * s = static_cast<MIDebugSession *>(is);
s->addCommand(VarListChildren,
QString("--all-values \"%1\" %2 %3")
.arg(varobj_).arg( c ).arg( c + fetchStep ), // fetch from .. to ..
new FetchMoreChildrenHandler(this, s));
if (sessionIsAlive()) {
debugSession->addCommand(VarListChildren,
QString("--all-values \"%1\" %2 %3")
// fetch from .. to ..
.arg(varobj_).arg(c).arg(c + fetchStep),
new FetchMoreChildrenHandler(this, debugSession));
}
}
......@@ -298,19 +287,18 @@ void MIVariable::handleUpdate(const Value& var)
const Value& child = children[i];
const QString& exp = child["exp"].literal();
IDebugSession* is = ICore::self()->debugController()->currentSession();
MIDebugSession * s = static_cast<MIDebugSession *>(is);
KDevelop::Variable* xvar = s->variableController()->
createVariable(model(), this, exp);
MIVariable* var = static_cast<MIVariable*>(xvar);
var->setTopLevel(false);
var->setVarobj(child["name"].literal());
bool hasMore = child["numchild"].toInt() != 0 || ( child.hasField("dynamic") && child["dynamic"].toInt()!=0 );
var->setHasMoreInitial(hasMore);
appendChild(var);
var->setType(child["type"].literal());
var->setValue(child["value"].literal());
var->setChanged(true);
if (debugSession) {
auto xvar = debugSession->variableController()->createVariable(model(), this, exp);
auto var = static_cast<MIVariable*>(xvar);
var->setTopLevel(false);
var->setVarobj(child["name"].literal());
bool hasMore = child["numchild"].toInt() != 0 || ( child.hasField("dynamic") && child["dynamic"].toInt()!=0 );
var->setHasMoreInitial(hasMore);
appendChild(var);
var->setType(child["type"].literal());
var->setValue(child["value"].literal());
var->setChanged(true);
}
}
}
......@@ -365,12 +353,10 @@ void MIVariable::formatChanged()
}
else
{
if (hasStartedSession()) {
IDebugSession* is = ICore::self()->debugController()->currentSession();
MIDebugSession * s = static_cast<MIDebugSession *>(is);
s->addCommand(VarSetFormat,
QString(" \"%1\" %2 ").arg(varobj_).arg(format2str(format())),
new SetFormatHandler(this));
if (sessionIsAlive()) {
debugSession->addCommand(VarSetFormat,
QString(" \"%1\" %2 ").arg(varobj_).arg(format2str(format())),
new SetFormatHandler(this));
}
}
}
......@@ -27,16 +27,17 @@
#include <debugger/variable/variablecollection.h>
#include <QMap>
#include <QPointer>
class CreateVarobjHandler;
class FetchMoreChildrenHandler;
namespace KDevMI {
class MIDebugSession;
class MIVariable : public KDevelop::Variable
{
public:
MIVariable(KDevelop::TreeModel* model, KDevelop::TreeItem* parent,
MIVariable(MIDebugSession *session, KDevelop::TreeModel* model, KDevelop::TreeItem* parent,
const QString& expression, const QString& display = "");
~MIVariable();
......@@ -46,11 +47,9 @@ public:
const QString& varobj() const;
void handleUpdate(const MI::Value& var);
static MIVariable *findByVarobjName(const QString& varobjName);
/* Called when debugger dies. Clears the association between varobj names
and Variable instances. */
static void markAllDead();
void markAsDead();
bool canSetFormat() const override { return true; }
......@@ -62,17 +61,19 @@ protected: // Variable overrides
protected: // Internal
friend class ::CreateVarobjHandler;
friend class ::FetchMoreChildrenHandler;
QString enquotedExpression() const;
bool sessionIsAlive() const;
void setVarobj(const QString& v);
QString varobj_;
QPointer<MIDebugSession> debugSession;
// How many children should be fetched in one
// increment.
static const int fetchStep = 5;
/* Map from GDB varobj name to GdbVariable.
FIXME: eventually, should be per-session map. */
static QMap<QString, MIVariable*> allVariables_;
};
} // end of KDevMI
......
......@@ -98,7 +98,7 @@ void MIVariableController::handleVarUpdate(const ResultRecord& r)
for (int i = 0; i < changed.size(); ++i)
{
const Value& var = changed[i];
MIVariable* v = MIVariable::findByVarobjName(var["name"].literal());
MIVariable* v = debugSession()->findVariableByVarobjName(var["name"].literal());
// v can be NULL here if we've already removed locals after step,
// but the corresponding -var-delete command is still in the queue.
if (v) {
......@@ -239,7 +239,7 @@ void MIVariableController::addWatchpoint(const ResultRecord& r)
Variable* MIVariableController::createVariable(TreeModel* model, TreeItem* parent,
const QString& expression, const QString& display)
{
return new MIVariable(model, parent, expression, display);
return new MIVariable(debugSession(), model, parent, expression, display);
}
void MIVariableController::handleEvent(IDebugSession::event_t event)
......@@ -250,6 +250,6 @@ void MIVariableController::handleEvent(IDebugSession::event_t event)
void MIVariableController::stateChanged(IDebugSession::DebuggerState state)
{
if (state == IDebugSession::EndedState) {
MIVariable::markAllDead();
debugSession()->markAllVariableDead();
}
}
......@@ -22,11 +22,13 @@
#include "gdbvariable.h"
#include "debugsession.h"
using namespace KDevelop;
using namespace KDevMI::GDB;
GdbVariable::GdbVariable(TreeModel *model, TreeItem *parent,
GdbVariable::GdbVariable(DebugSession *session, TreeModel *model, TreeItem *parent,
const QString& expression, const QString& display)
: MIVariable(model, parent, expression, display)
: MIVariable(session, model, parent, expression, display)
{
}
......@@ -31,13 +31,13 @@ class TreeItem;
}
namespace KDevMI { namespace GDB {
class DebugSession;
class GdbVariable : public KDevMI::MIVariable
{
Q_OBJECT
public:
GdbVariable(KDevelop::TreeModel* model, KDevelop::TreeItem* parent,
GdbVariable(DebugSession *session, KDevelop::TreeModel* model, KDevelop::TreeItem* parent,
const QString& expression, const QString& display = "");
};
......
......@@ -1261,7 +1261,7 @@ void GdbTest::testVariablesStopDebugger()
void GdbTest::testVariablesStartSecondSession()
{
TestDebugSession *session = new TestDebugSession;
QPointer<TestDebugSession> session = new TestDebugSession;
session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals);
TestLaunchConfiguration cfg;
......@@ -1270,15 +1270,15 @@ void GdbTest::testVariablesStartSecondSession()
QVERIFY(session->startDebugging(&cfg, m_iface));
WAIT_FOR_STATE(session, DebugSession::PausedState);
session = new TestDebugSession;
session->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals);
QPointer<TestDebugSession> session2 = new TestDebugSession;
session2->variableController()->setAutoUpdate(KDevelop::IVariableController::UpdateLocals);
breakpoints()->addCodeBreakpoint(QUrl::fromLocalFile(debugeeFileName), 38);
QVERIFY(session->startDebugging(&cfg, m_iface));
WAIT_FOR_STATE(session, DebugSession::PausedState);
QVERIFY(session2->startDebugging(&cfg, m_iface));
WAIT_FOR_STATE(session2, DebugSession::PausedState);
session->run();
WAIT_FOR_STATE(session, DebugSession::EndedState);
session2->run();
WAIT_FOR_STATE(session2, DebugSession::EndedState);
}
void GdbTest::testVariablesSwitchFrame()
......
......@@ -30,21 +30,12 @@ using namespace KDevelop;
using namespace KDevMI::LLDB;
using namespace KDevMI::MI;
LldbVariable::LldbVariable(TreeModel *model, TreeItem *parent,
LldbVariable::LldbVariable(DebugSession *session, TreeModel *model, TreeItem *parent,
const QString& expression, const QString& display)
: MIVariable(model, parent, expression, display)
: MIVariable(session, model, parent, expression, display)
{
}
void LldbVariable::updateAll(DebugSession *session)
{
for (auto it = allVariables_.begin(); it != allVariables_.end(); ++it) {
LldbVariable *var = qobject_cast<LldbVariable*>(it.value());
session->addCommand(VarUpdate, "--all-values " + it.key(),
var, &LldbVariable::handleRawUpdate);
}
}
void LldbVariable::handleRawUpdate(const ResultRecord& r)
{
qCDebug(DEBUGGERLLDB) << "handleRawUpdate for variable" << varobj();
......
......@@ -37,12 +37,10 @@ class LldbVariable : public MIVariable
Q_OBJECT
public:
LldbVariable(KDevelop::TreeModel* model, KDevelop::TreeItem* parent,
LldbVariable(DebugSession *session, KDevelop::TreeModel* model, KDevelop::TreeItem* parent,
const QString& expression, const QString& display = "");
void handleRawUpdate(const MI::ResultRecord &r);
static void updateAll(DebugSession *session);
};
} // end of namespace LLDB
......
......@@ -44,7 +44,7 @@ DebugSession *VariableController::debugSession() const
LldbVariable* VariableController::createVariable(TreeModel* model, TreeItem* parent,
const QString& expression, const QString& display)
{
return new LldbVariable(model, parent, expression, display);
return new LldbVariable(debugSession(), model, parent, expression, display);
}
void VariableController::update()
......@@ -61,6 +61,6 @@ void VariableController::update()
if ((autoUpdate() & UpdateLocals) ||
((autoUpdate() & UpdateWatches) && variableCollection()->watches()->childCount() > 0))
{
LldbVariable::updateAll(debugSession());
debugSession()->updateAllVariables();
}
}
......@@ -22,6 +22,7 @@
#include "debugsession.h"
#include "controllers/variable.h"
#include "dbgglobal.h"
#include "debuglog.h"
#include "lldbcommand.h"
......@@ -246,3 +247,12 @@ void DebugSession::handleFileExecAndSymbols(const MI::ResultRecord& r)
stopDebugger();
}
}
void DebugSession::updateAllVariables()
{
for (auto it = m_allVariables.begin(), ite = m_allVariables.end(); it != ite; ++it) {
LldbVariable *var = qobject_cast<LldbVariable*>(it.value());
addCommand(VarUpdate, "--all-values " + it.key(),
var, &LldbVariable::handleRawUpdate);
}
}
......@@ -57,6 +57,8 @@ public:
MI::MICommand *createCommand(MI::CommandType type, const QString &arguments,
MI::CommandFlags flags) const override;
void updateAllVariables();
public Q_SLOTS:
void interruptDebugger() override;
......@@ -73,8 +75,6 @@ private Q_SLOTS:
void handleFileExecAndSymbols(const MI::ResultRecord& r);
private:
friend class GdbTest;
BreakpointController *m_breakpointController;
VariableController *m_variableController;
LldbFrameStackModel *m_frameStackModel;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment