TypePrettyPrinter.cpp 10.4 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2
3
4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
9
** Commercial Usage
10
**
11
12
13
14
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
15
**
16
** GNU Lesser General Public License Usage
17
**
18
19
20
21
22
23
** 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.
24
**
25
** If you are unsure which license is appropriate for your use, please
hjk's avatar
hjk committed
26
** contact the sales department at http://qt.nokia.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
con's avatar
con committed
29
30

#include "TypePrettyPrinter.h"
Tobias Hunger's avatar
Tobias Hunger committed
31
32

#include "Overview.h"
con's avatar
con committed
33
#include <FullySpecifiedType.h>
34
#include <Literals.h>
con's avatar
con committed
35
36
37
#include <CoreTypes.h>
#include <Symbols.h>
#include <Scope.h>
38
39
#include <QStringList>
#include <QtDebug>
con's avatar
con committed
40
41
42

using namespace CPlusPlus;

43

con's avatar
con committed
44
TypePrettyPrinter::TypePrettyPrinter(const Overview *overview)
45
    : _overview(overview)
46
    , _needsParens(false)
con's avatar
con committed
47
48
49
50
51
52
53
54
55
56
57
{ }

TypePrettyPrinter::~TypePrettyPrinter()
{ }

const Overview *TypePrettyPrinter::overview() const
{ return _overview; }

QString TypePrettyPrinter::operator()(const FullySpecifiedType &ty)
{
    QString previousName = switchText();
58
    bool previousNeedsParens = switchNeedsParens(false);
con's avatar
con committed
59
    acceptType(ty);
60
    switchNeedsParens(previousNeedsParens);
61
    return switchText(previousName);
con's avatar
con committed
62
63
64
65
}

QString TypePrettyPrinter::operator()(const FullySpecifiedType &type, const QString &name)
{
66
    const QString previousName = switchName(name);
con's avatar
con committed
67
68
    QString text = operator()(type);
    if (! _name.isEmpty() && ! text.isEmpty()) {
69
70
        const QChar ch = text.at(text.size() - 1);
        if (ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char('>'))
con's avatar
con committed
71
72
            text += QLatin1Char(' ');
        text += _name;
73
74
    } else if (text.isEmpty()) {
        text = name;
con's avatar
con committed
75
76
77
78
79
80
81
82
    }
    (void) switchName(previousName);
    return text;
}


void TypePrettyPrinter::acceptType(const FullySpecifiedType &ty)
{
83
84
    const FullySpecifiedType previousFullySpecifiedType = _fullySpecifiedType;
    _fullySpecifiedType = ty;
con's avatar
con committed
85
    accept(ty.type());
86
    _fullySpecifiedType = previousFullySpecifiedType;
con's avatar
con committed
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
}

QString TypePrettyPrinter::switchName(const QString &name)
{
    const QString previousName = _name;
    _name = name;
    return previousName;
}

QString TypePrettyPrinter::switchText(const QString &name)
{
    QString previousName = _text;
    _text = name;
    return previousName;
}

103
bool TypePrettyPrinter::switchNeedsParens(bool needsParens)
con's avatar
con committed
104
{
105
106
107
    bool previousNeedsParens = _needsParens;
    _needsParens = needsParens;
    return previousNeedsParens;
con's avatar
con committed
108
109
}

110
void TypePrettyPrinter::visit(UndefinedType *)
con's avatar
con committed
111
{
112
113
114
115
116
117
    if (_fullySpecifiedType.isSigned() || _fullySpecifiedType.isUnsigned()) {
        prependSpaceUnlessBracket();
        if (_fullySpecifiedType.isSigned())
            _text.prepend(QLatin1String("signed"));
        else if (_fullySpecifiedType.isUnsigned())
            _text.prepend(QLatin1String("unsigned"));
con's avatar
con committed
118
119
    }

120
    prependCv(_fullySpecifiedType);
121
122
}

con's avatar
con committed
123
124
void TypePrettyPrinter::visit(VoidType *)
{
125
126
127
    prependSpaceUnlessBracket();
    _text.prepend(QLatin1String("void"));
    prependCv(_fullySpecifiedType);
128
}
con's avatar
con committed
129

130
131
void TypePrettyPrinter::visit(NamedType *type)
{
132
133
134
    prependSpaceUnlessBracket();
    _text.prepend(overview()->prettyName(type->name()));
    prependCv(_fullySpecifiedType);
135
136
137
138
}

void TypePrettyPrinter::visit(Namespace *type)
{
139
140
    _text.prepend(overview()->prettyName(type->name()));
    prependCv(_fullySpecifiedType);
141
142
}

143
void TypePrettyPrinter::visit(Class *classTy)
144
{
145
    _text.prepend(overview()->prettyName(classTy->name()));
146
    prependCv(_fullySpecifiedType);
147
148
149
150
151
}


void TypePrettyPrinter::visit(Enum *type)
{
152
    _text.prepend(overview()->prettyName(type->name()));
153
    prependCv(_fullySpecifiedType);
con's avatar
con committed
154
155
156
157
}

void TypePrettyPrinter::visit(IntegerType *type)
{
158
    prependSpaceUnlessBracket();
con's avatar
con committed
159
160
    switch (type->kind()) {
    case IntegerType::Char:
161
        _text.prepend(QLatin1String("char"));
con's avatar
con committed
162
163
        break;
    case IntegerType::WideChar:
164
        _text.prepend(QLatin1String("wchar_t"));
con's avatar
con committed
165
166
        break;
    case IntegerType::Bool:
167
        _text.prepend(QLatin1String("bool"));
con's avatar
con committed
168
169
        break;
    case IntegerType::Short:
170
        _text.prepend(QLatin1String("short"));
con's avatar
con committed
171
172
        break;
    case IntegerType::Int:
173
        _text.prepend(QLatin1String("int"));
con's avatar
con committed
174
175
        break;
    case IntegerType::Long:
176
        _text.prepend(QLatin1String("long"));
con's avatar
con committed
177
178
        break;
    case IntegerType::LongLong:
179
        _text.prepend(QLatin1String("long long"));
con's avatar
con committed
180
181
182
        break;
    }

183
184
185
186
187
188
189
190
191
    if (_fullySpecifiedType.isSigned() || _fullySpecifiedType.isUnsigned()) {
        prependWordSeparatorSpace();
        if (_fullySpecifiedType.isSigned())
            _text.prepend(QLatin1String("signed"));
        else if (_fullySpecifiedType.isUnsigned())
            _text.prepend(QLatin1String("unsigned"));
    }

    prependCv(_fullySpecifiedType);
con's avatar
con committed
192
193
194
195
}

void TypePrettyPrinter::visit(FloatType *type)
{
196
    prependSpaceUnlessBracket();
con's avatar
con committed
197
198
    switch (type->kind()) {
    case FloatType::Float:
199
        _text.prepend(QLatin1String("float"));
con's avatar
con committed
200
201
        break;
    case FloatType::Double:
202
        _text.prepend(QLatin1String("double"));
con's avatar
con committed
203
204
        break;
    case FloatType::LongDouble:
205
        _text.prepend(QLatin1String("long double"));
con's avatar
con committed
206
207
208
        break;
    }

209
    prependCv(_fullySpecifiedType);
con's avatar
con committed
210
211
212
213
}

void TypePrettyPrinter::visit(PointerToMemberType *type)
{
214
215
216
217
    prependCv(_fullySpecifiedType);
    _text.prepend(QLatin1String("::*"));
    _text.prepend(_overview->prettyName(type->memberName()));
    _needsParens = true;
con's avatar
con committed
218
219
220
221
222
    acceptType(type->elementType());
}

void TypePrettyPrinter::visit(PointerType *type)
{
223
224
225
226
227
228
229
    if (! _name.isEmpty()) {
        _text.prepend(_name);
        _name.clear();
    }
    prependCv(_fullySpecifiedType);
    _text.prepend(QLatin1String("*"));
    _needsParens = true;
con's avatar
con committed
230
231
232
233
234
    acceptType(type->elementType());
}

void TypePrettyPrinter::visit(ReferenceType *type)
{
235
236
237
238
239
240
241
242
    if (! _name.isEmpty()) {
        _text.prepend(_name);
        _name.clear();
    }
    prependCv(_fullySpecifiedType);

    if (_text.startsWith(QLatin1Char('&')))
        _text.prepend(QLatin1Char(' '));
243

244
245
246
247
248
    if (type->isRvalueReference())
        _text.prepend(QLatin1String("&&"));
    else
        _text.prepend(QLatin1String("&"));
    _needsParens = true;
con's avatar
con committed
249
250
251
252
253
    acceptType(type->elementType());
}

void TypePrettyPrinter::visit(ArrayType *type)
{
254
255
256
257
258
259
260
    if (_needsParens) {
        _text.prepend(QLatin1Char('('));
        _text.append(QLatin1Char(')'));
        _needsParens = false;
    } else if (! _name.isEmpty()) {
        _text.prepend(_name);
        _name.clear();
con's avatar
con committed
261
    }
262
263
264
    _text.append(QLatin1String("[]"));

    acceptType(type->elementType());
con's avatar
con committed
265
266
267
268
}

void TypePrettyPrinter::visit(Function *type)
{
269
270
    if (_needsParens) {
        _text.prepend(QLatin1Char('('));
con's avatar
con committed
271
        if (! _name.isEmpty()) {
272
273
            appendSpace();
            _text.append(_name);
con's avatar
con committed
274
275
            _name.clear();
        }
276
277
        _text.append(QLatin1Char(')'));
        _needsParens = false;
278
    } else if (! _name.isEmpty() && _overview->showFunctionSignatures()) {
279
280
        appendSpace();
        _text.append(_name);
con's avatar
con committed
281
282
283
        _name.clear();
    }

284
    if (_overview->showReturnTypes()) {
285
286
287
288
289
        const QString returnType = _overview->prettyType(type->returnType());
        if (!returnType.isEmpty()) {
            _text.prepend(QLatin1Char(' '));
            _text.prepend(returnType);
        }
290
291
    }

292
    if (_overview->showFunctionSignatures()) {
con's avatar
con committed
293
        Overview argumentText;
294
295
296
297
        argumentText.setShowReturnTypes(true);
        argumentText.setShowArgumentNames(false);
        argumentText.setShowFunctionSignatures(true);

298
        _text += QLatin1Char('(');
299

con's avatar
con committed
300
301
        for (unsigned index = 0; index < type->argumentCount(); ++index) {
            if (index != 0)
302
                _text += QLatin1String(", ");
con's avatar
con committed
303
304

            if (Argument *arg = type->argumentAt(index)->asArgument()) {
305
306
                if (index + 1 == _overview->markedArgument())
                    const_cast<Overview*>(_overview)->setMarkedArgumentBegin(_text.length());
307

Roberto Raggi's avatar
Roberto Raggi committed
308
                const Name *name = 0;
309
310

                if (_overview->showArgumentNames())
con's avatar
con committed
311
                    name = arg->name();
312

313
                _text += argumentText(arg->type(), name);
314

315
316
317
318
319
                if (_overview->showDefaultArguments()) {
                    if (const StringLiteral *initializer = arg->initializer()) {
                        _text += QLatin1String(" =");
                        _text += QString::fromUtf8(initializer->chars(), initializer->size());
                    }
320
321
                }

322
323
                if (index + 1 == _overview->markedArgument())
                    const_cast<Overview*>(_overview)->setMarkedArgumentEnd(_text.length());
con's avatar
con committed
324
325
326
327
            }
        }

        if (type->isVariadic())
328
            _text += QLatin1String("...");
329

330
        _text += QLatin1Char(')');
331
332
        if (type->isConst()) {
            appendSpace();
333
            _text += "const";
334
335
336
        }
        if (type->isVolatile()) {
            appendSpace();
337
            _text += "volatile";
338
339
340
        }
    }
}
con's avatar
con committed
341

342
void TypePrettyPrinter::appendSpace()
343
344
345
{
    if (_text.isEmpty())
        return;
con's avatar
con committed
346

347
    const QChar ch = _text.at(_text.length() - 1);
con's avatar
con committed
348

349
350
    if (ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char(')')
            || ch == QLatin1Char('>'))
351
        _text += QLatin1Char(' ');
con's avatar
con committed
352
353
}

354
void TypePrettyPrinter::prependSpaceUnlessBracket()
355
{
356
357
    if (_text.isEmpty())
        return;
358

359
    const QChar ch = _text.at(0);
360

361
362
    if (ch != QLatin1Char('['))
        _text.prepend(" ");
363
}
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388

void TypePrettyPrinter::prependWordSeparatorSpace()
{
    if (_text.isEmpty())
        return;

    const QChar ch = _text.at(0);

    if (ch.isLetterOrNumber())
        _text.prepend(" ");
}

void TypePrettyPrinter::prependCv(const FullySpecifiedType &ty)
{
    if (ty.isVolatile()) {
        prependWordSeparatorSpace();
        _text.prepend("volatile");
    }

    if (ty.isConst()) {
        prependWordSeparatorSpace();
        _text.prepend("const");
    }
}