From 06f35cbbd0d913df6328923d4301cec68758f272 Mon Sep 17 00:00:00 2001
From: hjk <hjk121@nokiamail.com>
Date: Wed, 15 Jan 2014 12:04:23 +0100
Subject: [PATCH] Debugger: Split type simplification into file of its own

This still needs to use a proper parser at some time.

Change-Id: Ia0afe593dd9dc32f22f80adb7232c04f4db79cf6
Reviewed-by: hjk <hjk121@nokiamail.com>
---
 src/plugins/debugger/debugger.pro         |   6 +-
 src/plugins/debugger/debugger.qbs         |   1 +
 src/plugins/debugger/debuggerprotocol.cpp | 256 ------------------
 src/plugins/debugger/debuggerprotocol.h   |   5 -
 src/plugins/debugger/simplifytype.cpp     | 301 ++++++++++++++++++++++
 src/plugins/debugger/simplifytype.h       |  47 ++++
 src/plugins/debugger/watchhandler.cpp     |   3 +-
 tests/auto/debugger/dumpers.pro           |   2 +
 tests/auto/debugger/simplifytypes.pro     |   2 +-
 tests/auto/debugger/tst_dumpers.cpp       |   3 +-
 tests/auto/debugger/tst_simplifytypes.cpp |   4 +-
 11 files changed, 362 insertions(+), 268 deletions(-)
 create mode 100644 src/plugins/debugger/simplifytype.cpp
 create mode 100644 src/plugins/debugger/simplifytype.h

diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index c9f794d55d6..03b260c6bc5 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 16927cb79ba..c1203368215 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 e225082b68b..83fa67abe69 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 74dc21de286..ed46dc1948b 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 00000000000..4e11afe7417
--- /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 00000000000..34cabfc9bd6
--- /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 989bb39fc08..6fb1406d10b 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 31e6ef98f05..2b23755c4c0 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 04d995a3477..df645f15131 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 d9080a3ebd2..e568a023951 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 b7dafa22dd0..6e3a882cfd8 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);
 }
 
-- 
GitLab