summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/debugger/debugger.pro6
-rw-r--r--src/plugins/debugger/debugger.qbs1
-rw-r--r--src/plugins/debugger/debuggerprotocol.cpp256
-rw-r--r--src/plugins/debugger/debuggerprotocol.h5
-rw-r--r--src/plugins/debugger/simplifytype.cpp301
-rw-r--r--src/plugins/debugger/simplifytype.h47
-rw-r--r--src/plugins/debugger/watchhandler.cpp3
-rw-r--r--tests/auto/debugger/dumpers.pro2
-rw-r--r--tests/auto/debugger/simplifytypes.pro2
-rw-r--r--tests/auto/debugger/tst_dumpers.cpp3
-rw-r--r--tests/auto/debugger/tst_simplifytypes.cpp4
11 files changed, 362 insertions, 268 deletions
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index c9f794d55d..03b260c6bc 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -72,7 +72,8 @@ HEADERS += \
debuggersourcepathmappingwidget.h \
memoryview.h \
localsandexpressionswindow.h \
- imageviewer.h
+ imageviewer.h \
+ simplifytype.h
SOURCES += \
basewindow.cpp \
@@ -127,7 +128,8 @@ SOURCES += \
debuggersourcepathmappingwidget.cpp \
memoryview.cpp \
localsandexpressionswindow.cpp \
- imageviewer.cpp
+ imageviewer.cpp \
+ simplifytype.cpp
FORMS += \
localsandexpressionsoptionspage.ui
diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs
index 16927cb79b..c120336821 100644
--- a/src/plugins/debugger/debugger.qbs
+++ b/src/plugins/debugger/debugger.qbs
@@ -88,6 +88,7 @@ QtcPlugin {
"watchhandler.cpp", "watchhandler.h",
"watchutils.cpp", "watchutils.h",
"watchwindow.cpp", "watchwindow.h",
+ "simplifytype.cpp", "simplifytype.h",
]
}
diff --git a/src/plugins/debugger/debuggerprotocol.cpp b/src/plugins/debugger/debuggerprotocol.cpp
index e225082b68..83fa67abe6 100644
--- a/src/plugins/debugger/debuggerprotocol.cpp
+++ b/src/plugins/debugger/debuggerprotocol.cpp
@@ -729,261 +729,5 @@ QString decodeData(const QByteArray &ba, int encoding)
return QCoreApplication::translate("Debugger", "<Encoding error>");
}
-// Simplify complicated STL template types,
-// such as 'std::basic_string<char,std::char_traits<char>,std::allocator<char> >'
-// -> 'std::string' and helpers.
-
-static QString chopConst(QString type)
-{
- while (1) {
- if (type.startsWith(QLatin1String("const")))
- type = type.mid(5);
- else if (type.startsWith(QLatin1Char(' ')))
- type = type.mid(1);
- else if (type.endsWith(QLatin1String("const")))
- type.chop(5);
- else if (type.endsWith(QLatin1Char(' ')))
- type.chop(1);
- else
- break;
- }
- return type;
-}
-
-static inline QRegExp stdStringRegExp(const QString &charType)
-{
- QString rc = QLatin1String("basic_string<");
- rc += charType;
- rc += QLatin1String(",[ ]?std::char_traits<");
- rc += charType;
- rc += QLatin1String(">,[ ]?std::allocator<");
- rc += charType;
- rc += QLatin1String("> >");
- const QRegExp re(rc);
- QTC_ASSERT(re.isValid(), /**/);
- return re;
-}
-
-// Simplify string types in a type
-// 'std::set<std::basic_string<char... > >' -> std::set<std::string>'
-static inline void simplifyStdString(const QString &charType, const QString &replacement,
- QString *type)
-{
- QRegExp stringRegexp = stdStringRegExp(charType);
- const int replacementSize = replacement.size();
- for (int pos = 0; pos < type->size(); ) {
- // Check next match
- const int matchPos = stringRegexp.indexIn(*type, pos);
- if (matchPos == -1)
- break;
- const int matchedLength = stringRegexp.matchedLength();
- type->replace(matchPos, matchedLength, replacement);
- pos = matchPos + replacementSize;
- // If we were inside an 'allocator<std::basic_string..char > >'
- // kill the following blank -> 'allocator<std::string>'
- if (pos + 1 < type->size() && type->at(pos) == QLatin1Char(' ')
- && type->at(pos + 1) == QLatin1Char('>'))
- type->remove(pos, 1);
- }
-}
-
-// Fix 'std::allocator<std::string >' -> 'std::allocator<std::string>',
-// which can happen when replacing/simplifying
-static inline QString fixNestedTemplates(QString s)
-{
- const int size = s.size();
- if (size > 3
- && s.at(size - 1) == QLatin1Char('>')
- && s.at(size - 2) == QLatin1Char(' ')
- && s.at(size - 3) != QLatin1Char('>'))
- s.remove(size - 2, 1);
- return s;
-}
-
-QString simplifySTLType(const QString &typeIn)
-{
- QString type = typeIn;
- if (type.startsWith(QLatin1String("class "))) // MSVC prepends class,struct
- type.remove(0, 6);
- if (type.startsWith(QLatin1String("struct ")))
- type.remove(0, 7);
-
- const bool isLibCpp = type.contains(QLatin1String("std::__1"));
- type.replace(QLatin1String("std::__1::"), QLatin1String("std::"));
- type.replace(QLatin1String("std::__debug::"), QLatin1String("std::"));
- type.replace(QLatin1Char('*'), QLatin1Char('@'));
-
- for (int i = 0; i < 10; ++i) {
- // boost::shared_ptr<...>::element_type
- if (type.startsWith(QLatin1String("boost::shared_ptr<"))
- && type.endsWith(QLatin1String(">::element_type")))
- type = type.mid(18, type.size() - 33);
-
- // std::shared_ptr<...>::element_type
- if (type.startsWith(QLatin1String("std::shared_ptr<"))
- && type.endsWith(QLatin1String(">::element_type")))
- type = type.mid(16, type.size() - 31);
-
- // std::ifstream
- QRegExp ifstreamRE(QLatin1String("std::basic_ifstream<char,\\s*std::char_traits<char>\\s*>"));
- ifstreamRE.setMinimal(true);
- QTC_ASSERT(ifstreamRE.isValid(), return typeIn);
- if (ifstreamRE.indexIn(type) != -1)
- type.replace(ifstreamRE.cap(0), QLatin1String("std::ifstream"));
-
-
- // std::__1::hash_node<int, void *>::value_type -> int
- if (isLibCpp) {
- //QRegExp hashNodeRE(QLatin1String("std::__hash_node<([^<>]*),\\s*void\\s*@>::value_type"));
- QRegExp hashNodeRE(QLatin1String("std::__hash_node<([^<>]*),\\s*void\\s*@>::value_type"));
- QTC_ASSERT(hashNodeRE.isValid(), return typeIn);
- if (hashNodeRE.indexIn(type) != -1)
- type.replace(hashNodeRE.cap(0), hashNodeRE.cap(1));
- }
-
- // Anything with a std::allocator
- int start = type.indexOf(QLatin1String("std::allocator<"));
- if (start != -1) {
- // search for matching '>'
- int pos;
- int level = 0;
- for (pos = start + 12; pos < type.size(); ++pos) {
- int c = type.at(pos).unicode();
- if (c == '<') {
- ++level;
- } else if (c == '>') {
- --level;
- if (level == 0)
- break;
- }
- }
- const QString alloc = fixNestedTemplates(type.mid(start, pos + 1 - start).trimmed());
- const QString inner = fixNestedTemplates(alloc.mid(15, alloc.size() - 16).trimmed());
-
- const QString allocEsc = QRegExp::escape(alloc);
- const QString innerEsc = QRegExp::escape(inner);
- if (inner == QLatin1String("char")) { // std::string
- simplifyStdString(QLatin1String("char"), QLatin1String("string"), &type);
- } else if (inner == QLatin1String("wchar_t")) { // std::wstring
- simplifyStdString(QLatin1String("wchar_t"), QLatin1String("wstring"), &type);
- } else if (inner == QLatin1String("unsigned short")) { // std::wstring/MSVC
- simplifyStdString(QLatin1String("unsigned short"), QLatin1String("wstring"), &type);
- }
- // std::vector, std::deque, std::list
- QRegExp re1(QString::fromLatin1("(vector|list|deque)<%1, ?%2\\s*>").arg(innerEsc, allocEsc));
- QTC_ASSERT(re1.isValid(), return typeIn);
- if (re1.indexIn(type) != -1)
- type.replace(re1.cap(0), QString::fromLatin1("%1<%2>").arg(re1.cap(1), inner));
-
- // std::stack
- QRegExp stackRE(QString::fromLatin1("stack<%1, ?std::deque<%2> >").arg(innerEsc, innerEsc));
- stackRE.setMinimal(true);
- QTC_ASSERT(stackRE.isValid(), return typeIn);
- if (stackRE.indexIn(type) != -1)
- type.replace(stackRE.cap(0), QString::fromLatin1("stack<%1>").arg(inner));
-
- // std::hash<char>
- QRegExp hashCharRE(QString::fromLatin1("hash<char, std::char_traits<char>, ?%1\\s*>").arg(allocEsc));
- hashCharRE.setMinimal(true);
- QTC_ASSERT(hashCharRE.isValid(), return typeIn);
- if (hashCharRE.indexIn(type) != -1)
- type.replace(hashCharRE.cap(0), QString::fromLatin1("hash<char>"));
-
- // std::set
- QRegExp setRE(QString::fromLatin1("set<%1, ?std::less<%2>, ?%3\\s*>").arg(innerEsc, innerEsc, allocEsc));
- setRE.setMinimal(true);
- QTC_ASSERT(setRE.isValid(), return typeIn);
- if (setRE.indexIn(type) != -1)
- type.replace(setRE.cap(0), QString::fromLatin1("set<%1>").arg(inner));
-
- // std::unordered_set
- QRegExp unorderedSetRE(QString::fromLatin1("unordered_set<%1, ?std::hash<%2>, ?std::equal_to<%3>, ?%4\\s*>")
- .arg(innerEsc, innerEsc, innerEsc, allocEsc));
- unorderedSetRE.setMinimal(true);
- QTC_ASSERT(unorderedSetRE.isValid(), return typeIn);
- if (unorderedSetRE.indexIn(type) != -1)
- type.replace(unorderedSetRE.cap(0), QString::fromLatin1("unordered_set<%1>").arg(inner));
-
- // std::map
- if (inner.startsWith(QLatin1String("std::pair<"))) {
- // search for outermost ',', split key and value
- int pos;
- int level = 0;
- for (pos = 10; pos < inner.size(); ++pos) {
- int c = inner.at(pos).unicode();
- if (c == '<')
- ++level;
- else if (c == '>')
- --level;
- else if (c == ',' && level == 0)
- break;
- }
- const QString key = chopConst(inner.mid(10, pos - 10));
- const QString keyEsc = QRegExp::escape(key);
- // Get value: MSVC: 'pair<a const ,b>', gcc: 'pair<const a, b>'
- if (inner.at(++pos) == QLatin1Char(' '))
- pos++;
- const QString value = inner.mid(pos, inner.size() - pos - 1).trimmed();
- const QString valueEsc = QRegExp::escape(value);
- QRegExp mapRE1(QString::fromLatin1("map<%1, ?%2, ?std::less<%3 ?>, ?%4\\s*>")
- .arg(keyEsc, valueEsc, keyEsc, allocEsc));
- mapRE1.setMinimal(true);
- QTC_ASSERT(mapRE1.isValid(), return typeIn);
- if (mapRE1.indexIn(type) != -1) {
- type.replace(mapRE1.cap(0), QString::fromLatin1("map<%1, %2>").arg(key, value));
- } else {
- QRegExp mapRE2(QString::fromLatin1("map<const %1, ?%2, ?std::less<const %3>, ?%4\\s*>")
- .arg(keyEsc, valueEsc, keyEsc, allocEsc));
- mapRE2.setMinimal(true);
- if (mapRE2.indexIn(type) != -1)
- type.replace(mapRE2.cap(0), QString::fromLatin1("map<const %1, %2>").arg(key, value));
- }
- }
-
- // std::unordered_map
- if (inner.startsWith(QLatin1String("std::pair<"))) {
- // search for outermost ',', split key and value
- int pos;
- int level = 0;
- for (pos = 10; pos < inner.size(); ++pos) {
- int c = inner.at(pos).unicode();
- if (c == '<')
- ++level;
- else if (c == '>')
- --level;
- else if (c == ',' && level == 0)
- break;
- }
- const QString key = chopConst(inner.mid(10, pos - 10));
- const QString keyEsc = QRegExp::escape(key);
- // Get value: MSVC: 'pair<a const ,b>', gcc: 'pair<const a, b>'
- if (inner.at(++pos) == QLatin1Char(' '))
- pos++;
- const QString value = inner.mid(pos, inner.size() - pos - 1).trimmed();
- const QString valueEsc = QRegExp::escape(value);
- QRegExp mapRE1(QString::fromLatin1("unordered_map<%1, ?%2, ?std::hash<%3 ?>, ?std::equal_to<%4 ?>, ?%5\\s*>")
- .arg(keyEsc, valueEsc, keyEsc, keyEsc, allocEsc));
- mapRE1.setMinimal(true);
- QTC_ASSERT(mapRE1.isValid(), return typeIn);
- if (mapRE1.indexIn(type) != -1)
- type.replace(mapRE1.cap(0), QString::fromLatin1("unordered_map<%1, %2>").arg(key, value));
-
- if (isLibCpp) {
- QRegExp mapRE2(QString::fromLatin1("unordered_map<std::string, ?%1, "
- "?std::hash<char>, ?std::equal_to<std::string>, ?%2\\s*>")
- .arg(valueEsc, allocEsc));
- mapRE2.setMinimal(true);
- QTC_ASSERT(mapRE2.isValid(), return typeIn);
- if (mapRE2.indexIn(type) != -1)
- type.replace(mapRE2.cap(0), QString::fromLatin1("unordered_map<std::string, %2>").arg(value));
- }
- }
- } // with std::allocator
- }
- type.replace(QLatin1Char('@'), QLatin1Char('*'));
- type.replace(QLatin1String(" >"), QLatin1String(">"));
- qDebug() << "TYPE: " << type;
- return type;
-}
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerprotocol.h b/src/plugins/debugger/debuggerprotocol.h
index 74dc21de28..ed46dc1948 100644
--- a/src/plugins/debugger/debuggerprotocol.h
+++ b/src/plugins/debugger/debuggerprotocol.h
@@ -221,11 +221,6 @@ enum DebuggerDisplay {
// Decode string data as returned by the dumper helpers.
QString decodeData(const QByteArray &baIn, int encoding);
-// Simplify complicated STL template types, such as
-// 'std::basic_string<char,std::char_traits<char>,std::allocator<char> > '->
-// 'std::string'.
-QString simplifySTLType(const QString &typeIn);
-
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/simplifytype.cpp b/src/plugins/debugger/simplifytype.cpp
new file mode 100644
index 0000000000..4e11afe741
--- /dev/null
+++ b/src/plugins/debugger/simplifytype.cpp
@@ -0,0 +1,301 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "simplifytype.h"
+
+#include <QRegExp>
+
+#include <ctype.h>
+
+#define QTC_ASSERT_STRINGIFY_HELPER(x) #x
+#define QTC_ASSERT_STRINGIFY(x) QTC_ASSERT_STRINGIFY_HELPER(x)
+#define QTC_ASSERT_STRING(cond) qDebug("SOFT ASSERT: \"" cond"\" in file " __FILE__ ", line " QTC_ASSERT_STRINGIFY(__LINE__))
+#define QTC_ASSERT(cond, action) if (cond) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0)
+
+namespace Debugger {
+namespace Internal {
+
+// Simplify complicated STL template types,
+// such as 'std::basic_string<char,std::char_traits<char>,std::allocator<char> >'
+// -> 'std::string' and helpers.
+
+static QString chopConst(QString type)
+{
+ while (1) {
+ if (type.startsWith(QLatin1String("const")))
+ type = type.mid(5);
+ else if (type.startsWith(QLatin1Char(' ')))
+ type = type.mid(1);
+ else if (type.endsWith(QLatin1String("const")))
+ type.chop(5);
+ else if (type.endsWith(QLatin1Char(' ')))
+ type.chop(1);
+ else
+ break;
+ }
+ return type;
+}
+
+static inline QRegExp stdStringRegExp(const QString &charType)
+{
+ QString rc = QLatin1String("basic_string<");
+ rc += charType;
+ rc += QLatin1String(",[ ]?std::char_traits<");
+ rc += charType;
+ rc += QLatin1String(">,[ ]?std::allocator<");
+ rc += charType;
+ rc += QLatin1String("> >");
+ const QRegExp re(rc);
+ QTC_ASSERT(re.isValid(), /**/);
+ return re;
+}
+
+// Simplify string types in a type
+// 'std::set<std::basic_string<char... > >' -> std::set<std::string>'
+static inline void simplifyStdString(const QString &charType, const QString &replacement,
+ QString *type)
+{
+ QRegExp stringRegexp = stdStringRegExp(charType);
+ const int replacementSize = replacement.size();
+ for (int pos = 0; pos < type->size(); ) {
+ // Check next match
+ const int matchPos = stringRegexp.indexIn(*type, pos);
+ if (matchPos == -1)
+ break;
+ const int matchedLength = stringRegexp.matchedLength();
+ type->replace(matchPos, matchedLength, replacement);
+ pos = matchPos + replacementSize;
+ // If we were inside an 'allocator<std::basic_string..char > >'
+ // kill the following blank -> 'allocator<std::string>'
+ if (pos + 1 < type->size() && type->at(pos) == QLatin1Char(' ')
+ && type->at(pos + 1) == QLatin1Char('>'))
+ type->remove(pos, 1);
+ }
+}
+
+// Fix 'std::allocator<std::string >' -> 'std::allocator<std::string>',
+// which can happen when replacing/simplifying
+static inline QString fixNestedTemplates(QString s)
+{
+ const int size = s.size();
+ if (size > 3
+ && s.at(size - 1) == QLatin1Char('>')
+ && s.at(size - 2) == QLatin1Char(' ')
+ && s.at(size - 3) != QLatin1Char('>'))
+ s.remove(size - 2, 1);
+ return s;
+}
+
+QString simplifyType(const QString &typeIn)
+{
+ QString type = typeIn;
+ if (type.startsWith(QLatin1String("class "))) // MSVC prepends class,struct
+ type.remove(0, 6);
+ if (type.startsWith(QLatin1String("struct ")))
+ type.remove(0, 7);
+
+ const bool isLibCpp = type.contains(QLatin1String("std::__1"));
+ type.replace(QLatin1String("std::__1::"), QLatin1String("std::"));
+ type.replace(QLatin1String("std::__debug::"), QLatin1String("std::"));
+ type.replace(QLatin1Char('*'), QLatin1Char('@'));
+
+ for (int i = 0; i < 10; ++i) {
+ // boost::shared_ptr<...>::element_type
+ if (type.startsWith(QLatin1String("boost::shared_ptr<"))
+ && type.endsWith(QLatin1String(">::element_type")))
+ type = type.mid(18, type.size() - 33);
+
+ // std::shared_ptr<...>::element_type
+ if (type.startsWith(QLatin1String("std::shared_ptr<"))
+ && type.endsWith(QLatin1String(">::element_type")))
+ type = type.mid(16, type.size() - 31);
+
+ // std::ifstream
+ QRegExp ifstreamRE(QLatin1String("std::basic_ifstream<char,\\s*std::char_traits<char>\\s*>"));
+ ifstreamRE.setMinimal(true);
+ QTC_ASSERT(ifstreamRE.isValid(), return typeIn);
+ if (ifstreamRE.indexIn(type) != -1)
+ type.replace(ifstreamRE.cap(0), QLatin1String("std::ifstream"));
+
+
+ // std::__1::hash_node<int, void *>::value_type -> int
+ if (isLibCpp) {
+ //QRegExp hashNodeRE(QLatin1String("std::__hash_node<([^<>]*),\\s*void\\s*@>::value_type"));
+ QRegExp hashNodeRE(QLatin1String("std::__hash_node<([^<>]*),\\s*void\\s*@>::value_type"));
+ QTC_ASSERT(hashNodeRE.isValid(), return typeIn);
+ if (hashNodeRE.indexIn(type) != -1)
+ type.replace(hashNodeRE.cap(0), hashNodeRE.cap(1));
+ }
+
+ // Anything with a std::allocator
+ int start = type.indexOf(QLatin1String("std::allocator<"));
+ if (start != -1) {
+ // search for matching '>'
+ int pos;
+ int level = 0;
+ for (pos = start + 12; pos < type.size(); ++pos) {
+ int c = type.at(pos).unicode();
+ if (c == '<') {
+ ++level;
+ } else if (c == '>') {
+ --level;
+ if (level == 0)
+ break;
+ }
+ }
+ const QString alloc = fixNestedTemplates(type.mid(start, pos + 1 - start).trimmed());
+ const QString inner = fixNestedTemplates(alloc.mid(15, alloc.size() - 16).trimmed());
+
+ const QString allocEsc = QRegExp::escape(alloc);
+ const QString innerEsc = QRegExp::escape(inner);
+ if (inner == QLatin1String("char")) { // std::string
+ simplifyStdString(QLatin1String("char"), QLatin1String("string"), &type);
+ } else if (inner == QLatin1String("wchar_t")) { // std::wstring
+ simplifyStdString(QLatin1String("wchar_t"), QLatin1String("wstring"), &type);
+ } else if (inner == QLatin1String("unsigned short")) { // std::wstring/MSVC
+ simplifyStdString(QLatin1String("unsigned short"), QLatin1String("wstring"), &type);
+ }
+ // std::vector, std::deque, std::list
+ QRegExp re1(QString::fromLatin1("(vector|list|deque)<%1, ?%2\\s*>").arg(innerEsc, allocEsc));
+ QTC_ASSERT(re1.isValid(), return typeIn);
+ if (re1.indexIn(type) != -1)
+ type.replace(re1.cap(0), QString::fromLatin1("%1<%2>").arg(re1.cap(1), inner));
+
+ // std::stack
+ QRegExp stackRE(QString::fromLatin1("stack<%1, ?std::deque<%2> >").arg(innerEsc, innerEsc));
+ stackRE.setMinimal(true);
+ QTC_ASSERT(stackRE.isValid(), return typeIn);
+ if (stackRE.indexIn(type) != -1)
+ type.replace(stackRE.cap(0), QString::fromLatin1("stack<%1>").arg(inner));
+
+ // std::hash<char>
+ QRegExp hashCharRE(QString::fromLatin1("hash<char, std::char_traits<char>, ?%1\\s*>").arg(allocEsc));
+ hashCharRE.setMinimal(true);
+ QTC_ASSERT(hashCharRE.isValid(), return typeIn);
+ if (hashCharRE.indexIn(type) != -1)
+ type.replace(hashCharRE.cap(0), QString::fromLatin1("hash<char>"));
+
+ // std::set
+ QRegExp setRE(QString::fromLatin1("set<%1, ?std::less<%2>, ?%3\\s*>").arg(innerEsc, innerEsc, allocEsc));
+ setRE.setMinimal(true);
+ QTC_ASSERT(setRE.isValid(), return typeIn);
+ if (setRE.indexIn(type) != -1)
+ type.replace(setRE.cap(0), QString::fromLatin1("set<%1>").arg(inner));
+
+ // std::unordered_set
+ QRegExp unorderedSetRE(QString::fromLatin1("unordered_set<%1, ?std::hash<%2>, ?std::equal_to<%3>, ?%4\\s*>")
+ .arg(innerEsc, innerEsc, innerEsc, allocEsc));
+ unorderedSetRE.setMinimal(true);
+ QTC_ASSERT(unorderedSetRE.isValid(), return typeIn);
+ if (unorderedSetRE.indexIn(type) != -1)
+ type.replace(unorderedSetRE.cap(0), QString::fromLatin1("unordered_set<%1>").arg(inner));
+
+ // std::map
+ if (inner.startsWith(QLatin1String("std::pair<"))) {
+ // search for outermost ',', split key and value
+ int pos;
+ int level = 0;
+ for (pos = 10; pos < inner.size(); ++pos) {
+ int c = inner.at(pos).unicode();
+ if (c == '<')
+ ++level;
+ else if (c == '>')
+ --level;
+ else if (c == ',' && level == 0)
+ break;
+ }
+ const QString key = chopConst(inner.mid(10, pos - 10));
+ const QString keyEsc = QRegExp::escape(key);
+ // Get value: MSVC: 'pair<a const ,b>', gcc: 'pair<const a, b>'
+ if (inner.at(++pos) == QLatin1Char(' '))
+ pos++;
+ const QString value = inner.mid(pos, inner.size() - pos - 1).trimmed();
+ const QString valueEsc = QRegExp::escape(value);
+ QRegExp mapRE1(QString::fromLatin1("map<%1, ?%2, ?std::less<%3 ?>, ?%4\\s*>")
+ .arg(keyEsc, valueEsc, keyEsc, allocEsc));
+ mapRE1.setMinimal(true);
+ QTC_ASSERT(mapRE1.isValid(), return typeIn);
+ if (mapRE1.indexIn(type) != -1) {
+ type.replace(mapRE1.cap(0), QString::fromLatin1("map<%1, %2>").arg(key, value));
+ } else {
+ QRegExp mapRE2(QString::fromLatin1("map<const %1, ?%2, ?std::less<const %3>, ?%4\\s*>")
+ .arg(keyEsc, valueEsc, keyEsc, allocEsc));
+ mapRE2.setMinimal(true);
+ if (mapRE2.indexIn(type) != -1)
+ type.replace(mapRE2.cap(0), QString::fromLatin1("map<const %1, %2>").arg(key, value));
+ }
+ }
+
+ // std::unordered_map
+ if (inner.startsWith(QLatin1String("std::pair<"))) {
+ // search for outermost ',', split key and value
+ int pos;
+ int level = 0;
+ for (pos = 10; pos < inner.size(); ++pos) {
+ int c = inner.at(pos).unicode();
+ if (c == '<')
+ ++level;
+ else if (c == '>')
+ --level;
+ else if (c == ',' && level == 0)
+ break;
+ }
+ const QString key = chopConst(inner.mid(10, pos - 10));
+ const QString keyEsc = QRegExp::escape(key);
+ // Get value: MSVC: 'pair<a const ,b>', gcc: 'pair<const a, b>'
+ if (inner.at(++pos) == QLatin1Char(' '))
+ pos++;
+ const QString value = inner.mid(pos, inner.size() - pos - 1).trimmed();
+ const QString valueEsc = QRegExp::escape(value);
+ QRegExp mapRE1(QString::fromLatin1("unordered_map<%1, ?%2, ?std::hash<%3 ?>, ?std::equal_to<%4 ?>, ?%5\\s*>")
+ .arg(keyEsc, valueEsc, keyEsc, keyEsc, allocEsc));
+ mapRE1.setMinimal(true);
+ QTC_ASSERT(mapRE1.isValid(), return typeIn);
+ if (mapRE1.indexIn(type) != -1)
+ type.replace(mapRE1.cap(0), QString::fromLatin1("unordered_map<%1, %2>").arg(key, value));
+
+ if (isLibCpp) {
+ QRegExp mapRE2(QString::fromLatin1("unordered_map<std::string, ?%1, "
+ "?std::hash<char>, ?std::equal_to<std::string>, ?%2\\s*>")
+ .arg(valueEsc, allocEsc));
+ mapRE2.setMinimal(true);
+ QTC_ASSERT(mapRE2.isValid(), return typeIn);
+ if (mapRE2.indexIn(type) != -1)
+ type.replace(mapRE2.cap(0), QString::fromLatin1("unordered_map<std::string, %2>").arg(value));
+ }
+ }
+ } // with std::allocator
+ }
+ type.replace(QLatin1Char('@'), QLatin1Char('*'));
+ type.replace(QLatin1String(" >"), QLatin1String(">"));
+ return type;
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/simplifytype.h b/src/plugins/debugger/simplifytype.h
new file mode 100644
index 0000000000..34cabfc9bd
--- /dev/null
+++ b/src/plugins/debugger/simplifytype.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DEBUGGER_SIMPLIFY_TYPE_H
+#define DEBUGGER_SIMPLIFY_TYPE_H
+
+#include <QString>
+
+namespace Debugger {
+namespace Internal {
+
+// Simplify complicated STL template types, such as
+// 'std::basic_string<char,std::char_traits<char>,std::allocator<char> > '->
+// 'std::string'.
+QString simplifyType(const QString &typeIn);
+
+} // namespace Internal
+} // namespace Debugger
+
+
+#endif // DEBUGGER_SIMPLIFY_TYPE_H
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp
index 989bb39fc0..6fb1406d10 100644
--- a/src/plugins/debugger/watchhandler.cpp
+++ b/src/plugins/debugger/watchhandler.cpp
@@ -36,6 +36,7 @@
#include "debuggerengine.h"
#include "debuggerinternalconstants.h"
#include "debuggerprotocol.h"
+#include "simplifytype.h"
#include "imageviewer.h"
#include "watchutils.h"
@@ -477,7 +478,7 @@ static QString niceTypeHelper(const QByteArray &typeIn)
const Cache::const_iterator it = cache.constFind(typeIn);
if (it != cache.constEnd())
return it.value();
- const QString simplified = simplifySTLType(QLatin1String(typeIn));
+ const QString simplified = simplifyType(QLatin1String(typeIn));
cache.insert(typeIn, simplified); // For simplicity, also cache unmodified types
return simplified;
}
diff --git a/tests/auto/debugger/dumpers.pro b/tests/auto/debugger/dumpers.pro
index 31e6ef98f0..2b23755c4c 100644
--- a/tests/auto/debugger/dumpers.pro
+++ b/tests/auto/debugger/dumpers.pro
@@ -23,12 +23,14 @@ include($$IDE_SOURCE_TREE/src/rpath.pri)
SOURCES += \
$$DEBUGGERDIR/debuggerprotocol.cpp \
+ $$DEBUGGERDIR/simplifytype.cpp \
$$DEBUGGERDIR/watchdata.cpp \
$$DEBUGGERDIR/watchutils.cpp \
tst_dumpers.cpp
HEADERS += \
$$DEBUGGERDIR/debuggerprotocol.h \
+ $$DEBUGGERDIR/simplifytype.h \
$$DEBUGGERDIR/watchdata.h \
$$DEBUGGERDIR/watchutils.h \
temporarydir.h
diff --git a/tests/auto/debugger/simplifytypes.pro b/tests/auto/debugger/simplifytypes.pro
index 04d995a347..df645f1513 100644
--- a/tests/auto/debugger/simplifytypes.pro
+++ b/tests/auto/debugger/simplifytypes.pro
@@ -9,4 +9,4 @@ INCLUDEPATH += $$DEBUGGERDIR
SOURCES += \
tst_simplifytypes.cpp \
- $$DEBUGGERDIR/debuggerprotocol.cpp \
+ $$DEBUGGERDIR/simplifytype.cpp \
diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp
index d9080a3ebd..e568a02395 100644
--- a/tests/auto/debugger/tst_dumpers.cpp
+++ b/tests/auto/debugger/tst_dumpers.cpp
@@ -28,6 +28,7 @@
****************************************************************************/
#include "debuggerprotocol.h"
+#include "simplifytype.h"
#include "watchdata.h"
#include "watchutils.h"
@@ -348,7 +349,7 @@ struct Type
}
}
QByteArray actualType =
- simplifySTLType(QString::fromLatin1(actualType0)).toLatin1();
+ simplifyType(QString::fromLatin1(actualType0)).toLatin1();
actualType.replace(' ', "");
actualType.replace("const", "");
QByteArray expectedType = type;
diff --git a/tests/auto/debugger/tst_simplifytypes.cpp b/tests/auto/debugger/tst_simplifytypes.cpp
index b7dafa22dd..6e3a882cfd 100644
--- a/tests/auto/debugger/tst_simplifytypes.cpp
+++ b/tests/auto/debugger/tst_simplifytypes.cpp
@@ -27,7 +27,7 @@
**
****************************************************************************/
-#include "debuggerprotocol.h"
+#include "simplifytype.h"
#include <QString>
#include <QtTest>
@@ -154,7 +154,7 @@ void SimplifyTypesTest::test()
{
QFETCH(QString, input);
QFETCH(QString, expected);
- const QString output = simplifySTLType(input);
+ const QString output = simplifyType(input);
QCOMPARE(output, expected);
}