Merge commit 'origin/1.1'

This commit is contained in:
con
2009-04-07 10:55:32 +02:00
26 changed files with 565 additions and 324 deletions

6
dist/changes-1.1.0 vendored
View File

@@ -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.

View File

@@ -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,

View File

@@ -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);

View File

@@ -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()

View File

@@ -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;

View File

@@ -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();

View File

@@ -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);

View File

@@ -79,6 +79,7 @@ enum DebuggerActionCode
// Stack
MaximalStackDepth,
ExpandStack,
// Watchers & Locals
WatchExpression,

View File

@@ -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"

View File

@@ -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);

View File

@@ -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. */

View File

@@ -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) {

View File

@@ -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();
//

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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;

View File

@@ -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);

View File

@@ -0,0 +1,12 @@
QT = core testlib
DEBUGGERDIR = ../../../src/plugins/debugger
UTILSDIR = ../../../src/libs
SOURCES += \
$$DEBUGGERDIR/gdbmi.cpp \
main.cpp \
INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR

View 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"

View File

@@ -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

View File

@@ -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)

View File

@@ -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; \
} \
};