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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

static QString fullyQualifiedName(Symbol *symbol, const Overview *overview)
{
    QStringList nestedNameSpecifier;

    for (Scope *scope = symbol->scope(); scope && scope->enclosingScope();
         scope = scope->enclosingScope())
    {
        Symbol *owner = scope->owner();

        if (! owner) {
            qWarning() << "invalid scope."; // ### better message.
            continue;
        }

        if (! owner->name())
59
            nestedNameSpecifier.prepend(QLatin1String("$anonymous"));
60
61
62
63
64
65
66
67
68
69
70
71
72

        else {
            const QString name = overview->prettyName(owner->name());

            nestedNameSpecifier.prepend(name);
        }
    }

    nestedNameSpecifier.append(overview->prettyName(symbol->name()));

    return nestedNameSpecifier.join(QLatin1String("::"));
}

con's avatar
con committed
73
TypePrettyPrinter::TypePrettyPrinter(const Overview *overview)
74
    : _overview(overview)
con's avatar
con committed
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
{ }

TypePrettyPrinter::~TypePrettyPrinter()
{ }

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

QString TypePrettyPrinter::operator()(const FullySpecifiedType &ty)
{
    QString previousName = switchText();
    acceptType(ty);
    return switchText(previousName).trimmed();
}

QString TypePrettyPrinter::operator()(const FullySpecifiedType &type, const QString &name)
{
    QString previousName = switchName(name);
    QString text = operator()(type);
    if (! _name.isEmpty() && ! text.isEmpty()) {
        QChar ch = text.at(text.size() - 1);
        if (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
            text += QLatin1Char(' ');
        text += _name;
99
100
    } else if (text.isEmpty()) {
        text = name;
con's avatar
con committed
101
102
103
104
105
106
107
108
109
    }
    (void) switchName(previousName);
    return text;
}


void TypePrettyPrinter::acceptType(const FullySpecifiedType &ty)
{
    if (ty.isSigned())
110
        _text += QLatin1String("signed ");
111
112

    else if (ty.isUnsigned())
113
        _text += QLatin1String("unsigned ");
114
115
116

    const FullySpecifiedType previousFullySpecifiedType = _fullySpecifiedType;
    _fullySpecifiedType = ty;
con's avatar
con committed
117
    accept(ty.type());
118
    _fullySpecifiedType = previousFullySpecifiedType;
con's avatar
con committed
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
}

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;
}

135
QList<FullySpecifiedType> TypePrettyPrinter::switchPtrOperators(const QList<FullySpecifiedType> &ptrOperators)
con's avatar
con committed
136
{
137
    QList<FullySpecifiedType> previousPtrOperators = _ptrOperators;
con's avatar
con committed
138
139
140
141
142
143
    _ptrOperators = ptrOperators;
    return previousPtrOperators;
}

void TypePrettyPrinter::applyPtrOperators(bool wantSpace)
{
144
145
146
    if (wantSpace && !_ptrOperators.isEmpty())
        space();

con's avatar
con committed
147
    for (int i = _ptrOperators.size() - 1; i != -1; --i) {
148
        const FullySpecifiedType op = _ptrOperators.at(i);
con's avatar
con committed
149

150
        if (op->isPointerType()) {
151
            _text += QLatin1Char('*');
152
            outCV(op);
con's avatar
con committed
153
        } else if (op->isReferenceType()) {
154
            _text += QLatin1Char('&');
155
156
        } else if (const PointerToMemberType *memPtrTy = op->asPointerToMemberType()) {
            space();
157
158
            _text += _overview->prettyName(memPtrTy->memberName());
            _text += QLatin1Char('*');
159
            outCV(op);
con's avatar
con committed
160
161
162
163
        }
    }
}

164
165
166
167
168
void TypePrettyPrinter::visit(UndefinedType *)
{
    applyPtrOperators();
}

con's avatar
con committed
169
170
void TypePrettyPrinter::visit(VoidType *)
{
171
    _text += QLatin1String("void");
172
173
    applyPtrOperators();
}
con's avatar
con committed
174

175
176
void TypePrettyPrinter::visit(NamedType *type)
{
177
    _text += overview()->prettyName(type->name());
178
179
180
181
182
183
184
185
186
    applyPtrOperators();
}

void TypePrettyPrinter::visit(Namespace *type)
{
    _text += overview()->prettyName(type->name());
    applyPtrOperators();
}

187
void TypePrettyPrinter::visit(Class *classTy)
188
{
189
190
191
192
193
194
    if (overview()->showFullyQualifiedNames())
        _text += fullyQualifiedName(classTy, overview());

    else
        _text += overview()->prettyName(classTy->name());

195
196
197
198
199
200
    applyPtrOperators();
}


void TypePrettyPrinter::visit(Enum *type)
{
201
202
203
204
205
206
    if (overview()->showFullyQualifiedNames())
        _text += fullyQualifiedName(type, overview());

    else
        _text += overview()->prettyName(type->name());

con's avatar
con committed
207
208
209
210
211
212
213
    applyPtrOperators();
}

void TypePrettyPrinter::visit(IntegerType *type)
{
    switch (type->kind()) {
    case IntegerType::Char:
214
        _text += QLatin1String("char");
con's avatar
con committed
215
216
        break;
    case IntegerType::WideChar:
217
        _text += QLatin1String("wchar_t");
con's avatar
con committed
218
219
        break;
    case IntegerType::Bool:
220
        _text += QLatin1String("bool");
con's avatar
con committed
221
222
        break;
    case IntegerType::Short:
223
        _text += QLatin1String("short");
con's avatar
con committed
224
225
        break;
    case IntegerType::Int:
226
        _text += QLatin1String("int");
con's avatar
con committed
227
228
        break;
    case IntegerType::Long:
229
        _text += QLatin1String("long");
con's avatar
con committed
230
231
        break;
    case IntegerType::LongLong:
232
        _text += QLatin1String("long long");
con's avatar
con committed
233
234
235
236
237
238
239
240
241
242
        break;
    }

    applyPtrOperators();
}

void TypePrettyPrinter::visit(FloatType *type)
{
    switch (type->kind()) {
    case FloatType::Float:
243
        _text += QLatin1String("float");
con's avatar
con committed
244
245
        break;
    case FloatType::Double:
246
        _text += QLatin1String("double");
con's avatar
con committed
247
248
        break;
    case FloatType::LongDouble:
249
        _text += QLatin1String("long double");
con's avatar
con committed
250
251
252
253
254
255
256
257
        break;
    }

    applyPtrOperators();
}

void TypePrettyPrinter::visit(PointerToMemberType *type)
{
258
259
260
261
    outCV(type->elementType());
    space();

    _ptrOperators.append(_fullySpecifiedType);
con's avatar
con committed
262
263
264
265
266
    acceptType(type->elementType());
}

void TypePrettyPrinter::visit(PointerType *type)
{
267
268
269
270
    outCV(type->elementType());
    space();

    _ptrOperators.append(_fullySpecifiedType);
con's avatar
con committed
271
272
273
274
275
    acceptType(type->elementType());
}

void TypePrettyPrinter::visit(ReferenceType *type)
{
276
277
278
279
    outCV(type->elementType());
    space();

    _ptrOperators.append(_fullySpecifiedType);
con's avatar
con committed
280
281
282
283
284
    acceptType(type->elementType());
}

void TypePrettyPrinter::visit(ArrayType *type)
{
285
    _text += overview()->prettyType(type->elementType());
con's avatar
con committed
286
    if (! _ptrOperators.isEmpty()) {
287
        _text += QLatin1Char('(');
con's avatar
con committed
288
289
        applyPtrOperators(false);
        if (! _name.isEmpty()) {
290
            _text += _name;
con's avatar
con committed
291
292
            _name.clear();
        }
293
        _text += QLatin1Char(')');
con's avatar
con committed
294
    }
295
    _text += QLatin1String("[]");
con's avatar
con committed
296
297
298
299
}

void TypePrettyPrinter::visit(Function *type)
{
300
    if (_overview->showReturnTypes())
301
        _text += _overview->prettyType(type->returnType());
con's avatar
con committed
302
303

    if (! _ptrOperators.isEmpty()) {
304
        _text += QLatin1Char('(');
con's avatar
con committed
305
        applyPtrOperators(false);
306

con's avatar
con committed
307
308
309
310
        if (! _name.isEmpty()) {
            _text += _name;
            _name.clear();
        }
311

312
        _text += QLatin1Char(')');
313

314
315
    } else if (! _name.isEmpty() && _overview->showFunctionSignatures()) {
        space();
316
        _text += _name;
con's avatar
con committed
317
318
319
        _name.clear();
    }

320
    if (_overview->showFunctionSignatures()) {
con's avatar
con committed
321
        Overview argumentText;
322
323
324
325
        argumentText.setShowReturnTypes(true);
        argumentText.setShowArgumentNames(false);
        argumentText.setShowFunctionSignatures(true);

326
        _text += QLatin1Char('(');
327

con's avatar
con committed
328
329
        for (unsigned index = 0; index < type->argumentCount(); ++index) {
            if (index != 0)
330
                _text += QLatin1String(", ");
con's avatar
con committed
331
332

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

Roberto Raggi's avatar
Roberto Raggi committed
336
                const Name *name = 0;
337
338

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

341
                _text += argumentText(arg->type(), name);
342

343
344
345
346
347
                if (_overview->showDefaultArguments()) {
                    if (const StringLiteral *initializer = arg->initializer()) {
                        _text += QLatin1String(" =");
                        _text += QString::fromUtf8(initializer->chars(), initializer->size());
                    }
348
349
                }

350
351
                if (index + 1 == _overview->markedArgument())
                    const_cast<Overview*>(_overview)->setMarkedArgumentEnd(_text.length());
con's avatar
con committed
352
353
354
355
            }
        }

        if (type->isVariadic())
356
            _text += QLatin1String("...");
357

358
        _text += QLatin1Char(')');
359
360
        if (type->isConst() && type->isVolatile()) {
            space();
361
            _text += "const volatile";
362
363
        } else if (type->isConst()) {
            space();
364
            _text += "const";
365
366
        } else if (type->isVolatile()) {
            space();
367
            _text += "volatile";
368
369
370
        }
    }
}
con's avatar
con committed
371

372
373
374
375
void TypePrettyPrinter::space()
{
    if (_text.isEmpty())
        return;
con's avatar
con committed
376

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

379
380
    if (ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char(')')
            || ch == QLatin1Char('>'))
381
        _text += QLatin1Char(' ');
con's avatar
con committed
382
383
}

384
385
386
void TypePrettyPrinter::outCV(const FullySpecifiedType &ty)
{
    if (ty.isConst() && ty.isVolatile())
387
        _text += QLatin1String("const volatile");
388
389

    else if (ty.isConst())
390
        _text += QLatin1String("const");
391
392

    else if (ty.isVolatile())
393
        _text += QLatin1String("volatile");
394
}