Commit 90ee1cc1 authored by Friedemann Kleint's avatar Friedemann Kleint

Debugger: Add infrastructure for message tracepoints.

Add context menu to add a 'message tracepoint', that is,
a trace point that outputs a user message and continues.
Intended to be a replacement for manually inserting
a qDebug() into the code to understand the call sequence.
Yet to be implemented for gdb.

Change-Id: I1c303001421fbbae74d98d15d52718579350db6e
Rubber-stamped-by: hjk
Reviewed-on: http://codereview.qt.nokia.com/756Reviewed-by: default avatarQt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: default avatarFriedemann Kleint <Friedemann.Kleint@nokia.com>
parent bcb46f3e
......@@ -329,6 +329,8 @@ void BreakHandler::saveBreakpoints()
map.insert(_("command"), data.command);
if (!data.expression.isEmpty())
map.insert(_("expression"), data.expression);
if (!data.message.isEmpty())
map.insert(_("message"), data.message);
list.append(map);
}
debuggerCore()->setSessionValue("Breakpoints", list);
......@@ -387,6 +389,9 @@ void BreakHandler::loadBreakpoints()
v = map.value(_("expression"));
if (v.isValid())
data.expression = v.toString();
v = map.value(_("message"));
if (v.isValid())
data.message = v.toString();
appendBreakpoint(data);
}
//qDebug() << "LOADED BREAKPOINTS" << this << list.size();
......@@ -719,6 +724,7 @@ PROPERTY(QByteArray, condition, setCondition)
GETTER(int, lineNumber)
PROPERTY(quint64, address, setAddress)
PROPERTY(QString, expression, setExpression)
PROPERTY(QString, message, setMessage)
PROPERTY(int, ignoreCount, setIgnoreCount)
bool BreakHandler::isEnabled(BreakpointModelId id) const
......@@ -1494,6 +1500,12 @@ QString BreakHandler::BreakpointItem::toToolTip() const
<< "</td><td>" << response.command
<< "</td></tr>";
}
if (!data.message.isEmpty() || !response.message.isEmpty()) {
str << "<tr><td>" << tr("Message:")
<< "</td><td>" << data.message
<< "</td><td>" << response.message
<< "</td></tr>";
}
if (!data.condition.isEmpty() || !response.condition.isEmpty()) {
str << "<tr><td>" << tr("Condition:")
<< "</td><td>" << data.condition
......
......@@ -121,6 +121,8 @@ public:
void setFunctionName(BreakpointModelId, const QString &functionName);
QString expression(BreakpointModelId id) const;
void setExpression(BreakpointModelId, const QString &expression);
QString message(BreakpointModelId id) const;
void setMessage(BreakpointModelId, const QString &m);
BreakpointType type(BreakpointModelId id) const;
void setType(BreakpointModelId id, const BreakpointType &type);
quint64 address(BreakpointModelId id) const;
......
......@@ -207,6 +207,8 @@ BreakpointParts BreakpointParameters::differencesTo
parts |= ModulePart;
if (command != rhs.command)
parts |= CommandPart;
if (message != rhs.message)
parts |= MessagePart;
return parts;
}
......@@ -275,6 +277,8 @@ QString BreakpointParameters::toString() const
ts << " Module: " << module;
if (!command.isEmpty())
ts << " Command: " << command;
if (!message.isEmpty())
ts << " Message: " << message;
return result;
}
......
......@@ -182,11 +182,12 @@ enum BreakpointParts
TypePart = 0x400,
PathUsagePart = 0x800,
CommandPart = 0x1000,
MessagePart = 0x2000,
AllParts = FileAndLinePart|FunctionPart
|ExpressionPart|AddressPart|ConditionPart
|IgnoreCountPart|ThreadSpecPart|ModulePart|TracePointPart
|EnabledPart|TypePart|PathUsagePart|CommandPart
|EnabledPart|TypePart|PathUsagePart|CommandPart|MessagePart
};
inline void operator|=(BreakpointParts &p, BreakpointParts r)
......@@ -229,6 +230,7 @@ public:
QString functionName;
QString module; //!< module for file name
QString command; //!< command to execute
QString message; //!< message
bool tracepoint;
};
......
......@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>543</width>
<height>427</height>
<height>440</height>
</rect>
</property>
<property name="windowTitle">
......@@ -201,6 +201,19 @@
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelMessage">
<property name="text">
<string>&amp;Message:</string>
</property>
<property name="buddy">
<cstring>lineEditMessage</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="lineEditMessage"/>
</item>
</layout>
</item>
<item>
......
......@@ -196,6 +196,7 @@ void BreakpointDialog::setPartsEnabled(unsigned partsMask)
m_ui.labelUseFullPath->setEnabled(partsMask & FileAndLinePart);
m_ui.comboBoxPathUsage->setEnabled(partsMask & FileAndLinePart);
m_ui.labelFunction->setEnabled(partsMask & FunctionPart);
m_ui.lineEditFunction->setEnabled(partsMask & FunctionPart);
......@@ -252,6 +253,7 @@ void BreakpointDialog::getParts(unsigned partsMask, BreakpointParameters *data)
{
data->enabled = m_ui.checkBoxEnabled->isChecked();
data->command = m_ui.lineEditCommand->text().trimmed();
data->message = m_ui.lineEditMessage->text();
if (partsMask & FileAndLinePart) {
data->lineNumber = m_ui.lineEditLineNumber->text().toInt();
......@@ -285,6 +287,7 @@ void BreakpointDialog::setParts(unsigned mask, const BreakpointParameters &data)
m_ui.checkBoxEnabled->setChecked(data.enabled);
m_ui.comboBoxPathUsage->setCurrentIndex(data.pathUsage);
m_ui.lineEditCommand->setText(data.command);
m_ui.lineEditMessage->setText(data.message);
if (mask & FileAndLinePart) {
m_ui.pathChooserFileName->setPath(data.fileName);
......
......@@ -1863,6 +1863,10 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
id = BreakpointModelId(breakpointIdG.data().toInt());
if (id && breakHandler()->engineBreakpointIds(this).contains(id)) {
const BreakpointResponse parameters = breakHandler()->response(id);
if (!parameters.message.isEmpty()) {
showMessage(parameters.message + QLatin1Char('\n'), AppOutput);
showMessage(parameters.message, LogMisc);
}
// Trace point? Just report.
number = parameters.id.majorPart();
if (parameters.tracepoint) {
......
......@@ -123,6 +123,7 @@
#include <QtGui/QTextCursor>
#include <QtGui/QToolButton>
#include <QtGui/QTreeWidget>
#include <QtGui/QInputDialog>
#include <climits>
......@@ -428,6 +429,27 @@ const char * const SNAPSHOT_KEY = "Ctrl+D,Ctrl+S";
namespace Internal {
// To be passed through margin menu action's data
struct BreakpointMenuContextData : public ContextData
{
enum Mode
{
Breakpoint,
MessageTracePoint
};
BreakpointMenuContextData() : mode(Breakpoint) {}
Mode mode;
};
} // namespace Internal
} // namespace Debugger
Q_DECLARE_METATYPE(Debugger::Internal::BreakpointMenuContextData)
namespace Debugger {
namespace Internal {
// FIXME: Outdated?
// The createCdbEngine function takes a list of options pages it can add to.
// This allows for having a "enabled" toggle on the page independently
......@@ -597,11 +619,33 @@ public slots:
{
const QAction *action = qobject_cast<const QAction *>(sender());
QTC_ASSERT(action, return);
const ContextData data = action->data().value<ContextData>();
const BreakpointMenuContextData data = action->data().value<BreakpointMenuContextData>();
QString message;
if (data.mode == BreakpointMenuContextData::MessageTracePoint) {
if (data.address) {
//: Message tracepoint: Address hit.
message = tr("0x%1 hit").arg(data.address, 0, 16);
} else {
//: Message tracepoint: %1 file, %2 line %3 function hit.
message = tr("%1:%2 %3() hit").arg(QFileInfo(data.fileName).fileName()).
arg(data.lineNumber).
arg(cppFunctionAt(data.fileName, data.lineNumber));
}
QInputDialog dialog; // Create wide input dialog.
dialog.setWindowFlags(dialog.windowFlags()
& ~(Qt::WindowContextHelpButtonHint|Qt::MSWindowsFixedSizeDialogHint));
dialog.resize(600, dialog.height());
dialog.setWindowTitle(tr("Add Message Tracepoint"));
dialog.setLabelText (tr("Message:"));
dialog.setTextValue(message);
if (dialog.exec() != QDialog::Accepted || dialog.textValue().isEmpty())
return;
message = dialog.textValue();
}
if (data.address)
toggleBreakpointByAddress(data.address);
toggleBreakpointByAddress(data.address, message);
else
toggleBreakpointByFileAndLine(data.fileName, data.lineNumber);
toggleBreakpointByFileAndLine(data.fileName, data.lineNumber, message);
}
void breakpointRemoveMarginActionTriggered()
......@@ -678,8 +722,10 @@ public slots:
void activatePreviousMode();
void activateDebugMode();
void toggleBreakpoint();
void toggleBreakpointByFileAndLine(const QString &fileName, int lineNumber);
void toggleBreakpointByAddress(quint64 address);
void toggleBreakpointByFileAndLine(const QString &fileName, int lineNumber,
const QString &tracePointMessage = QString());
void toggleBreakpointByAddress(quint64 address,
const QString &tracePointMessage = QString());
void onModeChanged(Core::IMode *mode);
void onCoreAboutToOpen();
void showSettingsDialog();
......@@ -1638,7 +1684,7 @@ void DebuggerPluginPrivate::requestContextMenu(ITextEditor *editor,
if (!isEditorDebuggable(editor))
return;
ContextData args;
BreakpointMenuContextData args;
args.lineNumber = lineNumber;
bool contextUsable = true;
......@@ -1700,6 +1746,17 @@ void DebuggerPluginPrivate::requestContextMenu(ITextEditor *editor,
connect(act, SIGNAL(triggered()),
SLOT(breakpointSetMarginActionTriggered()));
menu->addAction(act);
// Message trace point
args.mode = BreakpointMenuContextData::MessageTracePoint;
const QString tracePointText = args.address
? tr("Set Message Tracepoint at 0x%1...").arg(args.address, 0, 16)
: tr("Set Message Tracepoint at line %1...").arg(lineNumber);
act = new QAction(tracePointText, menu);
act->setData(QVariant::fromValue(args));
act->setEnabled(contextUsable);
connect(act, SIGNAL(triggered()),
SLOT(breakpointSetMarginActionTriggered()));
menu->addAction(act);
}
// Run to, jump to line below in stopped state.
if (currentEngine()->state() == InferiorStopOk && contextUsable) {
......@@ -1741,7 +1798,7 @@ void DebuggerPluginPrivate::toggleBreakpoint()
}
void DebuggerPluginPrivate::toggleBreakpointByFileAndLine(const QString &fileName,
int lineNumber)
int lineNumber, const QString &tracePointMessage)
{
BreakHandler *handler = m_breakHandler;
BreakpointModelId id =
......@@ -1753,13 +1810,16 @@ void DebuggerPluginPrivate::toggleBreakpointByFileAndLine(const QString &fileNam
handler->removeBreakpoint(id);
} else {
BreakpointParameters data(BreakpointByFileAndLine);
data.tracepoint = !tracePointMessage.isEmpty();
data.message = tracePointMessage;
data.fileName = fileName;
data.lineNumber = lineNumber;
handler->appendBreakpoint(data);
}
}
void DebuggerPluginPrivate::toggleBreakpointByAddress(quint64 address)
void DebuggerPluginPrivate::toggleBreakpointByAddress(quint64 address,
const QString &tracePointMessage)
{
BreakHandler *handler = m_breakHandler;
BreakpointModelId id = handler->findBreakpointByAddress(address);
......@@ -1768,6 +1828,8 @@ void DebuggerPluginPrivate::toggleBreakpointByAddress(quint64 address)
handler->removeBreakpoint(id);
} else {
BreakpointParameters data(BreakpointByAddress);
data.tracepoint = !tracePointMessage.isEmpty();
data.message = tracePointMessage;
data.address = address;
handler->appendBreakpoint(data);
}
......
......@@ -191,6 +191,7 @@ QDataStream &operator<<(QDataStream &stream, const BreakpointParameters &s)
stream << s.tracepoint;
stream << s.module;
stream << s.command;
stream << s.message;
return stream;
}
......@@ -210,6 +211,7 @@ QDataStream &operator>>(QDataStream &stream, BreakpointParameters &s)
stream >> b; s.tracepoint = b;
stream >> str ; s.module = str;
stream >> str ; s.command = str;
stream >> str ; s.message = str;
return stream;
}
......
......@@ -678,6 +678,14 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
return expr.toUtf8();
}
QString cppFunctionAt(const QString &fileName, int line)
{
using namespace CppTools;
using namespace CPlusPlus;
CppModelManagerInterface *modelManager = CppModelManagerInterface::instance();
return AbstractEditorSupport::functionAt(modelManager,
fileName, line, 1);
}
//////////////////////////////////////////////////////////////////////
//
......
......@@ -96,7 +96,7 @@ QString quoteUnprintableLatin1(const QByteArray &ba);
bool isCppEditor(Core::IEditor *editor);
QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
int *line, int *column, QString *function = 0);
QString cppFunctionAt(const QString &fileName, int line);
// Decode string data as returned by the dumper helpers.
QString decodeData(const QByteArray &baIn, int encoding);
......
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