forked from qt-creator/qt-creator
Merge branch 'master' of git@scm.dev.nokia.troll.no:creator/mainline
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QLinkedList>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QQueue>
|
||||
#include <QtCore/QLocale>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QMetaEnum>
|
||||
@@ -3572,15 +3573,15 @@ template <class Key, class Value>
|
||||
{
|
||||
QMapNode<Key, Value> *mn = 0;
|
||||
const int valueOffset = (char *)&(mn->value) - (char*)mn;
|
||||
d.put("(size_t)&(('"NS"QMapNode<");
|
||||
d.put("[\"(size_t)&(('"NS"QMapNode<");
|
||||
d.put(keyType);
|
||||
d.put(',');
|
||||
d.put(valueType);
|
||||
if (valueType[qstrlen(valueType) - 1] == '>')
|
||||
d.put(' ');
|
||||
d.put(">'*)0)->value=\"");
|
||||
d.put(">'*)0)->value\",\"");
|
||||
d.put(valueOffset);
|
||||
d.put('"');
|
||||
d.put("\"]");
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -3595,20 +3596,86 @@ template <class Key, class Value>
|
||||
{
|
||||
std::pair<Key, Value> *p = 0;
|
||||
const int valueOffset = (char *)&(p->second) - (char*)p;
|
||||
d.put("(size_t)&(('std::pair<");
|
||||
d.put("[\"(size_t)&(('std::pair<");
|
||||
d.put(keyType);
|
||||
d.put(" const ,");
|
||||
d.put(valueType);
|
||||
if (valueType[qstrlen(valueType) - 1] == '>')
|
||||
d.put(' ');
|
||||
d.put(">'*)0)->second=\"");
|
||||
d.put(">'*)0)->second\",\"");
|
||||
d.put(valueOffset);
|
||||
d.put('"');
|
||||
d.put("\"]");
|
||||
return d;
|
||||
}
|
||||
|
||||
#endif // Q_CC_MSVC
|
||||
|
||||
// Dump out sizes for CDB
|
||||
static inline void dumpSizes(QDumper &d)
|
||||
{
|
||||
// Sort by sizes
|
||||
typedef QMultiMap<size_t, const char *> SizeMap;
|
||||
SizeMap sizeMap;
|
||||
|
||||
sizeMap.insert(sizeof(int), "int");
|
||||
sizeMap.insert(sizeof(char*), "char*");
|
||||
sizeMap.insert(sizeof(QString), NS"QString");
|
||||
sizeMap.insert(sizeof(QStringList), NS"QStringList");
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
sizeMap.insert(sizeof(QObject), NS"QObject");
|
||||
sizeMap.insert(sizeof(QList<int>), NS"QList<int>");
|
||||
sizeMap.insert(sizeof(QLinkedList<int>), NS"QLinkedList<int>");
|
||||
sizeMap.insert(sizeof(QVector<int>), NS"QVector<int>");
|
||||
sizeMap.insert(sizeof(QQueue<int>), NS"QQueue<int>");
|
||||
#endif
|
||||
#if USE_QT_GUI
|
||||
sizeMap.insert(sizeof(QWidget), NS"QWidget");
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
sizeMap.insert(sizeof(std::string), "string");
|
||||
sizeMap.insert(sizeof(std::wstring), "wstring");
|
||||
#endif
|
||||
sizeMap.insert(sizeof(std::string), "std::string");
|
||||
sizeMap.insert(sizeof(std::wstring), "std::wstring");
|
||||
sizeMap.insert(sizeof(std::allocator<int>), "std::allocator");
|
||||
sizeMap.insert(sizeof(std::char_traits<char>), "std::char_traits<char>");
|
||||
sizeMap.insert(sizeof(std::char_traits<unsigned short>), "std::char_traits<unsigned short>");
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
#if QT_VERSION >= 0x040500
|
||||
sizeMap.insert(sizeof(QSharedPointer<int>), NS"QSharedPointer");
|
||||
sizeMap.insert(sizeof(QSharedDataPointer<QSharedData>), NS"QSharedDataPointer");
|
||||
sizeMap.insert(sizeof(QWeakPointer<int>), NS"QWeakPointer");
|
||||
#endif
|
||||
#endif // QT_BOOTSTRAPPED
|
||||
sizeMap.insert(sizeof(QPointer<QObject>), "QPointer");
|
||||
// Common map node types
|
||||
sizeMap.insert(sizeof(QMapNode<int,int >), NS"QMapNode<int,int>");
|
||||
sizeMap.insert(sizeof(QMapNode<int, QString>), NS"QMapNode<int,"NS"QString>");
|
||||
sizeMap.insert(sizeof(QMapNode<int, QVariant>), NS"QMapNode<int,"NS"QVariant>");
|
||||
sizeMap.insert(sizeof(QMapNode<QString, int>), NS"QMapNode<"NS"QString,int>");
|
||||
sizeMap.insert(sizeof(QMapNode<QString, QString>), NS"QMapNode<"NS"QString,"NS"QString>");
|
||||
sizeMap.insert(sizeof(QMapNode<QString, QVariant>), NS"QMapNode<"NS"QString,"NS"QVariant>");
|
||||
// Dump as lists of types preceded by size
|
||||
size_t lastSize = 0;
|
||||
d.put("sizes=[");
|
||||
const SizeMap::const_iterator cend = sizeMap.constEnd();
|
||||
for (SizeMap::const_iterator it = sizeMap.constBegin(); it != cend; ++it) {
|
||||
// new size list
|
||||
if (it.key() != lastSize) {
|
||||
if (lastSize)
|
||||
d.put("],");
|
||||
d.put("[\"");
|
||||
d.put(it.key());
|
||||
lastSize = it.key();
|
||||
d.put('"');
|
||||
}
|
||||
d.put(",\"");
|
||||
d.put(it.value());
|
||||
d.put('"');
|
||||
}
|
||||
d.put("]]");
|
||||
}
|
||||
|
||||
extern "C" Q_DECL_EXPORT
|
||||
void *qDumpObjectData440(
|
||||
int protocolVersion,
|
||||
@@ -3702,45 +3769,10 @@ void *qDumpObjectData440(
|
||||
d.put(",namespace=\""NS"\",");
|
||||
d.put("dumperversion=\"1.3\",");
|
||||
// Dump out size information
|
||||
d.put("sizes={");
|
||||
d.put("int=\"").put(sizeof(int)).put("\",")
|
||||
.put("char*=\"").put(sizeof(char*)).put("\",")
|
||||
.put(""NS"QString=\"").put(sizeof(QString)).put("\",")
|
||||
.put(""NS"QStringList=\"").put(sizeof(QStringList)).put("\",")
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
.put(""NS"QObject=\"").put(sizeof(QObject)).put("\",")
|
||||
#endif
|
||||
#if USE_QT_GUI
|
||||
.put(""NS"QWidget=\"").put(sizeof(QWidget)).put("\",")
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
.put("string=\"").put(sizeof(std::string)).put("\",")
|
||||
.put("wstring=\"").put(sizeof(std::wstring)).put("\",")
|
||||
#endif
|
||||
.put("std::string=\"").put(sizeof(std::string)).put("\",")
|
||||
.put("std::wstring=\"").put(sizeof(std::wstring)).put("\",")
|
||||
.put("std::allocator=\"").put(sizeof(std::allocator<int>)).put("\",")
|
||||
.put("std::char_traits<char>=\"").put(sizeof(std::char_traits<char>)).put("\",")
|
||||
.put("std::char_traits<unsigned short>=\"").put(sizeof(std::char_traits<unsigned short>)).put("\",")
|
||||
#ifndef QT_BOOTSTRAPPED
|
||||
#if QT_VERSION >= 0x040500
|
||||
.put(NS"QSharedPointer=\"").put(sizeof(QSharedPointer<int>)).put("\",")
|
||||
.put(NS"QSharedDataPointer=\"").put(sizeof(QSharedDataPointer<QSharedData>)).put("\",")
|
||||
.put(NS"QWeakPointer=\"").put(sizeof(QWeakPointer<int>)).put("\",")
|
||||
#endif
|
||||
#endif // QT_BOOTSTRAPPED
|
||||
.put("QPointer=\"").put(sizeof(QPointer<QObject>)).put("\",")
|
||||
// Common map node types
|
||||
.put(NS"QMapNode<int,int>=\"").put(sizeof(QMapNode<int,int >)).put("\",")
|
||||
.put(NS"QMapNode<int,"NS"QString>=\"").put(sizeof(QMapNode<int, QString>)).put("\",")
|
||||
.put(NS"QMapNode<int,"NS"QVariant>=\"").put(sizeof(QMapNode<int, QVariant>)).put("\",")
|
||||
.put(NS"QMapNode<"NS"QString,int>=\"").put(sizeof(QMapNode<QString, int>)).put("\",")
|
||||
.put(NS"QMapNode<"NS"QString,"NS"QString>=\"").put(sizeof(QMapNode<QString, QString>)).put("\",")
|
||||
.put(NS"QMapNode<"NS"QString,"NS"QVariant>=\"").put(sizeof(QMapNode<QString, QVariant>))
|
||||
.put("\"}");
|
||||
dumpSizes(d);
|
||||
// Write out common expression values for CDB
|
||||
#ifdef Q_CC_MSVC
|
||||
d.put(",expressions={");
|
||||
d.put(",expressions=[");
|
||||
putQMapNodeOffsetExpression<int,int>("int", "int", d).put(',');
|
||||
putQMapNodeOffsetExpression<int,QString>("int", NS"QString", d).put(',');
|
||||
putQMapNodeOffsetExpression<int,QVariant>("int", NS"QVariant", d).put(',');
|
||||
@@ -3754,11 +3786,11 @@ void *qDumpObjectData440(
|
||||
putStdPairValueOffsetExpression<QString,int>(NS"QString", "int", d).put(',');
|
||||
putStdPairValueOffsetExpression<std::string,std::string>(stdStringTypeC, stdStringTypeC, d).put(',');
|
||||
putStdPairValueOffsetExpression<int,std::string>("int", stdStringTypeC, d).put(',');
|
||||
putStdPairValueOffsetExpression<std::string,int>(stdStringTypeC, "int", d.put(','));
|
||||
putStdPairValueOffsetExpression<std::string,int>(stdStringTypeC, "int", d).put(',');
|
||||
putStdPairValueOffsetExpression<std::wstring,std::wstring>(stdWideStringTypeUShortC, stdWideStringTypeUShortC, d).put(',');
|
||||
putStdPairValueOffsetExpression<int,std::wstring>("int", stdWideStringTypeUShortC, d).put(',');
|
||||
putStdPairValueOffsetExpression<std::wstring,int>(stdWideStringTypeUShortC, "int", d);
|
||||
d.put('}');
|
||||
d.put(']');
|
||||
#endif // Q_CC_MSVC
|
||||
d.disarm();
|
||||
}
|
||||
|
||||
@@ -152,8 +152,6 @@ public:
|
||||
QList<QObject *> pendingChildInsertedEvents;
|
||||
QList<QPointer<QObject> > eventFilters;
|
||||
void *currentChildBeingDeleted;
|
||||
void *declarativeData;
|
||||
void *objectGuards;
|
||||
QAtomicPointer<void> sharedRefcount;
|
||||
int *deleteWatch;
|
||||
#endif
|
||||
|
||||
@@ -28,10 +28,12 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QLinkedList>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtGui/QAction>
|
||||
|
||||
@@ -138,6 +140,16 @@ static int dumpQIntList()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpQIntLinkedList()
|
||||
{
|
||||
QLinkedList<int> test = QLinkedList<int>() << 1 << 2;
|
||||
prepareInBuffer("QLinkedList", "local.qintlinkedlist", "local.qlinkedintlist", "int");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), 0, 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
fputc('\n', stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpQIntVector()
|
||||
{
|
||||
QVector<int> test = QVector<int>() << 42 << 43;
|
||||
@@ -148,6 +160,16 @@ static int dumpQIntVector()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpQQStringVector()
|
||||
{
|
||||
QVector<QString> test = QVector<QString>() << "42s" << "43s";
|
||||
prepareInBuffer("QVector", "local.qstringvector", "local.qstringvector", "QString");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), 0, 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
fputc('\n', stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpQMapIntInt()
|
||||
{
|
||||
QMap<int,int> test;
|
||||
@@ -176,6 +198,33 @@ static int dumpQMapIntString()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpQSetInt()
|
||||
{
|
||||
QSet<int> test;
|
||||
test.insert(42);
|
||||
test.insert(43);
|
||||
prepareInBuffer("QSet", "local.qsetint", "local.qsetint", "int");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), 0, 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
fputc('\n', stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dumpQMapQStringString()
|
||||
{
|
||||
QMap<QString,QString> test;
|
||||
QMapNode<QString,QString> mapNode;
|
||||
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
|
||||
test.insert(QLatin1String("42s"), QLatin1String("fortytwo"));
|
||||
test.insert(QLatin1String("423"), QLatin1String("fortytree"));
|
||||
prepareInBuffer("QMap", "local.qmapqstringqstring", "local.qmapqstringqstring", "QString@QString");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(QString), sizeof(mapNode), valueOffset);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
fputc('\n', stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpQVariant()
|
||||
{
|
||||
QVariant test(QLatin1String("item"));
|
||||
@@ -417,10 +466,14 @@ static TypeDumpFunctionMap registerTypes()
|
||||
rc.insert("QSharedPointer<QString>", dumpQSharedPointerQString);
|
||||
rc.insert("QStringList", dumpQStringList);
|
||||
rc.insert("QList<int>", dumpQIntList);
|
||||
rc.insert("QLinkedList<int>", dumpQIntLinkedList);
|
||||
rc.insert("QList<std::string>", dumpStdStringQList);
|
||||
rc.insert("QVector<int>", dumpQIntVector);
|
||||
rc.insert("QVector<QString>", dumpQQStringVector);
|
||||
rc.insert("QMap<int,QString>", dumpQMapIntString);
|
||||
rc.insert("QMap<QString,QString>", dumpQMapQStringString);
|
||||
rc.insert("QMap<int,int>", dumpQMapIntInt);
|
||||
rc.insert("QSet<int>", dumpQSetInt);
|
||||
rc.insert("string", dumpStdString);
|
||||
rc.insert("wstring", dumpStdWString);
|
||||
rc.insert("list<int>", dumpStdIntList);
|
||||
|
||||
@@ -38,6 +38,7 @@ BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, const QString &suf
|
||||
, _block(cursor.block())
|
||||
, _maxBlockCount(maxBlockCount)
|
||||
{
|
||||
_tokenize.setQtMocRunEnabled(true);
|
||||
_tokenize.setSkipComments(true);
|
||||
_text = _block.text().left(cursor.position() - cursor.block().position());
|
||||
|
||||
@@ -52,13 +53,10 @@ BackwardsScanner::BackwardsScanner(const QTextCursor &cursor, const QString &suf
|
||||
int BackwardsScanner::state() const
|
||||
{ return _tokenize.state(); }
|
||||
|
||||
const QList<SimpleToken> &BackwardsScanner::tokens() const
|
||||
{ return _tokens; }
|
||||
|
||||
const SimpleToken &BackwardsScanner::LA(int index) const
|
||||
SimpleToken BackwardsScanner::LA(int index) const
|
||||
{ return const_cast<BackwardsScanner *>(this)->fetchToken(_startToken - index); }
|
||||
|
||||
const SimpleToken &BackwardsScanner::operator[](int index) const
|
||||
SimpleToken BackwardsScanner::operator[](int index) const
|
||||
{ return const_cast<BackwardsScanner *>(this)->fetchToken(index); }
|
||||
|
||||
const SimpleToken &BackwardsScanner::fetchToken(int i)
|
||||
@@ -72,16 +70,15 @@ const SimpleToken &BackwardsScanner::fetchToken(int i)
|
||||
} else {
|
||||
++_blocksTokenized;
|
||||
|
||||
QString blockText = _block.text();
|
||||
const QString blockText = _block.text();
|
||||
_text.prepend(blockText);
|
||||
|
||||
QList<SimpleToken> adaptedTokens;
|
||||
for (int i = 0; i < _tokens.size(); ++i) {
|
||||
const SimpleToken &t = _tokens.at(i);
|
||||
const int position = t.position() + blockText.length();
|
||||
adaptedTokens.append(SimpleToken(t.kind(),
|
||||
position,
|
||||
t.length(),
|
||||
_text.midRef(position, t.length())));
|
||||
SimpleToken t = _tokens.at(i);
|
||||
t.setPosition(t.position() + blockText.length());
|
||||
t.setText(_text.midRef(t.position(), t.length()));
|
||||
adaptedTokens.append(t);
|
||||
}
|
||||
|
||||
_tokens = _tokenize(blockText, previousBlockState(_block));
|
||||
@@ -102,18 +99,22 @@ int BackwardsScanner::startPosition() const
|
||||
QString BackwardsScanner::text() const
|
||||
{ return _text; }
|
||||
|
||||
QString BackwardsScanner::text(int begin, int end) const
|
||||
QString BackwardsScanner::mid(int index) const
|
||||
{
|
||||
const SimpleToken &firstToken = _tokens.at(begin + _offset);
|
||||
const SimpleToken &lastToken = _tokens.at(end + _offset - 1);
|
||||
return _text.mid(firstToken.begin(), lastToken.end() - firstToken.begin());
|
||||
const SimpleToken &firstToken = _tokens.at(index + _offset);
|
||||
return _text.mid(firstToken.begin());
|
||||
}
|
||||
|
||||
QStringRef BackwardsScanner::textRef(int begin, int end) const
|
||||
QString BackwardsScanner::text(int index) const
|
||||
{
|
||||
const SimpleToken &firstToken = _tokens.at(begin + _offset);
|
||||
const SimpleToken &lastToken = _tokens.at(end + _offset - 1);
|
||||
return _text.midRef(firstToken.begin(), lastToken.end() - firstToken.begin());
|
||||
const SimpleToken &firstToken = _tokens.at(index + _offset);
|
||||
return _text.mid(firstToken.begin(), firstToken.length());
|
||||
}
|
||||
|
||||
QStringRef BackwardsScanner::textRef(int index) const
|
||||
{
|
||||
const SimpleToken &firstToken = _tokens.at(index + _offset);
|
||||
return _text.midRef(firstToken.begin(), firstToken.length());
|
||||
}
|
||||
|
||||
int BackwardsScanner::previousBlockState(const QTextBlock &block) const
|
||||
@@ -156,6 +157,17 @@ int BackwardsScanner::startOfMatchingBrace(int index) const
|
||||
--count;
|
||||
--i;
|
||||
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
||||
} else if (tk[index - 1].is(T_RBRACE)) {
|
||||
int i = index - 1;
|
||||
int count = 0;
|
||||
do {
|
||||
if (tk[i].is(T_LBRACE)) {
|
||||
if (! ++count)
|
||||
return i;
|
||||
} else if (tk[i].is(T_RBRACE))
|
||||
--count;
|
||||
--i;
|
||||
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
||||
} else if (tk[index - 1].is(T_GREATER)) {
|
||||
int i = index - 1;
|
||||
int count = 0;
|
||||
@@ -167,7 +179,71 @@ int BackwardsScanner::startOfMatchingBrace(int index) const
|
||||
--count;
|
||||
--i;
|
||||
} while (count != 0 && tk[i].isNot(T_EOF_SYMBOL));
|
||||
} else {
|
||||
Q_ASSERT(0);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
int BackwardsScanner::startOfLine(int index) const
|
||||
{
|
||||
const BackwardsScanner tk(*this);
|
||||
|
||||
forever {
|
||||
const SimpleToken &tok = tk[index - 1];
|
||||
|
||||
if (tok.is(T_EOF_SYMBOL))
|
||||
break;
|
||||
else if (tok.followsNewline())
|
||||
return index - 1;
|
||||
|
||||
--index;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
int BackwardsScanner::startOfBlock(int index) const
|
||||
{
|
||||
const BackwardsScanner tk(*this);
|
||||
|
||||
const int start = index;
|
||||
|
||||
forever {
|
||||
SimpleToken token = tk[index - 1];
|
||||
|
||||
if (token.is(T_EOF_SYMBOL)) {
|
||||
break;
|
||||
|
||||
} else if (token.is(T_GREATER)) {
|
||||
const int matchingBrace = startOfMatchingBrace(index);
|
||||
|
||||
if (matchingBrace != index && tk[matchingBrace - 1].is(T_TEMPLATE))
|
||||
index = matchingBrace;
|
||||
|
||||
} else if (token.is(T_RPAREN) || token.is(T_RBRACKET) || token.is(T_RBRACE)) {
|
||||
const int matchingBrace = startOfMatchingBrace(index);
|
||||
|
||||
if (matchingBrace != index)
|
||||
index = matchingBrace;
|
||||
|
||||
} else if (token.is(T_LPAREN) || token.is(T_LBRACKET)) {
|
||||
break; // unmatched brace
|
||||
|
||||
} else if (token.is(T_LBRACE)) {
|
||||
return index - 1;
|
||||
|
||||
}
|
||||
|
||||
--index;
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
int BackwardsScanner::indentation(int index) const
|
||||
{
|
||||
SimpleToken newline = operator[](startOfLine(index + 1));
|
||||
return newline.position();
|
||||
}
|
||||
|
||||
@@ -51,21 +51,26 @@ public:
|
||||
int startPosition() const;
|
||||
|
||||
QString text() const;
|
||||
QString text(int begin, int end) const;
|
||||
QStringRef textRef(int begin, int end) const;
|
||||
QString mid(int index) const;
|
||||
|
||||
QString text(int index) const;
|
||||
QStringRef textRef(int index) const;
|
||||
// 1-based
|
||||
const SimpleToken &LA(int index) const;
|
||||
SimpleToken LA(int index) const;
|
||||
|
||||
// n-la token is [startToken - n]
|
||||
const SimpleToken &operator[](int index) const; // ### deprecate
|
||||
SimpleToken operator[](int index) const; // ### deprecate
|
||||
|
||||
int indentation(int index) const;
|
||||
|
||||
int startOfLine(int index) const;
|
||||
int startOfMatchingBrace(int index) const;
|
||||
int startOfBlock(int index) const;
|
||||
|
||||
int previousBlockState(const QTextBlock &block) const;
|
||||
|
||||
private:
|
||||
const SimpleToken &fetchToken(int i);
|
||||
const QList<SimpleToken> &tokens() const;
|
||||
|
||||
private:
|
||||
QList<SimpleToken> _tokens;
|
||||
|
||||
@@ -150,7 +150,7 @@ QString ExpressionUnderCursor::operator()(const QTextCursor &cursor)
|
||||
if (i == initialSize)
|
||||
return QString();
|
||||
|
||||
return scanner.text(i, initialSize);
|
||||
return scanner.mid(i);
|
||||
}
|
||||
|
||||
int ExpressionUnderCursor::startOfFunctionCall(const QTextCursor &cursor) const
|
||||
|
||||
@@ -49,9 +49,9 @@ static bool shouldOverrideChar(const QChar &ch)
|
||||
}
|
||||
}
|
||||
|
||||
static bool isCompleteStringLiteral(const BackwardsScanner &tk, int index, int startToken)
|
||||
static bool isCompleteStringLiteral(const BackwardsScanner &tk, int index)
|
||||
{
|
||||
const QStringRef text = tk.textRef(index, startToken);
|
||||
const QStringRef text = tk.textRef(index);
|
||||
|
||||
if (text.length() < 2)
|
||||
return false;
|
||||
@@ -62,9 +62,9 @@ static bool isCompleteStringLiteral(const BackwardsScanner &tk, int index, int s
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isCompleteCharLiteral(const BackwardsScanner &tk, int index, int startToken)
|
||||
static bool isCompleteCharLiteral(const BackwardsScanner &tk, int index)
|
||||
{
|
||||
const QStringRef text = tk.textRef(index, startToken);
|
||||
const QStringRef text = tk.textRef(index);
|
||||
|
||||
if (text.length() < 2)
|
||||
return false;
|
||||
@@ -75,7 +75,16 @@ static bool isCompleteCharLiteral(const BackwardsScanner &tk, int index, int sta
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool shouldInsertMatchingText(const QChar &lookAhead)
|
||||
MatchingText::MatchingText()
|
||||
{ }
|
||||
|
||||
bool MatchingText::shouldInsertMatchingText(const QTextCursor &tc)
|
||||
{
|
||||
QTextDocument *doc = tc.document();
|
||||
return shouldInsertMatchingText(doc->characterAt(tc.selectionEnd()));
|
||||
}
|
||||
|
||||
bool MatchingText::shouldInsertMatchingText(const QChar &lookAhead)
|
||||
{
|
||||
switch (lookAhead.unicode()) {
|
||||
case '{': case '}':
|
||||
@@ -91,9 +100,6 @@ static bool shouldInsertMatchingText(const QChar &lookAhead)
|
||||
} // switch
|
||||
}
|
||||
|
||||
MatchingText::MatchingText()
|
||||
{ }
|
||||
|
||||
QString MatchingText::insertMatchingBrace(const QTextCursor &cursor, const QString &textToProcess,
|
||||
const QChar &la, int *skippedChars) const
|
||||
{
|
||||
@@ -133,7 +139,7 @@ QString MatchingText::insertMatchingBrace(const QTextCursor &cursor, const QStri
|
||||
if (text.length() != 1)
|
||||
qWarning() << Q_FUNC_INFO << "handle event compression";
|
||||
|
||||
if (isCompleteStringLiteral(tk, index - 1, startToken))
|
||||
if (isCompleteStringLiteral(tk, index - 1))
|
||||
return QLatin1String("\"");
|
||||
|
||||
return QString();
|
||||
@@ -141,7 +147,7 @@ QString MatchingText::insertMatchingBrace(const QTextCursor &cursor, const QStri
|
||||
if (text.length() != 1)
|
||||
qWarning() << Q_FUNC_INFO << "handle event compression";
|
||||
|
||||
if (isCompleteCharLiteral(tk, index - 1, startToken))
|
||||
if (isCompleteCharLiteral(tk, index - 1))
|
||||
return QLatin1String("'");
|
||||
|
||||
return QString();
|
||||
|
||||
@@ -41,6 +41,9 @@ class CPLUSPLUS_EXPORT MatchingText
|
||||
public:
|
||||
MatchingText();
|
||||
|
||||
static bool shouldInsertMatchingText(const QTextCursor &tc);
|
||||
static bool shouldInsertMatchingText(const QChar &lookAhead);
|
||||
|
||||
QString insertMatchingBrace(const QTextCursor &tc, const QString &text,
|
||||
const QChar &la, int *skippedChars) const;
|
||||
QString insertParagraphSeparator(const QTextCursor &tc) const;
|
||||
|
||||
@@ -35,6 +35,17 @@
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
SimpleToken::SimpleToken(const Token &token, const QStringRef &text)
|
||||
: _kind(token.f.kind)
|
||||
, _flags(0)
|
||||
, _position(token.begin())
|
||||
, _length(token.f.length)
|
||||
, _text(text)
|
||||
{
|
||||
f._whitespace = token.f.whitespace;
|
||||
f._newline = token.f.newline;
|
||||
}
|
||||
|
||||
bool SimpleToken::isLiteral() const
|
||||
{
|
||||
return _kind >= T_FIRST_LITERAL && _kind <= T_LAST_LITERAL;
|
||||
@@ -60,6 +71,11 @@ bool SimpleToken::isObjCAtKeyword() const
|
||||
return _kind >= T_FIRST_OBJC_AT_KEYWORD && _kind <= T_LAST_OBJC_AT_KEYWORD;
|
||||
}
|
||||
|
||||
const char *SimpleToken::name() const
|
||||
{
|
||||
return Token::name(_kind);
|
||||
}
|
||||
|
||||
SimpleLexer::SimpleLexer()
|
||||
: _lastState(0),
|
||||
_skipComments(false),
|
||||
@@ -113,6 +129,7 @@ QList<SimpleToken> SimpleLexer::operator()(const QString &text, int state)
|
||||
Lexer lex(firstChar, lastChar);
|
||||
lex.setQtMocRunEnabled(_qtMocRunEnabled);
|
||||
lex.setObjCEnabled(_objCEnabled);
|
||||
lex.setStartWithNewline(true);
|
||||
|
||||
if (! _skipComments)
|
||||
lex.setScanCommentTokens(true);
|
||||
@@ -128,12 +145,8 @@ QList<SimpleToken> SimpleLexer::operator()(const QString &text, int state)
|
||||
if (tk.is(T_EOF_SYMBOL))
|
||||
break;
|
||||
|
||||
SimpleToken simpleTk;
|
||||
simpleTk._kind = int(tk.f.kind);
|
||||
simpleTk._position = int(lex.tokenOffset());
|
||||
simpleTk._length = int(lex.tokenLength());
|
||||
simpleTk._text = text.midRef(simpleTk._position, simpleTk._length);
|
||||
|
||||
QStringRef spell = text.midRef(lex.tokenOffset(), lex.tokenLength());
|
||||
SimpleToken simpleTk(tk, spell);
|
||||
lex.setScanAngleStringLiteralTokens(false);
|
||||
|
||||
if (tk.f.newline && tk.is(T_POUND))
|
||||
|
||||
@@ -37,21 +37,18 @@
|
||||
namespace CPlusPlus {
|
||||
|
||||
class SimpleLexer;
|
||||
class Token;
|
||||
|
||||
class CPLUSPLUS_EXPORT SimpleToken
|
||||
{
|
||||
public:
|
||||
SimpleToken(int kind, int position, int length, const QStringRef &text)
|
||||
: _kind(kind)
|
||||
, _position(position)
|
||||
, _length(length)
|
||||
, _text(text)
|
||||
{ }
|
||||
SimpleToken(const Token &token, const QStringRef &text);
|
||||
|
||||
SimpleToken()
|
||||
: _kind(0),
|
||||
_position(0),
|
||||
_length(0)
|
||||
: _kind(0)
|
||||
, _flags(0)
|
||||
, _position(0)
|
||||
, _length(0)
|
||||
{ }
|
||||
|
||||
inline int kind() const
|
||||
@@ -72,6 +69,12 @@ public:
|
||||
inline QStringRef text() const
|
||||
{ return _text; }
|
||||
|
||||
inline bool followsNewline() const
|
||||
{ return f._newline; }
|
||||
|
||||
inline bool followsWhitespace() const
|
||||
{ return f._whitespace; }
|
||||
|
||||
inline bool is(int k) const { return _kind == k; }
|
||||
inline bool isNot(int k) const { return _kind != k; }
|
||||
|
||||
@@ -81,8 +84,27 @@ public:
|
||||
bool isComment() const;
|
||||
bool isObjCAtKeyword() const;
|
||||
|
||||
const char *name() const;
|
||||
|
||||
// internal
|
||||
inline void setPosition(int position)
|
||||
{ _position = position; }
|
||||
|
||||
// internal
|
||||
inline void setText(const QStringRef &text)
|
||||
{ _text = text; }
|
||||
|
||||
public:
|
||||
int _kind;
|
||||
short _kind;
|
||||
union {
|
||||
short _flags;
|
||||
|
||||
struct {
|
||||
short _newline: 1;
|
||||
short _whitespace: 1;
|
||||
} f;
|
||||
};
|
||||
|
||||
int _position;
|
||||
int _length;
|
||||
QStringRef _text;
|
||||
|
||||
@@ -176,10 +176,11 @@ void StyleHelper::horizontalGradient(QPainter *painter, const QRect &spanRect, c
|
||||
|
||||
QColor base = StyleHelper::baseColor();
|
||||
QLinearGradient grad(rect.topLeft(), rect.bottomLeft());
|
||||
|
||||
grad.setColorAt(0, highlightColor().lighter(120));
|
||||
grad.setColorAt(0.4, highlightColor());
|
||||
grad.setColorAt(0.401, base);
|
||||
if (rect.height() == navigationWidgetHeight()) {
|
||||
grad.setColorAt(0.4, highlightColor());
|
||||
grad.setColorAt(0.401, base);
|
||||
}
|
||||
grad.setColorAt(1, shadowColor());
|
||||
p->fillRect(rect, grad);
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <cplusplus/TokenUnderCursor.h>
|
||||
#include <cplusplus/TypeOfExpression.h>
|
||||
#include <cplusplus/MatchingText.h>
|
||||
#include <cplusplus/BackwardsScanner.h>
|
||||
#include <cpptools/cppmodelmanagerinterface.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -1263,17 +1264,17 @@ bool CPPEditor::isElectricCharacter(const QChar &ch) const
|
||||
{
|
||||
if (ch == QLatin1Char('{') ||
|
||||
ch == QLatin1Char('}') ||
|
||||
ch == QLatin1Char(':') ||
|
||||
ch == QLatin1Char('#')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 1
|
||||
QString CPPEditor::autoComplete(QTextCursor &cursor, const QString &textToInsert) const
|
||||
{
|
||||
bool checkBlockEnd = m_allowSkippingOfBlockEnd;
|
||||
m_allowSkippingOfBlockEnd = false;
|
||||
const bool checkBlockEnd = m_allowSkippingOfBlockEnd;
|
||||
m_allowSkippingOfBlockEnd = false; // consume blockEnd.
|
||||
|
||||
if (!contextAllowsAutoParentheses(cursor))
|
||||
return QString();
|
||||
@@ -1281,16 +1282,21 @@ QString CPPEditor::autoComplete(QTextCursor &cursor, const QString &textToInsert
|
||||
QString text = textToInsert;
|
||||
const QChar lookAhead = characterAt(cursor.selectionEnd());
|
||||
|
||||
QString autoText;
|
||||
int skippedChars = 0;
|
||||
|
||||
if (checkBlockEnd && (lookAhead == QChar::ParagraphSeparator && (! text.isEmpty() && text.at(0) == QLatin1Char('}')))) {
|
||||
skippedChars = 2;
|
||||
text = text.mid(1);
|
||||
}
|
||||
|
||||
MatchingText matchingText;
|
||||
autoText = matchingText.insertMatchingBrace(cursor, text, lookAhead, &skippedChars);
|
||||
int skippedChars = 0;
|
||||
const QString autoText = matchingText.insertMatchingBrace(cursor, text, lookAhead, &skippedChars);
|
||||
|
||||
if (checkBlockEnd && textToInsert.at(0) == QLatin1Char('}')) {
|
||||
if (textToInsert.length() > 1)
|
||||
qWarning() << "*** handle event compression";
|
||||
|
||||
int startPos = cursor.selectionEnd(), pos = startPos;
|
||||
while (characterAt(pos).isSpace())
|
||||
++pos;
|
||||
|
||||
if (characterAt(pos) == QLatin1Char('}'))
|
||||
skippedChars += (pos - startPos) + 1;
|
||||
}
|
||||
|
||||
if (skippedChars) {
|
||||
const int pos = cursor.position();
|
||||
@@ -1300,67 +1306,6 @@ QString CPPEditor::autoComplete(QTextCursor &cursor, const QString &textToInsert
|
||||
|
||||
return autoText;
|
||||
}
|
||||
#else
|
||||
QString CPPEditor::autoComplete(QTextCursor &cursor, const QString &text) const
|
||||
{
|
||||
bool checkBlockEnd = m_allowSkippingOfBlockEnd;
|
||||
m_allowSkippingOfBlockEnd = false;
|
||||
|
||||
if (!contextAllowsAutoParentheses(cursor))
|
||||
return QString();
|
||||
|
||||
QString autoText;
|
||||
QChar lookAhead = characterAt(cursor.selectionEnd());
|
||||
if (lookAhead.isSpace() // Only auto-insert when the text right of the cursor seems unrelated
|
||||
|| lookAhead == QLatin1Char('{')
|
||||
|| lookAhead == QLatin1Char('}')
|
||||
|| lookAhead == QLatin1Char(']')
|
||||
|| lookAhead == QLatin1Char(')')
|
||||
|| lookAhead == QLatin1Char(';')
|
||||
|| lookAhead == QLatin1Char(',')
|
||||
) {
|
||||
foreach (QChar c, text) {
|
||||
QChar close;
|
||||
if (c == QLatin1Char('(')) {
|
||||
close = QLatin1Char(')');
|
||||
} else if (c == QLatin1Char('['))
|
||||
close = QLatin1Char(']');
|
||||
else if (c == QLatin1Char('\"'))
|
||||
close = c;
|
||||
else if (c == QLatin1Char('\''))
|
||||
close = c;
|
||||
if (!close.isNull())
|
||||
autoText += close;
|
||||
}
|
||||
}
|
||||
|
||||
bool skip = false;
|
||||
QChar first = text.at(0);
|
||||
if (first == QLatin1Char(')')
|
||||
|| first == QLatin1Char(']')
|
||||
|| first == QLatin1Char(';')
|
||||
) {
|
||||
skip = (first == lookAhead);
|
||||
} else if (first == QLatin1Char('\"') || first == QLatin1Char('\'')) {
|
||||
if (first == lookAhead) {
|
||||
QChar lookBehind = characterAt(cursor.position()-1);
|
||||
skip = (lookBehind != '\\');
|
||||
}
|
||||
} else if (checkBlockEnd && first == QLatin1Char('}')
|
||||
&& lookAhead == QChar::ParagraphSeparator) {
|
||||
skip = (first == characterAt(cursor.position() + 1));
|
||||
cursor.movePosition(QTextCursor::Right);
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
int pos = cursor.position();
|
||||
cursor.setPosition(pos+1);
|
||||
cursor.setPosition(pos, QTextCursor::KeepAnchor);
|
||||
}
|
||||
|
||||
return autoText;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CPPEditor::autoBackspace(QTextCursor &cursor)
|
||||
{
|
||||
@@ -1398,7 +1343,6 @@ int CPPEditor::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor)
|
||||
if (!contextAllowsAutoParentheses(cursor))
|
||||
return 0;
|
||||
|
||||
|
||||
// verify that we indeed do have an extra opening brace in the document
|
||||
int braceDepth = document()->lastBlock().userState();
|
||||
if (braceDepth >= 0)
|
||||
@@ -1432,6 +1376,9 @@ int CPPEditor::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor)
|
||||
|
||||
bool CPPEditor::contextAllowsAutoParentheses(const QTextCursor &cursor) const
|
||||
{
|
||||
if (! MatchingText::shouldInsertMatchingText(cursor))
|
||||
return false;
|
||||
|
||||
CPlusPlus::TokenUnderCursor tokenUnderCursor;
|
||||
const SimpleToken tk = tokenUnderCursor(cursor);
|
||||
|
||||
@@ -1470,9 +1417,60 @@ static void indentCPPBlock(const CPPEditor::TabSettings &ts,
|
||||
|
||||
void CPPEditor::indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar)
|
||||
{
|
||||
QTextCursor tc(block);
|
||||
tc.movePosition(QTextCursor::EndOfBlock);
|
||||
|
||||
BackwardsScanner tk(tc, QString(), 400);
|
||||
const int tokenCount = tk.startToken();
|
||||
const int indentSize = tabSettings().m_indentSize;
|
||||
|
||||
if (tokenCount != 0) {
|
||||
const SimpleToken firstToken = tk[0];
|
||||
|
||||
if (firstToken.is(T_COLON)) {
|
||||
const int indent = tk.indentation(-1) + // indentation of the previous newline
|
||||
indentSize;
|
||||
tabSettings().indentLine(block, indent);
|
||||
return;
|
||||
} else if ((firstToken.is(T_PUBLIC) || firstToken.is(T_PROTECTED) || firstToken.is(T_PRIVATE) ||
|
||||
firstToken.is(T_Q_SIGNALS) || firstToken.is(T_Q_SLOTS)) && tk[1].is(T_COLON)) {
|
||||
const int startOfBlock = tk.startOfBlock(0);
|
||||
if (startOfBlock != 0) {
|
||||
const int indent = tk.indentation(startOfBlock);
|
||||
tabSettings().indentLine(block, indent);
|
||||
return;
|
||||
}
|
||||
} else if (firstToken.is(T_CASE) || firstToken.is(T_DEFAULT)) {
|
||||
const int startOfBlock = tk.startOfBlock(0);
|
||||
if (startOfBlock != 0) {
|
||||
const int indent = tk.indentation(startOfBlock);
|
||||
tabSettings().indentLine(block, indent);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((tokenCount == 0 || tk[0].isNot(T_POUND)) && typedChar.isNull() && (tk[-1].is(T_IDENTIFIER) || tk[-1].is(T_RPAREN))) {
|
||||
int tokenIndex = -1;
|
||||
if (tk[-1].is(T_RPAREN)) {
|
||||
const int matchingBrace = tk.startOfMatchingBrace(0);
|
||||
if (matchingBrace != 0 && tk[matchingBrace - 1].is(T_IDENTIFIER)) {
|
||||
tokenIndex = matchingBrace - 1;
|
||||
}
|
||||
}
|
||||
|
||||
const QString spell = tk.text(tokenIndex);
|
||||
if (tk[tokenIndex].followsNewline() && (spell.startsWith(QLatin1String("QT_")) ||
|
||||
spell.startsWith(QLatin1String("Q_")))) {
|
||||
const int indent = tk.indentation(tokenIndex);
|
||||
tabSettings().indentLine(block, indent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const TextEditor::TextBlockIterator begin(doc->begin());
|
||||
const TextEditor::TextBlockIterator end(block.next());
|
||||
|
||||
indentCPPBlock(tabSettings(), block, begin, end, typedChar);
|
||||
}
|
||||
|
||||
|
||||
@@ -554,7 +554,7 @@ static inline QString msgNotHandled(const QString &type)
|
||||
return QString::fromLatin1("The type '%1' is not handled.").arg(type);
|
||||
}
|
||||
|
||||
CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool dumpChildren, int source,
|
||||
CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool dumpChildren,
|
||||
QList<WatchData> *result, QString *errorMessage)
|
||||
{
|
||||
// Check failure cache and supported types
|
||||
@@ -593,7 +593,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
|
||||
arg(wd.name, wd.exp, wd.type);
|
||||
m_access->showDebuggerOutput(LogMisc, message);
|
||||
|
||||
const DumpExecuteResult der = executeDump(wd, td, dumpChildren, source, result, errorMessage);
|
||||
const DumpExecuteResult der = executeDump(wd, td, dumpChildren, result, errorMessage);
|
||||
if (der == DumpExecuteOk)
|
||||
return DumpOk;
|
||||
// Cache types that fail due to complicated template size expressions.
|
||||
@@ -610,7 +610,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
|
||||
|
||||
CdbDumperHelper::DumpExecuteResult
|
||||
CdbDumperHelper::executeDump(const WatchData &wd,
|
||||
const QtDumperHelper::TypeData& td, bool dumpChildren, int source,
|
||||
const QtDumperHelper::TypeData& td, bool dumpChildren,
|
||||
QList<WatchData> *result, QString *errorMessage)
|
||||
{
|
||||
QByteArray inBuffer;
|
||||
@@ -658,12 +658,10 @@ CdbDumperHelper::DumpExecuteResult
|
||||
}
|
||||
if (!callDumper(callCmd, inBuffer, &outputData, true, errorMessage))
|
||||
return DumpExecuteCallFailed;
|
||||
QtDumperResult dumpResult;
|
||||
if (!QtDumperHelper::parseValue(outputData, &dumpResult)) {
|
||||
if (!QtDumperHelper::parseValue(outputData, result)) {
|
||||
*errorMessage = QLatin1String("Parsing of value query output failed.");
|
||||
return DumpExecuteCallFailed;
|
||||
}
|
||||
*result = dumpResult.toWatchData(source);
|
||||
return DumpExecuteOk;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
|
||||
// Dump a WatchData item.
|
||||
enum DumpResult { DumpNotHandled, DumpOk, DumpError };
|
||||
DumpResult dumpType(const WatchData &d, bool dumpChildren, int source,
|
||||
DumpResult dumpType(const WatchData &d, bool dumpChildren,
|
||||
QList<WatchData> *result, QString *errorMessage);
|
||||
|
||||
inline CdbComInterfaces *comInterfaces() const { return m_cif; }
|
||||
@@ -113,7 +113,7 @@ private:
|
||||
DumpComplexExpressionEncountered,
|
||||
DumpExecuteCallFailed };
|
||||
DumpExecuteResult executeDump(const WatchData &wd,
|
||||
const QtDumperHelper::TypeData& td, bool dumpChildren, int source,
|
||||
const QtDumperHelper::TypeData& td, bool dumpChildren,
|
||||
QList<WatchData> *result, QString *errorMessage);
|
||||
|
||||
static bool writeToDebuggee(CIDebugDataSpaces *ds, const QByteArray &buffer, quint64 address, QString *errorMessage);
|
||||
|
||||
@@ -156,7 +156,7 @@ bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QSt
|
||||
derefedWd.name = QString(QLatin1Char('*'));
|
||||
derefedWd.iname = wd.iname + QLatin1String(".*");
|
||||
derefedWd.source = OwnerDumper | CdbStackFrameContext::ChildrenKnownBit;
|
||||
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(derefedWd, true, OwnerDumper, &m_dumperResult, errorMessage);
|
||||
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(derefedWd, true, &m_dumperResult, errorMessage);
|
||||
if (dr != CdbDumperHelper::DumpOk)
|
||||
break;
|
||||
// Insert the pointer item with 1 additional child + its dumper results
|
||||
@@ -166,8 +166,7 @@ bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QSt
|
||||
ptrWd.setHasChildren(true);
|
||||
ptrWd.setChildrenUnneeded();
|
||||
m_wh->insertData(ptrWd);
|
||||
foreach(const WatchData &dwd, m_dumperResult)
|
||||
m_wh->insertData(dwd);
|
||||
m_wh->insertBulkData(m_dumperResult);
|
||||
handled = true;
|
||||
} while (false);
|
||||
if (debugCDBWatchHandling)
|
||||
@@ -184,7 +183,8 @@ static inline void fixDumperResult(const WatchData &source,
|
||||
const int size = result->size();
|
||||
if (!size)
|
||||
return;
|
||||
// debugWatchDataList(*result, suppressGrandChildren ? ">fixDumperResult suppressGrandChildren" : ">fixDumperResult");
|
||||
if (debugCDBWatchHandling)
|
||||
debugWatchDataList(*result, suppressGrandChildren ? ">fixDumperResult suppressGrandChildren" : ">fixDumperResult");
|
||||
WatchData &returned = result->front();
|
||||
if (returned.iname != source.iname)
|
||||
return;
|
||||
@@ -198,6 +198,10 @@ static inline void fixDumperResult(const WatchData &source,
|
||||
returned.setValue(QCoreApplication::translate("CdbStackFrameContext", "<Unknown>"));
|
||||
}
|
||||
}
|
||||
// Indicate owner and known children
|
||||
returned.source = OwnerDumper;
|
||||
if (returned.isChildrenKnown() && returned.isHasChildrenKnown() && returned.hasChildren)
|
||||
returned.source |= CdbStackFrameContext::ChildrenKnownBit;
|
||||
if (size == 1)
|
||||
return;
|
||||
// If the model queries the expanding item by pretending childrenNeeded=1,
|
||||
@@ -208,6 +212,10 @@ static inline void fixDumperResult(const WatchData &source,
|
||||
QList<WatchData>::iterator it = result->begin();
|
||||
for (++it; it != wend; ++it) {
|
||||
WatchData &wd = *it;
|
||||
// Indicate owner and known children
|
||||
it->source = OwnerDumper;
|
||||
if (it->isChildrenKnown() && it->isHasChildrenKnown() && it->hasChildren)
|
||||
it->source |= CdbStackFrameContext::ChildrenKnownBit;
|
||||
if (wd.addr.isEmpty() && wd.isSomethingNeeded()) {
|
||||
wd.setHasChildren(false);
|
||||
wd.setAllUnneeded();
|
||||
@@ -218,7 +226,8 @@ static inline void fixDumperResult(const WatchData &source,
|
||||
wd.setHasChildren(false);
|
||||
}
|
||||
}
|
||||
// debugWatchDataList(*result, "<fixDumperResult");
|
||||
if (debugCDBWatchHandling)
|
||||
debugWatchDataList(*result, "<fixDumperResult");
|
||||
}
|
||||
|
||||
WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd)
|
||||
@@ -238,15 +247,14 @@ WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd)
|
||||
return *this;
|
||||
}
|
||||
// Try library dumpers.
|
||||
switch (m_dumper->dumpType(wd, true, OwnerDumper, &m_dumperResult, &errorMessage)) {
|
||||
switch (m_dumper->dumpType(wd, true, &m_dumperResult, &errorMessage)) {
|
||||
case CdbDumperHelper::DumpOk:
|
||||
if (debugCDBWatchHandling)
|
||||
qDebug() << "dumper triggered";
|
||||
// Dumpers omit types for complicated templates
|
||||
fixDumperResult(wd, &m_dumperResult, false);
|
||||
// Discard the original item and insert the dumper results
|
||||
foreach(const WatchData &dwd, m_dumperResult)
|
||||
m_wh->insertData(dwd);
|
||||
m_wh->insertBulkData(m_dumperResult);
|
||||
// Nasty side effect: Modify owner for the ignore predicate
|
||||
wd.source = OwnerDumper;
|
||||
break;
|
||||
@@ -325,13 +333,12 @@ bool CdbStackFrameContext::completeData(const WatchData &incompleteLocal,
|
||||
return true;
|
||||
}
|
||||
QList<WatchData> dumperResult;
|
||||
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(incompleteLocal, true, OwnerDumper, &dumperResult, errorMessage);
|
||||
const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(incompleteLocal, true, &dumperResult, errorMessage);
|
||||
if (dr == CdbDumperHelper::DumpOk) {
|
||||
// Hack to stop endless model recursion
|
||||
const bool suppressGrandChildren = !wh->isExpandedIName(incompleteLocal.iname);
|
||||
fixDumperResult(incompleteLocal, &dumperResult, suppressGrandChildren);
|
||||
foreach(const WatchData &dwd, dumperResult)
|
||||
wh->insertData(dwd);
|
||||
wh->insertBulkData(dumperResult);
|
||||
} else {
|
||||
const QString msg = QString::fromLatin1("Unable to further expand dumper watch data: '%1' (%2): %3/%4").arg(incompleteLocal.name, incompleteLocal.type).arg(int(dr)).arg(*errorMessage);
|
||||
qWarning("%s", qPrintable(msg));
|
||||
@@ -372,7 +379,7 @@ bool CdbStackFrameContext::editorToolTip(const QString &iname,
|
||||
// Check dumpers. Should actually be just one item.
|
||||
if (m_useDumpers && m_dumper->state() != CdbDumperHelper::Disabled) {
|
||||
QList<WatchData> result;
|
||||
if (CdbDumperHelper::DumpOk == m_dumper->dumpType(wd, false, OwnerDumper, &result, errorMessage)) {
|
||||
if (CdbDumperHelper::DumpOk == m_dumper->dumpType(wd, false, &result, errorMessage)) {
|
||||
foreach (const WatchData &dwd, result) {
|
||||
if (!value->isEmpty())
|
||||
value->append(QLatin1Char('\n'));
|
||||
|
||||
@@ -595,9 +595,9 @@ bool CdbSymbolGroupContext::debugValueToInteger(const DEBUG_VALUE &dv, qint64 *v
|
||||
* To add further types, have a look at the toString() output of the
|
||||
* symbol group. */
|
||||
|
||||
static QString msgStructuralError(const QString &type, int code)
|
||||
static QString msgStructuralError(const QString &name, const QString &type, int code)
|
||||
{
|
||||
return QString::fromLatin1("Warning: Internal dumper for '%1' failed with %2.").arg(type).arg(code);
|
||||
return QString::fromLatin1("Warning: Internal dumper for '%1' (%2) failed with %3.").arg(name, type).arg(code);
|
||||
}
|
||||
|
||||
static inline bool isStdStringOrPointer(const QString &type)
|
||||
@@ -631,7 +631,7 @@ CdbSymbolGroupContext::DumperResult
|
||||
rc = DumperError;
|
||||
break;
|
||||
default:
|
||||
qWarning("%s\n", qPrintable(msgStructuralError(wd->type, drc)));
|
||||
qWarning("%s\n", qPrintable(msgStructuralError(wd->iname, wd->type, drc)));
|
||||
rc = DumperNotHandled;
|
||||
break;
|
||||
}
|
||||
@@ -647,7 +647,7 @@ CdbSymbolGroupContext::DumperResult
|
||||
rc = DumperError;
|
||||
break;
|
||||
default:
|
||||
qWarning("%s\n", qPrintable(msgStructuralError(wd->type, drc)));
|
||||
qWarning("%s\n", qPrintable(msgStructuralError(wd->iname, wd->type, drc)));
|
||||
rc = DumperNotHandled;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3305,36 +3305,12 @@ static void parseSizeCache(const GdbMi &contents, QtDumperHelper *dumperHelper)
|
||||
void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const QVariant &)
|
||||
{
|
||||
const double dumperVersionRequired = 1.0;
|
||||
m_dumperHelper.clear();
|
||||
//qDebug() << "DATA DUMPER TRIAL:" << record.toString();
|
||||
|
||||
GdbMi contents;
|
||||
QTC_ASSERT(parseConsoleStream(record, &contents), /**/);
|
||||
GdbMi simple = contents.findChild("dumpers");
|
||||
|
||||
m_dumperHelper.setQtNamespace(_(contents.findChild("namespace").data()));
|
||||
GdbMi qtversion = contents.findChild("qtversion");
|
||||
int qtv = 0;
|
||||
if (qtversion.children().size() == 3) {
|
||||
qtv = (qtversion.childAt(0).data().toInt() << 16)
|
||||
+ (qtversion.childAt(1).data().toInt() << 8)
|
||||
+ qtversion.childAt(2).data().toInt();
|
||||
//qDebug() << "FOUND QT VERSION:" << qtversion.toString() << m_qtVersion;
|
||||
}
|
||||
m_dumperHelper.setQtVersion(qtv);
|
||||
//qDebug() << "CONTENTS:" << contents.toString();
|
||||
//qDebug() << "SIMPLE DUMPERS:" << simple.toString();
|
||||
|
||||
QStringList availableSimpleDebuggingHelpers;
|
||||
foreach (const GdbMi &item, simple.children())
|
||||
availableSimpleDebuggingHelpers.append(_(item.data()));
|
||||
m_dumperHelper.parseQueryTypes(availableSimpleDebuggingHelpers, QtDumperHelper::GdbDebugger);
|
||||
|
||||
if (availableSimpleDebuggingHelpers.isEmpty()) {
|
||||
if (!m_dumperInjectionLoad) // Retry if thread has not terminated yet.
|
||||
m_debuggingHelperState = DebuggingHelperUnavailable;
|
||||
showStatusMessage(tr("Debugging helpers not found."));
|
||||
} else {
|
||||
const bool ok = m_dumperHelper.parseQuery(contents, QtDumperHelper::GdbDebugger) && m_dumperHelper.typeCount();
|
||||
if (ok) {
|
||||
// Get version and sizes from dumpers. Expression cache
|
||||
// currently causes errors.
|
||||
const double dumperVersion = getDumperVersion(contents);
|
||||
@@ -3347,6 +3323,10 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
|
||||
m_debuggingHelperState = DebuggingHelperAvailable;
|
||||
const QString successMsg = tr("Dumper version %1, %n custom dumpers found.", 0, m_dumperHelper.typeCount()).arg(dumperVersion);
|
||||
showStatusMessage(successMsg);
|
||||
} else {
|
||||
if (!m_dumperInjectionLoad) // Retry if thread has not terminated yet.
|
||||
m_debuggingHelperState = DebuggingHelperUnavailable;
|
||||
showStatusMessage(tr("Debugging helpers not found."));
|
||||
}
|
||||
//qDebug() << m_dumperHelper.toString(true);
|
||||
//qDebug() << m_availableSimpleDebuggingHelpers << "DATA DUMPERS AVAILABLE";
|
||||
@@ -4318,7 +4298,8 @@ IDebuggerEngine *createSymbianEngine(DebuggerManager *parent,
|
||||
QSharedPointer<TrkOptions> options(new TrkOptions);
|
||||
options->fromSettings(Core::ICore::instance()->settings());
|
||||
|
||||
opts->push_back(new TrkOptionsPage(options));
|
||||
if (!qgetenv("QTCREATOR_WITH_S60").isEmpty())
|
||||
opts->push_back(new TrkOptionsPage(options));
|
||||
TrkGdbAdapter *adapter = new TrkGdbAdapter(options);
|
||||
GdbEngine *engine = new GdbEngine(parent, adapter);
|
||||
QObject::connect(adapter, SIGNAL(output(QString)),
|
||||
|
||||
@@ -227,6 +227,8 @@ QString WatchData::toString() const
|
||||
str << QLatin1Char('{');
|
||||
if (!iname.isEmpty())
|
||||
str << "iname=\"" << iname << doubleQuoteComma;
|
||||
if (!name.isEmpty() && name != iname)
|
||||
str << "name=\"" << name << doubleQuoteComma;
|
||||
if (!addr.isEmpty())
|
||||
str << "addr=\"" << addr << doubleQuoteComma;
|
||||
if (!exp.isEmpty())
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "watchutils.h"
|
||||
#include "watchhandler.h"
|
||||
#include "gdb/gdbmi.h"
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <texteditor/basetexteditor.h>
|
||||
@@ -491,172 +492,6 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
|
||||
return expr;
|
||||
}
|
||||
|
||||
// --------------- QtDumperResult
|
||||
|
||||
QtDumperResult::Child::Child() :
|
||||
keyEncoded(0),
|
||||
valueEncoded(0),
|
||||
childCount(-1),
|
||||
valueEnabled(true),
|
||||
valueEncountered(false)
|
||||
{
|
||||
}
|
||||
|
||||
QtDumperResult::QtDumperResult() :
|
||||
valueEncountered(false),
|
||||
valueEncoded(0),
|
||||
valueEnabled(true),
|
||||
childCount(-1),
|
||||
internal(false),
|
||||
childChildCount(-1)
|
||||
{
|
||||
}
|
||||
|
||||
void QtDumperResult::clear()
|
||||
{
|
||||
iname.clear();
|
||||
value.clear();
|
||||
address.clear();
|
||||
addressInfo.clear();
|
||||
type.clear();
|
||||
extra.clear();
|
||||
displayedType.clear();
|
||||
valueEncoded = 0;
|
||||
valueEncountered = false;
|
||||
valueEnabled = false;
|
||||
childCount = -1;
|
||||
internal = false;
|
||||
childType.clear();
|
||||
children.clear();
|
||||
childChildCount = -1;
|
||||
}
|
||||
|
||||
QList<WatchData> QtDumperResult::toWatchData(int source) const
|
||||
{
|
||||
QList<WatchData> rc;
|
||||
rc.push_back(WatchData());
|
||||
WatchData &root = rc.front();
|
||||
root.iname = iname;
|
||||
const QChar dot = QLatin1Char('.');
|
||||
const int lastDotIndex = root.iname.lastIndexOf(dot);
|
||||
root.exp = root.name = lastDotIndex == -1 ? iname : iname.mid(lastDotIndex + 1);
|
||||
if (valueEncountered) {
|
||||
root.setValue(decodeData(value, valueEncoded));
|
||||
root.valueEnabled = valueEnabled;
|
||||
}
|
||||
root.setType(type);
|
||||
if (!displayedType.isEmpty())
|
||||
root.displayedType = displayedType;
|
||||
root.setAddress(address);
|
||||
root.source = source;
|
||||
if (childCount >= 0)
|
||||
root.setHasChildren(childCount > 0);
|
||||
// Children. Sanity check after parsing sets childcount to list size
|
||||
// if list is not empty
|
||||
if (children.empty()) {
|
||||
if (childCount > 0)
|
||||
root.setChildrenNeeded();
|
||||
} else {
|
||||
root.setChildrenUnneeded();
|
||||
for (int c = 0; c < childCount; c++) {
|
||||
const Child &dchild = children.at(c);
|
||||
rc.push_back(WatchData());
|
||||
WatchData &wchild = rc.back();
|
||||
wchild.source = source;
|
||||
wchild.iname = iname;
|
||||
// Name can be empty for array-like things
|
||||
const QString iname = dchild.name.isEmpty() ? QString::number(c) : dchild.name;
|
||||
// Use key entry as name (which is used for map nodes)
|
||||
if (dchild.key.isEmpty()) {
|
||||
wchild.name = iname;
|
||||
} else {
|
||||
// Do not use map keys as iname since they might contain quotes.
|
||||
wchild.name = decodeData(dchild.key, dchild.keyEncoded);
|
||||
if (wchild.name.size() > 13) {
|
||||
wchild.name.truncate(12);
|
||||
wchild.name += QLatin1String("...");
|
||||
}
|
||||
}
|
||||
// Append iname to total iname.
|
||||
wchild.iname += dot;
|
||||
wchild.iname += iname;
|
||||
wchild.exp = dchild.exp;
|
||||
if (dchild.valueEncountered) {
|
||||
wchild.valueEnabled = dchild.valueEnabled;
|
||||
wchild.setValue(decodeData(dchild.value, dchild.valueEncoded));
|
||||
}
|
||||
wchild.setAddress(dchild.address);
|
||||
// The type setter sets hasChildren for known types.
|
||||
wchild.setType(dchild.type.isEmpty() ? childType : dchild.type);
|
||||
if (!dchild.displayedType.isEmpty())
|
||||
wchild.displayedType = dchild.displayedType;
|
||||
// Child overrides.
|
||||
const int effectiveChildChildCount = dchild.childCount == -1 ? childChildCount : dchild.childCount;
|
||||
switch (effectiveChildChildCount) {
|
||||
case -1: // In this case, trust WatchData::setType().
|
||||
break;
|
||||
case 0:
|
||||
wchild.setHasChildren(false);
|
||||
break;
|
||||
default:
|
||||
wchild.setHasChildren(true);
|
||||
wchild.setChildrenNeeded();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
QDebug nospace = qDebug().nospace();
|
||||
nospace << "QtDumperResult::toWatchData" << *this << '\n';
|
||||
foreach(const WatchData &wd, rc)
|
||||
nospace << " " << wd.toString() << '\n';
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug in, const QtDumperResult &d)
|
||||
{
|
||||
QDebug nospace = in.nospace();
|
||||
nospace << " iname=" << d.iname << " type=" << d.type
|
||||
<< " displayed=" << d.displayedType
|
||||
<< " address=" << d.address;
|
||||
if (!d.addressInfo.isEmpty())
|
||||
nospace << " addressInfo=" << d.addressInfo;
|
||||
if (d.valueEncountered) {
|
||||
nospace << " encoded=" << d.valueEncoded
|
||||
<< " value=" << d.value
|
||||
<< " enabled=" << d.valueEnabled;
|
||||
} else {
|
||||
nospace << " <no value>";
|
||||
}
|
||||
nospace << " childnumchild=" << d.childChildCount
|
||||
<< " internal=" << d.internal
|
||||
<< " extra='" << d.extra << "'\n";
|
||||
|
||||
const int realChildCount = d.children.size();
|
||||
if (d.childCount || realChildCount) {
|
||||
nospace << "childCount=" << d.childCount << '/' << realChildCount
|
||||
<< " childType=" << d.childType << '\n';
|
||||
for (int i = 0; i < realChildCount; i++) {
|
||||
const QtDumperResult::Child &c = d.children.at(i);
|
||||
nospace << " #" << i << " addr=" << c.address
|
||||
<< " enabled=" << c.valueEnabled
|
||||
<< " type=" << c.type << " exp=" << c.exp
|
||||
<< " name=" << c.name;
|
||||
if (!c.key.isEmpty())
|
||||
nospace << " keyencoded=" << c.keyEncoded << " key=" << c.key;
|
||||
if (c.valueEncountered) {
|
||||
nospace << " valueencoded=" << c.valueEncoded << " value=" << c.value;
|
||||
} else {
|
||||
nospace << " <no value>";
|
||||
}
|
||||
nospace << "childcount=" << c.childCount << '\n';
|
||||
}
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
// ----------------- QtDumperHelper::TypeData
|
||||
QtDumperHelper::TypeData::TypeData() :
|
||||
type(UnknownType),
|
||||
@@ -725,6 +560,10 @@ QString QtDumperHelper::toString(bool debug) const
|
||||
for (SizeCache::const_iterator it = m_sizeCache.constBegin(); it != scend; ++it) {
|
||||
str << ' ' << it.key() << '=' << it.value();
|
||||
}
|
||||
str << "\nExpression cache: (" << m_expressionCache.size() << ")\n";
|
||||
const QMap<QString, QString>::const_iterator excend = m_expressionCache.constEnd();
|
||||
for (QMap<QString, QString>::const_iterator it = m_expressionCache.constBegin(); it != excend; ++it)
|
||||
str << " " << it.key() << ' ' << it.value() << '\n';
|
||||
return rc;
|
||||
}
|
||||
const QString nameSpace = m_qtNamespace.isEmpty() ? QCoreApplication::translate("QtDumperHelper", "<none>") : m_qtNamespace;
|
||||
@@ -749,11 +588,6 @@ QString QtDumperHelper::qtNamespace() const
|
||||
return m_qtNamespace;
|
||||
}
|
||||
|
||||
void QtDumperHelper::setQtNamespace(const QString &qtNamespace)
|
||||
{
|
||||
m_qtNamespace = qtNamespace;
|
||||
}
|
||||
|
||||
int QtDumperHelper::typeCount() const
|
||||
{
|
||||
return m_nameTypeMap.size();
|
||||
@@ -842,23 +676,6 @@ QString QtDumperHelper::qtVersionString() const
|
||||
return rc;
|
||||
}
|
||||
|
||||
void QtDumperHelper::setQtVersion(int v)
|
||||
{
|
||||
m_qtVersion = v;
|
||||
}
|
||||
|
||||
void QtDumperHelper::setQtVersion(const QString &v)
|
||||
{
|
||||
m_qtVersion = 0;
|
||||
const QStringList vl = v.split(QLatin1Char('.'));
|
||||
if (vl.size() == 3) {
|
||||
const int major = vl.at(0).toInt();
|
||||
const int minor = vl.at(1).toInt();
|
||||
const int patch = vl.at(2).toInt();
|
||||
m_qtVersion = (major << 16) | (minor << 8) | patch;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse a list of types.
|
||||
void QtDumperHelper::parseQueryTypes(const QStringList &l, Debugger debugger)
|
||||
{
|
||||
@@ -1049,134 +866,6 @@ bool DumperParser::handleValue(const char *k, int size)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parse 'query' (1) protocol response of the custom dumpers:
|
||||
* "'dumpers=["QByteArray","QDateTime",..."std::basic_string",],
|
||||
* qtversion=["4","5","1"],namespace="""' */
|
||||
|
||||
class QueryDumperParser : public DumperParser {
|
||||
public:
|
||||
typedef QPair<QString, int> SizeEntry;
|
||||
explicit QueryDumperParser(const char *s);
|
||||
|
||||
struct Data {
|
||||
QString qtNameSpace;
|
||||
QString qtVersion;
|
||||
QString dumperVersion;
|
||||
QStringList types;
|
||||
QList<SizeEntry> sizes;
|
||||
QMap<QString, QString> expressionCache;
|
||||
};
|
||||
|
||||
inline Data data() const { return m_data; }
|
||||
|
||||
protected:
|
||||
virtual bool handleKeyword(const char *k, int size);
|
||||
virtual bool handleListStart();
|
||||
virtual bool handleListEnd();
|
||||
virtual bool handleHashEnd();
|
||||
virtual bool handleValue(const char *k, int size);
|
||||
|
||||
private:
|
||||
enum Mode { None, ExpectingDumpers, ExpectingQtVersion, ExpectingDumperVersion,
|
||||
ExpectingNameSpace, ExpectingSizes, ExpectingExpressionCache };
|
||||
Mode m_mode;
|
||||
Data m_data;
|
||||
QString m_lastSizeType;
|
||||
QString m_lastExpression;
|
||||
};
|
||||
|
||||
QueryDumperParser::QueryDumperParser(const char *s) :
|
||||
DumperParser(s),
|
||||
m_mode(None)
|
||||
{
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleKeyword(const char *k, int size)
|
||||
{
|
||||
switch (m_mode) {
|
||||
case ExpectingSizes:
|
||||
m_lastSizeType = QString::fromLatin1(k, size);
|
||||
return true;
|
||||
case ExpectingExpressionCache:
|
||||
m_lastExpression = QString::fromLatin1(k, size);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!qstrncmp(k, "dumpers", size)) {
|
||||
m_mode = ExpectingDumpers;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "qtversion", size)) {
|
||||
m_mode = ExpectingQtVersion;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "dumperversion", size)) {
|
||||
m_mode = ExpectingDumperVersion;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "namespace", size)) {
|
||||
m_mode = ExpectingNameSpace;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "sizes", size)) {
|
||||
m_mode = ExpectingSizes;
|
||||
return true;
|
||||
}
|
||||
if (!qstrncmp(k, "expressions", size)) {
|
||||
m_mode = ExpectingExpressionCache;
|
||||
return true;
|
||||
}
|
||||
qWarning("%s Unexpected keyword %s.\n", Q_FUNC_INFO, QByteArray(k, size).constData());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleListStart()
|
||||
{
|
||||
return m_mode == ExpectingDumpers || m_mode == ExpectingQtVersion;
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleListEnd()
|
||||
{
|
||||
m_mode = None;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleHashEnd()
|
||||
{
|
||||
m_mode = None; // Size hash
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryDumperParser::handleValue(const char *k, int size)
|
||||
{
|
||||
switch (m_mode) {
|
||||
case None:
|
||||
return false;
|
||||
case ExpectingDumpers:
|
||||
m_data.types.push_back(QString::fromLatin1(k, size));
|
||||
break;
|
||||
case ExpectingNameSpace:
|
||||
m_data.qtNameSpace = QString::fromLatin1(k, size);
|
||||
break;
|
||||
case ExpectingDumperVersion:
|
||||
m_data.dumperVersion = QString::fromLatin1(k, size);
|
||||
break;
|
||||
case ExpectingQtVersion: // ["4","1","5"]
|
||||
if (!m_data.qtVersion.isEmpty())
|
||||
m_data.qtVersion += QLatin1Char('.');
|
||||
m_data.qtVersion += QString::fromLatin1(k, size);
|
||||
break;
|
||||
case ExpectingSizes:
|
||||
m_data.sizes.push_back(SizeEntry(m_lastSizeType, QString::fromLatin1(k, size).toInt()));
|
||||
break;
|
||||
case ExpectingExpressionCache:
|
||||
m_data.expressionCache.insert(m_lastExpression, QString::fromLatin1(k, size));
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline QString qClassName(const QString &qtNamespace, const char *className)
|
||||
{
|
||||
if (qtNamespace.isEmpty())
|
||||
@@ -1194,36 +883,73 @@ void QtDumperHelper::setQClassPrefixes(const QString &qNamespace)
|
||||
m_qSharedPointerPrefix = qClassName(qNamespace, "QSharedPointer");
|
||||
m_qSharedDataPointerPrefix = qClassName(qNamespace, "QSharedDataPointer");
|
||||
m_qWeakPointerPrefix = qClassName(qNamespace, "QWeakPointer");
|
||||
m_qListPrefix = qClassName(qNamespace, "QList");
|
||||
m_qLinkedListPrefix = qClassName(qNamespace, "QLinkedList");
|
||||
m_qVectorPrefix = qClassName(qNamespace, "QVector");
|
||||
}
|
||||
|
||||
static inline double getDumperVersion(const GdbMi &contents)
|
||||
{
|
||||
const GdbMi dumperVersionG = contents.findChild("dumperversion");
|
||||
if (dumperVersionG.type() != GdbMi::Invalid) {
|
||||
bool ok;
|
||||
const double v = QString::fromAscii(dumperVersionG.data()).toDouble(&ok);
|
||||
if (ok)
|
||||
return v;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
bool QtDumperHelper::parseQuery(const GdbMi &contents, Debugger debugger)
|
||||
{
|
||||
clear();
|
||||
if (debug > 1)
|
||||
qDebug() << "parseQuery" << contents.toString(true, 2);
|
||||
|
||||
// Common info, dumper version, etc
|
||||
m_qtNamespace = QLatin1String(contents.findChild("namespace").data());
|
||||
int qtv = 0;
|
||||
const GdbMi qtversion = contents.findChild("qtversion");
|
||||
if (qtversion.children().size() == 3) {
|
||||
qtv = (qtversion.childAt(0).data().toInt() << 16)
|
||||
+ (qtversion.childAt(1).data().toInt() << 8)
|
||||
+ qtversion.childAt(2).data().toInt();
|
||||
}
|
||||
m_qtVersion = qtv;
|
||||
// Get list of helpers
|
||||
QStringList availableSimpleDebuggingHelpers;
|
||||
foreach (const GdbMi &item, contents.findChild("dumpers").children())
|
||||
availableSimpleDebuggingHelpers.append(QLatin1String(item.data()));
|
||||
parseQueryTypes(availableSimpleDebuggingHelpers, debugger);
|
||||
m_dumperVersion = getDumperVersion(contents);
|
||||
// Parse sizes
|
||||
foreach (const GdbMi &sizesList, contents.findChild("sizes").children()) {
|
||||
const int childCount = sizesList.childCount();
|
||||
if (childCount > 1) {
|
||||
const int size = sizesList.childAt(0).data().toInt();
|
||||
for (int c = 1; c < childCount; c++)
|
||||
addSize(QLatin1String(sizesList.childAt(c).data()), size);
|
||||
}
|
||||
}
|
||||
// Parse expressions
|
||||
foreach (const GdbMi &exprList, contents.findChild("expressions").children())
|
||||
if (exprList.childCount() == 2)
|
||||
m_expressionCache.insert(QLatin1String(exprList.childAt(0).data()),
|
||||
QLatin1String(exprList.childAt(1).data()));
|
||||
return true;
|
||||
}
|
||||
|
||||
// parse a query
|
||||
bool QtDumperHelper::parseQuery(const char *data, Debugger debugger)
|
||||
{
|
||||
QueryDumperParser parser(data);
|
||||
if (!parser.run())
|
||||
QByteArray fullData = data;
|
||||
fullData.insert(0, '{');
|
||||
fullData.append(data);
|
||||
fullData.append('}');
|
||||
GdbMi root(fullData);
|
||||
if (!root.isValid())
|
||||
return false;
|
||||
clear();
|
||||
m_qtNamespace = parser.data().qtNameSpace;
|
||||
setQtVersion(parser.data().qtVersion);
|
||||
setQClassPrefixes(m_qtNamespace);
|
||||
parseQueryTypes(parser.data().types, debugger);
|
||||
foreach (const QueryDumperParser::SizeEntry &se, parser.data().sizes)
|
||||
addSize(se.first, se.second);
|
||||
m_expressionCache = parser.data().expressionCache;
|
||||
// Version
|
||||
if (!parser.data().dumperVersion.isEmpty()) {
|
||||
double dumperVersion;
|
||||
bool ok;
|
||||
dumperVersion = parser.data().dumperVersion.toDouble(&ok);
|
||||
if (ok)
|
||||
m_dumperVersion = dumperVersion;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void QtDumperHelper::addExpression(const QString &expression, const QString &value)
|
||||
{
|
||||
m_expressionCache.insert(expression, value);
|
||||
return parseQuery(root, debugger);
|
||||
}
|
||||
|
||||
void QtDumperHelper::addSize(const QString &name, int size)
|
||||
@@ -1316,6 +1042,14 @@ QtDumperHelper::SpecialSizeType QtDumperHelper::specialSizeType(const QString &t
|
||||
return QSharedDataPointerSize;
|
||||
if (typeName.startsWith(m_qWeakPointerPrefix))
|
||||
return QWeakPointerSize;
|
||||
if (typeName.startsWith(m_qListPrefix))
|
||||
return QListSize;
|
||||
if (typeName.startsWith(m_qLinkedListPrefix))
|
||||
return QLinkedListSize;
|
||||
if (typeName.startsWith(m_qVectorPrefix))
|
||||
return QVectorSize;
|
||||
if (typeName.startsWith(m_qQueuePrefix))
|
||||
return QQueueSize;
|
||||
return SpecialSizeCount;
|
||||
}
|
||||
|
||||
@@ -1504,233 +1238,173 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
||||
qDebug() << '\n' << Q_FUNC_INFO << '\n' << data.toString() << "\n-->" << outertype << td.type << extraArgs;
|
||||
}
|
||||
|
||||
/* Parse value:
|
||||
* "iname="local.sl",addr="0x0012BA84",value="<3 items>",valuedisabled="true",
|
||||
* numchild="3",childtype="QString",childnumchild="0",
|
||||
* children=[{name="0",value="<binhex>",valueencoded="2"},
|
||||
* {name="1",value="dAB3AG8A",valueencoded="2"},
|
||||
* {name="2",value="dABoAHIAZQBlAA==",valueencoded="2"}]" */
|
||||
// GdbMi parsing helpers for parsing dumper value results
|
||||
|
||||
class ValueDumperParser : public DumperParser
|
||||
static bool gdbMiGetIntValue(int *target,
|
||||
const GdbMi &node,
|
||||
const char *child)
|
||||
{
|
||||
public:
|
||||
explicit ValueDumperParser(const char *s);
|
||||
*target = -1;
|
||||
const GdbMi childNode = node.findChild(child);
|
||||
if (!childNode.isValid())
|
||||
return false;
|
||||
bool ok;
|
||||
*target = childNode.data().toInt(&ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
inline QtDumperResult result() const { return m_result; }
|
||||
// Find a string child node and assign value if it exists.
|
||||
// Optionally decode.
|
||||
static bool gdbMiGetStringValue(QString *target,
|
||||
const GdbMi &node,
|
||||
const char *child,
|
||||
const char *encodingChild = 0)
|
||||
{
|
||||
target->clear();
|
||||
const GdbMi childNode = node.findChild(child);
|
||||
if (!childNode.isValid())
|
||||
return false;
|
||||
// Encoded data
|
||||
if (encodingChild) {
|
||||
int encoding;
|
||||
if (!gdbMiGetIntValue(&encoding, node, encodingChild))
|
||||
encoding = 0;
|
||||
*target = decodeData(childNode.data(), encoding);
|
||||
return true;
|
||||
}
|
||||
// Plain data
|
||||
*target = QLatin1String(childNode.data());
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool handleKeyword(const char *k, int size);
|
||||
virtual bool handleHashStart();
|
||||
virtual bool handleValue(const char *k, int size);
|
||||
static bool gdbMiGetBoolValue(bool *target,
|
||||
const GdbMi &node,
|
||||
const char *child)
|
||||
{
|
||||
*target = false;
|
||||
const GdbMi childNode = node.findChild(child);
|
||||
if (!childNode.isValid())
|
||||
return false;
|
||||
*target = childNode.data() == "true";
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
enum Mode { None, ExpectingIName, ExpectingAddress, ExpectingValue,
|
||||
ExpectingType, ExpectingDisplayedType, ExpectingInternal,
|
||||
ExpectingValueEnabled, ExpectingValueEncoded,
|
||||
ExpectingCommonChildType, ExpectingChildCount,
|
||||
ExpectingChildChildOverrideCount,
|
||||
ExpectingExtra,
|
||||
IgnoreNext,
|
||||
ChildModeStart,
|
||||
ExpectingChildren,ExpectingChildName, ExpectingChildAddress,
|
||||
ExpectingChildExpression, ExpectingChildType,
|
||||
ExpectingChildDisplayedType,
|
||||
ExpectingChildKey, ExpectingChildKeyEncoded,
|
||||
ExpectingChildValue, ExpectingChildValueEncoded,
|
||||
ExpectingChildValueEnabled, ExpectingChildChildCount,
|
||||
IgnoreNextChildMode
|
||||
};
|
||||
/* Context to store parameters that influence the next level children.
|
||||
* (next level only, it is not further inherited). For example, the root item
|
||||
* can provide a "childtype" node that specifies the type of the children. */
|
||||
|
||||
static inline Mode nextMode(Mode in, const char *keyword, int size);
|
||||
struct GdbMiRecursionContext {
|
||||
GdbMiRecursionContext(int recursionLevelIn = 0) :
|
||||
recursionLevel(recursionLevelIn), childNumChild(-1), childIndex(0) {}
|
||||
|
||||
Mode m_mode;
|
||||
QtDumperResult m_result;
|
||||
int recursionLevel;
|
||||
int childNumChild;
|
||||
int childIndex;
|
||||
QString childType;
|
||||
QString parentIName;
|
||||
};
|
||||
|
||||
ValueDumperParser::ValueDumperParser(const char *s) :
|
||||
DumperParser(s),
|
||||
m_mode(None)
|
||||
static void gbdMiToWatchData(const GdbMi &root,
|
||||
const GdbMiRecursionContext &ctx,
|
||||
QList<WatchData> *wl)
|
||||
{
|
||||
}
|
||||
|
||||
// Check key words
|
||||
ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword, int size)
|
||||
{
|
||||
// Careful with same prefix
|
||||
switch (size) {
|
||||
case 3:
|
||||
if (!qstrncmp(keyword, "exp", size))
|
||||
return ExpectingChildExpression;
|
||||
if (!qstrncmp(keyword, "key", size))
|
||||
return ExpectingChildKey;
|
||||
break;
|
||||
case 4:
|
||||
if (!qstrncmp(keyword, "addr", size))
|
||||
return in > ChildModeStart ? ExpectingChildAddress : ExpectingAddress;
|
||||
if (!qstrncmp(keyword, "type", size))
|
||||
return in > ChildModeStart ? ExpectingChildType : ExpectingType;
|
||||
if (!qstrncmp(keyword, "name", size))
|
||||
return ExpectingChildName;
|
||||
break;
|
||||
case 5:
|
||||
if (!qstrncmp(keyword, "iname", size))
|
||||
return ExpectingIName;
|
||||
if (!qstrncmp(keyword, "value", size))
|
||||
return in > ChildModeStart ? ExpectingChildValue : ExpectingValue;
|
||||
if (!qstrncmp(keyword, "extra", size))
|
||||
return ExpectingExtra;
|
||||
break;
|
||||
case 8:
|
||||
if (!qstrncmp(keyword, "children", size))
|
||||
return ExpectingChildren;
|
||||
if (!qstrncmp(keyword, "numchild", size))
|
||||
return in > ChildModeStart ? ExpectingChildChildCount : ExpectingChildCount;
|
||||
if (!qstrncmp(keyword, "internal", size))
|
||||
return ExpectingInternal;
|
||||
break;
|
||||
case 9:
|
||||
if (!qstrncmp(keyword, "childtype", size))
|
||||
return ExpectingCommonChildType;
|
||||
break;
|
||||
case 10:
|
||||
if (!qstrncmp(keyword, "keyencoded", size))
|
||||
return ExpectingChildKeyEncoded;
|
||||
break;
|
||||
case 12:
|
||||
if (!qstrncmp(keyword, "valueencoded", size))
|
||||
return in > ChildModeStart ? ExpectingChildValueEncoded : ExpectingValueEncoded;
|
||||
break;
|
||||
case 13:
|
||||
if (!qstrncmp(keyword, "valueenabled", size))
|
||||
return in > ChildModeStart ? ExpectingChildValueEnabled : ExpectingValueEnabled;
|
||||
if (!qstrncmp(keyword, "displayedtype", size))
|
||||
return in > ChildModeStart ? ExpectingChildDisplayedType : ExpectingDisplayedType;
|
||||
if (!qstrncmp(keyword, "childnumchild", size))
|
||||
return ExpectingChildChildOverrideCount;
|
||||
break;
|
||||
}
|
||||
return in > ChildModeStart ? IgnoreNextChildMode : IgnoreNext;
|
||||
}
|
||||
|
||||
bool ValueDumperParser::handleKeyword(const char *k, int size)
|
||||
{
|
||||
const Mode newMode = nextMode(m_mode, k, size);
|
||||
if (debug && newMode == IgnoreNext)
|
||||
qWarning("%s Unexpected keyword %s.\n", Q_FUNC_INFO, QByteArray(k, size).constData());
|
||||
m_mode = newMode;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValueDumperParser::handleHashStart()
|
||||
{
|
||||
m_result.children.push_back(QtDumperResult::Child());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValueDumperParser::handleValue(const char *k, int size)
|
||||
{
|
||||
const QByteArray valueBA(k, size);
|
||||
switch (m_mode) {
|
||||
case None:
|
||||
case ChildModeStart:
|
||||
return false;
|
||||
case ExpectingIName:
|
||||
m_result.iname = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingAddress: {
|
||||
const QString address = QString::fromLatin1(valueBA);
|
||||
if (address.startsWith(QLatin1String("0x"))) {
|
||||
m_result.address = address;
|
||||
} else {
|
||||
m_result.addressInfo = address;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ExpectingValue:
|
||||
m_result.valueEncountered = true;
|
||||
m_result.value = valueBA;
|
||||
break;
|
||||
case ExpectingValueEnabled:
|
||||
m_result.valueEnabled = valueBA == "true";
|
||||
break;
|
||||
case ExpectingValueEncoded:
|
||||
m_result.valueEncoded = QString::fromLatin1(valueBA).toInt();
|
||||
break;
|
||||
case ExpectingType:
|
||||
m_result.type = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingDisplayedType:
|
||||
m_result.displayedType = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingExtra:
|
||||
m_result.extra = valueBA;
|
||||
break;
|
||||
case ExpectingInternal:
|
||||
m_result.internal = valueBA == "true";
|
||||
break;
|
||||
case ExpectingCommonChildType:
|
||||
m_result.childType = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingChildCount:
|
||||
m_result.childCount = QString::fromLatin1(valueBA).toInt();
|
||||
break;
|
||||
case ExpectingChildChildOverrideCount:
|
||||
m_result.childChildCount = QString::fromLatin1(valueBA).toInt();
|
||||
break;
|
||||
case ExpectingChildren:
|
||||
case IgnoreNextChildMode:
|
||||
case IgnoreNext:
|
||||
break;
|
||||
case ExpectingChildName:
|
||||
m_result.children.back().name = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingChildAddress:
|
||||
m_result.children.back().address = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingChildKeyEncoded:
|
||||
m_result.children.back().keyEncoded = QString::fromLatin1(valueBA).toInt();
|
||||
break;
|
||||
case ExpectingChildKey:
|
||||
m_result.children.back().key = valueBA;
|
||||
break;
|
||||
case ExpectingChildValue:
|
||||
m_result.children.back().valueEncountered = true;
|
||||
m_result.children.back().value = valueBA;
|
||||
break;
|
||||
case ExpectingChildExpression:
|
||||
m_result.children.back().exp = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingChildValueEncoded:
|
||||
m_result.children.back().valueEncoded = QString::fromLatin1(valueBA).toInt();
|
||||
break;
|
||||
case ExpectingChildValueEnabled:
|
||||
m_result.children.back().valueEnabled = valueBA == "true";
|
||||
break;
|
||||
case ExpectingChildType:
|
||||
m_result.children.back().type = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingChildDisplayedType:
|
||||
m_result.children.back().displayedType = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingChildChildCount:
|
||||
m_result.children.back().childCount = QString::fromLatin1(valueBA).toInt();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r)
|
||||
{
|
||||
ValueDumperParser parser(data);
|
||||
|
||||
if (!parser.run())
|
||||
return false;
|
||||
*r = parser.result();
|
||||
// Sanity
|
||||
if (!r->children.empty() && r->childCount != r->children.size())
|
||||
r->childCount = r->children.size();
|
||||
if (debug > 1)
|
||||
qDebug() << '\n' << data << '\n' << *r;
|
||||
qDebug() << Q_FUNC_INFO << '\n' << root.toString(false, 0);
|
||||
WatchData w;
|
||||
QString v;
|
||||
// Check for name/iname and use as expression default
|
||||
if (ctx.recursionLevel == 0) {
|
||||
// parents have only iname, from which name is derived
|
||||
if (!gdbMiGetStringValue(&w.iname, root, "iname"))
|
||||
qWarning("Internal error: iname missing");
|
||||
w.name = w.iname;
|
||||
const int lastDotPos = w.name.lastIndexOf(QLatin1Char('.'));
|
||||
if (lastDotPos != -1)
|
||||
w.name.remove(0, lastDotPos + 1);
|
||||
w.exp = w.name;
|
||||
} else {
|
||||
// Children can have a 'name' attribute. If missing, assume array index
|
||||
// For display purposes, it can be overridden by "key"
|
||||
if (!gdbMiGetStringValue(&w.name, root, "name")) {
|
||||
w.name = QString::number(ctx.childIndex);
|
||||
}
|
||||
// Set iname
|
||||
w.iname = ctx.parentIName;
|
||||
w.iname += QLatin1Char('.');
|
||||
w.iname += w.name;
|
||||
// Key?
|
||||
QString key;
|
||||
if (gdbMiGetStringValue(&key, root, "key", "keyencoded")) {
|
||||
w.name = key.size() > 13 ? key.mid(0, 13) + QLatin1String("...") : key;
|
||||
}
|
||||
}
|
||||
if (w.name.isEmpty()) {
|
||||
const QString msg = QString::fromLatin1("Internal error: Unable to determine name at level %1/%2 for %3").arg(ctx.recursionLevel).arg(w.iname, QLatin1String(root.toString(true, 2)));
|
||||
qWarning("%s\n", qPrintable(msg));
|
||||
}
|
||||
gdbMiGetStringValue(&w.displayedType, root, "displayedtype");
|
||||
if (gdbMiGetStringValue(&v, root, "editvalue"))
|
||||
w.editvalue = v.toLatin1();
|
||||
if (gdbMiGetStringValue(&v, root, "exp"))
|
||||
w.exp = v;
|
||||
gdbMiGetStringValue(&w.addr, root, "addr");
|
||||
gdbMiGetStringValue(&w.saddr, root, "saddr");
|
||||
gdbMiGetBoolValue(&w.valueEnabled, root, "valueenabled");
|
||||
gdbMiGetBoolValue(&w.valueEditable, root, "valueeditable");
|
||||
if (gdbMiGetStringValue(&v, root, "valuetooltip", "valuetooltipencoded"))
|
||||
w.setValue(v);
|
||||
if (gdbMiGetStringValue(&v, root, "value", "valueencoded"))
|
||||
w.setValue(v);
|
||||
// Type from context or self
|
||||
if (ctx.childType.isEmpty()) {
|
||||
if (gdbMiGetStringValue(&v, root, "type"))
|
||||
w.setType(v);
|
||||
} else {
|
||||
w.setType(ctx.childType);
|
||||
}
|
||||
// child count?
|
||||
int numChild = -1;
|
||||
if (ctx.childNumChild >= 0) {
|
||||
numChild = ctx.childNumChild;
|
||||
} else {
|
||||
gdbMiGetIntValue(&numChild, root, "numchild");
|
||||
}
|
||||
if (numChild >= 0)
|
||||
w.setHasChildren(numChild > 0);
|
||||
wl->push_back(w);
|
||||
// Parse children with a new context
|
||||
if (numChild == 0)
|
||||
return;
|
||||
const GdbMi childrenNode = root.findChild("children");
|
||||
if (!childrenNode.isValid())
|
||||
return;
|
||||
const QList<GdbMi> children =childrenNode.children();
|
||||
if (children.empty())
|
||||
return;
|
||||
wl->back().setChildrenUnneeded();
|
||||
GdbMiRecursionContext nextLevelContext(ctx.recursionLevel + 1);
|
||||
nextLevelContext.parentIName = w.iname;
|
||||
gdbMiGetStringValue(&nextLevelContext.childType, root, "childtype");
|
||||
if (!gdbMiGetIntValue(&nextLevelContext.childNumChild, root, "childnumchild"))
|
||||
nextLevelContext.childNumChild = -1;
|
||||
foreach(const GdbMi &child, children) {
|
||||
gbdMiToWatchData(child, nextLevelContext, wl);
|
||||
nextLevelContext.childIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
bool QtDumperHelper::parseValue(const char *data,
|
||||
QList<WatchData> *l)
|
||||
{
|
||||
l->clear();
|
||||
QByteArray fullData = data;
|
||||
fullData.insert(0, '{');
|
||||
fullData.append(data);
|
||||
fullData.append('}');
|
||||
GdbMi root(fullData);
|
||||
if (!root.isValid())
|
||||
return false;
|
||||
gbdMiToWatchData(root, GdbMiRecursionContext(), l);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class WatchData;
|
||||
class GdbMi;
|
||||
|
||||
QString dotEscape(QString str);
|
||||
QString currentTime();
|
||||
@@ -89,49 +90,6 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
|
||||
// Decode string data as returned by the dumper helpers.
|
||||
QString decodeData(const QByteArray &baIn, int encoding);
|
||||
|
||||
// Result of a dumper call.
|
||||
struct QtDumperResult
|
||||
{
|
||||
struct Child {
|
||||
Child();
|
||||
|
||||
int keyEncoded;
|
||||
int valueEncoded;
|
||||
int childCount;
|
||||
bool valueEnabled;
|
||||
QString name;
|
||||
QString address;
|
||||
QString exp;
|
||||
QString type;
|
||||
QString displayedType;
|
||||
QByteArray key;
|
||||
bool valueEncountered;
|
||||
QByteArray value;
|
||||
};
|
||||
|
||||
QtDumperResult();
|
||||
void clear();
|
||||
QList<WatchData> toWatchData(int source = 0) const;
|
||||
|
||||
QString iname;
|
||||
QString address;
|
||||
QString addressInfo; // "<synthetic>" or such, in the 2nd adress field.
|
||||
QString type;
|
||||
QString extra;
|
||||
QString displayedType;
|
||||
bool valueEncountered;
|
||||
QByteArray value;
|
||||
int valueEncoded;
|
||||
bool valueEnabled;
|
||||
int childCount;
|
||||
bool internal;
|
||||
QString childType;
|
||||
int childChildCount;
|
||||
QList <Child> children;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug in, const QtDumperResult &d);
|
||||
|
||||
/* Attempt to put common code of the dumper handling into a helper
|
||||
* class.
|
||||
* "Custom dumper" is a library compiled against the current
|
||||
@@ -181,7 +139,6 @@ public:
|
||||
void clear();
|
||||
|
||||
double dumperVersion() const { return m_dumperVersion; }
|
||||
void setDumperVersion(double v) { m_dumperVersion = v; }
|
||||
|
||||
int typeCount() const;
|
||||
// Look up a simple, non-template type
|
||||
@@ -192,17 +149,14 @@ public:
|
||||
|
||||
int qtVersion() const;
|
||||
QString qtVersionString() const;
|
||||
void setQtVersion(int v);
|
||||
void setQtVersion(const QString &v);
|
||||
|
||||
QString qtNamespace() const;
|
||||
void setQtNamespace(const QString &qtNamespace);
|
||||
|
||||
// Complete parse of "query" (protocol 1) response from debuggee buffer.
|
||||
// 'data' excludes the leading indicator character.
|
||||
bool parseQuery(const char *data, Debugger debugger);
|
||||
// Set up from pre-parsed type list
|
||||
void parseQueryTypes(const QStringList &l, Debugger debugger);
|
||||
bool parseQuery(const GdbMi &data, Debugger debugger);
|
||||
// Sizes can be added as the debugger determines them
|
||||
void addSize(const QString &name, int size);
|
||||
|
||||
// Determine the parameters required for an "evaluate" (protocol 2) call
|
||||
void evaluationParameters(const WatchData &data,
|
||||
@@ -213,7 +167,7 @@ public:
|
||||
|
||||
// Parse the value response (protocol 2) from debuggee buffer.
|
||||
// 'data' excludes the leading indicator character.
|
||||
static bool parseValue(const char *data, QtDumperResult *r);
|
||||
static bool parseValue(const char *data, QList<WatchData> *l);
|
||||
|
||||
// What kind of debugger expressions are required to dump that type.
|
||||
// A debugger with restricted expression syntax can handle
|
||||
@@ -228,9 +182,6 @@ public:
|
||||
|
||||
QString toString(bool debug = false) const;
|
||||
|
||||
// Helpers for debuggers that use a different dumper parser.
|
||||
void addSize(const QString &name, int size);
|
||||
void addExpression(const QString &expression, const QString &value);
|
||||
|
||||
static QString msgDumperOutdated(double requiredVersion, double currentVersion);
|
||||
|
||||
@@ -241,6 +192,7 @@ private:
|
||||
// Look up a simple (namespace) type
|
||||
static Type specialType(QString s);
|
||||
QString evaluationSizeofTypeExpression(const QString &typeName, Debugger d) const;
|
||||
void parseQueryTypes(const QStringList &l, Debugger debugger);
|
||||
|
||||
NameTypeMap m_nameTypeMap;
|
||||
SizeCache m_sizeCache;
|
||||
@@ -250,7 +202,9 @@ private:
|
||||
// They are not complete (std::allocator<X>).
|
||||
enum SpecialSizeType { IntSize, PointerSize, StdAllocatorSize,
|
||||
QSharedPointerSize, QSharedDataPointerSize,
|
||||
QWeakPointerSize, QPointerSize, SpecialSizeCount };
|
||||
QWeakPointerSize, QPointerSize,
|
||||
QListSize, QLinkedListSize, QVectorSize, QQueueSize,
|
||||
SpecialSizeCount };
|
||||
|
||||
// Resolve name to enumeration or SpecialSizeCount (invalid)
|
||||
SpecialSizeType specialSizeType(const QString &t) const;
|
||||
@@ -268,6 +222,10 @@ private:
|
||||
QString m_qSharedPointerPrefix;
|
||||
QString m_qSharedDataPointerPrefix;
|
||||
QString m_qWeakPointerPrefix;
|
||||
QString m_qListPrefix;
|
||||
QString m_qLinkedListPrefix;
|
||||
QString m_qVectorPrefix;
|
||||
QString m_qQueuePrefix;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d);
|
||||
|
||||
@@ -106,7 +106,7 @@ QString DebuggingHelperLibrary::debuggingHelperLibraryByInstallData(const QStrin
|
||||
|
||||
foreach(const QString &directory, debuggingHelperLibraryDirectories(qtInstallData)) {
|
||||
const QFileInfo fi(helperFilePath(directory));
|
||||
if (fi.exists() && fi.lastModified() > lastModified)
|
||||
if (fi.exists() && fi.lastModified() >= lastModified)
|
||||
return fi.filePath();
|
||||
}
|
||||
return QString();
|
||||
|
||||
@@ -341,6 +341,7 @@ OutputWindow::OutputWindow(QWidget *parent)
|
||||
: QPlainTextEdit(parent)
|
||||
{
|
||||
m_enforceNewline = false;
|
||||
m_scrollToBottom = false;
|
||||
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
//setCenterOnScroll(false);
|
||||
@@ -392,8 +393,18 @@ OutputWindow::~OutputWindow()
|
||||
Core::ICore::instance()->removeContextObject(m_outputWindowContext);
|
||||
}
|
||||
|
||||
void OutputWindow::showEvent(QShowEvent *e)
|
||||
{
|
||||
QPlainTextEdit::showEvent(e);
|
||||
if (m_scrollToBottom) {
|
||||
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
|
||||
}
|
||||
m_scrollToBottom = false;
|
||||
}
|
||||
|
||||
void OutputWindow::appendOutput(const QString &out)
|
||||
{
|
||||
m_scrollToBottom = true;
|
||||
QString s = out;
|
||||
m_enforceNewline = true; // make appendOutputInline put in a newline next time
|
||||
if (s.endsWith(QLatin1Char('\n'))) {
|
||||
@@ -407,6 +418,7 @@ void OutputWindow::appendOutput(const QString &out)
|
||||
|
||||
void OutputWindow::appendOutputInline(const QString &out)
|
||||
{
|
||||
m_scrollToBottom = true;
|
||||
setMaximumBlockCount(MaxBlockCount);
|
||||
|
||||
int newline = -1;
|
||||
@@ -439,6 +451,7 @@ void OutputWindow::appendOutputInline(const QString &out)
|
||||
|
||||
void OutputWindow::insertLine()
|
||||
{
|
||||
m_scrollToBottom = true;
|
||||
setMaximumBlockCount(MaxBlockCount);
|
||||
appendPlainText(QString());
|
||||
enableUndoRedo();
|
||||
|
||||
@@ -126,10 +126,13 @@ public:
|
||||
void appendOutputInline(const QString &out);
|
||||
void insertLine();
|
||||
|
||||
void showEvent(QShowEvent *);
|
||||
|
||||
private:
|
||||
Core::BaseContext *m_outputWindowContext;
|
||||
void enableUndoRedo();
|
||||
bool m_enforceNewline;
|
||||
bool m_scrollToBottom;
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -367,8 +367,7 @@ QByteArray MSVCToolChain::predefinedMacros()
|
||||
QByteArray key = split.at(0).mid(1);
|
||||
QByteArray value = split.at(1);
|
||||
if (!value.isEmpty()) {
|
||||
value = value.mid(1);
|
||||
value.chop(1);
|
||||
value.chop(1); //remove '\n'
|
||||
}
|
||||
QByteArray newDefine = "#define " + key + " " + value + '\n';
|
||||
m_predefinedMacros.append(newDefine);
|
||||
|
||||
@@ -22,5 +22,5 @@ SUPPORT_QT_S60 = $$(QTCREATOR_WITH_S60)
|
||||
$$PWD/rvcttoolchain.h
|
||||
FORMS += $$PWD/s60devicespreferencepane.ui
|
||||
OTHER_FILES += $$PWD/qt-s60-todo.txt
|
||||
include(../../shared/trk/trk.pri)||error("could not include trk.pri")
|
||||
include(../../../shared/trk/trk.pri)||error("could not include trk.pri")
|
||||
}
|
||||
|
||||
@@ -2118,7 +2118,7 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ;
|
||||
token_buffer[1].dval = yylval = lexer->dval();
|
||||
token_buffer[1].loc = yylloc = location(lexer);
|
||||
|
||||
if (t_action(errorState, yytoken)) {
|
||||
if (token_buffer[0].token != -1 && t_action(errorState, yytoken)) {
|
||||
QString msg = QString::fromUtf8("Removed token");
|
||||
if (const char *tokenSpell = spell[token_buffer[0].token]) {
|
||||
msg += QLatin1String(": `");
|
||||
|
||||
@@ -397,13 +397,14 @@ void Launcher::handleWaitForFinished(const TrkResult &result)
|
||||
|
||||
void Launcher::handleSupportMask(const TrkResult &result)
|
||||
{
|
||||
const char *data = result.data.data();
|
||||
const char *data = result.data.data() + 1;
|
||||
|
||||
QByteArray str;
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
//str.append(" [" + formatByte(data[i]) + "]: ");
|
||||
for (int j = 0; j < 8; ++j)
|
||||
if (data[i] & (1 << j))
|
||||
str.append(QByteArray::number(i * 8 + j, 16));
|
||||
str.append(QByteArray::number(i * 8 + j, 16) + " ");
|
||||
}
|
||||
logMessage("SUPPORTED: " + str);
|
||||
}
|
||||
|
||||
@@ -12,3 +12,4 @@ SOURCES += tst_aggregate.cpp \
|
||||
HEADERS += $$AGGREGATION_PATH/aggregate.h \
|
||||
$$AGGREGATION_PATH/aggregation_global.h
|
||||
|
||||
TARGET=tst_$$TARGET
|
||||
|
||||
@@ -3,7 +3,6 @@ TEMPLATE = subdirs
|
||||
SUBDIRS += \
|
||||
cplusplus \
|
||||
debugger \
|
||||
extensionsystem \
|
||||
fakevim \
|
||||
# profilereader \
|
||||
aggregation
|
||||
|
||||
@@ -3,3 +3,5 @@ CONFIG += qt warn_on console depend_includepath
|
||||
QT = core testlib
|
||||
include(../shared/shared.pri)
|
||||
SOURCES += tst_ast.cpp
|
||||
TARGET=tst_$$TARGET
|
||||
|
||||
|
||||
@@ -5,3 +5,4 @@ QT = core testlib
|
||||
include(../../../../src/libs/cplusplus/cplusplus-lib.pri)
|
||||
|
||||
SOURCES += tst_lookup.cpp
|
||||
TARGET=tst_$$TARGET
|
||||
|
||||
@@ -4,3 +4,4 @@ QT = core testlib
|
||||
include(../shared/shared.pri)
|
||||
|
||||
SOURCES += tst_semantic.cpp
|
||||
TARGET=tst_$$TARGET
|
||||
|
||||
@@ -14,3 +14,5 @@ DEFINES += MACROSDEBUG
|
||||
|
||||
INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR $$MACROSDIR
|
||||
|
||||
TARGET = tst_$$TARGET
|
||||
|
||||
|
||||
@@ -12,3 +12,5 @@ DEFINES += MACROSDEBUG
|
||||
|
||||
INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR $$MACROSDIR
|
||||
|
||||
TARGET = tst_$$TARGET
|
||||
|
||||
|
||||
@@ -1501,7 +1501,7 @@ template <typename K, typename V>
|
||||
append(" isSimpleValue: ").append(N(simpleVal)).
|
||||
append(" keyOffset: ").append(N(transKeyOffset)).append(" valueOffset: ").
|
||||
append(N(transValOffset)).append(" mapnodesize: ").
|
||||
append(N(nodeSize)).append("',children=[");
|
||||
append(N(qulonglong(nodeSize))).append("',children=["); // 64bit Linux hack
|
||||
typedef typename QMap<K, V>::iterator mapIter;
|
||||
for (mapIter it = map.begin(); it != map.end(); ++it) {
|
||||
if (it != map.begin())
|
||||
@@ -2368,7 +2368,9 @@ void tst_Debugger::initTestCase()
|
||||
d.weakref = d.strongref = 0; // That's what the destructor expects.
|
||||
QVERIFY(sizeof(int) == sizeof(d.weakref));
|
||||
QVERIFY(sizeof(int) == sizeof(d.strongref));
|
||||
QVERIFY(sizeof(QObjectPrivate) == sizeof(ObjectPrivate));
|
||||
const size_t qObjectPrivateSize = sizeof(QObjectPrivate);
|
||||
const size_t objectPrivateSize = sizeof(ObjectPrivate);
|
||||
QVERIFY2(qObjectPrivateSize == objectPrivateSize, QString::fromLatin1("QObjectPrivate=%1 ObjectPrivate=%2").arg(qObjectPrivateSize).arg(objectPrivateSize).toLatin1().constData());
|
||||
VERIFY_OFFSETOF(threadData);
|
||||
VERIFY_OFFSETOF(extraData);
|
||||
VERIFY_OFFSETOF(objectName);
|
||||
@@ -2379,11 +2381,12 @@ void tst_Debugger::initTestCase()
|
||||
VERIFY_OFFSETOF(currentChildBeingDeleted);
|
||||
VERIFY_OFFSETOF(connectedSignals);
|
||||
VERIFY_OFFSETOF(deleteWatch);
|
||||
#ifdef QT3_SUPPORT
|
||||
#if QT_VERSION < 0x040600
|
||||
VERIFY_OFFSETOF(pendingChildInsertedEvents);
|
||||
#else
|
||||
VERIFY_OFFSETOF(declarativeData);
|
||||
VERIFY_OFFSETOF(objectGuards);
|
||||
#endif
|
||||
#endif
|
||||
#if QT_VERSION >= 0x040600
|
||||
VERIFY_OFFSETOF(sharedRefcount);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -21,3 +21,4 @@ HEADERS += \
|
||||
|
||||
INCLUDEPATH += $$FAKEVIMDIR $$UTILSDIR
|
||||
|
||||
TARGET=tst_$$TARGET
|
||||
|
||||
@@ -14,3 +14,4 @@ HEADERS += \
|
||||
profilereader.h \
|
||||
profilecache.h \
|
||||
qtversionmanager.h
|
||||
TARGET=tst_$$TARGET
|
||||
|
||||
Reference in New Issue
Block a user