Warning: That file was not part of the compilation database. It may have many parsing errors.

1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** 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.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*
43 cppcodemarker.cpp
44*/
45
46#include "atom.h"
47#include "cppcodemarker.h"
48#include "node.h"
49#include "text.h"
50#include "tree.h"
51
52#include <ctype.h>
53
54QT_BEGIN_NAMESPACE
55
56/*!
57 The constructor does nothing.
58 */
59CppCodeMarker::CppCodeMarker()
60{
61 // nothing.
62}
63
64/*!
65 The destructor does nothing.
66 */
67CppCodeMarker::~CppCodeMarker()
68{
69 // nothing.
70}
71
72/*!
73 Returns true.
74 */
75bool CppCodeMarker::recognizeCode(const QString & /* code */)
76{
77 return true;
78}
79
80/*!
81 Returns true if \a ext is any of a list of file extensions
82 for the C++ language.
83 */
84bool CppCodeMarker::recognizeExtension(const QString& ext)
85{
86 return ext == "c" ||
87 ext == "c++" ||
88 ext == "cc" ||
89 ext == "cpp" ||
90 ext == "cxx" ||
91 ext == "ch" ||
92 ext == "h" ||
93 ext == "h++" ||
94 ext == "hh" ||
95 ext == "hpp" ||
96 ext == "hxx";
97}
98
99/*!
100 Returns true if \a lang is either "C" or "Cpp".
101 */
102bool CppCodeMarker::recognizeLanguage(const QString &lang)
103{
104 return lang == "C" || lang == "Cpp";
105}
106
107/*!
108 Returns the type of atom used to represent C++ code in the documentation.
109*/
110Atom::Type CppCodeMarker::atomType() const
111{
112 return Atom::Code;
113}
114
115/*!
116 Returns the \a node name, or "()" if \a node is a
117 Node::Function node.
118 */
119QString CppCodeMarker::plainName(const Node *node)
120{
121 QString name = node->name();
122 if (node->type() == Node::Function)
123 name += "()";
124 return name;
125}
126
127QString CppCodeMarker::plainFullName(const Node *node, const Node *relative)
128{
129 if (node->name().isEmpty()) {
130 return "global";
131 }
132 else {
133 QString fullName;
134 while (node) {
135 fullName.prepend(plainName(node));
136 if (node->parent() == relative || node->parent()->name().isEmpty())
137 break;
138 fullName.prepend("::");
139 node = node->parent();
140 }
141 return fullName;
142 }
143}
144
145QString CppCodeMarker::markedUpCode(const QString &code,
146 const Node *relative,
147 const Location &location)
148{
149 return addMarkUp(code, relative, location);
150}
151
152QString CppCodeMarker::markedUpSynopsis(const Node *node,
153 const Node * /* relative */,
154 SynopsisStyle style)
155{
156 const int MaxEnumValues = 6;
157 const FunctionNode *func;
158 const PropertyNode *property;
159 const VariableNode *variable;
160 const EnumNode *enume;
161 const TypedefNode *typedeff;
162 QString synopsis;
163 QString extra;
164 QString name;
165
166 name = taggedNode(node);
167 if (style != Detailed)
168 name = linkTag(node, name);
169 name = "<@name>" + name + "</@name>";
170
171 if (style == Detailed && !node->parent()->name().isEmpty() &&
172 node->type() != Node::Property)
173 name.prepend(taggedNode(node->parent()) + "::");
174
175 switch (node->type()) {
176 case Node::Namespace:
177 synopsis = "namespace " + name;
178 break;
179 case Node::Class:
180 synopsis = "class " + name;
181 break;
182 case Node::Function:
183 case Node::QmlSignal:
184 case Node::QmlMethod:
185 func = (const FunctionNode *) node;
186 if (style != SeparateList && !func->returnType().isEmpty())
187 synopsis = typified(func->returnType()) + " ";
188 synopsis += name;
189 if (func->metaness() != FunctionNode::MacroWithoutParams) {
190 synopsis += " (";
191 if (!func->parameters().isEmpty()) {
192 synopsis += " ";
193 QList<Parameter>::ConstIterator p = func->parameters().begin();
194 while (p != func->parameters().end()) {
195 if (p != func->parameters().begin())
196 synopsis += ", ";
197 synopsis += typified((*p).leftType());
198 if (style != SeparateList && !(*p).name().isEmpty())
199 synopsis +=
200 " <@param>" + protect((*p).name()) + "</@param>";
201 synopsis += protect((*p).rightType());
202 if (style != SeparateList && !(*p).defaultValue().isEmpty())
203 synopsis += " = " + protect((*p).defaultValue());
204 ++p;
205 }
206 synopsis += " ";
207 }
208 synopsis += ")";
209 }
210 if (func->isConst())
211 synopsis += " const";
212
213 if (style == Summary || style == Accessors) {
214 if (func->virtualness() != FunctionNode::NonVirtual)
215 synopsis.prepend("virtual ");
216 if (func->virtualness() == FunctionNode::PureVirtual)
217 synopsis.append(" = 0");
218 }
219 else if (style == SeparateList) {
220 if (!func->returnType().isEmpty() && func->returnType() != "void")
221 synopsis += " : " + typified(func->returnType());
222 }
223 else {
224 QStringList bracketed;
225 if (func->isStatic()) {
226 bracketed += "static";
227 }
228 else if (func->virtualness() != FunctionNode::NonVirtual) {
229 if (func->virtualness() == FunctionNode::PureVirtual)
230 bracketed += "pure";
231 bracketed += "virtual";
232 }
233
234 if (func->access() == Node::Protected) {
235 bracketed += "protected";
236 }
237 else if (func->access() == Node::Private) {
238 bracketed += "private";
239 }
240
241 if (func->metaness() == FunctionNode::Signal) {
242 bracketed += "signal";
243 }
244 else if (func->metaness() == FunctionNode::Slot) {
245 bracketed += "slot";
246 }
247 if (!bracketed.isEmpty())
248 extra += " [" + bracketed.join(" ") + "]";
249 }
250 break;
251 case Node::Enum:
252 enume = static_cast<const EnumNode *>(node);
253 synopsis = "enum " + name;
254 if (style == Summary) {
255 synopsis += " { ";
256
257 QStringList documentedItems = enume->doc().enumItemNames();
258 if (documentedItems.isEmpty()) {
259 foreach (const EnumItem &item, enume->items())
260 documentedItems << item.name();
261 }
262 QStringList omitItems = enume->doc().omitEnumItemNames();
263 foreach (const QString &item, omitItems)
264 documentedItems.removeAll(item);
265
266 if (documentedItems.size() <= MaxEnumValues) {
267 for (int i = 0; i < documentedItems.size(); ++i) {
268 if (i != 0)
269 synopsis += ", ";
270 synopsis += documentedItems.at(i);
271 }
272 }
273 else {
274 for (int i = 0; i < documentedItems.size(); ++i) {
275 if (i < MaxEnumValues-2 || i == documentedItems.size()-1) {
276 if (i != 0)
277 synopsis += ", ";
278 synopsis += documentedItems.at(i);
279 }
280 else if (i == MaxEnumValues - 1) {
281 synopsis += ", ...";
282 }
283 }
284 }
285 if (!documentedItems.isEmpty())
286 synopsis += " ";
287 synopsis += "}";
288 }
289 break;
290 case Node::Typedef:
291 typedeff = static_cast<const TypedefNode *>(node);
292 if (typedeff->associatedEnum()) {
293 synopsis = "flags " + name;
294 }
295 else {
296 synopsis = "typedef " + name;
297 }
298 break;
299 case Node::Property:
300 property = static_cast<const PropertyNode *>(node);
301 synopsis = name + " : " + typified(property->qualifiedDataType());
302 break;
303 case Node::Variable:
304 variable = static_cast<const VariableNode *>(node);
305 if (style == SeparateList) {
306 synopsis = name + " : " + typified(variable->dataType());
307 }
308 else {
309 synopsis = typified(variable->leftType()) + " " +
310 name + protect(variable->rightType());
311 }
312 break;
313 default:
314 synopsis = name;
315 }
316
317 if (style == Summary) {
318 if (node->status() == Node::Preliminary) {
319 extra += " (preliminary)";
320 }
321 else if (node->status() == Node::Deprecated) {
322 extra += " (deprecated)";
323 }
324 else if (node->status() == Node::Obsolete) {
325 extra += " (obsolete)";
326 }
327 }
328
329 if (!extra.isEmpty()) {
330 extra.prepend("<@extra>");
331 extra.append("</@extra>");
332 }
333 return synopsis + extra;
334}
335
336#ifdef QDOC_QML
337/*!
338 */
339QString CppCodeMarker::markedUpQmlItem(const Node* node, bool summary)
340{
341 QString name = taggedQmlNode(node);
342 if (summary) {
343 name = linkTag(node,name);
344 } else if (node->type() == Node::QmlProperty) {
345 const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(node);
346 if (pn->isAttached())
347 name.prepend(pn->element() + QLatin1Char('.'));
348 }
349 name = "<@name>" + name + "</@name>";
350 QString synopsis = name;
351 if (node->type() == Node::QmlProperty) {
352 const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(node);
353 synopsis += " : " + typified(pn->dataType());
354 }
355
356 QString extra;
357 if (summary) {
358 if (node->status() == Node::Preliminary) {
359 extra += " (preliminary)";
360 }
361 else if (node->status() == Node::Deprecated) {
362 extra += " (deprecated)";
363 }
364 else if (node->status() == Node::Obsolete) {
365 extra += " (obsolete)";
366 }
367 }
368
369 if (!extra.isEmpty()) {
370 extra.prepend("<@extra>");
371 extra.append("</@extra>");
372 }
373 return synopsis + extra;
374}
375#endif
376
377QString CppCodeMarker::markedUpName(const Node *node)
378{
379 QString name = linkTag(node, taggedNode(node));
380 if (node->type() == Node::Function)
381 name += "()";
382 return name;
383}
384
385QString CppCodeMarker::markedUpFullName(const Node *node, const Node *relative)
386{
387 if (node->name().isEmpty()) {
388 return "global";
389 }
390 else {
391 QString fullName;
392 for (;;) {
393 fullName.prepend(markedUpName(node));
394 if (node->parent() == relative || node->parent()->name().isEmpty())
395 break;
396 fullName.prepend("<@op>::</@op>");
397 node = node->parent();
398 }
399 return fullName;
400 }
401}
402
403QString CppCodeMarker::markedUpEnumValue(const QString &enumValue,
404 const Node *relative)
405{
406 const Node *node = relative->parent();
407 QString fullName;
408 while (node->parent()) {
409 fullName.prepend(markedUpName(node));
410 if (node->parent() == relative || node->parent()->name().isEmpty())
411 break;
412 fullName.prepend("<@op>::</@op>");
413 node = node->parent();
414 }
415 if (!fullName.isEmpty())
416 fullName.append("<@op>::</@op>");
417 fullName.append(enumValue);
418 return fullName;
419}
420
421QString CppCodeMarker::markedUpIncludes(const QStringList& includes)
422{
423 QString code;
424
425 QStringList::ConstIterator inc = includes.begin();
426 while (inc != includes.end()) {
427 code += "<@preprocessor>#include &lt;<@headerfile>" + *inc + "</@headerfile>&gt;</@preprocessor>\n";
428 ++inc;
429 }
430 return code;
431}
432
433QString CppCodeMarker::functionBeginRegExp(const QString& funcName)
434{
435 return "^" + QRegExp::escape(funcName) + "$";
436
437}
438
439QString CppCodeMarker::functionEndRegExp(const QString& /* funcName */)
440{
441 return "^\\}$";
442}
443
444QList<Section> CppCodeMarker::sections(const InnerNode *inner,
445 SynopsisStyle style,
446 Status status)
447{
448 QList<Section> sections;
449
450 if (inner->type() == Node::Class) {
451 const ClassNode *classe = static_cast<const ClassNode *>(inner);
452
453 if (style == Summary) {
454 FastSection privateFunctions(classe,
455 "Private Functions",
456 "",
457 "private function",
458 "private functions");
459 FastSection privateSlots(classe, "Private Slots", "", "private slot", "private slots");
460 FastSection privateTypes(classe, "Private Types", "", "private type", "private types");
461 FastSection protectedFunctions(classe,
462 "Protected Functions",
463 "",
464 "protected function",
465 "protected functions");
466 FastSection protectedSlots(classe,
467 "Protected Slots",
468 "",
469 "protected slot",
470 "protected slots");
471 FastSection protectedTypes(classe,
472 "Protected Types",
473 "",
474 "protected type",
475 "protected types");
476 FastSection protectedVariables(classe,
477 "Protected Variables",
478 "",
479 "protected type",
480 "protected variables");
481 FastSection publicFunctions(classe,
482 "Public Functions",
483 "",
484 "public function",
485 "public functions");
486 FastSection publicSignals(classe, "Signals", "", "signal", "signals");
487 FastSection publicSlots(classe, "Public Slots", "", "public slot", "public slots");
488 FastSection publicTypes(classe, "Public Types", "", "public type", "public types");
489 FastSection publicVariables(classe,
490 "Public Variables",
491 "",
492 "public variable",
493 "public variables");
494 FastSection properties(classe, "Properties", "", "property", "properties");
495 FastSection relatedNonMembers(classe,
496 "Related Non-Members",
497 "",
498 "related non-member",
499 "related non-members");
500 FastSection staticPrivateMembers(classe,
501 "Static Private Members",
502 "",
503 "static private member",
504 "static private members");
505 FastSection staticProtectedMembers(classe,
506 "Static Protected Members",
507 "",
508 "static protected member",
509 "static protected members");
510 FastSection staticPublicMembers(classe,
511 "Static Public Members",
512 "",
513 "static public member",
514 "static public members");
515 FastSection macros(inner, "Macros", "", "macro", "macros");
516
517 NodeList::ConstIterator r = classe->relatedNodes().begin();
518 while (r != classe->relatedNodes().end()) {
519 if ((*r)->type() == Node::Function) {
520 FunctionNode *func = static_cast<FunctionNode *>(*r);
521 if (func->isMacro())
522 insert(macros, *r, style, status);
523 else
524 insert(relatedNonMembers, *r, style, status);
525 }
526 else {
527 insert(relatedNonMembers, *r, style, status);
528 }
529 ++r;
530 }
531
532 QStack<const ClassNode *> stack;
533 stack.push(classe);
534
535 while (!stack.isEmpty()) {
536 const ClassNode *ancestorClass = stack.pop();
537
538 NodeList::ConstIterator c = ancestorClass->childNodes().begin();
539 while (c != ancestorClass->childNodes().end()) {
540 bool isSlot = false;
541 bool isSignal = false;
542 bool isStatic = false;
543 if ((*c)->type() == Node::Function) {
544 const FunctionNode *func = (const FunctionNode *) *c;
545 isSlot = (func->metaness() == FunctionNode::Slot);
546 isSignal = (func->metaness() == FunctionNode::Signal);
547 isStatic = func->isStatic();
548 }
549 else if ((*c)->type() == Node::Variable) {
550 const VariableNode *var = static_cast<const VariableNode *>(*c);
551 isStatic = var->isStatic();
552 }
553
554 switch ((*c)->access()) {
555 case Node::Public:
556 if (isSlot) {
557 insert(publicSlots, *c, style, status);
558 }
559 else if (isSignal) {
560 insert(publicSignals, *c, style, status);
561 }
562 else if (isStatic) {
563 if ((*c)->type() != Node::Variable
564 || !(*c)->doc().isEmpty())
565 insert(staticPublicMembers,*c,style,status);
566 }
567 else if ((*c)->type() == Node::Property) {
568 insert(properties, *c, style, status);
569 }
570 else if ((*c)->type() == Node::Variable) {
571 if (!(*c)->doc().isEmpty())
572 insert(publicVariables, *c, style, status);
573 }
574 else if ((*c)->type() == Node::Function) {
575 if (!insertReimpFunc(publicFunctions,*c,status))
576 insert(publicFunctions, *c, style, status);
577 }
578 else {
579 insert(publicTypes, *c, style, status);
580 }
581 break;
582 case Node::Protected:
583 if (isSlot) {
584 insert(protectedSlots, *c, style, status);
585 }
586 else if (isStatic) {
587 if ((*c)->type() != Node::Variable
588 || !(*c)->doc().isEmpty())
589 insert(staticProtectedMembers,*c,style,status);
590 }
591 else if ((*c)->type() == Node::Variable) {
592 if (!(*c)->doc().isEmpty())
593 insert(protectedVariables,*c,style,status);
594 }
595 else if ((*c)->type() == Node::Function) {
596 if (!insertReimpFunc(protectedFunctions,*c,status))
597 insert(protectedFunctions, *c, style, status);
598 }
599 else {
600 insert(protectedTypes, *c, style, status);
601 }
602 break;
603 case Node::Private:
604 if (isSlot) {
605 insert(privateSlots, *c, style, status);
606 }
607 else if (isStatic) {
608 if ((*c)->type() != Node::Variable
609 || !(*c)->doc().isEmpty())
610 insert(staticPrivateMembers,*c,style,status);
611 }
612 else if ((*c)->type() == Node::Function) {
613 if (!insertReimpFunc(privateFunctions,*c,status))
614 insert(privateFunctions, *c, style, status);
615 }
616 else {
617 insert(privateTypes,*c,style,status);
618 }
619 }
620 ++c;
621 }
622
623 QList<RelatedClass>::ConstIterator r =
624 ancestorClass->baseClasses().begin();
625 while (r != ancestorClass->baseClasses().end()) {
626 stack.prepend((*r).node);
627 ++r;
628 }
629 }
630
631 append(sections, publicTypes);
632 append(sections, properties);
633 append(sections, publicFunctions);
634 append(sections, publicSlots);
635 append(sections, publicSignals);
636 append(sections, publicVariables);
637 append(sections, staticPublicMembers);
638 append(sections, protectedTypes);
639 append(sections, protectedFunctions);
640 append(sections, protectedSlots);
641 append(sections, protectedVariables);
642 append(sections, staticProtectedMembers);
643 append(sections, privateTypes);
644 append(sections, privateFunctions);
645 append(sections, privateSlots);
646 append(sections, staticPrivateMembers);
647 append(sections, relatedNonMembers);
648 append(sections, macros);
649 }
650 else if (style == Detailed) {
651 FastSection memberFunctions(classe,"Member Function Documentation","func","member","members");
652 FastSection memberTypes(classe,"Member Type Documentation","types","member","members");
653 FastSection memberVariables(classe,"Member Variable Documentation","vars","member","members");
654 FastSection properties(classe,"Property Documentation","prop","member","members");
655 FastSection relatedNonMembers(classe,"Related Non-Members","relnonmem","member","members");
656 FastSection macros(classe,"Macro Documentation","macros","member","members");
657
658 NodeList::ConstIterator r = classe->relatedNodes().begin();
659 while (r != classe->relatedNodes().end()) {
660 if ((*r)->type() == Node::Function) {
661 FunctionNode *func = static_cast<FunctionNode *>(*r);
662 if (func->isMacro())
663 insert(macros, *r, style, status);
664 else
665 insert(relatedNonMembers, *r, style, status);
666 }
667 else {
668 insert(relatedNonMembers, *r, style, status);
669 }
670 ++r;
671 }
672
673 NodeList::ConstIterator c = classe->childNodes().begin();
674 while (c != classe->childNodes().end()) {
675 if ((*c)->type() == Node::Enum ||
676 (*c)->type() == Node::Typedef) {
677 insert(memberTypes, *c, style, status);
678 }
679 else if ((*c)->type() == Node::Property) {
680 insert(properties, *c, style, status);
681 }
682 else if ((*c)->type() == Node::Variable) {
683 if (!(*c)->doc().isEmpty())
684 insert(memberVariables, *c, style, status);
685 }
686 else if ((*c)->type() == Node::Function) {
687 FunctionNode *function = static_cast<FunctionNode *>(*c);
688 if (!function->associatedProperty())
689 insert(memberFunctions, function, style, status);
690 }
691 ++c;
692 }
693
694 append(sections, memberTypes);
695 append(sections, properties);
696 append(sections, memberFunctions);
697 append(sections, memberVariables);
698 append(sections, relatedNonMembers);
699 append(sections, macros);
700 }
701 else {
702 FastSection all(classe,"","","member","members");
703
704 QStack<const ClassNode *> stack;
705 stack.push(classe);
706
707 while (!stack.isEmpty()) {
708 const ClassNode *ancestorClass = stack.pop();
709
710 NodeList::ConstIterator c = ancestorClass->childNodes().begin();
711 while (c != ancestorClass->childNodes().end()) {
712 if ((*c)->access() != Node::Private &&
713 (*c)->type() != Node::Property)
714 insert(all, *c, style, status);
715 ++c;
716 }
717
718 QList<RelatedClass>::ConstIterator r =
719 ancestorClass->baseClasses().begin();
720 while (r != ancestorClass->baseClasses().end()) {
721 stack.prepend((*r).node);
722 ++r;
723 }
724 }
725 append(sections, all);
726 }
727 }
728 else {
729 if (style == Summary || style == Detailed) {
730 FastSection namespaces(inner,
731 "Namespaces",
732 style == Detailed ? "nmspace" : "",
733 "namespace",
734 "namespaces");
735 FastSection classes(inner,
736 "Classes",
737 style == Detailed ? "classes" : "",
738 "class",
739 "classes");
740 FastSection types(inner,
741 style == Summary ? "Types" : "Type Documentation",
742 style == Detailed ? "types" : "",
743 "type",
744 "types");
745 FastSection functions(inner,
746 style == Summary ?
747 "Functions" : "Function Documentation",
748 style == Detailed ? "func" : "",
749 "function",
750 "functions");
751 FastSection macros(inner,
752 style == Summary ?
753 "Macros" : "Macro Documentation",
754 style == Detailed ? "macros" : "",
755 "macro",
756 "macros");
757
758 NodeList nodeList = inner->childNodes();
759 nodeList += inner->relatedNodes();
760
761 NodeList::ConstIterator n = nodeList.begin();
762 while (n != nodeList.end()) {
763 switch ((*n)->type()) {
764 case Node::Namespace:
765 insert(namespaces, *n, style, status);
766 break;
767 case Node::Class:
768 insert(classes, *n, style, status);
769 break;
770 case Node::Enum:
771 case Node::Typedef:
772 insert(types, *n, style, status);
773 break;
774 case Node::Function:
775 {
776 FunctionNode *func = static_cast<FunctionNode *>(*n);
777 if (func->isMacro())
778 insert(macros, *n, style, status);
779 else
780 insert(functions, *n, style, status);
781 }
782 break;
783 default:
784 ;
785 }
786 ++n;
787 }
788 append(sections, namespaces);
789 append(sections, classes);
790 append(sections, types);
791 append(sections, functions);
792 append(sections, macros);
793 }
794 }
795
796 return sections;
797}
798
799const Node *CppCodeMarker::resolveTarget(const QString& target,
800 const Tree* tree,
801 const Node* relative,
802 const Node* self)
803{
804 if (target.endsWith("()")) {
805 const FunctionNode *func;
806 QString funcName = target;
807 funcName.chop(2);
808
809 QStringList path = funcName.split("::");
810 if ((func = tree->findFunctionNode(path,
811 relative,
812 Tree::SearchBaseClasses))
813 && func->metaness() != FunctionNode::MacroWithoutParams)
814 return func;
815 }
816 else if (target.contains("#")) {
817 // ### this doesn't belong here; get rid of TargetNode hack
818 int hashAt = target.indexOf("#");
819 QString link = target.left(hashAt);
820 QString ref = target.mid(hashAt + 1);
821 const Node *node;
822 if (link.isEmpty()) {
823 node = relative;
824 }
825 else {
826 QStringList path(link);
827 node = tree->findNode(path, tree->root(), Tree::SearchBaseClasses);
828 }
829 if (node && node->isInnerNode()) {
830 const Atom *atom = node->doc().body().firstAtom();
831 while (atom) {
832 if (atom->type() == Atom::Target && atom->string() == ref) {
833 Node *parentNode = const_cast<Node *>(node);
834 return new TargetNode(static_cast<InnerNode*>(parentNode),
835 ref);
836 }
837 atom = atom->next();
838 }
839 }
840 }
841 else {
842 QStringList path = target.split("::");
843 const Node *node;
844 int flags = Tree::SearchBaseClasses |
845 Tree::SearchEnumValues |
846 Tree::NonFunction;
847 if ((node = tree->findNode(path,
848 relative,
849 flags,
850 self)))
851 return node;
852 }
853 return 0;
854}
855
856static const char * const typeTable[] = {
857 "bool", "char", "double", "float", "int", "long", "short",
858 "signed", "unsigned", "uint", "ulong", "ushort", "uchar", "void",
859 "qlonglong", "qulonglong",
860 "qint", "qint8", "qint16", "qint32", "qint64",
861 "quint", "quint8", "quint16", "quint32", "quint64",
862 "qreal", "cond", 0
863};
864
865static const char * const keywordTable[] = {
866 "and", "and_eq", "asm", "auto", "bitand", "bitor", "break",
867 "case", "catch", "class", "compl", "const", "const_cast",
868 "continue", "default", "delete", "do", "dynamic_cast", "else",
869 "enum", "explicit", "export", "extern", "false", "for", "friend",
870 "goto", "if", "include", "inline", "monitor", "mutable", "namespace",
871 "new", "not", "not_eq", "operator", "or", "or_eq", "private", "protected",
872 "public", "register", "reinterpret_cast", "return", "sizeof",
873 "static", "static_cast", "struct", "switch", "template", "this",
874 "throw", "true", "try", "typedef", "typeid", "typename", "union",
875 "using", "virtual", "volatile", "wchar_t", "while", "xor",
876 "xor_eq", "synchronized",
877 // Qt specific
878 "signals", "slots", "emit", 0
879};
880
881/*
882 @char
883 @class
884 @comment
885 @function
886 @keyword
887 @number
888 @op
889 @preprocessor
890 @string
891 @type
892*/
893
894QString CppCodeMarker::addMarkUp(const QString &in,
895 const Node * /* relative */,
896 const Location & /* location */)
897{
898#define readChar() \
899 ch = (i < (int)code.length()) ? code[i++].cell() : EOF
900
901 QString code = in;
902
903 QMap<QString, int> types;
904 QMap<QString, int> keywords;
905 int j = 0;
906 while (typeTable[j] != 0) {
907 types.insert(QString(typeTable[j]), 0);
908 j++;
909 }
910 j = 0;
911 while (keywordTable[j] != 0) {
912 keywords.insert(QString(keywordTable[j]), 0);
913 j++;
914 }
915
916 QString out("");
917 int braceDepth = 0;
918 int parenDepth = 0;
919 int i = 0;
920 int start = 0;
921 int finish = 0;
922 QChar ch;
923 QRegExp classRegExp("Qt?(?:[A-Z3]+[a-z][A-Za-z]*|t)");
924 QRegExp functionRegExp("q([A-Z][a-z]+)+");
925
926 readChar();
927
928 while (ch != EOF) {
929 QString tag;
930 bool target = false;
931
932 if (ch.isLetter() || ch == '_') {
933 QString ident;
934 do {
935 ident += ch;
936 finish = i;
937 readChar();
938 } while (ch.isLetterOrNumber() || ch == '_');
939
940 if (classRegExp.exactMatch(ident)) {
941 tag = QLatin1String("type");
942 } else if (functionRegExp.exactMatch(ident)) {
943 tag = QLatin1String("func");
944 target = true;
945 } else if (types.contains(ident)) {
946 tag = QLatin1String("type");
947 } else if (keywords.contains(ident)) {
948 tag = QLatin1String("keyword");
949 } else if (braceDepth == 0 && parenDepth == 0) {
950 if (QString(code.unicode() + i - 1, code.length() - (i - 1))
951 .indexOf(QRegExp(QLatin1String("^\\s*\\("))) == 0)
952 tag = QLatin1String("func");
953 target = true;
954 }
955 } else if (ch.isDigit()) {
956 do {
957 finish = i;
958 readChar();
959 } while (ch.isLetterOrNumber() || ch == '.');
960 tag = QLatin1String("number");
961 } else {
962 switch (ch.unicode()) {
963 case '+':
964 case '-':
965 case '!':
966 case '%':
967 case '^':
968 case '&':
969 case '*':
970 case ',':
971 case '.':
972 case '<':
973 case '=':
974 case '>':
975 case '?':
976 case '[':
977 case ']':
978 case '|':
979 case '~':
980 finish = i;
981 readChar();
982 tag = QLatin1String("op");
983 break;
984 case '"':
985 finish = i;
986 readChar();
987
988 while (ch != EOF && ch != '"') {
989 if (ch == '\\')
990 readChar();
991 readChar();
992 }
993 finish = i;
994 readChar();
995 tag = QLatin1String("string");
996 break;
997 case '#':
998 finish = i;
999 readChar();
1000 while (ch != EOF && ch != '\n') {
1001 if (ch == '\\')
1002 readChar();
1003 finish = i;
1004 readChar();
1005 }
1006 tag = QLatin1String("preprocessor");
1007 break;
1008 case '\'':
1009 finish = i;
1010 readChar();
1011
1012 while (ch != EOF && ch != '\'') {
1013 if (ch == '\\')
1014 readChar();
1015 readChar();
1016 }
1017 finish = i;
1018 readChar();
1019 tag = QLatin1String("char");
1020 break;
1021 case '(':
1022 finish = i;
1023 readChar();
1024 parenDepth++;
1025 break;
1026 case ')':
1027 finish = i;
1028 readChar();
1029 parenDepth--;
1030 break;
1031 case ':':
1032 finish = i;
1033 readChar();
1034 if (ch == ':') {
1035 finish = i;
1036 readChar();
1037 tag = QLatin1String("op");
1038 }
1039 break;
1040 case '/':
1041 finish = i;
1042 readChar();
1043 if (ch == '/') {
1044 do {
1045 finish = i;
1046 readChar();
1047 } while (ch != EOF && ch != '\n');
1048 tag = QLatin1String("comment");
1049 } else if (ch == '*') {
1050 bool metAster = false;
1051 bool metAsterSlash = false;
1052
1053 finish = i;
1054 readChar();
1055
1056 while (!metAsterSlash) {
1057 if (ch == EOF)
1058 break;
1059
1060 if (ch == '*')
1061 metAster = true;
1062 else if (metAster && ch == '/')
1063 metAsterSlash = true;
1064 else
1065 metAster = false;
1066 finish = i;
1067 readChar();
1068 }
1069 tag = QLatin1String("comment");
1070 } else {
1071 tag = QLatin1String("op");
1072 }
1073 break;
1074 case '{':
1075 finish = i;
1076 readChar();
1077 braceDepth++;
1078 break;
1079 case '}':
1080 finish = i;
1081 readChar();
1082 braceDepth--;
1083 break;
1084 default:
1085 finish = i;
1086 readChar();
1087 }
1088 }
1089
1090 QString text;
1091 text = code.mid(start, finish - start);
1092 start = finish;
1093
1094 if (!tag.isEmpty()) {
1095 out += QLatin1String("<@") + tag;
1096 if (target)
1097 out += QLatin1String(" target=\"") + text + QLatin1String("()\"");
1098 out += QLatin1String(">");
1099 }
1100
1101 out += protect(text);
1102
1103 if (!tag.isEmpty())
1104 out += QLatin1String("</@") + tag + QLatin1String(">");
1105 }
1106
1107 if (start < code.length()) {
1108 out += protect(code.mid(start));
1109 }
1110
1111 return out;
1112}
1113
1114#ifdef QDOC_QML
1115/*!
1116 This function is for documenting QML properties. It returns
1117 the list of documentation sections for the children of the
1118 \a qmlClassNode.
1119
1120 Currently, it only handles QML property groups.
1121 */
1122QList<Section> CppCodeMarker::qmlSections(const QmlClassNode* qmlClassNode,
1123 SynopsisStyle style,
1124 const Tree* tree)
1125{
1126 QList<Section> sections;
1127 if (qmlClassNode) {
1128 if (style == Summary) {
1129 FastSection qmlproperties(qmlClassNode,
1130 "Properties",
1131 "",
1132 "property",
1133 "properties");
1134 FastSection qmlattachedproperties(qmlClassNode,
1135 "Attached Properties",
1136 "",
1137 "property",
1138 "properties");
1139 FastSection qmlsignals(qmlClassNode,
1140 "Signal Handlers",
1141 "",
1142 "signal handler",
1143 "signal handlers");
1144 FastSection qmlattachedsignals(qmlClassNode,
1145 "Attached Signal Handlers",
1146 "",
1147 "signal handler",
1148 "signal handlers");
1149 FastSection qmlmethods(qmlClassNode,
1150 "Methods",
1151 "",
1152 "method",
1153 "methods");
1154 FastSection qmlattachedmethods(qmlClassNode,
1155 "Attached Methods",
1156 "",
1157 "method",
1158 "methods");
1159
1160 NodeList::ConstIterator c = qmlClassNode->childNodes().begin();
1161 while (c != qmlClassNode->childNodes().end()) {
1162 if ((*c)->subType() == Node::QmlPropertyGroup) {
1163 const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(*c);
1164 NodeList::ConstIterator p = qpgn->childNodes().begin();
1165 while (p != qpgn->childNodes().end()) {
1166 if ((*p)->type() == Node::QmlProperty) {
1167 const QmlPropertyNode* pn = static_cast<const QmlPropertyNode*>(*p);
1168 if (pn->isAttached())
1169 insert(qmlattachedproperties,*p,style,Okay);
1170 else
1171 insert(qmlproperties,*p,style,Okay);
1172 }
1173 ++p;
1174 }
1175 }
1176 else if ((*c)->type() == Node::QmlSignal) {
1177 const FunctionNode* sn = static_cast<const FunctionNode*>(*c);
1178 if (sn->isAttached())
1179 insert(qmlattachedsignals,*c,style,Okay);
1180 else
1181 insert(qmlsignals,*c,style,Okay);
1182 }
1183 else if ((*c)->type() == Node::QmlMethod) {
1184 const FunctionNode* mn = static_cast<const FunctionNode*>(*c);
1185 if (mn->isAttached())
1186 insert(qmlattachedmethods,*c,style,Okay);
1187 else
1188 insert(qmlmethods,*c,style,Okay);
1189 }
1190 ++c;
1191 }
1192 append(sections,qmlproperties);
1193 append(sections,qmlattachedproperties);
1194 append(sections,qmlsignals);
1195 append(sections,qmlattachedsignals);
1196 append(sections,qmlmethods);
1197 append(sections,qmlattachedmethods);
1198 }
1199 else if (style == Detailed) {
1200 FastSection qmlproperties(qmlClassNode, "Property Documentation","qmlprop","member","members");
1201 FastSection qmlattachedproperties(qmlClassNode,"Attached Property Documentation","qmlattprop",
1202 "member","members");
1203 FastSection qmlsignals(qmlClassNode,"Signal Handler Documentation","qmlsig","handler","handlers");
1204 FastSection qmlattachedsignals(qmlClassNode,"Attached Signal Handler Documentation","qmlattsig",
1205 "handler","handlers");
1206 FastSection qmlmethods(qmlClassNode,"Method Documentation","qmlmeth","member","members");
1207 FastSection qmlattachedmethods(qmlClassNode,"Attached Method Documentation","qmlattmeth",
1208 "member","members");
1209 NodeList::ConstIterator c = qmlClassNode->childNodes().begin();
1210 while (c != qmlClassNode->childNodes().end()) {
1211 if ((*c)->subType() == Node::QmlPropertyGroup) {
1212 const QmlPropGroupNode* pgn = static_cast<const QmlPropGroupNode*>(*c);
1213 if (pgn->isAttached())
1214 insert(qmlattachedproperties,*c,style,Okay);
1215 else
1216 insert(qmlproperties,*c,style,Okay);
1217 }
1218 else if ((*c)->type() == Node::QmlSignal) {
1219 const FunctionNode* sn = static_cast<const FunctionNode*>(*c);
1220 if (sn->isAttached())
1221 insert(qmlattachedsignals,*c,style,Okay);
1222 else
1223 insert(qmlsignals,*c,style,Okay);
1224 }
1225 else if ((*c)->type() == Node::QmlMethod) {
1226 const FunctionNode* mn = static_cast<const FunctionNode*>(*c);
1227 if (mn->isAttached())
1228 insert(qmlattachedmethods,*c,style,Okay);
1229 else
1230 insert(qmlmethods,*c,style,Okay);
1231 }
1232 ++c;
1233 }
1234 append(sections,qmlproperties);
1235 append(sections,qmlattachedproperties);
1236 append(sections,qmlsignals);
1237 append(sections,qmlattachedsignals);
1238 append(sections,qmlmethods);
1239 append(sections,qmlattachedmethods);
1240 }
1241 else {
1242 FastSection all(qmlClassNode,"","","member","members");
1243
1244 QStack<const QmlClassNode*> stack;
1245 stack.push(qmlClassNode);
1246
1247 while (!stack.isEmpty()) {
1248 const QmlClassNode* ancestorClass = stack.pop();
1249
1250 NodeList::ConstIterator c = ancestorClass->childNodes().begin();
1251 while (c != ancestorClass->childNodes().end()) {
1252 // if ((*c)->access() != Node::Private)
1253 if ((*c)->subType() == Node::QmlPropertyGroup) {
1254 const QmlPropGroupNode* qpgn = static_cast<const QmlPropGroupNode*>(*c);
1255 NodeList::ConstIterator p = qpgn->childNodes().begin();
1256 while (p != qpgn->childNodes().end()) {
1257 if ((*p)->type() == Node::QmlProperty) {
1258 insert(all,*p,style,Okay);
1259 }
1260 ++p;
1261 }
1262 }
1263 else
1264 insert(all,*c,style,Okay);
1265 ++c;
1266 }
1267
1268 if (!ancestorClass->links().empty()) {
1269 if (ancestorClass->links().contains(Node::InheritsLink)) {
1270 QPair<QString,QString> linkPair;
1271 linkPair = ancestorClass->links()[Node::InheritsLink];
1272 QStringList strList(linkPair.first);
1273 const Node* n = tree->findNode(strList,Node::Fake);
1274 if (n && n->subType() == Node::QmlClass) {
1275 const QmlClassNode* qcn = static_cast<const QmlClassNode*>(n);
1276 stack.prepend(qcn);
1277 }
1278 }
1279 }
1280 }
1281 append(sections, all);
1282 }
1283 }
1284
1285 return sections;
1286}
1287#endif
1288
1289QT_END_NAMESPACE
1290

Warning: That file was not part of the compilation database. It may have many parsing errors.