From e801434799f8f4b25028f63c2595bd810277edb7 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Fri, 13 Feb 2009 15:37:42 +0100
Subject: [PATCH] Improved the type pretty printer.

---
 src/libs/cplusplus/Overview.cpp          |   9 +-
 src/libs/cplusplus/Overview.h            |   5 +-
 src/libs/cplusplus/TypePrettyPrinter.cpp | 240 +++++++++++++----------
 src/libs/cplusplus/TypePrettyPrinter.h   |  28 +--
 4 files changed, 156 insertions(+), 126 deletions(-)

diff --git a/src/libs/cplusplus/Overview.cpp b/src/libs/cplusplus/Overview.cpp
index 2494d11ec5e..0f973753d0b 100644
--- a/src/libs/cplusplus/Overview.cpp
+++ b/src/libs/cplusplus/Overview.cpp
@@ -68,6 +68,11 @@ bool Overview::showReturnTypes() const
     return _showReturnTypes;
 }
 
+unsigned Overview::markArgument() const
+{
+    return _markArgument;
+}
+
 void Overview::setMarkArgument(unsigned position)
 {
     _markArgument = position;
@@ -98,9 +103,5 @@ QString Overview::prettyType(const FullySpecifiedType &ty,
                              const QString &name) const
 {
     TypePrettyPrinter pp(this);
-    pp.setMarkArgument(_markArgument);
-    pp.setShowArgumentNames(_showArgumentNames);
-    pp.setShowReturnTypes(_showReturnTypes);
-    pp.setShowFunctionSignatures(_showFunctionSignatures);
     return pp(ty, name);
 }
diff --git a/src/libs/cplusplus/Overview.h b/src/libs/cplusplus/Overview.h
index fa1f3cf919f..6918ee45ff8 100644
--- a/src/libs/cplusplus/Overview.h
+++ b/src/libs/cplusplus/Overview.h
@@ -57,7 +57,10 @@ public:
     bool showFunctionSignatures() const;
     void setShowFunctionSignatures(bool showFunctionSignatures);
 
-    void setMarkArgument(unsigned position); // 1-based
+    // 1-based
+    // ### rename
+    unsigned markArgument() const;
+    void setMarkArgument(unsigned position);
 
     QString operator()(Name *name) const
     { return prettyName(name); }
diff --git a/src/libs/cplusplus/TypePrettyPrinter.cpp b/src/libs/cplusplus/TypePrettyPrinter.cpp
index 6fd6a2cf245..6e46361b7f4 100644
--- a/src/libs/cplusplus/TypePrettyPrinter.cpp
+++ b/src/libs/cplusplus/TypePrettyPrinter.cpp
@@ -42,37 +42,12 @@ using namespace CPlusPlus;
 
 TypePrettyPrinter::TypePrettyPrinter(const Overview *overview)
     : _overview(overview),
-      _name(0),
-      _markArgument(0),
-      _showArgumentNames(false),
-      _showReturnTypes(false),
-      _showFunctionSignatures(true)
+      _name(0)
 { }
 
 TypePrettyPrinter::~TypePrettyPrinter()
 { }
 
-bool TypePrettyPrinter::showArgumentNames() const
-{ return _showArgumentNames; }
-
-void TypePrettyPrinter::setShowArgumentNames(bool showArgumentNames)
-{ _showArgumentNames = showArgumentNames; }
-
-bool TypePrettyPrinter::showReturnTypes() const
-{ return _showReturnTypes; }
-
-void TypePrettyPrinter::setShowReturnTypes(bool showReturnTypes)
-{ _showReturnTypes = showReturnTypes; }
-
-bool TypePrettyPrinter::showFunctionSignatures() const
-{ return _showFunctionSignatures; }
-
-void TypePrettyPrinter::setShowFunctionSignatures(bool showFunctionSignatures)
-{ _showFunctionSignatures = showFunctionSignatures; }
-
-void TypePrettyPrinter::setMarkArgument(unsigned position)
-{ _markArgument = position; }
-
 const Overview *TypePrettyPrinter::overview() const
 { return _overview; }
 
@@ -102,15 +77,16 @@ QString TypePrettyPrinter::operator()(const FullySpecifiedType &type, const QStr
 
 void TypePrettyPrinter::acceptType(const FullySpecifiedType &ty)
 {
-    if (ty.isConst())
-        _text += QLatin1String("const ");
-    if (ty.isVolatile())
-        _text += QLatin1String("volatile ");
     if (ty.isSigned())
-        _text += QLatin1String("signed ");
-    if (ty.isUnsigned())
-        _text += QLatin1String("unsigned ");
+        out(QLatin1String("signed "));
+
+    else if (ty.isUnsigned())
+        out(QLatin1String("unsigned "));
+
+    const FullySpecifiedType previousFullySpecifiedType = _fullySpecifiedType;
+    _fullySpecifiedType = ty;
     accept(ty.type());
+    _fullySpecifiedType = previousFullySpecifiedType;
 }
 
 QString TypePrettyPrinter::switchName(const QString &name)
@@ -127,9 +103,9 @@ QString TypePrettyPrinter::switchText(const QString &name)
     return previousName;
 }
 
-QList<Type *> TypePrettyPrinter::switchPtrOperators(const QList<Type *> &ptrOperators)
+QList<FullySpecifiedType> TypePrettyPrinter::switchPtrOperators(const QList<FullySpecifiedType> &ptrOperators)
 {
-    QList<Type *> previousPtrOperators = _ptrOperators;
+    QList<FullySpecifiedType> previousPtrOperators = _ptrOperators;
     _ptrOperators = ptrOperators;
     return previousPtrOperators;
 }
@@ -137,31 +113,53 @@ QList<Type *> TypePrettyPrinter::switchPtrOperators(const QList<Type *> &ptrOper
 void TypePrettyPrinter::applyPtrOperators(bool wantSpace)
 {
     for (int i = _ptrOperators.size() - 1; i != -1; --i) {
-        Type *op = _ptrOperators.at(i);
+        const FullySpecifiedType op = _ptrOperators.at(i);
 
         if (i == 0 && wantSpace)
-            _text += QLatin1Char(' ');
-
-        if (PointerType *ptrTy = op->asPointerType()) {
-            _text += QLatin1Char('*');
-            if (ptrTy->elementType().isConst())
-                _text += " const";
-            if (ptrTy->elementType().isVolatile())
-                _text += " volatile";
+            space();
+
+        if (op->isPointerType()) {
+            out(QLatin1Char('*'));
+            outCV(op);
         } else if (op->isReferenceType()) {
-            _text += QLatin1Char('&');
-        } else if (PointerToMemberType *memPtrTy = op->asPointerToMemberType()) {
-            _text += QLatin1Char(' ');
-            _text += _overview->prettyName(memPtrTy->memberName());
-            _text += QLatin1Char('*');
+            out(QLatin1Char('&'));
+        } else if (const PointerToMemberType *memPtrTy = op->asPointerToMemberType()) {
+            space();
+            out(_overview->prettyName(memPtrTy->memberName()));
+            out(QLatin1Char('*'));
+            outCV(op);
         }
     }
 }
 
 void TypePrettyPrinter::visit(VoidType *)
 {
-    _text += QLatin1String("void");
+    out(QLatin1String("void"));
+    applyPtrOperators();
+}
 
+void TypePrettyPrinter::visit(NamedType *type)
+{
+    out(overview()->prettyName(type->name()));
+    applyPtrOperators();
+}
+
+void TypePrettyPrinter::visit(Namespace *type)
+{
+    _text += overview()->prettyName(type->name());
+    applyPtrOperators();
+}
+
+void TypePrettyPrinter::visit(Class *type)
+{
+    _text += overview()->prettyName(type->name());
+    applyPtrOperators();
+}
+
+
+void TypePrettyPrinter::visit(Enum *type)
+{
+    _text += overview()->prettyName(type->name());
     applyPtrOperators();
 }
 
@@ -169,25 +167,25 @@ void TypePrettyPrinter::visit(IntegerType *type)
 {
     switch (type->kind()) {
     case IntegerType::Char:
-        _text += QLatin1String("char");
+        out(QLatin1String("char"));
         break;
     case IntegerType::WideChar:
-        _text += QLatin1String("wchar_t");
+        out(QLatin1String("wchar_t"));
         break;
     case IntegerType::Bool:
-        _text += QLatin1String("bool");
+        out(QLatin1String("bool"));
         break;
     case IntegerType::Short:
-        _text += QLatin1String("short");
+        out(QLatin1String("short"));
         break;
     case IntegerType::Int:
-        _text += QLatin1String("int");
+        out(QLatin1String("int"));
         break;
     case IntegerType::Long:
-        _text += QLatin1String("long");
+        out(QLatin1String("long"));
         break;
     case IntegerType::LongLong:
-        _text += QLatin1String("long long");
+        out(QLatin1String("long long"));
         break;
     }
 
@@ -198,13 +196,13 @@ void TypePrettyPrinter::visit(FloatType *type)
 {
     switch (type->kind()) {
     case FloatType::Float:
-        _text += QLatin1String("float");
+        out(QLatin1String("float"));
         break;
     case FloatType::Double:
-        _text += QLatin1String("double");
+        out(QLatin1String("double"));
         break;
     case FloatType::LongDouble:
-        _text += QLatin1String("long double");
+        out(QLatin1String("long double"));
         break;
     }
 
@@ -213,99 +211,135 @@ void TypePrettyPrinter::visit(FloatType *type)
 
 void TypePrettyPrinter::visit(PointerToMemberType *type)
 {
-    _ptrOperators.append(type);
+    outCV(type->elementType());
+    space();
+
+    _ptrOperators.append(_fullySpecifiedType);
     acceptType(type->elementType());
 }
 
 void TypePrettyPrinter::visit(PointerType *type)
 {
-    _ptrOperators.append(type);
+    outCV(type->elementType());
+    space();
+
+    _ptrOperators.append(_fullySpecifiedType);
     acceptType(type->elementType());
 }
 
 void TypePrettyPrinter::visit(ReferenceType *type)
 {
-    _ptrOperators.append(type);
+    outCV(type->elementType());
+    space();
+
+    _ptrOperators.append(_fullySpecifiedType);
     acceptType(type->elementType());
 }
 
 void TypePrettyPrinter::visit(ArrayType *type)
 {
-    _text += overview()->prettyType(type->elementType());
+    out(overview()->prettyType(type->elementType()));
     if (! _ptrOperators.isEmpty()) {
-        _text += QLatin1Char('(');
+        out(QLatin1Char('('));
         applyPtrOperators(false);
         if (! _name.isEmpty()) {
-            _text += _name;
+            out(_name);
             _name.clear();
         }
-        _text += QLatin1Char(')');
+        out(QLatin1Char(')'));
     }
-    _text += QLatin1String("[]");
-}
-
-void TypePrettyPrinter::visit(NamedType *type)
-{
-    _text += overview()->prettyName(type->name());
-    applyPtrOperators();
+    out(QLatin1String("[]"));
 }
 
 void TypePrettyPrinter::visit(Function *type)
 {
-    if (_showReturnTypes)
-        _text += _overview->prettyType(type->returnType());
+    if (_overview->showReturnTypes())
+        out(_overview->prettyType(type->returnType()));
 
     if (! _ptrOperators.isEmpty()) {
-        _text += QLatin1Char('(');
+        out(QLatin1Char('('));
         applyPtrOperators(false);
         if (! _name.isEmpty()) {
             _text += _name;
             _name.clear();
         }
-        _text += QLatin1Char(')');
-    } else if (! _name.isEmpty() && _showFunctionSignatures) {
-        _text += QLatin1Char(' '); // ### fixme
-        _text += _name;
+        out(QLatin1Char(')'));
+    } else if (! _name.isEmpty() && _overview->showFunctionSignatures()) {
+        space();
+        out(_name);
         _name.clear();
     }
 
-    if (_showFunctionSignatures) {
+    if (_overview->showFunctionSignatures()) {
         Overview argumentText;
-        _text += QLatin1Char('(');
+        argumentText.setShowReturnTypes(true);
+        argumentText.setShowArgumentNames(false);
+        argumentText.setShowFunctionSignatures(true);
+
+        out(QLatin1Char('('));
+
         for (unsigned index = 0; index < type->argumentCount(); ++index) {
             if (index != 0)
-                _text += QLatin1String(", ");
+                out(QLatin1String(", "));
 
             if (Argument *arg = type->argumentAt(index)->asArgument()) {
-                if (index + 1 == _markArgument)
-                    _text += QLatin1String("<b>");
+                if (index + 1 == _overview->markArgument())
+                    out(QLatin1String("<b>"));
+
                 Name *name = 0;
-                if (_showArgumentNames)
+
+                if (_overview->showArgumentNames())
                     name = arg->name();
-                _text += argumentText(arg->type(), name);
-                if (index + 1 == _markArgument)
-                    _text += QLatin1String("</b>");
+
+                out(argumentText(arg->type(), name));
+
+                if (index + 1 == _overview->markArgument())
+                    out(QLatin1String("</b>"));
             }
         }
 
         if (type->isVariadic())
-            _text += QLatin1String("...");
+            out(QLatin1String("..."));
+
+        out(QLatin1Char(')'));
+        if (type->isConst() && type->isVolatile()) {
+            space();
+            out("const volatile");
+        } else if (type->isConst()) {
+            space();
+            out("const");
+        } else if (type->isVolatile()) {
+            space();
+            out("volatile");
+        }
+    }
+}
 
-        _text += QLatin1Char(')');
+void TypePrettyPrinter::space()
+{
+    if (_text.isEmpty())
+        return;
 
-        if (type->isConst())
-            _text += QLatin1String(" const");
+    const QChar ch = _text.at(_text.length() - 1);
 
-        if (type->isVolatile())
-            _text += QLatin1String(" volatile");
-    }
+    if (ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char(')'))
+        _text += QLatin1Char(' ');
 }
 
-void TypePrettyPrinter::visit(Namespace *type)
-{ _text += overview()->prettyName(type->name()); }
+void TypePrettyPrinter::out(const QString &text)
+{ _text += text; }
 
-void TypePrettyPrinter::visit(Class *type)
-{ _text += overview()->prettyName(type->name()); }
+void TypePrettyPrinter::out(const QChar &ch)
+{ _text += ch; }
 
-void TypePrettyPrinter::visit(Enum *type)
-{ _text += overview()->prettyName(type->name()); }
+void TypePrettyPrinter::outCV(const FullySpecifiedType &ty)
+{
+    if (ty.isConst() && ty.isVolatile())
+        out(QLatin1String("const volatile"));
+
+    else if (ty.isConst())
+        out(QLatin1String("const"));
+
+    else if (ty.isVolatile())
+        out(QLatin1String("volatile"));
+}
diff --git a/src/libs/cplusplus/TypePrettyPrinter.h b/src/libs/cplusplus/TypePrettyPrinter.h
index 790999dc824..6191cf01af0 100644
--- a/src/libs/cplusplus/TypePrettyPrinter.h
+++ b/src/libs/cplusplus/TypePrettyPrinter.h
@@ -33,7 +33,8 @@
 #ifndef TYPEPRETTYPRINTER_H
 #define TYPEPRETTYPRINTER_H
 
-#include "TypeVisitor.h"
+#include <TypeVisitor.h>
+#include <FullySpecifiedType.h>
 #include <QString>
 #include <QList>
 
@@ -50,23 +51,12 @@ public:
 
     const Overview *overview() const;
 
-    bool showArgumentNames() const;
-    void setShowArgumentNames(bool showArgumentNames);
-
-    bool showReturnTypes() const;
-    void setShowReturnTypes(bool showReturnTypes);
-
-    bool showFunctionSignatures() const;
-    void setShowFunctionSignatures(bool showFunctionSignatures);
-
-    void setMarkArgument(unsigned position); // 1-based
-
     QString operator()(const FullySpecifiedType &type);
     QString operator()(const FullySpecifiedType &type, const QString &name);
 
 protected:
     QString switchText(const QString &text = QString());
-    QList<Type *> switchPtrOperators(const QList<Type *> &ptrOperators);
+    QList<FullySpecifiedType> switchPtrOperators(const QList<FullySpecifiedType> &ptrOperators);
     QString switchName(const QString &name);
 
     void applyPtrOperators(bool wantSpace = true);
@@ -85,15 +75,17 @@ protected:
     virtual void visit(Class *type);
     virtual void visit(Enum *type);
 
+    void space();
+    void out(const QString &text);
+    void out(const QChar &ch);
+    void outCV(const FullySpecifiedType &ty);
+
 private:
     const Overview *_overview;
     QString _name;
     QString _text;
-    QList<Type *> _ptrOperators;
-    unsigned _markArgument;
-    bool _showArgumentNames: 1;
-    bool _showReturnTypes: 1;
-    bool _showFunctionSignatures: 1;
+    FullySpecifiedType _fullySpecifiedType;
+    QList<FullySpecifiedType> _ptrOperators;
 };
 
 } // end of namespace CPlusPlus
-- 
GitLab