clean up WatchData

Reviewed-by: hjk
This commit is contained in:
Arvid Ephraim Picciani
2010-10-15 13:00:14 +02:00
parent 235430fd8a
commit 4d14920ad6
7 changed files with 180 additions and 156 deletions

View File

@@ -3613,7 +3613,6 @@ WatchData GdbEngine::localVariable(const GdbMi &item,
data.iname = "local." + name; data.iname = "local." + name;
data.name = nam; data.name = nam;
data.exp = name; data.exp = name;
data.framekey = m_currentFrame + data.name;
setWatchDataType(data, item.findChild("type")); setWatchDataType(data, item.findChild("type"));
if (uninitializedVariables.contains(data.name)) { if (uninitializedVariables.contains(data.name)) {
data.setError(WatchData::msgNotInScope()); data.setError(WatchData::msgNotInScope());

View File

@@ -90,7 +90,7 @@ QDataStream& operator>>(QDataStream& s, WatchData &data)
QString value; QString value;
QString type; QString type;
bool hasChildren; bool hasChildren;
s >> data.exp >> data.name >> value >> type >> hasChildren >> data.objectId; s >> data.exp >> data.name >> value >> type >> hasChildren >> data.id;
data.setType(type.toUtf8(), false); data.setType(type.toUtf8(), false);
data.setValue(value); data.setValue(value);
data.setHasChildren(hasChildren); data.setHasChildren(hasChildren);
@@ -535,7 +535,7 @@ void QmlEngine::updateWatchData(const Internal::WatchData &data, const Internal:
if (!data.name.isEmpty() && data.isChildrenNeeded() if (!data.name.isEmpty() && data.isChildrenNeeded()
&& watchHandler()->isExpandedIName(data.iname)) && watchHandler()->isExpandedIName(data.iname))
expandObject(data.iname, data.objectId); expandObject(data.iname, data.id);
{ {
QByteArray reply; QByteArray reply;
@@ -630,7 +630,7 @@ void QmlEngine::messageReceived(const QByteArray &message)
if (watchHandler()->expandedINames().contains(data.iname)) { if (watchHandler()->expandedINames().contains(data.iname)) {
needPing = true; needPing = true;
expandObject(data.iname, data.objectId); expandObject(data.iname, data.id);
} }
} }
@@ -640,7 +640,7 @@ void QmlEngine::messageReceived(const QByteArray &message)
if (watchHandler()->expandedINames().contains(data.iname)) { if (watchHandler()->expandedINames().contains(data.iname)) {
needPing = true; needPing = true;
expandObject(data.iname, data.objectId); expandObject(data.iname, data.id);
} }
} }
@@ -710,7 +710,7 @@ void QmlEngine::messageReceived(const QByteArray &message)
if (watchHandler()->expandedINames().contains(data.iname)) { if (watchHandler()->expandedINames().contains(data.iname)) {
needPing = true; needPing = true;
expandObject(data.iname, data.objectId); expandObject(data.iname, data.id);
} }
} }
if (needPing) if (needPing)
@@ -726,7 +726,7 @@ void QmlEngine::messageReceived(const QByteArray &message)
watchHandler()->insertData(data); watchHandler()->insertData(data);
if (watchHandler()->expandedINames().contains(data.iname)) { if (watchHandler()->expandedINames().contains(data.iname)) {
needPing = true; needPing = true;
expandObject(data.iname, data.objectId); expandObject(data.iname, data.id);
} }
} }
if (needPing) if (needPing)

View File

@@ -702,9 +702,11 @@ void ScriptEngine::updateLocals()
m_scriptEngine->setAgent(0); m_scriptEngine->setAgent(0);
WatchData data; WatchData data;
data.id = m_watchIdCounter++;
m_watchIdToScriptValue.insert(data.id, context->activationObject());
data.iname = "local"; data.iname = "local";
data.name = _(data.iname); data.name = _(data.iname);
data.scriptValue = context->activationObject();
watchHandler()->beginCycle(); watchHandler()->beginCycle();
updateSubItem(data); updateSubItem(data);
watchHandler()->endCycle(); watchHandler()->endCycle();
@@ -744,8 +746,8 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
//SDEBUG("\nUPDATE SUBITEM: " << data.toString() << data.scriptValue.toString()); //SDEBUG("\nUPDATE SUBITEM: " << data.toString() << data.scriptValue.toString());
QTC_ASSERT(data.isValid(), return); QTC_ASSERT(data.isValid(), return);
const QScriptValue &ob = m_watchIdToScriptValue.value(data.id);
if (data.isTypeNeeded() || data.isValueNeeded()) { if (data.isTypeNeeded() || data.isValueNeeded()) {
const QScriptValue &ob = data.scriptValue;
if (ob.isArray()) { if (ob.isArray()) {
data.setType("Array", false); data.setType("Array", false);
data.setValue(QString(QLatin1Char(' '))); data.setValue(QString(QLatin1Char(' ')));
@@ -802,14 +804,15 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
} }
if (data.isChildrenNeeded()) { if (data.isChildrenNeeded()) {
QScriptValueIterator it(data.scriptValue); QScriptValueIterator it(ob);
while (it.hasNext()) { while (it.hasNext()) {
it.next(); it.next();
WatchData data1; WatchData data1;
data1.iname = data.iname + '.' + it.name().toLatin1(); data1.iname = data.iname + '.' + it.name().toLatin1();
data1.exp = it.name().toLatin1(); data1.exp = it.name().toLatin1();
data1.name = it.name(); data1.name = it.name();
data1.scriptValue = it.value(); data.id = m_watchIdCounter++;
m_watchIdToScriptValue.insert(data.id, it.value());
if (watchHandler()->isExpandedIName(data1.iname)) { if (watchHandler()->isExpandedIName(data1.iname)) {
data1.setChildrenNeeded(); data1.setChildrenNeeded();
} else { } else {
@@ -822,7 +825,7 @@ void ScriptEngine::updateSubItem(const WatchData &data0)
} }
if (data.isHasChildrenNeeded()) { if (data.isHasChildrenNeeded()) {
QScriptValueIterator it(data.scriptValue); QScriptValueIterator it(ob);
data.setHasChildren(it.hasNext()); data.setHasChildren(it.hasNext());
} }

View File

@@ -34,6 +34,7 @@
#include <QtCore/QSharedPointer> #include <QtCore/QSharedPointer>
#include <QtCore/QScopedPointer> #include <QtCore/QScopedPointer>
#include <QtCore/QHash>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QScriptEngine; class QScriptEngine;
@@ -114,6 +115,8 @@ private:
QString m_scriptContents; QString m_scriptContents;
QString m_scriptFileName; QString m_scriptFileName;
QScopedPointer<ScriptAgent> m_scriptAgent; QScopedPointer<ScriptAgent> m_scriptAgent;
QHash<quint64,QScriptValue> m_watchIdToScriptValue;
quint64 m_watchIdCounter;
bool m_stopped; bool m_stopped;
bool m_stopOnNextLine; bool m_stopOnNextLine;

View File

@@ -1,12 +1,10 @@
#include "watchdata.h" #include "watchdata.h"
#include "watchutils.h"
#include <QtCore/QTextStream> #include <QtCore/QTextStream>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtGui/QApplication> #include <QtCore/QCoreApplication>
#include <QtGui/QTextDocument> // Qt::escape
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// //
@@ -17,19 +15,107 @@
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
enum GuessChildrenResult { HasChildren, HasNoChildren, HasPossiblyChildren };
static QString qt_escape(const QString& plain)
{
QString rich;
rich.reserve(int(plain.length() * 1.1));
for (int i = 0; i < plain.length(); ++i) {
if (plain.at(i) == QLatin1Char('<'))
rich += QLatin1String("&lt;");
else if (plain.at(i) == QLatin1Char('>'))
rich += QLatin1String("&gt;");
else if (plain.at(i) == QLatin1Char('&'))
rich += QLatin1String("&amp;");
else if (plain.at(i) == QLatin1Char('"'))
rich += QLatin1String("&quot;");
else
rich += plain.at(i);
}
return rich;
}
bool isPointerType(const QByteArray &type)
{
return type.endsWith('*') || type.endsWith("* const");
}
bool isCharPointerType(const QByteArray &type)
{
return type == "char *" || type == "const char *" || type == "char const *";
}
bool isIntType(const QByteArray &type)
{
if (type.isEmpty())
return false;
switch (type.at(0)) {
case 'b':
return type == "bool";
case 'c':
return type == "char";
case 'i':
return type == "int" || type == "int64";
case 'l':
return type == "long"
|| type == "long long";
case 'p':
return type == "ptrdiff_t";
case 'q':
return type == "qint16" || type == "quint16"
|| type == "qint32" || type == "quint32"
|| type == "qint64" || type == "quint64";
case 's':
return type == "short"
|| type == "signed"
|| type == "size_t"
|| type == "std::size_t"
|| type == "std::ptrdiff_t"
|| type.startsWith("signed ");
case 'u':
return type == "unsigned"
|| type.startsWith("unsigned ");
default:
return false;
}
}
bool isFloatType(const QByteArray &type)
{
return type == "float" || type == "double" || type == "qreal";
}
bool isIntOrFloatType(const QByteArray &type)
{
return isIntType(type) || isFloatType(type);
}
GuessChildrenResult guessChildren(const QByteArray &type)
{
if (isIntOrFloatType(type))
return HasNoChildren;
if (isCharPointerType(type))
return HasNoChildren;
if (isPointerType(type))
return HasChildren;
if (type.endsWith("QString"))
return HasNoChildren;
return HasPossiblyChildren;
}
WatchData::WatchData() : WatchData::WatchData() :
id(0),
state(InitialState),
editformat(0), editformat(0),
address(0), address(0),
hasChildren(false),
generation(-1), generation(-1),
hasChildren(false),
valueEnabled(true), valueEnabled(true),
valueEditable(true), valueEditable(true),
error(false), error(false),
source(0),
objectId(0),
state(InitialState),
changed(false), changed(false),
sortId(0) sortId(0),
source(0)
{ {
} }
@@ -45,7 +131,6 @@ bool WatchData::isEqual(const WatchData &other) const
&& displayedType == other.displayedType && displayedType == other.displayedType
&& variable == other.variable && variable == other.variable
&& address == other.address && address == other.address
&& framekey == other.framekey
&& hasChildren == other.hasChildren && hasChildren == other.hasChildren
&& valueEnabled == other.valueEnabled && valueEnabled == other.valueEnabled
&& valueEditable == other.valueEditable && valueEditable == other.valueEditable
@@ -213,8 +298,6 @@ QString WatchData::toString() const
if (isChildrenNeeded()) if (isChildrenNeeded())
str << "children=<needed>,"; str << "children=<needed>,";
if (source)
str << "source=" << source;
str.flush(); str.flush();
if (res.endsWith(QLatin1Char(','))) if (res.endsWith(QLatin1Char(',')))
res.truncate(res.size() - 1); res.truncate(res.size() - 1);
@@ -226,7 +309,7 @@ static void formatToolTipRow(QTextStream &str,
const QString &category, const QString &value) const QString &category, const QString &value)
{ {
str << "<tr><td>" << category << "</td><td> : </td><td>" str << "<tr><td>" << category << "</td><td> : </td><td>"
<< Qt::escape(value) << "</td></tr>"; << qt_escape(value) << "</td></tr>";
} }
static QString typeToolTip(const WatchData &wd) static QString typeToolTip(const WatchData &wd)
@@ -247,19 +330,19 @@ QString WatchData::toToolTip() const
QString res; QString res;
QTextStream str(&res); QTextStream str(&res);
str << "<html><body><table>"; str << "<html><body><table>";
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Name"), name); formatToolTipRow(str, tr("Name"), name);
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Expression"), exp); formatToolTipRow(str, tr("Expression"), exp);
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Type"), typeToolTip(*this)); formatToolTipRow(str, tr("Type"), typeToolTip(*this));
QString val = value; QString val = value;
if (value.size() > 1000) { if (value.size() > 1000) {
val.truncate(1000); val.truncate(1000);
val += QCoreApplication::translate("Debugger::Internal::WatchHandler", " ... <cut off>"); val += tr(" ... <cut off>");
} }
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Value"), val); formatToolTipRow(str, tr("Value"), val);
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Object Address"), formatToolTipRow(str, tr("Object Address"),
QString::fromAscii(hexAddress())); QString::fromAscii(hexAddress()));
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Internal ID"), iname); formatToolTipRow(str, tr("Internal ID"), iname);
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Generation"), formatToolTipRow(str, tr("Generation"),
QString::number(generation)); QString::number(generation));
str << "</table></body></html>"; str << "</table></body></html>";
return res; return res;

View File

@@ -33,6 +33,7 @@
#include <QtCore/QMetaType> #include <QtCore/QMetaType>
#include <QtCore/QtGlobal> #include <QtCore/QtGlobal>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QCoreApplication>
#include <QtScript/QScriptValue> #include <QtScript/QScriptValue>
namespace Debugger { namespace Debugger {
@@ -45,11 +46,11 @@ public:
enum State enum State
{ {
Complete = 0, Complete = 0,
HasChildrenNeeded = 1, HasChildrenNeeded = 1,
ValueNeeded = 2, ValueNeeded = 2,
TypeNeeded = 4, TypeNeeded = 4,
ChildrenNeeded = 8, ChildrenNeeded = 8,
NeededMask = ValueNeeded NeededMask = ValueNeeded
| TypeNeeded | TypeNeeded
@@ -62,81 +63,84 @@ public:
| HasChildrenNeeded | HasChildrenNeeded
}; };
void setValue(const QString &);
void setType(const QByteArray &, bool guessChildrenFromType = true);
void setValueToolTip(const QString &);
void setError(const QString &);
void setAddress(const quint64 &);
void setHexAddress(const QByteArray &a);
bool isSomethingNeeded() const { return state & NeededMask; } bool isSomethingNeeded() const { return state & NeededMask; }
void setAllNeeded() { state = NeededMask; } void setAllNeeded() { state = NeededMask; }
void setAllUnneeded() { state = State(0); } void setAllUnneeded() { state = State(0); }
bool isTypeNeeded() const { return state & TypeNeeded; } bool isTypeNeeded() const { return state & TypeNeeded; }
bool isTypeKnown() const { return !(state & TypeNeeded); } bool isTypeKnown() const { return !(state & TypeNeeded); }
void setTypeNeeded() { state = State(state | TypeNeeded); } void setTypeNeeded() { state = State(state | TypeNeeded); }
void setTypeUnneeded() { state = State(state & ~TypeNeeded); } void setTypeUnneeded() { state = State(state & ~TypeNeeded); }
bool isValueNeeded() const { return state & ValueNeeded; } bool isValueNeeded() const { return state & ValueNeeded; }
bool isValueKnown() const { return !(state & ValueNeeded); } bool isValueKnown() const { return !(state & ValueNeeded); }
void setValueNeeded() { state = State(state | ValueNeeded); } void setValueNeeded() { state = State(state | ValueNeeded); }
void setValueUnneeded() { state = State(state & ~ValueNeeded); } void setValueUnneeded() { state = State(state & ~ValueNeeded); }
bool isChildrenNeeded() const { return state & ChildrenNeeded; } bool isChildrenNeeded() const { return state & ChildrenNeeded; }
bool isChildrenKnown() const { return !(state & ChildrenNeeded); } bool isChildrenKnown() const { return !(state & ChildrenNeeded); }
void setChildrenNeeded() { state = State(state | ChildrenNeeded); } void setChildrenNeeded() { state = State(state | ChildrenNeeded); }
void setChildrenUnneeded() { state = State(state & ~ChildrenNeeded); } void setChildrenUnneeded() { state = State(state & ~ChildrenNeeded); }
bool isHasChildrenNeeded() const { return state & HasChildrenNeeded; } bool isHasChildrenNeeded() const { return state & HasChildrenNeeded; }
bool isHasChildrenKnown() const { return !(state & HasChildrenNeeded); } bool isHasChildrenKnown() const { return !(state & HasChildrenNeeded); }
void setHasChildrenNeeded() { state = State(state | HasChildrenNeeded); } void setHasChildrenNeeded() { state = State(state | HasChildrenNeeded); }
void setHasChildrenUnneeded() { state = State(state & ~HasChildrenNeeded); } void setHasChildrenUnneeded() { state = State(state & ~HasChildrenNeeded); }
void setHasChildren(bool c) { hasChildren = c; setHasChildrenUnneeded(); void setHasChildren(bool c) { hasChildren = c; setHasChildrenUnneeded();
if (!c) setChildrenUnneeded(); } if (!c) setChildrenUnneeded(); }
QString toString() const; bool isLocal() const { return iname.startsWith("local."); }
QString toToolTip() const;
bool isLocal() const { return iname.startsWith("local."); }
bool isWatcher() const { return iname.startsWith("watch."); } bool isWatcher() const { return iname.startsWith("watch."); }
bool isValid() const { return !iname.isEmpty(); } bool isValid() const { return !iname.isEmpty(); }
bool isEqual(const WatchData &other) const; bool isEqual(const WatchData &other) const;
quint64 coreAddress() const;
QByteArray hexAddress() const; void setError(const QString &);
void setValue(const QString &);
void setValueToolTip(const QString &);
void setType(const QByteArray &, bool guessChildrenFromType = true);
void setAddress(const quint64 &);
void setHexAddress(const QByteArray &a);
QString toString() const;
QString toToolTip() const;
static QString msgNotInScope(); static QString msgNotInScope();
static QString shadowedName(const QString &name, int seen); static QString shadowedName(const QString &name, int seen);
static const QString &shadowedNameFormat(); static const QString &shadowedNameFormat();
public: quint64 coreAddress() const;
QByteArray iname; // Internal name sth like 'local.baz.public.a' QByteArray hexAddress() const;
QByteArray exp; // The expression
QString name; // Displayed name
QString value; // Displayed value
QByteArray editvalue; // Displayed value
int editformat; // Format of displayed value
QString valuetooltip; // Tooltip in value column
QString typeFormats; // Selection of formats of displayed value
QByteArray type; // Type for further processing
QString displayedType;// Displayed type (optional)
QByteArray variable; // Name of internal Gdb variable if created
quint64 address; // Displayed address
QString framekey; // Key for type cache
QScriptValue scriptValue; // If needed...
bool hasChildren;
int generation; // When updated?
bool valueEnabled; // Value will be greyed out or not
bool valueEditable; // Value will be editable
bool error;
QByteArray dumperFlags;
public: public:
int source; // Originated from dumper or symbol evaluation? (CDB only) quint64 id; // Token for the engine for internal mapping
quint64 objectId; // Object id used for the QMLEngine qint32 state; // 'needed' flags;
int state; QByteArray iname; // Internal name sth like 'local.baz.public.a'
QByteArray exp; // The expression
QString name; // Displayed name
QString value; // Displayed value
QByteArray editvalue; // Displayed value
qint32 editformat; // Format of displayed value
QString valuetooltip; // Tooltip in value column
QString typeFormats; // Selection of formats of displayed value
QByteArray type; // Type for further processing
QString displayedType;// Displayed type (optional)
quint64 address; // Displayed address
qint32 generation; // When updated?
bool hasChildren;
bool valueEnabled; // Value will be greyed out or not
bool valueEditable; // Value will be editable
bool error;
bool changed; bool changed;
int sortId; qint32 sortId;
QByteArray dumperFlags;
Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::WatchHandler)
public:
// FIXME: this is engine specific data that should be mapped internally
QByteArray variable; // Name of internal Gdb variable if created
qint32 source; // Originated from dumper or symbol evaluation? (CDB only)
}; };
} // namespace Internal } // namespace Internal

View File

@@ -273,16 +273,6 @@ bool isKeyWord(const QString &exp)
|| exp == QLatin1String("while"); || exp == QLatin1String("while");
} }
bool isPointerType(const QByteArray &type)
{
return type.endsWith('*') || type.endsWith("* const");
}
bool isCharPointerType(const QByteArray &type)
{
return type == "char *" || type == "const char *" || type == "char const *";
}
bool startsWithDigit(const QString &str) bool startsWithDigit(const QString &str)
{ {
return !str.isEmpty() && str.at(0).isDigit(); return !str.isEmpty() && str.at(0).isDigit();
@@ -540,69 +530,11 @@ QString extractTypeFromPTypeOutput(const QString &str)
return res.simplified(); return res.simplified();
} }
bool isIntType(const QByteArray &type)
{
if (type.isEmpty())
return false;
switch (type.at(0)) {
case 'b':
return type == "bool";
case 'c':
return type == "char";
case 'i':
return type == "int" || type == "int64";
case 'l':
return type == "long"
|| type == "long long";
case 'p':
return type == "ptrdiff_t";
case 'q':
return type == "qint16" || type == "quint16"
|| type == "qint32" || type == "quint32"
|| type == "qint64" || type == "quint64";
case 's':
return type == "short"
|| type == "signed"
|| type == "size_t"
|| type == "std::size_t"
|| type == "std::ptrdiff_t"
|| type.startsWith("signed ");
case 'u':
return type == "unsigned"
|| type.startsWith("unsigned ");
default:
return false;
}
}
bool isSymbianIntType(const QByteArray &type) bool isSymbianIntType(const QByteArray &type)
{ {
return type == "TInt" || type == "TBool"; return type == "TInt" || type == "TBool";
} }
bool isFloatType(const QByteArray &type)
{
return type == "float" || type == "double" || type == "qreal";
}
bool isIntOrFloatType(const QByteArray &type)
{
return isIntType(type) || isFloatType(type);
}
GuessChildrenResult guessChildren(const QByteArray &type)
{
if (isIntOrFloatType(type))
return HasNoChildren;
if (isCharPointerType(type))
return HasNoChildren;
if (isPointerType(type))
return HasChildren;
if (type.endsWith("QString"))
return HasNoChildren;
return HasPossiblyChildren;
}
QByteArray sizeofTypeExpression(const QByteArray &type, QtDumperHelper::Debugger debugger) QByteArray sizeofTypeExpression(const QByteArray &type, QtDumperHelper::Debugger debugger)
{ {
if (type.endsWith('*')) if (type.endsWith('*'))