1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "TypePrettyPrinter.h"
37 #include <FullySpecifiedType.h>
39 #include <CoreTypes.h>
42 #include <QStringList>
45 using namespace CPlusPlus;
48 TypePrettyPrinter::TypePrettyPrinter(const Overview *overview)
53 TypePrettyPrinter::~TypePrettyPrinter()
56 const Overview *TypePrettyPrinter::overview() const
59 QString TypePrettyPrinter::operator()(const FullySpecifiedType &ty)
61 QString previousName = switchText();
62 bool previousNeedsParens = switchNeedsParens(false);
64 switchNeedsParens(previousNeedsParens);
65 return switchText(previousName);
68 QString TypePrettyPrinter::operator()(const FullySpecifiedType &type, const QString &name)
70 const QString previousName = switchName(name);
71 QString text = operator()(type);
72 if (! _name.isEmpty() && ! text.isEmpty()) {
73 const QChar ch = text.at(text.size() - 1);
74 if (ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char('>'))
75 text += QLatin1Char(' ');
77 } else if (text.isEmpty()) {
80 (void) switchName(previousName);
85 void TypePrettyPrinter::acceptType(const FullySpecifiedType &ty)
87 const FullySpecifiedType previousFullySpecifiedType = _fullySpecifiedType;
88 _fullySpecifiedType = ty;
90 _fullySpecifiedType = previousFullySpecifiedType;
93 QString TypePrettyPrinter::switchName(const QString &name)
95 const QString previousName = _name;
100 QString TypePrettyPrinter::switchText(const QString &name)
102 QString previousName = _text;
107 bool TypePrettyPrinter::switchNeedsParens(bool needsParens)
109 bool previousNeedsParens = _needsParens;
110 _needsParens = needsParens;
111 return previousNeedsParens;
114 void TypePrettyPrinter::visit(UndefinedType *)
116 if (_fullySpecifiedType.isSigned() || _fullySpecifiedType.isUnsigned()) {
117 prependSpaceUnlessBracket();
118 if (_fullySpecifiedType.isSigned())
119 _text.prepend(QLatin1String("signed"));
120 else if (_fullySpecifiedType.isUnsigned())
121 _text.prepend(QLatin1String("unsigned"));
124 prependCv(_fullySpecifiedType);
127 void TypePrettyPrinter::visit(VoidType *)
129 prependSpaceUnlessBracket();
130 _text.prepend(QLatin1String("void"));
131 prependCv(_fullySpecifiedType);
134 void TypePrettyPrinter::visit(NamedType *type)
136 prependSpaceUnlessBracket();
137 _text.prepend(overview()->prettyName(type->name()));
138 prependCv(_fullySpecifiedType);
141 void TypePrettyPrinter::visit(Namespace *type)
143 _text.prepend(overview()->prettyName(type->name()));
144 prependCv(_fullySpecifiedType);
147 void TypePrettyPrinter::visit(Template *type)
149 if (Symbol *d = type->declaration()) {
150 if (overview()->showTemplateParameters() && ! _name.isEmpty()) {
151 _name += QLatin1Char('<');
152 for (unsigned index = 0; index < type->templateParameterCount(); ++index) {
154 _name += QLatin1String(", ");
155 QString arg = overview()->prettyName(type->templateParameterAt(index)->name());
157 arg += QLatin1Char('T');
158 arg += QString::number(index + 1);
162 _name += QLatin1Char('>');
164 acceptType(d->type());
166 prependCv(_fullySpecifiedType);
169 void TypePrettyPrinter::visit(Class *classTy)
171 _text.prepend(overview()->prettyName(classTy->name()));
172 prependCv(_fullySpecifiedType);
176 void TypePrettyPrinter::visit(Enum *type)
178 _text.prepend(overview()->prettyName(type->name()));
179 prependCv(_fullySpecifiedType);
182 void TypePrettyPrinter::visit(IntegerType *type)
184 prependSpaceUnlessBracket();
185 switch (type->kind()) {
186 case IntegerType::Char:
187 _text.prepend(QLatin1String("char"));
189 case IntegerType::WideChar:
190 _text.prepend(QLatin1String("wchar_t"));
192 case IntegerType::Bool:
193 _text.prepend(QLatin1String("bool"));
195 case IntegerType::Short:
196 _text.prepend(QLatin1String("short"));
198 case IntegerType::Int:
199 _text.prepend(QLatin1String("int"));
201 case IntegerType::Long:
202 _text.prepend(QLatin1String("long"));
204 case IntegerType::LongLong:
205 _text.prepend(QLatin1String("long long"));
209 if (_fullySpecifiedType.isSigned() || _fullySpecifiedType.isUnsigned()) {
210 prependWordSeparatorSpace();
211 if (_fullySpecifiedType.isSigned())
212 _text.prepend(QLatin1String("signed"));
213 else if (_fullySpecifiedType.isUnsigned())
214 _text.prepend(QLatin1String("unsigned"));
217 prependCv(_fullySpecifiedType);
220 void TypePrettyPrinter::visit(FloatType *type)
222 prependSpaceUnlessBracket();
223 switch (type->kind()) {
224 case FloatType::Float:
225 _text.prepend(QLatin1String("float"));
227 case FloatType::Double:
228 _text.prepend(QLatin1String("double"));
230 case FloatType::LongDouble:
231 _text.prepend(QLatin1String("long double"));
235 prependCv(_fullySpecifiedType);
238 void TypePrettyPrinter::visit(PointerToMemberType *type)
240 prependCv(_fullySpecifiedType);
241 _text.prepend(QLatin1String("::*"));
242 _text.prepend(_overview->prettyName(type->memberName()));
244 acceptType(type->elementType());
247 void TypePrettyPrinter::visit(PointerType *type)
249 if (! _name.isEmpty()) {
250 _text.prepend(_name);
253 prependCv(_fullySpecifiedType);
254 _text.prepend(QLatin1String("*"));
256 acceptType(type->elementType());
259 void TypePrettyPrinter::visit(ReferenceType *type)
261 if (! _name.isEmpty()) {
262 _text.prepend(_name);
265 prependCv(_fullySpecifiedType);
267 if (_text.startsWith(QLatin1Char('&')))
268 _text.prepend(QLatin1Char(' '));
270 if (type->isRvalueReference())
271 _text.prepend(QLatin1String("&&"));
273 _text.prepend(QLatin1String("&"));
275 acceptType(type->elementType());
278 void TypePrettyPrinter::visit(ArrayType *type)
281 _text.prepend(QLatin1Char('('));
282 _text.append(QLatin1Char(')'));
283 _needsParens = false;
284 } else if (! _name.isEmpty()) {
285 _text.prepend(_name);
288 _text.append(QLatin1String("[]"));
290 acceptType(type->elementType());
293 void TypePrettyPrinter::visit(Function *type)
296 _text.prepend(QLatin1Char('('));
297 if (! _name.isEmpty()) {
302 _text.append(QLatin1Char(')'));
303 _needsParens = false;
304 } else if (! _name.isEmpty() && _overview->showFunctionSignatures()) {
310 if (_overview->showReturnTypes()) {
311 const QString returnType = _overview->prettyType(type->returnType());
312 if (!returnType.isEmpty()) {
313 _text.prepend(QLatin1Char(' '));
314 _text.prepend(returnType);
318 if (_overview->showFunctionSignatures()) {
319 Overview argumentText;
320 argumentText.setShowReturnTypes(true);
321 argumentText.setShowArgumentNames(false);
322 argumentText.setShowFunctionSignatures(true);
324 _text += QLatin1Char('(');
326 for (unsigned index = 0; index < type->argumentCount(); ++index) {
328 _text += QLatin1String(", ");
330 if (Argument *arg = type->argumentAt(index)->asArgument()) {
331 if (index + 1 == _overview->markedArgument())
332 const_cast<Overview*>(_overview)->setMarkedArgumentBegin(_text.length());
334 const Name *name = 0;
336 if (_overview->showArgumentNames())
339 _text += argumentText(arg->type(), name);
341 if (_overview->showDefaultArguments()) {
342 if (const StringLiteral *initializer = arg->initializer()) {
343 _text += QLatin1String(" =");
344 _text += QString::fromUtf8(initializer->chars(), initializer->size());
348 if (index + 1 == _overview->markedArgument())
349 const_cast<Overview*>(_overview)->setMarkedArgumentEnd(_text.length());
353 if (type->isVariadic())
354 _text += QLatin1String("...");
356 _text += QLatin1Char(')');
357 if (type->isConst()) {
361 if (type->isVolatile()) {
368 void TypePrettyPrinter::appendSpace()
373 const QChar ch = _text.at(_text.length() - 1);
375 if (ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char(')')
376 || ch == QLatin1Char('>'))
377 _text += QLatin1Char(' ');
380 void TypePrettyPrinter::prependSpaceUnlessBracket()
385 const QChar ch = _text.at(0);
387 if (ch != QLatin1Char('['))
391 void TypePrettyPrinter::prependWordSeparatorSpace()
396 const QChar ch = _text.at(0);
398 if (ch.isLetterOrNumber())
402 void TypePrettyPrinter::prependCv(const FullySpecifiedType &ty)
404 if (ty.isVolatile()) {
405 prependWordSeparatorSpace();
406 _text.prepend("volatile");
410 prependWordSeparatorSpace();
411 _text.prepend("const");