return s << data.functionName << data.fileName << data.lineNumber;
}
-typedef JSAgentStackData JSBreakpointData;
+struct JSAgentBreakpointData
+{
+ QByteArray functionName;
+ QByteArray fileName;
+ qint32 lineNumber;
+};
+
+typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints;
+
+QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data)
+{
+ return s << data.functionName << data.fileName << data.lineNumber;
+}
+
+QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data)
+{
+ return s >> data.functionName >> data.fileName >> data.lineNumber;
+}
+
+bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2)
+{
+ return b1.lineNumber == b2.lineNumber && b1.fileName == b2.fileName;
+}
+
+uint qHash(const JSAgentBreakpointData &b)
+{
+ return b.lineNumber ^ qHash(b.fileName);
+}
class JSDebuggerAgentPrivate
{
int stepCount;
QEventLoop loop;
- QHash <qint64, QString> filenames;
- QSet< QPair<QString, qint32> > breakpointList;
+ QHash<qint64, QString> filenames;
+ JSAgentBreakpoints breakpoints;
QStringList watchExpressions;
QSet<qint64> knownObjectIds;
};
return; //no re-entrency
// check breakpoints
- if (!breakpointList.isEmpty()) {
+ if (!breakpoints.isEmpty()) {
QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId);
QScriptContext *ctx = engine()->currentContext();
QScriptContextInfo info(ctx);
QPair<QString, qint32> key = qMakePair(filename, lineNumber);
it = filenames.insert(scriptId, filename);
}
- QPair<QString, qint32> key = qMakePair(*it, lineNumber);
- if (breakpointList.contains(key)) {
+ JSAgentBreakpointData bp;
+ bp.fileName = it->toUtf8();
+ bp.lineNumber = lineNumber;
+ if (breakpoints.contains(bp)) {
stopped();
return;
}
QByteArray command;
ds >> command;
if (command == "BREAKPOINTS") {
- ds >> breakpointList;
+ ds >> breakpoints;
+ //qDebug() << "BREAKPOINTS";
+ //foreach (const JSAgentBreakpointData &bp, breakpoints)
+ // qDebug() << "BREAKPOINT: " << bp.fileName << bp.lineNumber;
} else if (command == "WATCH_EXPRESSIONS") {
ds >> watchExpressions;
} else if (command == "STEPOVER") {
{
for (int index = size() - 1; index >= 0; --index) {
BreakpointData *bd = at(index);
- if (bd->type == BreakpointData::WatchpointType && bd->address == address)
+ if (bd->isWatchpoint() && bd->address == address)
return index;
}
return -1;
const BreakpointData *data = at(index);
QMap<QString, QVariant> map;
// Do not persist Watchpoints.
- //if (data->type == BreakpointData::WatchpointType)
+ //if (data->isWatchpoint())
// continue;
- if (data->type != BreakpointData::BreakpointType)
+ if (data->type != BreakpointByFileAndLine)
map.insert(_("type"), data->type);
if (!data->fileName.isEmpty())
map.insert(_("filename"), data->fileName);
data->useFullPath = bool(v.toInt());
v = map.value(_("type"));
if (v.isValid())
- data->type = BreakpointData::Type(v.toInt());
+ data->type = BreakpointType(v.toInt());
data->setMarkerFileName(data->fileName);
data->setMarkerLineNumber(data->lineNumber);
append(data);
return str.isEmpty() ? empty : str;
}
if (role == Qt::DecorationRole) {
- if (data->type == BreakpointData::WatchpointType)
+ if (data->isWatchpoint())
return m_watchpointIcon;
if (!data->enabled)
return m_disabledBreakpointIcon;
case 7:
if (role == Qt::DisplayRole) {
QString displayValue;
- const quint64 effectiveAddress = data->type == BreakpointData::WatchpointType ?
- data->address : data->bpAddress;
+ const quint64 effectiveAddress
+ = data->isWatchpoint() ? data->address : data->bpAddress;
if (effectiveAddress)
displayValue += QString::fromAscii("0x%1").arg(effectiveAddress, 0, 16);
if (!data->bpState.isEmpty()) {
BreakpointData::BreakpointData() :
id(nextBPId()), enabled(true),
- pending(true), type(BreakpointType),
+ pending(true), type(BreakpointByFileAndLine),
ignoreCount(0), lineNumber(0), address(0),
useFullPath(false),
bpIgnoreCount(0), bpLineNumber(0),
data->threadSpec = threadSpec;
data->funcName = funcName;
data->useFullPath = useFullPath;
- if (isSetByFunction()) {
+ if (data->type == BreakpointByFunction) {
// FIXME: Would removing it be better then leaving this
// "history" around?
data->m_markerFileName = m_markerFileName;
QString BreakpointData::toToolTip() const
{
+ QString t = tr("Unknown Breakpoint Type");
+ switch (type) {
+ case BreakpointByFileAndLine:
+ t = tr("Breakpoint by File and Line");
+ break;
+ case BreakpointByFunction:
+ t = tr("Breakpoint by Function");
+ break;
+ case BreakpointByAddress:
+ t = tr("Breakpoint by Address");
+ break;
+ case Watchpoint:
+ t = tr("Watchpoint");
+ break;
+ }
+
QString rc;
QTextStream str(&rc);
str << "<html><body><table>"
<< "<tr><td>" << tr("Breakpoint Number:")
<< "</td><td>" << bpNumber << "</td></tr>"
<< "<tr><td>" << tr("Breakpoint Type:")
- << "</td><td>"
- << (type == BreakpointType ? tr("Breakpoint")
- : type == WatchpointType ? tr("Watchpoint")
- : tr("Unknown breakpoint type"))
- << "</td></tr>"
+ << "</td><td>" << t << "</td></tr>"
<< "<tr><td>" << tr("State:")
<< "</td><td>" << bpState << "</td></tr>"
<< "</table><br><hr><table>"
<< "<tr><td>" << tr("Internal Number:")
<< "</td><td>—</td><td>" << bpNumber << "</td></tr>"
<< "<tr><td>" << tr("File Name:")
- << "</td><td>" << QDir::toNativeSeparators(fileName) << "</td><td>" << QDir::toNativeSeparators(bpFileName) << "</td></tr>"
+ << "</td><td>" << QDir::toNativeSeparators(fileName)
+ << "</td><td>" << QDir::toNativeSeparators(bpFileName) << "</td></tr>"
<< "<tr><td>" << tr("Function Name:")
<< "</td><td>" << funcName << "</td><td>" << bpFuncName << "</td></tr>"
<< "<tr><td>" << tr("Line Number:") << "</td><td>";
//
//////////////////////////////////////////////////////////////////
+enum BreakpointType
+{
+ BreakpointByFileAndLine,
+ BreakpointByFunction,
+ BreakpointByAddress,
+ Watchpoint,
+};
+
class BreakpointData
{
public:
friend class BreakHandler;
public:
- enum Type { BreakpointType, WatchpointType };
-
quint64 id;
bool enabled; // Should we talk to the debugger engine?
bool pending; // Does the debugger engine know about us already?
- Type type; // Type of breakpoint.
+ BreakpointType type; // Type of breakpoint.
// This "user requested information" will get stored in the session.
QString fileName; // Short name of source file.
void setMarkerLineNumber(int lineNumber);
int markerLineNumber() const { return m_markerLineNumber; }
- bool isSetByFunction() const { return !funcName.isEmpty(); }
- bool isSetByFileAndLine() const { return !fileName.isEmpty(); }
+ bool isWatchpoint() const { return type == Watchpoint; }
+ bool isBreakpoint() const { return type != Watchpoint; } // Enough for now.
Q_DECLARE_TR_FUNCTIONS(BreakHandler)
// TODO: move those to breakhandler
+private:
// Taken from either user input or gdb responses.
QString m_markerFileName; // Used to locate the marker.
int m_markerLineNumber;
comboBoxType->insertItem(3, tr("Address"));
pathChooserFileName->setExpectedKind(Utils::PathChooser::File);
connect(comboBoxType, SIGNAL(activated(int)), SLOT(typeChanged(int)));
- lineEditIgnoreCount->setValidator(new QIntValidator(0, 2147483647, lineEditIgnoreCount));
+ lineEditIgnoreCount->setValidator(
+ new QIntValidator(0, 2147483647, lineEditIgnoreCount));
}
bool BreakpointDialog::showDialog(BreakpointData *data)
enum { debugBP = 0 };
// Convert breakpoint structs
-CdbCore::BreakPoint breakPointFromBreakPointData(const Debugger::Internal::BreakpointData &bpd)
+CdbCore::BreakPoint breakPointFromBreakPointData(const BreakpointData &bpd)
{
CdbCore::BreakPoint rc;
- rc.type = bpd.type == Debugger::Internal::BreakpointData::BreakpointType ?
- CdbCore::BreakPoint::Code : CdbCore::BreakPoint::Data;
+ rc.type = bpd.type == Watchpoint ?
+ CdbCore::BreakPoint::Data :
+ CdbCore::BreakPoint::Code ;
rc.address = bpd.address;
if (!bpd.threadSpec.isEmpty()) {
} else if (child.hasName("thread")) {
data->bpThreadSpec = child.data();
} else if (child.hasName("type")) {
- if (child.data().contains("reakpoint")) // "breakpoint", "hw breakpoint"
- data->type = BreakpointData::BreakpointType;
- else // FIXME: Incomplete list of cases.
- data->type = BreakpointData::WatchpointType;
+ // FIXME: This should not change the type.
+ //if (child.data().contains("reakpoint")) // "breakpoint", "hw breakpoint"
+ // ; // data->type = BreakpointData::BreakpointType;
+ //else // FIXME: Incomplete list of cases.
+ // data->type = Watchpoint;
}
// This field is not present. Contents needs to be parsed from
// the plain "ignore" response.
const BreakpointData *data = breakHandler()->at(index);
// Set up fallback in case of pending breakpoints which aren't handled
// by the MI interface.
- if (data->type == BreakpointData::WatchpointType) {
+ if (data->type == Watchpoint) {
postCommand("watch " + bpAddressSpec(data->address),
NeedsStop | RebuildBreakpointModel,
CB(handleWatchInsert), index);
namespace Debugger {
namespace Internal {
+struct JSAgentBreakpointData
+{
+ QByteArray functionName;
+ QByteArray fileName;
+ qint32 lineNumber;
+};
+
+uint qHash(const JSAgentBreakpointData &b)
+{
+ return b.lineNumber ^ qHash(b.fileName);
+}
+
+QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data)
+{
+ return s << data.functionName << data.fileName << data.lineNumber;
+}
+
+QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data)
+{
+ return s >> data.functionName >> data.fileName >> data.lineNumber;
+}
+
+bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2)
+{
+ return b1.lineNumber == b2.lineNumber && b1.fileName == b2.fileName;
+}
+
+typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints;
+
+
QDataStream &operator>>(QDataStream &s, WatchData &data)
{
data = WatchData();
{
Internal::BreakHandler *handler = breakHandler();
//bool updateNeeded = false;
- QSet< QPair<QString, qint32> > breakList;
+ Internal::JSAgentBreakpoints breakpoints;
for (int index = 0; index != handler->size(); ++index) {
Internal::BreakpointData *data = handler->at(index);
QString processedFilename = data->fileName;
if (isShadowBuildProject())
processedFilename = toShadowBuildFilename(data->fileName);
- breakList << qMakePair(processedFilename, data->lineNumber);
+ Internal::JSAgentBreakpointData bp;
+ bp.fileName = processedFilename.toUtf8();
+ bp.lineNumber = data->lineNumber;
+ bp.functionName = data->funcName.toUtf8();
+ breakpoints.insert(bp);
}
QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly);
rs << QByteArray("BREAKPOINTS");
- rs << breakList;
- //qDebug() << Q_FUNC_INFO << breakList;
+ rs << breakpoints;
+ //qDebug() << Q_FUNC_INFO << breakpoints;
sendMessage(reply);
}
bool QmlEngine::acceptsBreakpoint(const Internal::BreakpointData *br)
{
- return br->fileName.endsWith(QLatin1String("qml"))
- || br->fileName.endsWith(QLatin1String("js"));
+ return br->fileName.endsWith(QLatin1String(".qml"))
+ || br->fileName.endsWith(QLatin1String(".js"));
}
void QmlEngine::loadSymbols(const QString &moduleName)
QByteArray command;
stream >> command;
- showMessage(QLatin1String("RECEIVED RESPONSE: ") + Internal::quoteUnprintableLatin1(message));
+ showMessage(QLatin1String("RECEIVED RESPONSE: ")
+ + Internal::quoteUnprintableLatin1(message));
+
if (command == "STOPPED") {
- if (state() == InferiorRunOk) {
+ if (state() == InferiorRunOk)
notifyInferiorSpontaneousStop();
- }
Internal::StackFrames stackFrames;
QList<Internal::WatchData> watches;
// Make breakpoint non-pending
//
QString file;
+ QString function;
int line = -1;
if (!stackFrames.isEmpty()) {
file = stackFrames.at(0).file;
line = stackFrames.at(0).line;
+ function = stackFrames.at(0).function;
if (isShadowBuildProject()) {
file = fromShadowBuildFilename(file);
Internal::BreakpointData *data = handler->at(index);
QString processedFilename = data->fileName;
- if (processedFilename == file
- && data->lineNumber == line) {
+ if (processedFilename == file && data->lineNumber == line) {
data->pending = false;
data->bpFileName = file;
data->bpLineNumber = line;
+ data->bpFuncName = function;
handler->updateMarker(data);
}
}
const int index = handler->findWatchPointIndexByAddress(address);
if (index == -1) {
BreakpointData *data = new BreakpointData;
- data->type = BreakpointData::WatchpointType;
+ data->type = Watchpoint;
data->address = address;
handler->appendBreakpoint(data);
} else {