OSDN Git Service

4ca7b4202d81fab4710e528be2da214ec6b7928d
[qt-creator-jp/qt-creator-jp.git] / src / libs / cplusplus / TypePrettyPrinter.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
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
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
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.
24 **
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.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "TypePrettyPrinter.h"
35
36 #include "Overview.h"
37 #include <FullySpecifiedType.h>
38 #include <Literals.h>
39 #include <CoreTypes.h>
40 #include <Symbols.h>
41 #include <Scope.h>
42 #include <QStringList>
43 #include <QtDebug>
44
45 using namespace CPlusPlus;
46
47
48 TypePrettyPrinter::TypePrettyPrinter(const Overview *overview)
49     : _overview(overview)
50     , _needsParens(false)
51 { }
52
53 TypePrettyPrinter::~TypePrettyPrinter()
54 { }
55
56 const Overview *TypePrettyPrinter::overview() const
57 { return _overview; }
58
59 QString TypePrettyPrinter::operator()(const FullySpecifiedType &ty)
60 {
61     QString previousName = switchText();
62     bool previousNeedsParens = switchNeedsParens(false);
63     acceptType(ty);
64     switchNeedsParens(previousNeedsParens);
65     return switchText(previousName);
66 }
67
68 QString TypePrettyPrinter::operator()(const FullySpecifiedType &type, const QString &name)
69 {
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(' ');
76         text += _name;
77     } else if (text.isEmpty()) {
78         text = name;
79     }
80     (void) switchName(previousName);
81     return text;
82 }
83
84
85 void TypePrettyPrinter::acceptType(const FullySpecifiedType &ty)
86 {
87     const FullySpecifiedType previousFullySpecifiedType = _fullySpecifiedType;
88     _fullySpecifiedType = ty;
89     accept(ty.type());
90     _fullySpecifiedType = previousFullySpecifiedType;
91 }
92
93 QString TypePrettyPrinter::switchName(const QString &name)
94 {
95     const QString previousName = _name;
96     _name = name;
97     return previousName;
98 }
99
100 QString TypePrettyPrinter::switchText(const QString &name)
101 {
102     QString previousName = _text;
103     _text = name;
104     return previousName;
105 }
106
107 bool TypePrettyPrinter::switchNeedsParens(bool needsParens)
108 {
109     bool previousNeedsParens = _needsParens;
110     _needsParens = needsParens;
111     return previousNeedsParens;
112 }
113
114 void TypePrettyPrinter::visit(UndefinedType *)
115 {
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"));
122     }
123
124     prependCv(_fullySpecifiedType);
125 }
126
127 void TypePrettyPrinter::visit(VoidType *)
128 {
129     prependSpaceUnlessBracket();
130     _text.prepend(QLatin1String("void"));
131     prependCv(_fullySpecifiedType);
132 }
133
134 void TypePrettyPrinter::visit(NamedType *type)
135 {
136     prependSpaceUnlessBracket();
137     _text.prepend(overview()->prettyName(type->name()));
138     prependCv(_fullySpecifiedType);
139 }
140
141 void TypePrettyPrinter::visit(Namespace *type)
142 {
143     _text.prepend(overview()->prettyName(type->name()));
144     prependCv(_fullySpecifiedType);
145 }
146
147 void TypePrettyPrinter::visit(Template *type)
148 {
149     if (Symbol *d = type->declaration()) {
150         if (overview()->showTemplateParameters() && ! _name.isEmpty()) {
151             _name += QLatin1Char('<');
152             for (unsigned index = 0; index < type->templateParameterCount(); ++index) {
153                 if (index)
154                     _name += QLatin1String(", ");
155                 QString arg = overview()->prettyName(type->templateParameterAt(index)->name());
156                 if (arg.isEmpty()) {
157                     arg += QLatin1Char('T');
158                     arg += QString::number(index + 1);
159                 }
160                 _name += arg;
161             }
162             _name += QLatin1Char('>');
163         }
164         acceptType(d->type());
165     }
166     prependCv(_fullySpecifiedType);
167 }
168
169 void TypePrettyPrinter::visit(Class *classTy)
170 {
171     _text.prepend(overview()->prettyName(classTy->name()));
172     prependCv(_fullySpecifiedType);
173 }
174
175
176 void TypePrettyPrinter::visit(Enum *type)
177 {
178     _text.prepend(overview()->prettyName(type->name()));
179     prependCv(_fullySpecifiedType);
180 }
181
182 void TypePrettyPrinter::visit(IntegerType *type)
183 {
184     prependSpaceUnlessBracket();
185     switch (type->kind()) {
186     case IntegerType::Char:
187         _text.prepend(QLatin1String("char"));
188         break;
189     case IntegerType::WideChar:
190         _text.prepend(QLatin1String("wchar_t"));
191         break;
192     case IntegerType::Bool:
193         _text.prepend(QLatin1String("bool"));
194         break;
195     case IntegerType::Short:
196         _text.prepend(QLatin1String("short"));
197         break;
198     case IntegerType::Int:
199         _text.prepend(QLatin1String("int"));
200         break;
201     case IntegerType::Long:
202         _text.prepend(QLatin1String("long"));
203         break;
204     case IntegerType::LongLong:
205         _text.prepend(QLatin1String("long long"));
206         break;
207     }
208
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"));
215     }
216
217     prependCv(_fullySpecifiedType);
218 }
219
220 void TypePrettyPrinter::visit(FloatType *type)
221 {
222     prependSpaceUnlessBracket();
223     switch (type->kind()) {
224     case FloatType::Float:
225         _text.prepend(QLatin1String("float"));
226         break;
227     case FloatType::Double:
228         _text.prepend(QLatin1String("double"));
229         break;
230     case FloatType::LongDouble:
231         _text.prepend(QLatin1String("long double"));
232         break;
233     }
234
235     prependCv(_fullySpecifiedType);
236 }
237
238 void TypePrettyPrinter::visit(PointerToMemberType *type)
239 {
240     prependCv(_fullySpecifiedType);
241     _text.prepend(QLatin1String("::*"));
242     _text.prepend(_overview->prettyName(type->memberName()));
243     _needsParens = true;
244     acceptType(type->elementType());
245 }
246
247 void TypePrettyPrinter::visit(PointerType *type)
248 {
249     if (! _name.isEmpty()) {
250         _text.prepend(_name);
251         _name.clear();
252     }
253     prependCv(_fullySpecifiedType);
254     _text.prepend(QLatin1String("*"));
255     _needsParens = true;
256     acceptType(type->elementType());
257 }
258
259 void TypePrettyPrinter::visit(ReferenceType *type)
260 {
261     if (! _name.isEmpty()) {
262         _text.prepend(_name);
263         _name.clear();
264     }
265     prependCv(_fullySpecifiedType);
266
267     if (_text.startsWith(QLatin1Char('&')))
268         _text.prepend(QLatin1Char(' '));
269
270     if (type->isRvalueReference())
271         _text.prepend(QLatin1String("&&"));
272     else
273         _text.prepend(QLatin1String("&"));
274     _needsParens = true;
275     acceptType(type->elementType());
276 }
277
278 void TypePrettyPrinter::visit(ArrayType *type)
279 {
280     if (_needsParens) {
281         _text.prepend(QLatin1Char('('));
282         _text.append(QLatin1Char(')'));
283         _needsParens = false;
284     } else if (! _name.isEmpty()) {
285         _text.prepend(_name);
286         _name.clear();
287     }
288     _text.append(QLatin1String("[]"));
289
290     acceptType(type->elementType());
291 }
292
293 void TypePrettyPrinter::visit(Function *type)
294 {
295     if (_needsParens) {
296         _text.prepend(QLatin1Char('('));
297         if (! _name.isEmpty()) {
298             appendSpace();
299             _text.append(_name);
300             _name.clear();
301         }
302         _text.append(QLatin1Char(')'));
303         _needsParens = false;
304     } else if (! _name.isEmpty() && _overview->showFunctionSignatures()) {
305         appendSpace();
306         _text.append(_name);
307         _name.clear();
308     }
309
310     if (_overview->showReturnTypes()) {
311         const QString returnType = _overview->prettyType(type->returnType());
312         if (!returnType.isEmpty()) {
313             _text.prepend(QLatin1Char(' '));
314             _text.prepend(returnType);
315         }
316     }
317
318     if (_overview->showFunctionSignatures()) {
319         Overview argumentText;
320         argumentText.setShowReturnTypes(true);
321         argumentText.setShowArgumentNames(false);
322         argumentText.setShowFunctionSignatures(true);
323
324         _text += QLatin1Char('(');
325
326         for (unsigned index = 0; index < type->argumentCount(); ++index) {
327             if (index != 0)
328                 _text += QLatin1String(", ");
329
330             if (Argument *arg = type->argumentAt(index)->asArgument()) {
331                 if (index + 1 == _overview->markedArgument())
332                     const_cast<Overview*>(_overview)->setMarkedArgumentBegin(_text.length());
333
334                 const Name *name = 0;
335
336                 if (_overview->showArgumentNames())
337                     name = arg->name();
338
339                 _text += argumentText(arg->type(), name);
340
341                 if (_overview->showDefaultArguments()) {
342                     if (const StringLiteral *initializer = arg->initializer()) {
343                         _text += QLatin1String(" =");
344                         _text += QString::fromUtf8(initializer->chars(), initializer->size());
345                     }
346                 }
347
348                 if (index + 1 == _overview->markedArgument())
349                     const_cast<Overview*>(_overview)->setMarkedArgumentEnd(_text.length());
350             }
351         }
352
353         if (type->isVariadic())
354             _text += QLatin1String("...");
355
356         _text += QLatin1Char(')');
357         if (type->isConst()) {
358             appendSpace();
359             _text += "const";
360         }
361         if (type->isVolatile()) {
362             appendSpace();
363             _text += "volatile";
364         }
365     }
366 }
367
368 void TypePrettyPrinter::appendSpace()
369 {
370     if (_text.isEmpty())
371         return;
372
373     const QChar ch = _text.at(_text.length() - 1);
374
375     if (ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char(')')
376             || ch == QLatin1Char('>'))
377         _text += QLatin1Char(' ');
378 }
379
380 void TypePrettyPrinter::prependSpaceUnlessBracket()
381 {
382     if (_text.isEmpty())
383         return;
384
385     const QChar ch = _text.at(0);
386
387     if (ch != QLatin1Char('['))
388         _text.prepend(" ");
389 }
390
391 void TypePrettyPrinter::prependWordSeparatorSpace()
392 {
393     if (_text.isEmpty())
394         return;
395
396     const QChar ch = _text.at(0);
397
398     if (ch.isLetterOrNumber())
399         _text.prepend(" ");
400 }
401
402 void TypePrettyPrinter::prependCv(const FullySpecifiedType &ty)
403 {
404     if (ty.isVolatile()) {
405         prependWordSeparatorSpace();
406         _text.prepend("volatile");
407     }
408
409     if (ty.isConst()) {
410         prependWordSeparatorSpace();
411         _text.prepend("const");
412     }
413 }
414