forked from qt-creator/qt-creator
Merge commit 'origin/1.1'
This commit is contained in:
6
dist/changes-1.1.0
vendored
6
dist/changes-1.1.0
vendored
@@ -13,11 +13,9 @@ General
|
||||
* Completely reworked editor split mechanism.
|
||||
|
||||
Editing
|
||||
* Completion for constructors in variable initialization.
|
||||
* Some support for Obj-C++ //TODO: what does that mean more concrete?
|
||||
* Some support for doxygen style comments //TODO: what does that mean more concrete?
|
||||
* More intelligent adding of braces.
|
||||
* Improved function argument completion.
|
||||
* Improved function argument hint.
|
||||
* More checkpoints in editor history.
|
||||
* Ctrl-click for jumping to a symbol definition.
|
||||
* Context help for form editor widgets.
|
||||
@@ -40,12 +38,12 @@ Debugging
|
||||
* Make strategy to load shared objects configurable (auto-solib-add).
|
||||
* Maximum stack depth configurable.
|
||||
* Improved interaction in the Locals&Watchers view.
|
||||
* Experimental cdb debugger.
|
||||
|
||||
Wizards
|
||||
* It is now possible to choose file suffixes in the options dialog.
|
||||
* Code of language change event is now generated correctly (added call
|
||||
to base class).
|
||||
* Generated header guards now adapt to file extension.
|
||||
|
||||
Designer
|
||||
* Added signal/slot editor.
|
||||
|
||||
@@ -223,14 +223,13 @@ QList<Symbol *> LookupContext::resolve(Name *name, const QList<Scope *> &visible
|
||||
continue;
|
||||
|
||||
if (q->nameCount() > 1) {
|
||||
Name *classOrNamespaceName = 0;
|
||||
|
||||
if (q->nameCount() == 1)
|
||||
classOrNamespaceName = q->nameAt(0);
|
||||
else
|
||||
classOrNamespaceName = control()->qualifiedNameId(q->names(),
|
||||
q->nameCount() - 1);
|
||||
Name *classOrNamespaceName = control()->qualifiedNameId(q->names(),
|
||||
q->nameCount() - 1);
|
||||
|
||||
if (Identifier *classOrNamespaceNameId = identifier(classOrNamespaceName)) {
|
||||
if (classOrNamespaceNameId->isEqualTo(id))
|
||||
continue;
|
||||
}
|
||||
|
||||
const QList<Symbol *> resolvedClassOrNamespace =
|
||||
resolveClassOrNamespace(classOrNamespaceName, visibleScopes);
|
||||
@@ -455,7 +454,7 @@ void LookupContext::expandFunction(Scope *scope,
|
||||
expandedScopes->append(function->arguments());
|
||||
if (QualifiedNameId *q = function->name()->asQualifiedNameId()) {
|
||||
Name *nestedNameSpec = 0;
|
||||
if (q->nameCount() == 1 && q->isGlobal())
|
||||
if (q->nameCount() == 1)
|
||||
nestedNameSpec = q->nameAt(0);
|
||||
else
|
||||
nestedNameSpec = control()->qualifiedNameId(q->names(), q->nameCount() - 1,
|
||||
|
||||
@@ -1336,13 +1336,16 @@ void EditorManager::updateActions()
|
||||
m_d->m_revertToSavedAction->setEnabled(curEditor != 0
|
||||
&& !curEditor->file()->fileName().isEmpty() && curEditor->file()->isModified());
|
||||
|
||||
m_d->m_saveAsAction->setText(tr("Save %1 As...").arg(fName));
|
||||
m_d->m_saveAction->setText(tr("&Save %1").arg(fName));
|
||||
m_d->m_revertToSavedAction->setText(tr("Revert %1 to Saved").arg(fName));
|
||||
QString quotedName;
|
||||
if (!fName.isEmpty())
|
||||
quotedName = '"' + fName + '"';
|
||||
m_d->m_saveAsAction->setText(tr("Save %1 As...").arg(quotedName));
|
||||
m_d->m_saveAction->setText(tr("&Save %1").arg(quotedName));
|
||||
m_d->m_revertToSavedAction->setText(tr("Revert %1 to Saved").arg(quotedName));
|
||||
|
||||
|
||||
m_d->m_closeCurrentEditorAction->setEnabled(curEditor != 0);
|
||||
m_d->m_closeCurrentEditorAction->setText(tr("Close %1").arg(fName));
|
||||
m_d->m_closeCurrentEditorAction->setText(tr("Close %1").arg(quotedName));
|
||||
m_d->m_closeAllEditorsAction->setEnabled(openedCount > 0);
|
||||
|
||||
m_d->m_gotoNextDocHistoryAction->setEnabled(m_d->m_editorHistory.count() > 0);
|
||||
|
||||
@@ -419,11 +419,11 @@ EditorView::EditorView(EditorModel *model, QWidget *parent) :
|
||||
m_statusWidgetButton->setText(tr("Placeholder"));
|
||||
hbox->addWidget(m_statusWidgetButton);
|
||||
|
||||
m_statusHLine->setVisible(false);
|
||||
m_statusWidget->setVisible(false);
|
||||
tl->addWidget(m_statusHLine);
|
||||
tl->addWidget(m_statusWidget);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EditorView::~EditorView()
|
||||
|
||||
@@ -602,22 +602,6 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
|
||||
if (!doc)
|
||||
return link;
|
||||
|
||||
// Handle include directives
|
||||
const unsigned lineno = cursor.blockNumber() + 1;
|
||||
foreach (const Document::Include &incl, doc->includes()) {
|
||||
if (incl.line() == lineno && incl.resolved()) {
|
||||
link.fileName = incl.fileName();
|
||||
link.pos = cursor.block().position();
|
||||
link.length = cursor.block().length();
|
||||
return link;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the last symbol up to the cursor position
|
||||
Symbol *lastSymbol = doc->findSymbolAt(line, column);
|
||||
if (!lastSymbol)
|
||||
return link;
|
||||
|
||||
QTextCursor tc = cursor;
|
||||
|
||||
static TokenUnderCursor tokenUnderCursor;
|
||||
@@ -625,14 +609,27 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
|
||||
QTextBlock block;
|
||||
const SimpleToken tk = tokenUnderCursor(tc, &block);
|
||||
|
||||
if (tk.isLiteral() || tk.isComment()) {
|
||||
// Drop out if we're at a number, string or comment
|
||||
return link;
|
||||
// Handle include directives
|
||||
if (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL)) {
|
||||
const unsigned lineno = cursor.blockNumber() + 1;
|
||||
foreach (const Document::Include &incl, doc->includes()) {
|
||||
if (incl.line() == lineno && incl.resolved()) {
|
||||
link.fileName = incl.fileName();
|
||||
link.pos = cursor.block().position() + tk.position() + 1;
|
||||
link.length = tk.length() - 2;
|
||||
return link;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tk.isNot(T_IDENTIFIER))
|
||||
return link;
|
||||
|
||||
// Find the last symbol up to the cursor position
|
||||
Symbol *lastSymbol = doc->findSymbolAt(line, column);
|
||||
if (!lastSymbol)
|
||||
return link;
|
||||
|
||||
const int nameStart = tk.position();
|
||||
const int nameLength = tk.length();
|
||||
const int endOfName = nameStart + nameLength;
|
||||
@@ -668,7 +665,7 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
|
||||
def = findDefinition(symbol);
|
||||
|
||||
link = linkToSymbol(def ? def : symbol);
|
||||
link.pos = nameStart;
|
||||
link.pos = block.position() + nameStart;
|
||||
link.length = nameLength;
|
||||
return link;
|
||||
|
||||
|
||||
@@ -383,9 +383,9 @@ void FunctionArgumentWidget::updateHintText()
|
||||
|
||||
const QDesktopWidget *desktop = QApplication::desktop();
|
||||
#ifdef Q_OS_MAC
|
||||
const QRect screen = desktop->availableGeometry(desktop->screenNumber(m_popupFrame));
|
||||
const QRect screen = desktop->availableGeometry(desktop->screenNumber(m_editor->widget()));
|
||||
#else
|
||||
const QRect screen = desktop->screenGeometry(desktop->screenNumber(m_popupFrame));
|
||||
const QRect screen = desktop->screenGeometry(desktop->screenNumber(m_editor->widget()));
|
||||
#endif
|
||||
|
||||
const QSize sz = m_popupFrame->sizeHint();
|
||||
|
||||
@@ -314,6 +314,10 @@ DebuggerSettings *theDebuggerSettings()
|
||||
item->setDefaultValue(20);
|
||||
instance->insertItem(MaximalStackDepth, item);
|
||||
|
||||
item = new SavedAction(instance);
|
||||
item->setText(QObject::tr("Reload full stack"));
|
||||
instance->insertItem(ExpandStack, item);
|
||||
|
||||
item = new SavedAction(instance);
|
||||
item->setText(QObject::tr("Execute line"));
|
||||
instance->insertItem(ExecuteCommand, item);
|
||||
|
||||
@@ -79,6 +79,7 @@ enum DebuggerActionCode
|
||||
|
||||
// Stack
|
||||
MaximalStackDepth,
|
||||
ExpandStack,
|
||||
|
||||
// Watchers & Locals
|
||||
WatchExpression,
|
||||
|
||||
@@ -148,8 +148,7 @@ extern IDebuggerEngine *createWinEngine(DebuggerManager *)
|
||||
#endif
|
||||
extern IDebuggerEngine *createScriptEngine(DebuggerManager *parent);
|
||||
|
||||
DebuggerManager::DebuggerManager() :
|
||||
m_attachCoreAction(0)
|
||||
DebuggerManager::DebuggerManager()
|
||||
{
|
||||
init();
|
||||
}
|
||||
@@ -294,11 +293,9 @@ void DebuggerManager::init()
|
||||
m_attachExternalAction = new QAction(this);
|
||||
m_attachExternalAction->setText(tr("Attach to Running External Application..."));
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
m_attachCoreAction = new QAction(this);
|
||||
m_attachCoreAction->setText(tr("Attach to Core..."));
|
||||
connect(m_attachCoreAction, SIGNAL(triggered()), this, SLOT(attachCore()));
|
||||
#endif
|
||||
|
||||
m_continueAction = new QAction(this);
|
||||
m_continueAction->setText(tr("Continue"));
|
||||
@@ -1172,7 +1169,7 @@ void DebuggerManager::setStatus(int status)
|
||||
if (status == m_status)
|
||||
return;
|
||||
|
||||
if (!isAllowedTransition(m_status, status)) {
|
||||
if (0 && !isAllowedTransition(m_status, status)) {
|
||||
const QString msg = QString::fromLatin1("%1: UNEXPECTED TRANSITION: %2 -> %3").
|
||||
arg(QLatin1String(Q_FUNC_INFO), QLatin1String(stateName(m_status)), QLatin1String(stateName(status)));
|
||||
qWarning("%s", qPrintable(msg));
|
||||
@@ -1193,8 +1190,11 @@ void DebuggerManager::setStatus(int status)
|
||||
|
||||
m_startExternalAction->setEnabled(!started && !starting);
|
||||
m_attachExternalAction->setEnabled(!started && !starting);
|
||||
if (m_attachCoreAction)
|
||||
m_attachCoreAction->setEnabled(!started && !starting);
|
||||
#ifdef Q_OS_WIN
|
||||
m_attachCoreAction->setEnabled(false);
|
||||
#else
|
||||
m_attachCoreAction->setEnabled(!started && !starting);
|
||||
#endif
|
||||
m_watchAction->setEnabled(ready);
|
||||
m_breakAction->setEnabled(true);
|
||||
|
||||
@@ -1372,7 +1372,7 @@ void DebuggerManager::disassemblerDockToggled(bool on)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Sourec files specific stuff
|
||||
// Source files specific stuff
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1449,4 +1449,19 @@ void DebuggerManager::reloadRegisters()
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Testing
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DebuggerManager::runTest(const QString &fileName)
|
||||
{
|
||||
m_executable = fileName;
|
||||
m_processArgs = QStringList() << "--run-debuggee";
|
||||
m_workingDir = QString();
|
||||
if (!startNewDebugger(StartInternal))
|
||||
emit debuggingFinished();
|
||||
}
|
||||
|
||||
#include "debuggermanager.moc"
|
||||
|
||||
@@ -341,6 +341,7 @@ public:
|
||||
private:
|
||||
void init();
|
||||
void setDebuggerType(DebuggerType type);
|
||||
void runTest(const QString &fileName);
|
||||
QDockWidget *createDockForWidget(QWidget *widget);
|
||||
Q_SLOT void createNewDock(QWidget *widget);
|
||||
|
||||
|
||||
@@ -796,6 +796,11 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
|
||||
|
||||
void DebuggerPlugin::extensionsInitialized()
|
||||
{
|
||||
// time gdb -i mi -ex 'debuggerplugin.cpp:800' -ex r -ex q bin/qtcreator.bin
|
||||
QByteArray env = qgetenv("QTC_DEBUGGER_TEST");
|
||||
//qDebug() << "EXTENSIONS INITIALIZED:" << env;
|
||||
if (!env.isEmpty())
|
||||
m_manager->runTest(QString::fromLocal8Bit(env));
|
||||
}
|
||||
|
||||
/*! Activates the previous mode when the current mode is the debug mode. */
|
||||
|
||||
@@ -230,6 +230,9 @@ void GdbEngine::initializeConnections()
|
||||
this, SLOT(reloadRegisters()));
|
||||
connect(theDebuggerAction(FormatNatural), SIGNAL(triggered()),
|
||||
this, SLOT(reloadRegisters()));
|
||||
|
||||
connect(theDebuggerAction(ExpandStack), SIGNAL(triggered()),
|
||||
this, SLOT(reloadFullStack()));
|
||||
}
|
||||
|
||||
void GdbEngine::initializeVariables()
|
||||
@@ -373,16 +376,18 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
||||
|
||||
GdbMi record;
|
||||
while (from != to) {
|
||||
if (*from != ',') {
|
||||
qDebug() << "MALFORMED ASYNC OUTPUT" << from;
|
||||
return;
|
||||
}
|
||||
++from; // skip ','
|
||||
GdbMi data;
|
||||
data.parseResultOrValue(from, to);
|
||||
if (data.isValid()) {
|
||||
//qDebug() << "parsed response: " << data.toString();
|
||||
record.m_children += data;
|
||||
if (*from == ',') {
|
||||
++from; // skip ','
|
||||
data.parseResultOrValue(from, to);
|
||||
if (data.isValid()) {
|
||||
//qDebug() << "parsed response: " << data.toString();
|
||||
record.m_children += data;
|
||||
record.m_type = GdbMi::Tuple;
|
||||
}
|
||||
} else {
|
||||
// happens on archer where we get
|
||||
// 23^running <NL> *running,thread-id="all" <NL> (gdb)
|
||||
record.m_type = GdbMi::Tuple;
|
||||
}
|
||||
}
|
||||
@@ -395,6 +400,10 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
||||
// target-name="/usr/lib/libdrm.so.2",
|
||||
// host-name="/usr/lib/libdrm.so.2",
|
||||
// symbols-loaded="0"
|
||||
} else if (asyncClass == "library-unloaded") {
|
||||
// Archer has 'id="/usr/lib/libdrm.so.2",
|
||||
// target-name="/usr/lib/libdrm.so.2",
|
||||
// host-name="/usr/lib/libdrm.so.2"
|
||||
} else if (asyncClass == "thread-group-created") {
|
||||
// Archer has "{id="28902"}"
|
||||
} else if (asyncClass == "thread-created") {
|
||||
@@ -403,6 +412,8 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
||||
// Archer has "{id="28902"}"
|
||||
} else if (asyncClass == "thread-exited") {
|
||||
//"{id="1",group-id="28902"}"
|
||||
} else if (asyncClass == "thread-selected") {
|
||||
//"{id="2"}"
|
||||
#ifdef Q_OS_MAC
|
||||
} else if (asyncClass == "shlibs-updated") {
|
||||
// MAC announces updated libs
|
||||
@@ -473,14 +484,16 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
||||
|
||||
from = inner;
|
||||
if (from != to) {
|
||||
if (*from != ',') {
|
||||
qDebug() << "MALFORMED RESULT OUTPUT" << from;
|
||||
return;
|
||||
if (*from == ',') {
|
||||
++from;
|
||||
record.data.parseTuple_helper(from, to);
|
||||
record.data.m_type = GdbMi::Tuple;
|
||||
record.data.m_name = "data";
|
||||
} else {
|
||||
// Archer has this
|
||||
record.data.m_type = GdbMi::Tuple;
|
||||
record.data.m_name = "data";
|
||||
}
|
||||
++from;
|
||||
record.data.parseTuple_helper(from, to);
|
||||
record.data.m_type = GdbMi::Tuple;
|
||||
record.data.m_name = "data";
|
||||
}
|
||||
|
||||
//qDebug() << "\nLOG STREAM:" + m_pendingLogStreamOutput;
|
||||
@@ -803,7 +816,7 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type,
|
||||
break;
|
||||
|
||||
case StackListFrames:
|
||||
handleStackListFrames(record);
|
||||
handleStackListFrames(record, cookie.toBool());
|
||||
break;
|
||||
case StackListThreads:
|
||||
handleStackListThreads(record, cookie.toInt());
|
||||
@@ -1301,12 +1314,18 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
||||
#endif
|
||||
}
|
||||
|
||||
void GdbEngine::reloadFullStack()
|
||||
{
|
||||
QString cmd = "-stack-list-frames";
|
||||
sendSynchronizedCommand(cmd, StackListFrames, true);
|
||||
}
|
||||
|
||||
void GdbEngine::reloadStack()
|
||||
{
|
||||
QString cmd = "-stack-list-frames";
|
||||
if (int stackDepth = theDebuggerAction(MaximalStackDepth)->value().toInt())
|
||||
cmd += " 0 " + QString::number(stackDepth);
|
||||
sendSynchronizedCommand(cmd, StackListFrames);
|
||||
sendSynchronizedCommand(cmd, StackListFrames, false);
|
||||
}
|
||||
|
||||
void GdbEngine::handleAsyncOutput2(const GdbMi &data)
|
||||
@@ -2450,7 +2469,7 @@ void GdbEngine::handleStackSelectThread(const GdbResultRecord &record, int)
|
||||
}
|
||||
|
||||
|
||||
void GdbEngine::handleStackListFrames(const GdbResultRecord &record)
|
||||
void GdbEngine::handleStackListFrames(const GdbResultRecord &record, bool isFull)
|
||||
{
|
||||
QList<StackFrame> stackFrames;
|
||||
|
||||
@@ -2501,30 +2520,11 @@ void GdbEngine::handleStackListFrames(const GdbResultRecord &record)
|
||||
topFrame = i;
|
||||
}
|
||||
|
||||
if (n >= theDebuggerAction(MaximalStackDepth)->value().toInt()) {
|
||||
StackFrame frame(n);
|
||||
frame.file = "...";
|
||||
frame.function = "...";
|
||||
frame.from = "...";
|
||||
frame.line = 0;
|
||||
frame.address = "...";
|
||||
stackFrames.append(frame);
|
||||
}
|
||||
bool canExpand = !isFull
|
||||
&& (n >= theDebuggerAction(MaximalStackDepth)->value().toInt());
|
||||
theDebuggerAction(ExpandStack)->setEnabled(canExpand);
|
||||
qq->stackHandler()->setFrames(stackFrames, canExpand);
|
||||
|
||||
qq->stackHandler()->setFrames(stackFrames);
|
||||
|
||||
#if 0
|
||||
if (0 && topFrame != -1) {
|
||||
// updates of locals already triggered early
|
||||
const StackFrame &frame = qq->stackHandler()->currentFrame();
|
||||
if (frame.isUsable())
|
||||
q->gotoLocation(frame.file, frame.line, true);
|
||||
else
|
||||
qDebug() << "FULL NAME NOT USABLE 0: " << frame.file;
|
||||
} else {
|
||||
activateFrame(topFrame);
|
||||
}
|
||||
#else
|
||||
if (topFrame != -1) {
|
||||
// updates of locals already triggered early
|
||||
const StackFrame &frame = qq->stackHandler()->currentFrame();
|
||||
@@ -2533,7 +2533,6 @@ void GdbEngine::handleStackListFrames(const GdbResultRecord &record)
|
||||
else
|
||||
qDebug() << "FULL NAME NOT USABLE 0: " << frame.file << topFrame;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GdbEngine::selectThread(int index)
|
||||
@@ -2562,6 +2561,10 @@ void GdbEngine::activateFrame(int frameIndex)
|
||||
//qDebug() << "ACTIVATE FRAME: " << frameIndex << oldIndex
|
||||
// << stackHandler->currentIndex();
|
||||
|
||||
if (frameIndex == stackHandler->stackSize()) {
|
||||
reloadFullStack();
|
||||
return;
|
||||
}
|
||||
QTC_ASSERT(frameIndex < stackHandler->stackSize(), return);
|
||||
|
||||
if (oldIndex != frameIndex) {
|
||||
|
||||
@@ -277,10 +277,11 @@ private:
|
||||
//
|
||||
// Stack specific stuff
|
||||
//
|
||||
void handleStackListFrames(const GdbResultRecord &record);
|
||||
void handleStackListFrames(const GdbResultRecord &record, bool isFull);
|
||||
void handleStackSelectThread(const GdbResultRecord &record, int cookie);
|
||||
void handleStackListThreads(const GdbResultRecord &record, int cookie);
|
||||
void reloadStack();
|
||||
Q_SLOT void reloadStack();
|
||||
Q_SLOT void reloadFullStack();
|
||||
|
||||
|
||||
//
|
||||
|
||||
@@ -115,18 +115,18 @@ void GdbMi::parseValue(const char *&from, const char *to)
|
||||
{
|
||||
//qDebug() << "parseValue: " << QByteArray::fromUtf16(from, to - from);
|
||||
switch (*from) {
|
||||
case '{':
|
||||
parseTuple(from, to);
|
||||
break;
|
||||
case '[':
|
||||
parseList(from, to);
|
||||
break;
|
||||
case '"':
|
||||
m_type = Const;
|
||||
m_data = parseCString(from, to);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case '{':
|
||||
parseTuple(from, to);
|
||||
break;
|
||||
case '[':
|
||||
parseList(from, to);
|
||||
break;
|
||||
case '"':
|
||||
m_type = Const;
|
||||
m_data = parseCString(from, to);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,52 +211,53 @@ void GdbMi::dumpChildren(QByteArray * str, bool multiline, int indent) const
|
||||
}
|
||||
}
|
||||
|
||||
static QByteArray escaped(QByteArray ba)
|
||||
{
|
||||
ba.replace("\"", "\\\"");
|
||||
return ba;
|
||||
}
|
||||
|
||||
QByteArray GdbMi::toString(bool multiline, int indent) const
|
||||
{
|
||||
QByteArray result;
|
||||
switch (m_type) {
|
||||
case Invalid:
|
||||
if (multiline) {
|
||||
result += ind(indent) + "Invalid\n";
|
||||
} else {
|
||||
result += "Invalid";
|
||||
}
|
||||
break;
|
||||
case Const:
|
||||
if (!m_name.isEmpty())
|
||||
result += m_name + "=";
|
||||
if (multiline) {
|
||||
result += "\"" + m_data + "\"";
|
||||
} else {
|
||||
result += "\"" + m_data + "\"";
|
||||
}
|
||||
break;
|
||||
case Tuple:
|
||||
if (!m_name.isEmpty())
|
||||
result += m_name + "=";
|
||||
if (multiline) {
|
||||
result += "{\n";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += '\n' + ind(indent) + "}";
|
||||
} else {
|
||||
result += "{";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += "}";
|
||||
}
|
||||
break;
|
||||
case List:
|
||||
if (!m_name.isEmpty())
|
||||
result += m_name + "=";
|
||||
if (multiline) {
|
||||
result += "[\n";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += "]";
|
||||
} else {
|
||||
result += "[";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += '\n' + ind(indent) + "]";
|
||||
}
|
||||
break;
|
||||
case Invalid:
|
||||
if (multiline)
|
||||
result += ind(indent) + "Invalid\n";
|
||||
else
|
||||
result += "Invalid";
|
||||
break;
|
||||
case Const:
|
||||
if (!m_name.isEmpty())
|
||||
result += m_name + "=";
|
||||
result += "\"" + escaped(m_data) + "\"";
|
||||
break;
|
||||
case Tuple:
|
||||
if (!m_name.isEmpty())
|
||||
result += m_name + "=";
|
||||
if (multiline) {
|
||||
result += "{\n";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += '\n' + ind(indent) + "}";
|
||||
} else {
|
||||
result += "{";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += "}";
|
||||
}
|
||||
break;
|
||||
case List:
|
||||
if (!m_name.isEmpty())
|
||||
result += m_name + "=";
|
||||
if (multiline) {
|
||||
result += "[\n";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += '\n' + ind(indent) + "]";
|
||||
} else {
|
||||
result += "[";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += "]";
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -319,152 +320,5 @@ QByteArray GdbResultRecord::toString() const
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GdbStreamOutput
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if 0
|
||||
|
||||
static const char test1[] =
|
||||
"1^done,stack=[frame={level=\"0\",addr=\"0x00000000004061ca\","
|
||||
"func=\"main\",file=\"test1.cpp\","
|
||||
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}]\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test2[] =
|
||||
"2^done,stack=[frame={level=\"0\",addr=\"0x00002ac058675840\","
|
||||
"func=\"QApplication\",file=\"/home/apoenitz/dev/qt/src/gui/kernel/qapplication.cpp\","
|
||||
"fullname=\"/home/apoenitz/dev/qt/src/gui/kernel/qapplication.cpp\",line=\"592\"},"
|
||||
"frame={level=\"1\",addr=\"0x00000000004061e0\",func=\"main\",file=\"test1.cpp\","
|
||||
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}]\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test3[] =
|
||||
"3^done,stack=[frame={level=\"0\",addr=\"0x00000000004061ca\","
|
||||
"func=\"main\",file=\"test1.cpp\","
|
||||
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}]\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test4[] =
|
||||
"&\"source /home/apoenitz/dev/ide/main/bin/gdb/qt4macros\\n\"\n"
|
||||
"4^done\n"
|
||||
"(gdb)\n";
|
||||
|
||||
|
||||
static const char test5[] =
|
||||
"1*stopped,reason=\"breakpoint-hit\",bkptno=\"1\",thread-id=\"1\","
|
||||
"frame={addr=\"0x0000000000405738\",func=\"main\","
|
||||
"args=[{name=\"argc\",value=\"1\"},{name=\"argv\",value=\"0x7fff1ac78f28\"}],"
|
||||
"file=\"test1.cpp\",fullname=\"/home/apoenitz/work/test1/test1.cpp\","
|
||||
"line=\"209\"}\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test6[] =
|
||||
"{u = {u = 2048, v = 16788279, w = -689265400}, a = 1, b = -689265424, c = 11063, s = {static null = {<No data fields>}, static shared_null = {ref = {value = 2}, alloc = 0, size = 0, data = 0x6098da, clean = 0, simpletext = 0, righttoleft = 0, asciiCache = 0, capacity = 0, reserved = 0, array = {0}}, static shared_empty = {ref = {value = 1}, alloc = 0, size = 0, data = 0x2b37d84f8fba, clean = 0, simpletext = 0, righttoleft = 0, asciiCache = 0, capacity = 0, reserved = 0, array = {0}}, d = 0x6098c0, static codecForCStrings = 0x0}}";
|
||||
|
||||
static const char test8[] =
|
||||
"8^done,data={locals={{name=\"a\"},{name=\"w\"}}}\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test9[] =
|
||||
"9^done,data={locals=[name=\"baz\",name=\"urgs\",name=\"purgs\"]}\n"
|
||||
"(gdb)\n";
|
||||
|
||||
|
||||
static const char test10[] =
|
||||
"16^done,name=\"urgs\",numchild=\"1\",type=\"Urgs\"\n"
|
||||
"(gdb)\n"
|
||||
"17^done,name=\"purgs\",numchild=\"1\",type=\"Urgs *\"\n"
|
||||
"(gdb)\n"
|
||||
"18^done,name=\"bar\",numchild=\"0\",type=\"int\"\n"
|
||||
"(gdb)\n"
|
||||
"19^done,name=\"z\",numchild=\"0\",type=\"int\"\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test11[] =
|
||||
"[{name=\"size\",value=\"1\",type=\"size_t\",readonly=\"true\"},"
|
||||
"{name=\"0\",value=\"one\",type=\"QByteArray\"}]";
|
||||
|
||||
static const char test12[] =
|
||||
"{iname=\"local.hallo\",value=\"\\\"\\\"\",type=\"QByteArray\",numchild=\"0\"}";
|
||||
|
||||
static struct Tester {
|
||||
|
||||
Tester() {
|
||||
//test(test10);
|
||||
test2(test12);
|
||||
//test(test4);
|
||||
//apple();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void test(const char* input)
|
||||
{
|
||||
//qDebug("\n<<<<\n%s\n====\n%s\n>>>>\n", input,
|
||||
//qPrintable(GdbResponse(input).toString()));
|
||||
}
|
||||
|
||||
void test2(const char* input)
|
||||
{
|
||||
GdbMi mi(input);
|
||||
qDebug("\n<<<<\n%s\n====\n%s\n>>>>\n", input,
|
||||
qPrintable(mi.toString()));
|
||||
}
|
||||
|
||||
void apple()
|
||||
{
|
||||
QByteArray input(test9);
|
||||
/*
|
||||
qDebug() << "input: " << input;
|
||||
input = input.replace("{{","[");
|
||||
input = input.replace("},{",",");
|
||||
input = input.replace("}}","]");
|
||||
qDebug() << "input: " << input;
|
||||
GdbResponse response(input);
|
||||
qDebug() << "read: " << response.toString();
|
||||
GdbMi list = response.results[0].data.findChild("data").findChild("locals");
|
||||
QByteArrayList locals;
|
||||
foreach (const GdbMi &item, list.children())
|
||||
locals.append(item.string());
|
||||
qDebug() << "Locals (new): " << locals;
|
||||
*/
|
||||
}
|
||||
void parse(const QByteArray &str)
|
||||
{
|
||||
QByteArray result;
|
||||
result += "\n ";
|
||||
int indent = 0;
|
||||
int from = 0;
|
||||
int to = str.size();
|
||||
if (str.size() && str[0] == '{' /*'}'*/) {
|
||||
++from;
|
||||
--to;
|
||||
}
|
||||
for (int i = from; i < to; ++i) {
|
||||
if (str[i] == '{')
|
||||
result += "{\n" + QByteArray(2*++indent + 1, ' ');
|
||||
else if (str[i] == '}') {
|
||||
if (!result.isEmpty() && result[result.size() - 1] != '\n')
|
||||
result += "\n";
|
||||
result += QByteArray(2*--indent + 1, ' ') + "}\n";
|
||||
}
|
||||
else if (str[i] == ',') {
|
||||
if (true || !result.isEmpty() && result[result.size() - 1] != '\n')
|
||||
result += "\n";
|
||||
result += QByteArray(2*indent, ' ');
|
||||
}
|
||||
else
|
||||
result += str[i];
|
||||
}
|
||||
qDebug() << "result:\n" << result;
|
||||
}
|
||||
|
||||
} dummy;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -57,12 +57,13 @@ StackHandler::StackHandler(QObject *parent)
|
||||
{
|
||||
m_emptyIcon = QIcon(":/gdbdebugger/images/empty.svg");
|
||||
m_positionIcon = QIcon(":/gdbdebugger/images/location.svg");
|
||||
m_canExpand = false;
|
||||
}
|
||||
|
||||
int StackHandler::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
// Since the stack is not a tree, row count is 0 for any valid parent
|
||||
return parent.isValid() ? 0 : m_stackFrames.size();
|
||||
return parent.isValid() ? 0 : (m_stackFrames.size() + m_canExpand);
|
||||
}
|
||||
|
||||
int StackHandler::columnCount(const QModelIndex &parent) const
|
||||
@@ -72,9 +73,15 @@ int StackHandler::columnCount(const QModelIndex &parent) const
|
||||
|
||||
QVariant StackHandler::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= m_stackFrames.size())
|
||||
if (!index.isValid() || index.row() >= m_stackFrames.size() + m_canExpand)
|
||||
return QVariant();
|
||||
|
||||
if (index.row() == m_stackFrames.size()) {
|
||||
if (role == Qt::DisplayRole && index.column() == 0)
|
||||
return "<...>";
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const StackFrame &frame = m_stackFrames.at(index.row());
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
@@ -123,10 +130,12 @@ QVariant StackHandler::headerData(int section, Qt::Orientation orientation, int
|
||||
|
||||
Qt::ItemFlags StackHandler::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (index.row() >= m_stackFrames.size())
|
||||
if (index.row() >= m_stackFrames.size() + m_canExpand)
|
||||
return 0;
|
||||
if (index.row() == m_stackFrames.size())
|
||||
return QAbstractTableModel::flags(index);
|
||||
const StackFrame &frame = m_stackFrames.at(index.row());
|
||||
const bool isValid = !frame.file.isEmpty() && !frame.function.isEmpty();
|
||||
const bool isValid = (!frame.file.isEmpty() && !frame.function.isEmpty());
|
||||
return isValid ? QAbstractTableModel::flags(index) : Qt::ItemFlags(0);
|
||||
}
|
||||
|
||||
@@ -160,8 +169,9 @@ void StackHandler::removeAll()
|
||||
reset();
|
||||
}
|
||||
|
||||
void StackHandler::setFrames(const QList<StackFrame> &frames)
|
||||
void StackHandler::setFrames(const QList<StackFrame> &frames, bool canExpand)
|
||||
{
|
||||
m_canExpand = canExpand;
|
||||
m_stackFrames = frames;
|
||||
if (m_currentIndex >= m_stackFrames.size())
|
||||
m_currentIndex = m_stackFrames.size() - 1;
|
||||
|
||||
@@ -64,7 +64,7 @@ class StackHandler : public QAbstractTableModel
|
||||
public:
|
||||
StackHandler(QObject *parent = 0);
|
||||
|
||||
void setFrames(const QList<StackFrame> &frames);
|
||||
void setFrames(const QList<StackFrame> &frames, bool canExpand = false);
|
||||
QList<StackFrame> frames() const;
|
||||
void setCurrentIndex(int index);
|
||||
int currentIndex() const { return m_currentIndex; }
|
||||
@@ -88,6 +88,7 @@ private:
|
||||
int m_currentIndex;
|
||||
QIcon m_positionIcon;
|
||||
QIcon m_emptyIcon;
|
||||
bool m_canExpand;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
act2->setCheckable(true);
|
||||
act2->setChecked(m_alwaysResizeColumnsToContents);
|
||||
|
||||
menu.addAction(theDebuggerAction(ExpandStack));
|
||||
menu.addAction(act0);
|
||||
menu.addSeparator();
|
||||
menu.addAction(act1);
|
||||
|
||||
@@ -871,10 +871,11 @@ void WatchHandler::watchExpression(const QString &exp)
|
||||
{
|
||||
// FIXME: 'exp' can contain illegal characters
|
||||
//MODEL_DEBUG("WATCH: " << exp);
|
||||
static int counter = 0;
|
||||
WatchData data;
|
||||
data.exp = exp;
|
||||
data.name = exp;
|
||||
data.iname = QLatin1String("watch.") + exp;
|
||||
data.iname = QLatin1String("watch.") + QString::number(counter++);
|
||||
insertData(data);
|
||||
m_watchers.append(exp);
|
||||
saveWatchers();
|
||||
@@ -993,7 +994,6 @@ void WatchHandler::reinitializeWatchersHelper()
|
||||
data.variable.clear();
|
||||
data.setAllNeeded();
|
||||
data.valuedisabled = false;
|
||||
data.iname = QLatin1String("watch.") + QString::number(i);
|
||||
data.name = exp;
|
||||
data.exp = exp;
|
||||
insertData(data);
|
||||
|
||||
@@ -213,6 +213,7 @@ public:
|
||||
|
||||
EventResult handleEvent(QKeyEvent *ev);
|
||||
bool wantsOverride(QKeyEvent *ev);
|
||||
void handleCommand(const QString &cmd); // sets m_tc + handleExCommand
|
||||
void handleExCommand(const QString &cmd);
|
||||
|
||||
void installEventFilter();
|
||||
@@ -350,6 +351,7 @@ public:
|
||||
bool m_needMoreUndo;
|
||||
|
||||
// extra data for '.'
|
||||
void replay(const QString &text);
|
||||
QString m_dotCommand;
|
||||
bool m_inReplay; // true if we are executing a '.'
|
||||
|
||||
@@ -1007,11 +1009,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
|
||||
qDebug() << "REPEATING" << m_dotCommand;
|
||||
QString savedCommand = m_dotCommand;
|
||||
m_dotCommand.clear();
|
||||
m_inReplay = true;
|
||||
for (int i = count(); --i >= 0; )
|
||||
foreach (QChar c, savedCommand)
|
||||
handleKey(c.unicode(), c.unicode(), QString(c));
|
||||
m_inReplay = false;
|
||||
replay(savedCommand);
|
||||
enterCommandMode();
|
||||
m_dotCommand = savedCommand;
|
||||
} else if (key == '<' && m_visualMode == NoVisualMode) {
|
||||
@@ -1643,6 +1641,13 @@ void FakeVimHandler::Private::selectRange(int beginLine, int endLine)
|
||||
setPosition(firstPositionInLine(endLine + 1));
|
||||
}
|
||||
|
||||
void FakeVimHandler::Private::handleCommand(const QString &cmd)
|
||||
{
|
||||
m_tc = EDITOR(textCursor());
|
||||
handleExCommand(cmd);
|
||||
EDITOR(setTextCursor(m_tc));
|
||||
}
|
||||
|
||||
void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
|
||||
{
|
||||
QString cmd = cmd0;
|
||||
@@ -1665,10 +1670,11 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
|
||||
|
||||
//qDebug() << "RANGE: " << beginLine << endLine << cmd << cmd0 << m_marks;
|
||||
|
||||
static QRegExp reWrite("^w!?( (.*))?$");
|
||||
static QRegExp reDelete("^d( (.*))?$");
|
||||
static QRegExp reSet("^set?( (.*))?$");
|
||||
static QRegExp reHistory("^his(tory)?( (.*))?$");
|
||||
static QRegExp reNormal("^norm(al)?( (.*))?$");
|
||||
static QRegExp reSet("^set?( (.*))?$");
|
||||
static QRegExp reWrite("^w!?( (.*))?$");
|
||||
|
||||
if (cmd.isEmpty()) {
|
||||
setPosition(firstPositionInLine(beginLine));
|
||||
@@ -1769,6 +1775,9 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
|
||||
redo();
|
||||
enterCommandMode();
|
||||
updateMiniBuffer();
|
||||
} else if (reNormal.indexIn(cmd) != -1) { // :normal
|
||||
enterCommandMode();
|
||||
replay(reNormal.cap(3));
|
||||
} else if (reSet.indexIn(cmd) != -1) { // :set
|
||||
showBlackMessage(QString());
|
||||
QString arg = reSet.cap(2);
|
||||
@@ -2341,6 +2350,15 @@ void FakeVimHandler::Private::handleStartOfLine()
|
||||
moveToFirstNonBlankOnLine();
|
||||
}
|
||||
|
||||
void FakeVimHandler::Private::replay(const QString &command)
|
||||
{
|
||||
//qDebug() << "REPLAY: " << command;
|
||||
m_inReplay = true;
|
||||
for (int i = count(); --i >= 0; )
|
||||
foreach (QChar c, command)
|
||||
handleKey(c.unicode(), c.unicode(), QString(c));
|
||||
m_inReplay = false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -2403,7 +2421,7 @@ void FakeVimHandler::restoreWidget()
|
||||
|
||||
void FakeVimHandler::handleCommand(const QString &cmd)
|
||||
{
|
||||
d->handleExCommand(cmd);
|
||||
d->handleCommand(cmd);
|
||||
}
|
||||
|
||||
void FakeVimHandler::setCurrentFileName(const QString &fileName)
|
||||
|
||||
@@ -240,7 +240,7 @@ void ScriptEditor::updateDocumentNow()
|
||||
errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
|
||||
|
||||
QTextCharFormat warningFormat;
|
||||
warningFormat.setUnderlineColor(Qt::yellow);
|
||||
warningFormat.setUnderlineColor(Qt::darkYellow);
|
||||
warningFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline);
|
||||
|
||||
QTextEdit::ExtraSelection sel;
|
||||
|
||||
@@ -224,15 +224,15 @@ public:
|
||||
ProFileEvaluator::Private::Private(ProFileEvaluator *q_)
|
||||
: q(q_)
|
||||
{
|
||||
// Global parser state
|
||||
m_prevLineNo = 0;
|
||||
m_prevProFile = 0;
|
||||
|
||||
// Configuration, more or less
|
||||
m_verbose = true;
|
||||
m_block = 0;
|
||||
m_commentItem = 0;
|
||||
m_syntaxError = 0;
|
||||
m_lineNo = 0;
|
||||
m_contNextLine = false;
|
||||
m_cumulative = true;
|
||||
|
||||
// Evaluator state
|
||||
m_updateCondition = false;
|
||||
m_condition = ConditionFalse;
|
||||
m_invertNext = false;
|
||||
@@ -248,8 +248,13 @@ bool ProFileEvaluator::Private::read(ProFile *pro)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parser state
|
||||
m_block = 0;
|
||||
m_commentItem = 0;
|
||||
m_contNextLine = false;
|
||||
m_syntaxError = false;
|
||||
m_lineNo = 1;
|
||||
m_blockstack.clear();
|
||||
m_blockstack.push(pro);
|
||||
|
||||
QTextStream ts(&file);
|
||||
|
||||
12
tests/auto/debugger/debugger.pro
Normal file
12
tests/auto/debugger/debugger.pro
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
QT = core testlib
|
||||
|
||||
DEBUGGERDIR = ../../../src/plugins/debugger
|
||||
UTILSDIR = ../../../src/libs
|
||||
|
||||
SOURCES += \
|
||||
$$DEBUGGERDIR/gdbmi.cpp \
|
||||
main.cpp \
|
||||
|
||||
INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR
|
||||
|
||||
153
tests/auto/debugger/main.cpp
Normal file
153
tests/auto/debugger/main.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
#include "gdbmi.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtTest/QtTest>
|
||||
//#include <QtTest/qtest_gui.h>
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
static const char test1[] =
|
||||
"[frame={level=\"0\",addr=\"0x00000000004061ca\","
|
||||
"func=\"main\",file=\"test1.cpp\","
|
||||
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}]";
|
||||
|
||||
static const char test2[] =
|
||||
"[frame={level=\"0\",addr=\"0x00002ac058675840\","
|
||||
"func=\"QApplication\",file=\"/home/apoenitz/dev/qt/src/gui/kernel/qapplication.cpp\","
|
||||
"fullname=\"/home/apoenitz/dev/qt/src/gui/kernel/qapplication.cpp\",line=\"592\"},"
|
||||
"frame={level=\"1\",addr=\"0x00000000004061e0\",func=\"main\",file=\"test1.cpp\","
|
||||
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}]";
|
||||
|
||||
static const char test3[] =
|
||||
"[stack={frame={level=\"0\",addr=\"0x00000000004061ca\","
|
||||
"func=\"main\",file=\"test1.cpp\","
|
||||
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}}]";
|
||||
|
||||
static const char test4[] =
|
||||
"&\"source /home/apoenitz/dev/ide/main/bin/gdb/qt4macros\\n\""
|
||||
"4^done\n";
|
||||
|
||||
static const char test5[] =
|
||||
"[reason=\"breakpoint-hit\",bkptno=\"1\",thread-id=\"1\","
|
||||
"frame={addr=\"0x0000000000405738\",func=\"main\","
|
||||
"args=[{name=\"argc\",value=\"1\"},{name=\"argv\",value=\"0x7fff1ac78f28\"}],"
|
||||
"file=\"test1.cpp\",fullname=\"/home/apoenitz/work/test1/test1.cpp\","
|
||||
"line=\"209\"}]";
|
||||
|
||||
static const char test8[] =
|
||||
"[data={locals={{name=\"a\"},{name=\"w\"}}}]";
|
||||
|
||||
static const char test9[] =
|
||||
"[data={locals=[name=\"baz\",name=\"urgs\",name=\"purgs\"]}]";
|
||||
|
||||
static const char test10[] =
|
||||
"[name=\"urgs\",numchild=\"1\",type=\"Urgs\"]";
|
||||
|
||||
static const char test11[] =
|
||||
"[{name=\"size\",value=\"1\",type=\"size_t\",readonly=\"true\"},"
|
||||
"{name=\"0\",value=\"one\",type=\"QByteArray\"}]";
|
||||
|
||||
static const char test12[] =
|
||||
"[{iname=\"local.hallo\",value=\"\\\"\\\"\",type=\"QByteArray\","
|
||||
"numchild=\"0\"}]";
|
||||
|
||||
class tst_Debugger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
tst_Debugger() {}
|
||||
|
||||
void testMi(const char* input)
|
||||
{
|
||||
QCOMPARE('\n' + QString::fromLatin1(GdbMi(input).toString(false)),
|
||||
'\n' + QString(input));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void mi1() { testMi(test1); }
|
||||
void mi2() { testMi(test2); }
|
||||
void mi3() { testMi(test3); }
|
||||
//void mi4() { testMi(test4); }
|
||||
void mi5() { testMi(test5); }
|
||||
void mi8() { testMi(test8); }
|
||||
void mi9() { testMi(test9); }
|
||||
void mi10() { testMi(test10); }
|
||||
void mi11() { testMi(test11); }
|
||||
void mi12() { testMi(test12); }
|
||||
void runQtc();
|
||||
|
||||
public slots:
|
||||
void readStandardOutput();
|
||||
void readStandardError();
|
||||
|
||||
private:
|
||||
QProcess m_proc; // the Qt Creator process
|
||||
};
|
||||
|
||||
static QByteArray stripped(QByteArray ba)
|
||||
{
|
||||
for (int i = ba.size(); --i >= 0; ) {
|
||||
if (ba.at(i) == '\n' || ba.at(i) == ' ')
|
||||
ba.chop(1);
|
||||
else
|
||||
break;
|
||||
}
|
||||
return ba;
|
||||
}
|
||||
|
||||
void tst_Debugger::readStandardOutput()
|
||||
{
|
||||
qDebug() << "qtcreator-out: " << stripped(m_proc.readAllStandardOutput());
|
||||
}
|
||||
|
||||
void tst_Debugger::readStandardError()
|
||||
{
|
||||
qDebug() << "qtcreator-err: " << stripped(m_proc.readAllStandardError());
|
||||
}
|
||||
|
||||
void tst_Debugger::runQtc()
|
||||
{
|
||||
QString test = QFileInfo(qApp->arguments().at(0)).absoluteFilePath();
|
||||
QString qtc = QFileInfo(test).absolutePath() + "/../../../bin/qtcreator.bin";
|
||||
qtc = QFileInfo(qtc).absoluteFilePath();
|
||||
QStringList env = QProcess::systemEnvironment();
|
||||
env.append("QTC_DEBUGGER_TEST=" + test);
|
||||
m_proc.setEnvironment(env);
|
||||
connect(&m_proc, SIGNAL(readyReadStandardOutput()),
|
||||
this, SLOT(readStandardOutput()));
|
||||
connect(&m_proc, SIGNAL(readyReadStandardError()),
|
||||
this, SLOT(readStandardError()));
|
||||
m_proc.start(qtc);
|
||||
m_proc.waitForStarted();
|
||||
QCOMPARE(m_proc.state(), QProcess::Running);
|
||||
m_proc.waitForFinished();
|
||||
QCOMPARE(m_proc.state(), QProcess::NotRunning);
|
||||
}
|
||||
|
||||
void runDebuggee()
|
||||
{
|
||||
qDebug() << "RUNNING DEBUGGEE";
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
QStringList args = app.arguments();
|
||||
|
||||
|
||||
if (args.size() == 2 && args.at(1) == "--run-debuggee") {
|
||||
runDebuggee();
|
||||
return 0;
|
||||
}
|
||||
|
||||
tst_Debugger test;
|
||||
return QTest::qExec(&test, argc, argv);
|
||||
}
|
||||
|
||||
#include "main.moc"
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
|
||||
QT += testlib
|
||||
|
||||
FAKEVIMSOURCE = ../../../src/plugins/fakevim
|
||||
|
||||
INCLUDEPATH += $$FAKEVIMSOURCE
|
||||
FAKEVIMDIR = ../../../src/plugins/fakevim
|
||||
UTILSDIR = ../../../src/libs
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
$$FAKEVIMSOURCE/handler.cpp
|
||||
$$FAKEVIMDIR/fakevimhandler.cpp \
|
||||
$$FAKEVIMDIR/fakevimactions.cpp \
|
||||
$$UTILSDIR/utils/savedaction.cpp \
|
||||
$$UTILSDIR/utils/pathchooser.cpp \
|
||||
$$UTILSDIR/utils/basevalidatinglineedit.cpp \
|
||||
|
||||
HEADERS += \
|
||||
$$FAKEVIMSOURCE/handler.h
|
||||
$$FAKEVIMDIR/fakevimhandler.h \
|
||||
$$FAKEVIMDIR/fakevimactions.h \
|
||||
$$UTILSDIR/utils/savedaction.h \
|
||||
$$UTILSDIR/utils/pathchooser.h \
|
||||
$$UTILSDIR/utils/basevalidatinglineedit.h \
|
||||
|
||||
INCLUDEPATH += $$FAKEVIMDIR $$UTILSDIR
|
||||
|
||||
|
||||
@@ -27,18 +27,167 @@
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "handler.h"
|
||||
#include "fakevimhandler.h"
|
||||
|
||||
#include <QtCore/QSet>
|
||||
#include <QtGui/QPlainTextEdit>
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <QtCore/QSet>
|
||||
|
||||
using namespace FakeVim;
|
||||
using namespace FakeVim::Internal;
|
||||
|
||||
|
||||
class tst_FakeVim : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
tst_FakeVim();
|
||||
|
||||
void setup();
|
||||
void send(const QString &command); // send a normal command
|
||||
void sendEx(const QString &command); // send an ex command
|
||||
|
||||
QString cleaned(QString wanted) { wanted.remove('$'); return wanted; }
|
||||
|
||||
public slots:
|
||||
void changeStatusData(const QString &info) { m_statusData = info; }
|
||||
void changeStatusMessage(const QString &info) { m_statusMessage = info; }
|
||||
void changeExtraInformation(const QString &info) { m_infoMessage = info; }
|
||||
|
||||
public:
|
||||
QString m_statusMessage;
|
||||
QString m_statusData;
|
||||
QString m_infoMessage;
|
||||
|
||||
private slots:
|
||||
void commandI();
|
||||
void commandDollar();
|
||||
|
||||
private:
|
||||
QPlainTextEdit m_editor;
|
||||
FakeVimHandler m_handler;
|
||||
QList<QTextEdit::ExtraSelection> m_selection;
|
||||
|
||||
static const QString lines;
|
||||
static const QString escape;
|
||||
};
|
||||
|
||||
const QString tst_FakeVim::lines =
|
||||
"\n"
|
||||
"#include <QtCore>\n"
|
||||
"#include <QtGui>\n"
|
||||
"\n"
|
||||
"int main(int argc, char *argv[])\n"
|
||||
"{\n"
|
||||
" QApplication app(argc, argv);\n"
|
||||
"\n"
|
||||
" return app.exec();\n"
|
||||
"}\n";
|
||||
|
||||
const QString tst_FakeVim::escape = QChar(27);
|
||||
|
||||
tst_FakeVim::tst_FakeVim()
|
||||
: m_handler(&m_editor, this)
|
||||
{
|
||||
|
||||
QObject::connect(&m_handler, SIGNAL(commandBufferChanged(QString)),
|
||||
this, SLOT(changeStatusMessage(QString)));
|
||||
QObject::connect(&m_handler, SIGNAL(extraInformationChanged(QString)),
|
||||
this, SLOT(changeExtraInformation(QString)));
|
||||
QObject::connect(&m_handler, SIGNAL(statusDataChanged(QString)),
|
||||
this, SLOT(changeStatusData(QString)));
|
||||
}
|
||||
|
||||
void tst_FakeVim::setup()
|
||||
{
|
||||
m_statusMessage.clear();
|
||||
m_statusData.clear();
|
||||
m_infoMessage.clear();
|
||||
m_editor.setPlainText(lines);
|
||||
QCOMPARE(m_editor.toPlainText(), lines);
|
||||
}
|
||||
|
||||
void tst_FakeVim::send(const QString &command)
|
||||
{
|
||||
m_handler.handleCommand("normal " + command);
|
||||
}
|
||||
|
||||
void tst_FakeVim::sendEx(const QString &command)
|
||||
{
|
||||
m_handler.handleCommand(command);
|
||||
}
|
||||
|
||||
#define checkContents(wanted) \
|
||||
do { QString want = cleaned(wanted); \
|
||||
QString got = m_editor.toPlainText(); \
|
||||
QStringList wantlist = want.split('\n'); \
|
||||
QStringList gotlist = got.split('\n'); \
|
||||
QCOMPARE(gotlist.size(), wantlist.size()); \
|
||||
for (int i = 0; i < wantlist.size() && i < gotlist.size(); ++i) { \
|
||||
QString g = QString("line %1: %2").arg(i + 1).arg(gotlist.at(i)); \
|
||||
QString w = QString("line %1: %2").arg(i + 1).arg(wantlist.at(i)); \
|
||||
QCOMPARE(g, w); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define checkText(cmd, wanted) \
|
||||
do { \
|
||||
send(cmd); \
|
||||
checkContents(wanted); \
|
||||
int p = (wanted).indexOf('$'); \
|
||||
QCOMPARE(m_editor.textCursor().position(), p); \
|
||||
} while (0)
|
||||
|
||||
#define checkTextEx(cmd, wanted) \
|
||||
do { \
|
||||
sendEx(cmd); \
|
||||
checkContents(wanted); \
|
||||
int p = (wanted).indexOf('$'); \
|
||||
QCOMPARE(m_editor.textCursor().position(), p); \
|
||||
} while (0)
|
||||
|
||||
#define checkPosition(cmd, pos) \
|
||||
do { \
|
||||
send(cmd); \
|
||||
QCOMPARE(m_editor.textCursor().position(), pos); \
|
||||
} while (0)
|
||||
|
||||
void tst_FakeVim::commandI()
|
||||
{
|
||||
setup();
|
||||
|
||||
// empty insertion at start of document
|
||||
checkText("i" + escape, "$" + lines);
|
||||
checkText("u", "$" + lines);
|
||||
|
||||
// small insertion at start of document
|
||||
checkText("ix" + escape, "$x" + lines);
|
||||
checkText("u", "$" + lines);
|
||||
|
||||
// small insertion at start of document
|
||||
checkText("ixxx" + escape, "xx$x" + lines);
|
||||
checkText("u", "$" + lines);
|
||||
|
||||
// combine insertions
|
||||
checkText("ia" + escape, "$a" + lines);
|
||||
checkText("ibx" + escape, "b$xa" + lines);
|
||||
checkText("icyy" + escape, "bcy$yxa" + lines);
|
||||
checkText("u", "b$xa" + lines);
|
||||
checkText("u", "$a" + lines); // undo broken
|
||||
checkTextEx("redo", "b$xa" + lines);
|
||||
checkText("u", "$a" + lines);
|
||||
checkText("u", "$" + lines);
|
||||
}
|
||||
|
||||
void tst_FakeVim::commandDollar()
|
||||
{
|
||||
setup();
|
||||
checkPosition("$", 0);
|
||||
checkPosition("j", 2);
|
||||
}
|
||||
|
||||
|
||||
QTEST_MAIN(tst_FakeVim)
|
||||
|
||||
|
||||
@@ -1078,7 +1078,8 @@ struct QMetaTypeId<QHostAddress>
|
||||
{
|
||||
static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||
if (!metatype_id)
|
||||
metatype_id = qRegisterMetaType<QHostAddress>("myns::QHostAddress");
|
||||
metatype_id = qRegisterMetaType<QHostAddress>
|
||||
("myns::QHostAddress");
|
||||
return metatype_id; \
|
||||
} \
|
||||
};
|
||||
@@ -1091,7 +1092,8 @@ struct QMetaTypeId< QMap<uint, QStringList> >
|
||||
{
|
||||
static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||
if (!metatype_id)
|
||||
metatype_id = qRegisterMetaType< QMap<uint, QStringList> >("myns::QMap<uint, myns::QStringList>");
|
||||
metatype_id = qRegisterMetaType< QMap<uint, QStringList> >
|
||||
("myns::QMap<uint, myns::QStringList>");
|
||||
return metatype_id; \
|
||||
} \
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user