diff --git a/dist/changes-1.1.0 b/dist/changes-1.1.0 index d19bcc0d8c5df511b7255ac21813d7a34f6bd814..ca31d5783c2470901e45d092b21b4ec9a59f153d 100644 --- a/dist/changes-1.1.0 +++ b/dist/changes-1.1.0 @@ -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. diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 64f6bc1e012532105259f4f39852acb5aa698af8..f5a0edd66bc9c780cdf285e76e81a9c69dbc0e18 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -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, diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 8e79b50f6aa381e27dbda7c185948998394129ad..48542bad97faee523f63ed78eb6a45708268e7ac 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -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); diff --git a/src/plugins/coreplugin/editormanager/editorview.cpp b/src/plugins/coreplugin/editormanager/editorview.cpp index 92ed402dcbc4743f9e30bba1a1058ab24029e546..930a20c2dfd4291cd85b6b969a9c1b129dc3091d 100644 --- a/src/plugins/coreplugin/editormanager/editorview.cpp +++ b/src/plugins/coreplugin/editormanager/editorview.cpp @@ -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() diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 1593b6118c2eda68fd402b269f7df27dd0da9a5a..a6fbcfc03044ecfe0d5652f591fa01aee777087f 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -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; diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 9a9dd71ec3cbcf49652f243a47acf90398f7ffdc..981c48f01c8cb990af7e877cf30892902bb57f36 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -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(); diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 95f9c3b1104213ec36739c3b68d3de30d142595e..fc963d0798f25e5bc64c48ea03db538c27417f2e 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -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); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 31e04199f534c7195af11e9cd560bbc54ae27f55..cb51e551aa0315ad23dc7fad4dc7df606691d2d4 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -79,6 +79,7 @@ enum DebuggerActionCode // Stack MaximalStackDepth, + ExpandStack, // Watchers & Locals WatchExpression, diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index ea973c0c69221db16942c8b0d6e5a65d7d6669e1..4b7ac701bf73b8077d60dc9e2717201de9f0d54f 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -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" diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index 77150b452b2822aaa1bc1bd9b6a24536b696c544..72c1467c52efe4243c46dc8f40bc0bbe018f23dc 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -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); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index fbe80e4588216fd69cd53c8095a14e77b47d97a2..29a1b19ab8b0fd69a05b59a4979ae1fc4c22b6e6 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -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. */ diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index f1fea3104eb3075b79871d6b331e85ec8490a8c6..2a82bbda4cf315a0e2bd7b558a50138daf3a7055 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -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); - } - - qq->stackHandler()->setFrames(stackFrames); + bool canExpand = !isFull + && (n >= theDebuggerAction(MaximalStackDepth)->value().toInt()); + theDebuggerAction(ExpandStack)->setEnabled(canExpand); + qq->stackHandler()->setFrames(stackFrames, canExpand); -#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) { diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index 0ea15012e982dfca77c71a00fbf939d594130bcc..79d95f34fcabf90c7fda1160d89a63409f56613f 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -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(); // diff --git a/src/plugins/debugger/gdbmi.cpp b/src/plugins/debugger/gdbmi.cpp index 2e778cb8e83c9b6965f56ccc7c81d6a0cf65def8..82fdaf4fd13487684dd92c9de56e55de12008a26 100644 --- a/src/plugins/debugger/gdbmi.cpp +++ b/src/plugins/debugger/gdbmi.cpp @@ -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 diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index 17c8168c7c3c3f156053f69ffc42af2d4a969da2..d8beb63a3e66631f04f50e81e2dfe3d0ee7f0c3d 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -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; diff --git a/src/plugins/debugger/stackhandler.h b/src/plugins/debugger/stackhandler.h index ae073e3d1369f74a42ba6eeb9b5df0580c545205..c928a6fed92913351031f1e9072ecf65a8a6639d 100644 --- a/src/plugins/debugger/stackhandler.h +++ b/src/plugins/debugger/stackhandler.h @@ -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; }; diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp index e0340ce0ae8e3908276a0a37c22b1228056c8e24..cac2a40bed9ce194a5728519008779b7459425a3 100644 --- a/src/plugins/debugger/stackwindow.cpp +++ b/src/plugins/debugger/stackwindow.cpp @@ -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); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index b2af8278d94ba1a6818ea2d3d1d007695d500fd7..76d27768e19acad7f750ae8f60095593e2f0fcc8 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -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); diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 96d02733017ec660867d87617c137ca4863d4b82..9a4339fd1922382eaf1c8a97e8b0fbb2e96a39a9 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -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) diff --git a/src/plugins/qtscripteditor/qtscripteditor.cpp b/src/plugins/qtscripteditor/qtscripteditor.cpp index 701f6005291e544900d8c3d4e84b032418d93d9c..16244140235b81ce336357f01bb943d1c5370f28 100644 --- a/src/plugins/qtscripteditor/qtscripteditor.cpp +++ b/src/plugins/qtscripteditor/qtscripteditor.cpp @@ -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; diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index bbfeba7dd7e6039abfeb89ce8c2577ba5ba8fca9..19041d7bb77cb884663dfa89704630e98abb2d5e 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -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); diff --git a/tests/auto/debugger/debugger.pro b/tests/auto/debugger/debugger.pro new file mode 100644 index 0000000000000000000000000000000000000000..6f6e9357741412cf1f0c9dfd463a7097f3c6a72c --- /dev/null +++ b/tests/auto/debugger/debugger.pro @@ -0,0 +1,12 @@ + +QT = core testlib + +DEBUGGERDIR = ../../../src/plugins/debugger +UTILSDIR = ../../../src/libs + +SOURCES += \ + $$DEBUGGERDIR/gdbmi.cpp \ + main.cpp \ + +INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR + diff --git a/tests/auto/debugger/main.cpp b/tests/auto/debugger/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f59a54a6790c92e5b99ac94de0d93404559c0b92 --- /dev/null +++ b/tests/auto/debugger/main.cpp @@ -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" + diff --git a/tests/auto/fakevim/fakevim.pro b/tests/auto/fakevim/fakevim.pro index 539a40f335c9e64b377e9fba993e7e8906094088..04fefc12d30548202540f2b9cf6dea67a3d89d80 100644 --- a/tests/auto/fakevim/fakevim.pro +++ b/tests/auto/fakevim/fakevim.pro @@ -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 diff --git a/tests/auto/fakevim/main.cpp b/tests/auto/fakevim/main.cpp index 5445ba3f048621839f5dd9aaf1fb8acc144667ec..700b25d63db3ca76dc35a322466a5c8163a8e2ce 100644 --- a/tests/auto/fakevim/main.cpp +++ b/tests/auto/fakevim/main.cpp @@ -27,18 +27,167 @@ ** **************************************************************************/ -#include "handler.h" +#include "fakevimhandler.h" -#include <QtTest/QtTest> #include <QtCore/QSet> +#include <QtGui/QPlainTextEdit> + +#include <QtTest/QtTest> + +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) diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 8b51d7f8b767f506cd1470f587749433b3bd3ba9..d50180c4ad2fc60fee3e15b04e8a7b58f69c7878 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -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; \ } \ };