1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the tools applications of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
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
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
48 #include "cppcodemarker.h"
55 static int insertTagAround(QString
&result
, int pos
, int len
, const QString
&tagName
,
56 const QString
&attributes
= QString())
59 //s.reserve(result.size() + tagName.size() * 2 + attributes.size() + 20);
60 s
+= result
.midRef(0, pos
);
61 s
+= QLatin1Char('<');
63 if (!attributes
.isEmpty()) {
64 s
+= QLatin1Char(' ');
67 s
+= QLatin1Char('>');
68 s
+= result
.midRef(pos
, len
);
69 s
+= QLatin1String("</");
71 s
+= QLatin1Char('>');
72 s
+= result
.midRef(pos
+ len
);
73 int diff
= s
.length() - result
.length();
79 The constructor does nothing.
81 CppCodeMarker::CppCodeMarker()
87 The destructor does nothing.
89 CppCodeMarker::~CppCodeMarker()
97 bool CppCodeMarker::recognizeCode(const QString
& /* code */)
103 Returns true if \a ext is any of a list of file extensions
104 for the C++ language.
106 bool CppCodeMarker::recognizeExtension(const QString
& ext
)
122 Returns true if \a lang is either "C" or "Cpp".
124 bool CppCodeMarker::recognizeLanguage(const QString
&lang
)
126 return lang
== "C" || lang
== "Cpp";
130 Returns the \a node name, or "()" if \a node is a
133 QString
CppCodeMarker::plainName(const Node
*node
)
135 QString name
= node
->name();
136 if (node
->type() == Node::Function
)
141 QString
CppCodeMarker::plainFullName(const Node
*node
, const Node
*relative
)
143 if (node
->name().isEmpty()) {
149 fullName
.prepend(plainName(node
));
150 if (node
->parent() == relative
|| node
->parent()->name().isEmpty())
152 fullName
.prepend("::");
153 node
= node
->parent();
159 QString
CppCodeMarker::markedUpCode(const QString
&code
,
160 const Node
*relative
,
161 const QString
&dirPath
)
163 return addMarkUp(protect(code
), relative
, dirPath
);
166 QString
CppCodeMarker::markedUpSynopsis(const Node
*node
,
167 const Node
* /* relative */,
170 const int MaxEnumValues
= 6;
171 const FunctionNode
*func
;
172 const PropertyNode
*property
;
173 const VariableNode
*variable
;
174 const EnumNode
*enume
;
175 const TypedefNode
*typedeff
;
180 name
= taggedNode(node
);
181 if (style
!= Detailed
)
182 name
= linkTag(node
, name
);
183 name
= "<@name>" + name
+ "</@name>";
185 if (style
== Detailed
&& !node
->parent()->name().isEmpty() &&
186 node
->type() != Node::Property
)
187 name
.prepend(taggedNode(node
->parent()) + "::");
189 switch (node
->type()) {
190 case Node::Namespace
:
191 synopsis
= "namespace " + name
;
194 synopsis
= "class " + name
;
197 case Node::QmlSignal
:
198 case Node::QmlMethod
:
199 func
= (const FunctionNode
*) node
;
200 if (style
!= SeparateList
&& !func
->returnType().isEmpty())
201 synopsis
= typified(func
->returnType()) + " ";
203 if (func
->metaness() != FunctionNode::MacroWithoutParams
) {
205 if (!func
->parameters().isEmpty()) {
207 QList
<Parameter
>::ConstIterator p
= func
->parameters().begin();
208 while (p
!= func
->parameters().end()) {
209 if (p
!= func
->parameters().begin())
211 synopsis
+= typified((*p
).leftType());
212 if (style
!= SeparateList
&& !(*p
).name().isEmpty())
214 " <@param>" + protect((*p
).name()) + "</@param>";
215 synopsis
+= protect((*p
).rightType());
216 if (style
!= SeparateList
&& !(*p
).defaultValue().isEmpty())
217 synopsis
+= " = " + protect((*p
).defaultValue());
225 synopsis
+= " const";
227 if (style
== Summary
|| style
== Accessors
) {
228 if (func
->virtualness() != FunctionNode::NonVirtual
)
229 synopsis
.prepend("virtual ");
230 if (func
->virtualness() == FunctionNode::PureVirtual
)
231 synopsis
.append(" = 0");
233 else if (style
== SeparateList
) {
234 if (!func
->returnType().isEmpty() && func
->returnType() != "void")
235 synopsis
+= " : " + typified(func
->returnType());
238 QStringList bracketed
;
239 if (func
->isStatic()) {
240 bracketed
+= "static";
242 else if (func
->virtualness() != FunctionNode::NonVirtual
) {
243 if (func
->virtualness() == FunctionNode::PureVirtual
)
245 bracketed
+= "virtual";
248 if (func
->access() == Node::Protected
) {
249 bracketed
+= "protected";
251 else if (func
->access() == Node::Private
) {
252 bracketed
+= "private";
255 if (func
->metaness() == FunctionNode::Signal
) {
256 bracketed
+= "signal";
258 else if (func
->metaness() == FunctionNode::Slot
) {
261 if (!bracketed
.isEmpty())
262 extra
+= " [" + bracketed
.join(" ") + "]";
266 enume
= static_cast<const EnumNode
*>(node
);
267 synopsis
= "enum " + name
;
268 if (style
== Summary
) {
271 QStringList documentedItems
= enume
->doc().enumItemNames();
272 if (documentedItems
.isEmpty()) {
273 foreach (const EnumItem
&item
, enume
->items())
274 documentedItems
<< item
.name();
276 QStringList omitItems
= enume
->doc().omitEnumItemNames();
277 foreach (const QString
&item
, omitItems
)
278 documentedItems
.removeAll(item
);
280 if (documentedItems
.size() <= MaxEnumValues
) {
281 for (int i
= 0; i
< documentedItems
.size(); ++i
) {
284 synopsis
+= documentedItems
.at(i
);
288 for (int i
= 0; i
< documentedItems
.size(); ++i
) {
289 if (i
< MaxEnumValues
-2 || i
== documentedItems
.size()-1) {
292 synopsis
+= documentedItems
.at(i
);
294 else if (i
== MaxEnumValues
- 1) {
299 if (!documentedItems
.isEmpty())
305 typedeff
= static_cast<const TypedefNode
*>(node
);
306 if (typedeff
->associatedEnum()) {
307 synopsis
= "flags " + name
;
310 synopsis
= "typedef " + name
;
314 property
= static_cast<const PropertyNode
*>(node
);
315 synopsis
= name
+ " : " + typified(property
->qualifiedDataType());
318 variable
= static_cast<const VariableNode
*>(node
);
319 if (style
== SeparateList
) {
320 synopsis
= name
+ " : " + typified(variable
->dataType());
323 synopsis
= typified(variable
->leftType()) + " " +
324 name
+ protect(variable
->rightType());
331 if (style
== Summary
) {
332 if (node
->status() == Node::Preliminary
) {
333 extra
+= " (preliminary)";
335 else if (node
->status() == Node::Deprecated
) {
336 extra
+= " (deprecated)";
338 else if (node
->status() == Node::Obsolete
) {
339 extra
+= " (obsolete)";
343 if (!extra
.isEmpty()) {
344 extra
.prepend("<@extra>");
345 extra
.append("</@extra>");
347 return synopsis
+ extra
;
353 QString
CppCodeMarker::markedUpQmlItem(const Node
* node
, bool summary
)
355 QString name
= taggedQmlNode(node
);
357 name
= linkTag(node
,name
);
358 } else if (node
->type() == Node::QmlProperty
) {
359 const QmlPropertyNode
* pn
= static_cast<const QmlPropertyNode
*>(node
);
360 if (pn
->isAttached())
361 name
.prepend(pn
->element() + QLatin1Char('.'));
363 name
= "<@name>" + name
+ "</@name>";
364 QString synopsis
= name
;
365 if (node
->type() == Node::QmlProperty
) {
366 const QmlPropertyNode
* pn
= static_cast<const QmlPropertyNode
*>(node
);
367 synopsis
+= " : " + typified(pn
->dataType());
372 if (node
->status() == Node::Preliminary
) {
373 extra
+= " (preliminary)";
375 else if (node
->status() == Node::Deprecated
) {
376 extra
+= " (deprecated)";
378 else if (node
->status() == Node::Obsolete
) {
379 extra
+= " (obsolete)";
383 if (!extra
.isEmpty()) {
384 extra
.prepend("<@extra>");
385 extra
.append("</@extra>");
387 return synopsis
+ extra
;
391 QString
CppCodeMarker::markedUpName(const Node
*node
)
393 QString name
= linkTag(node
, taggedNode(node
));
394 if (node
->type() == Node::Function
)
399 QString
CppCodeMarker::markedUpFullName(const Node
*node
, const Node
*relative
)
401 if (node
->name().isEmpty()) {
407 fullName
.prepend(markedUpName(node
));
408 if (node
->parent() == relative
|| node
->parent()->name().isEmpty())
410 fullName
.prepend("<@op>::</@op>");
411 node
= node
->parent();
417 QString
CppCodeMarker::markedUpEnumValue(const QString
&enumValue
,
418 const Node
*relative
)
420 const Node
*node
= relative
->parent();
422 while (node
->parent()) {
423 fullName
.prepend(markedUpName(node
));
424 if (node
->parent() == relative
|| node
->parent()->name().isEmpty())
426 fullName
.prepend("<@op>::</@op>");
427 node
= node
->parent();
429 if (!fullName
.isEmpty())
430 fullName
.append("<@op>::</@op>");
431 fullName
.append(enumValue
);
435 QString
CppCodeMarker::markedUpIncludes(const QStringList
& includes
)
439 QStringList::ConstIterator inc
= includes
.begin();
440 while (inc
!= includes
.end()) {
441 code
+= "#include <<@headerfile>" + *inc
+ "</@headerfile>>\n";
444 return addMarkUp(code
, 0, "");
447 QString
CppCodeMarker::functionBeginRegExp(const QString
& funcName
)
449 return "^" + QRegExp::escape(funcName
) + "$";
453 QString
CppCodeMarker::functionEndRegExp(const QString
& /* funcName */)
459 FastSection
privateReimpFuncs(classe
,
460 "Private Reimplemented Functions",
461 "private reimplemented function",
462 "private reimplemented functions");
463 FastSection
protectedReimpFuncs(classe
,
464 "Protected Reimplemented Functions",
465 "protected reimplemented function",
466 "protected reimplemented functions");
467 FastSection
publicReimpFuncs(classe
,
468 "Public Reimplemented Functions",
469 "public reimplemented function",
470 "public reimplemented functions");
473 QList
<Section
> CppCodeMarker::sections(const InnerNode
*inner
,
477 QList
<Section
> sections
;
479 if (inner
->type() == Node::Class
) {
480 const ClassNode
*classe
= static_cast<const ClassNode
*>(inner
);
482 if (style
== Summary
) {
483 FastSection
privateFunctions(classe
,
486 "private functions");
487 FastSection
privateSlots(classe
, "Private Slots", "private slot", "private slots");
488 FastSection
privateTypes(classe
, "Private Types", "private type", "private types");
489 FastSection
protectedFunctions(classe
,
490 "Protected Functions",
491 "protected function",
492 "protected functions");
493 FastSection
protectedSlots(classe
,
497 FastSection
protectedTypes(classe
,
501 FastSection
protectedVariables(classe
,
502 "Protected Variables",
504 "protected variables");
505 FastSection
publicFunctions(classe
,
509 FastSection
publicSignals(classe
, "Signals", "signal", "signals");
510 FastSection
publicSlots(classe
, "Public Slots", "public slot", "public slots");
511 FastSection
publicTypes(classe
, "Public Types", "public type", "public types");
512 FastSection
publicVariables(classe
,
516 FastSection
properties(classe
, "Properties", "property", "properties");
517 FastSection
relatedNonMembers(classe
,
518 "Related Non-Members",
519 "related non-member",
520 "related non-members");
521 FastSection
staticPrivateMembers(classe
,
522 "Static Private Members",
523 "static private member",
524 "static private members");
525 FastSection
staticProtectedMembers(classe
,
526 "Static Protected Members",
527 "static protected member",
528 "static protected members");
529 FastSection
staticPublicMembers(classe
,
530 "Static Public Members",
531 "static public member",
532 "static public members");
533 FastSection
macros(inner
, "Macros", "macro", "macros");
535 NodeList::ConstIterator r
= classe
->relatedNodes().begin();
536 while (r
!= classe
->relatedNodes().end()) {
537 if ((*r
)->type() == Node::Function
) {
538 FunctionNode
*func
= static_cast<FunctionNode
*>(*r
);
540 insert(macros
, *r
, style
, status
);
542 insert(relatedNonMembers
, *r
, style
, status
);
545 insert(relatedNonMembers
, *r
, style
, status
);
550 QStack
<const ClassNode
*> stack
;
553 while (!stack
.isEmpty()) {
554 const ClassNode
*ancestorClass
= stack
.pop();
556 NodeList::ConstIterator c
= ancestorClass
->childNodes().begin();
557 while (c
!= ancestorClass
->childNodes().end()) {
559 bool isSignal
= false;
560 bool isStatic
= false;
561 if ((*c
)->type() == Node::Function
) {
562 const FunctionNode
*func
= (const FunctionNode
*) *c
;
563 isSlot
= (func
->metaness() == FunctionNode::Slot
);
564 isSignal
= (func
->metaness() == FunctionNode::Signal
);
565 isStatic
= func
->isStatic();
567 else if ((*c
)->type() == Node::Variable
) {
568 const VariableNode
*var
= static_cast<const VariableNode
*>(*c
);
569 isStatic
= var
->isStatic();
572 switch ((*c
)->access()) {
575 insert(publicSlots
, *c
, style
, status
);
578 insert(publicSignals
, *c
, style
, status
);
581 if ((*c
)->type() != Node::Variable
582 || !(*c
)->doc().isEmpty())
583 insert(staticPublicMembers
,*c
,style
,status
);
585 else if ((*c
)->type() == Node::Property
) {
586 insert(properties
, *c
, style
, status
);
588 else if ((*c
)->type() == Node::Variable
) {
589 if (!(*c
)->doc().isEmpty())
590 insert(publicVariables
, *c
, style
, status
);
592 else if ((*c
)->type() == Node::Function
) {
593 if (!insertReimpFunc(publicFunctions
,*c
,status
))
594 insert(publicFunctions
, *c
, style
, status
);
597 insert(publicTypes
, *c
, style
, status
);
600 case Node::Protected
:
602 insert(protectedSlots
, *c
, style
, status
);
605 if ((*c
)->type() != Node::Variable
606 || !(*c
)->doc().isEmpty())
607 insert(staticProtectedMembers
,*c
,style
,status
);
609 else if ((*c
)->type() == Node::Variable
) {
610 if (!(*c
)->doc().isEmpty())
611 insert(protectedVariables
,*c
,style
,status
);
613 else if ((*c
)->type() == Node::Function
) {
614 if (!insertReimpFunc(protectedFunctions
,*c
,status
))
615 insert(protectedFunctions
, *c
, style
, status
);
618 insert(protectedTypes
, *c
, style
, status
);
623 insert(privateSlots
, *c
, style
, status
);
626 if ((*c
)->type() != Node::Variable
627 || !(*c
)->doc().isEmpty())
628 insert(staticPrivateMembers
,*c
,style
,status
);
630 else if ((*c
)->type() == Node::Function
) {
631 if (!insertReimpFunc(privateFunctions
,*c
,status
))
632 insert(privateFunctions
, *c
, style
, status
);
635 insert(privateTypes
,*c
,style
,status
);
641 QList
<RelatedClass
>::ConstIterator r
=
642 ancestorClass
->baseClasses().begin();
643 while (r
!= ancestorClass
->baseClasses().end()) {
644 stack
.prepend((*r
).node
);
649 append(sections
, publicTypes
);
650 append(sections
, properties
);
651 append(sections
, publicFunctions
);
652 append(sections
, publicSlots
);
653 append(sections
, publicSignals
);
654 append(sections
, publicVariables
);
655 append(sections
, staticPublicMembers
);
656 append(sections
, protectedTypes
);
657 append(sections
, protectedFunctions
);
658 append(sections
, protectedSlots
);
659 append(sections
, protectedVariables
);
660 append(sections
, staticProtectedMembers
);
661 append(sections
, privateTypes
);
662 append(sections
, privateFunctions
);
663 append(sections
, privateSlots
);
664 append(sections
, staticPrivateMembers
);
665 append(sections
, relatedNonMembers
);
666 append(sections
, macros
);
668 else if (style
== Detailed
) {
669 FastSection
memberFunctions(classe
,"Member Function Documentation");
670 FastSection
memberTypes(classe
,"Member Type Documentation");
671 FastSection
memberVariables(classe
,"Member Variable Documentation");
672 FastSection
properties(classe
,"Property Documentation");
673 FastSection
relatedNonMembers(classe
,"Related Non-Members");
674 FastSection
macros(classe
,"Macro Documentation");
676 NodeList::ConstIterator r
= classe
->relatedNodes().begin();
677 while (r
!= classe
->relatedNodes().end()) {
678 if ((*r
)->type() == Node::Function
) {
679 FunctionNode
*func
= static_cast<FunctionNode
*>(*r
);
681 insert(macros
, *r
, style
, status
);
683 insert(relatedNonMembers
, *r
, style
, status
);
686 insert(relatedNonMembers
, *r
, style
, status
);
691 NodeList::ConstIterator c
= classe
->childNodes().begin();
692 while (c
!= classe
->childNodes().end()) {
693 if ((*c
)->type() == Node::Enum
||
694 (*c
)->type() == Node::Typedef
) {
695 insert(memberTypes
, *c
, style
, status
);
697 else if ((*c
)->type() == Node::Property
) {
698 insert(properties
, *c
, style
, status
);
700 else if ((*c
)->type() == Node::Variable
) {
701 if (!(*c
)->doc().isEmpty())
702 insert(memberVariables
, *c
, style
, status
);
704 else if ((*c
)->type() == Node::Function
) {
705 FunctionNode
*function
= static_cast<FunctionNode
*>(*c
);
706 if (!function
->associatedProperty())
707 insert(memberFunctions
, function
, style
, status
);
712 append(sections
, memberTypes
);
713 append(sections
, properties
);
714 append(sections
, memberFunctions
);
715 append(sections
, memberVariables
);
716 append(sections
, relatedNonMembers
);
717 append(sections
, macros
);
720 FastSection
all(classe
);
722 QStack
<const ClassNode
*> stack
;
725 while (!stack
.isEmpty()) {
726 const ClassNode
*ancestorClass
= stack
.pop();
728 NodeList::ConstIterator c
= ancestorClass
->childNodes().begin();
729 while (c
!= ancestorClass
->childNodes().end()) {
730 if ((*c
)->access() != Node::Private
&&
731 (*c
)->type() != Node::Property
)
732 insert(all
, *c
, style
, status
);
736 QList
<RelatedClass
>::ConstIterator r
=
737 ancestorClass
->baseClasses().begin();
738 while (r
!= ancestorClass
->baseClasses().end()) {
739 stack
.prepend((*r
).node
);
743 append(sections
, all
);
747 if (style
== Summary
|| style
== Detailed
) {
748 FastSection
namespaces(inner
,
752 FastSection
classes(inner
,
756 FastSection
types(inner
,
758 "Types" : "Type Documentation",
761 FastSection
functions(inner
,
763 "Functions" : "Function Documentation",
766 FastSection
macros(inner
,
768 "Macros" : "Macro Documentation",
772 NodeList nodeList
= inner
->childNodes();
773 nodeList
+= inner
->relatedNodes();
775 NodeList::ConstIterator n
= nodeList
.begin();
776 while (n
!= nodeList
.end()) {
777 switch ((*n
)->type()) {
778 case Node::Namespace
:
779 insert(namespaces
, *n
, style
, status
);
782 insert(classes
, *n
, style
, status
);
786 insert(types
, *n
, style
, status
);
790 FunctionNode
*func
= static_cast<FunctionNode
*>(*n
);
792 insert(macros
, *n
, style
, status
);
794 insert(functions
, *n
, style
, status
);
802 append(sections
, namespaces
);
803 append(sections
, classes
);
804 append(sections
, types
);
805 append(sections
, functions
);
806 append(sections
, macros
);
813 const Node
*CppCodeMarker::resolveTarget(const QString
&target
,
815 const Node
*relative
)
817 if (target
.endsWith("()")) {
818 const FunctionNode
*func
;
819 QString funcName
= target
;
822 QStringList path
= funcName
.split("::");
823 if ((func
= tree
->findFunctionNode(path
,
825 Tree::SearchBaseClasses
))
826 && func
->metaness() != FunctionNode::MacroWithoutParams
)
829 else if (target
.contains("#")) {
830 // ### this doesn't belong here; get rid of TargetNode hack
831 int hashAt
= target
.indexOf("#");
832 QString link
= target
.left(hashAt
);
833 QString ref
= target
.mid(hashAt
+ 1);
835 if (link
.isEmpty()) {
839 QStringList
path(link
);
840 node
= tree
->findNode(path
, tree
->root(), Tree::SearchBaseClasses
);
842 if (node
&& node
->isInnerNode()) {
843 const Atom
*atom
= node
->doc().body().firstAtom();
845 if (atom
->type() == Atom::Target
&& atom
->string() == ref
) {
846 Node
*parentNode
= const_cast<Node
*>(node
);
847 return new TargetNode(static_cast<InnerNode
*>(parentNode
),
855 QStringList path
= target
.split("::");
857 if ((node
= tree
->findNode(path
,
859 Tree::SearchBaseClasses
|
860 Tree::SearchEnumValues
|
867 QString
CppCodeMarker::addMarkUp(const QString
& protectedCode
,
868 const Node
* /* relative */,
869 const QString
& /* dirPath */)
871 static QRegExp
globalInclude("#include +<([^<>&]+)>");
872 static QRegExp
yHasTypeX("(?:^|\n *)([a-zA-Z_][a-zA-Z_0-9]*)"
873 "(?:<[^;{}]+>)?(?: *(?:\\*|&) *| +)"
874 "([a-zA-Z_][a-zA-Z_0-9]*)? *[,;()=]");
875 static QRegExp
xNewY("([a-zA-Z_][a-zA-Z_0-9]*) *= *new +([a-zA-Z_0-9]+)");
876 static QRegExp
xDotY("\\b([a-zA-Z_][a-zA-Z_0-9]*) *(?:\\.|->|,[ \n]*S(?:IGNAL|LOT)\\() *"
877 "([a-zA-Z_][a-zA-Z_0-9]*)(?= *\\()");
878 static QRegExp
xIsStaticZOfY("[\n:;{(=] *(([a-zA-Z_0-9]+)::([a-zA-Z_0-9]+))(?= *\\()");
879 static QRegExp
classX("[:,][ \n]*(?:p(?:ublic|r(?:otected|ivate))[ \n]+)?"
880 "([a-zA-Z_][a-zA-Z_0-9]*)");
881 static QRegExp
globalX("[\n{()=] *([a-zA-Z_][a-zA-Z_0-9]*)[ \n]*\\(");
882 static QRegExp
multiLineComment("/(?:( )?\\*(?:[^*]+|\\*(?! /))*\\*\\1/)");
883 multiLineComment
.setMinimal(true);
884 static QRegExp
singleLineCommentLine("(?:^|\n)(?:[^&]|&(?!quot;)|"(?:[^&\\\\]|&(?!quot;)|\\\\"|\\\\(?!"))*")*//(?!!)[^!\n]*");
885 static QRegExp
singleLineComment("//(?!!)[^!\n]*");
886 static QRegExp
preprocessor("(?:^|\n)(#[ \t]*(?:include|if|elif|endif|error|pragma|define"
887 "|warning)(?:(?:\\\\\n|\\n#)[^\n]*)*)");
888 static QRegExp
literals(""(?:[^\\\\&]|\\\\[^\n]|&(?!quot;))*""
889 "|'(?:[^\\\\]|\\\\(?:[^x0-9']|x[0-9a-f]{1,4}|[0-9]{1,3}))'");
891 QString result
= protectedCode
;
896 Mark global includes. For example:
898 #include <<@headerfile>QString</@headerfile>
901 while ((pos
= result
.indexOf(globalInclude
, pos
)) != -1)
902 pos
+= globalInclude
.matchedLength()
903 + insertTagAround(result
,
904 globalInclude
.pos(1),
905 globalInclude
.cap(1).length(),
909 Look for variable definitions and similar constructs, mark
910 the data type, and remember the type of the variable.
912 QMap
<QString
, QSet
<QString
> > typesForVariable
;
914 while ((pos
= yHasTypeX
.indexIn(result
, pos
)) != -1) {
915 QString x
= yHasTypeX
.cap(1);
916 QString y
= yHasTypeX
.cap(2);
919 typesForVariable
[y
].insert(x
);
922 Without the minus one at the end, 'void member(Class
923 var)' would give 'member' as a variable of type 'void',
924 but would ignore 'Class var'. (### Is that true?)
926 pos
+= yHasTypeX
.matchedLength()
927 + insertTagAround(result
,
934 Do syntax highlighting of preprocessor directives.
937 while ((pos
= preprocessor
.indexIn(result
, pos
)) != -1)
938 pos
+= preprocessor
.matchedLength()
939 + insertTagAround(result
,
941 preprocessor
.cap(1).length(),
945 Deal with string and character literals.
948 while ((pos
= literals
.indexIn(result
, pos
)) != -1)
949 pos
+= literals
.matchedLength()
950 + insertTagAround(result
,
952 literals
.matchedLength(),
954 QLatin1Char(' ') ? "@string" : "@char");
957 Look for 'var = new Class'.
960 while ((pos
= xNewY
.indexIn(result
, pos
)) != -1) {
961 QString x
= xNewY
.cap(1);
962 QString y
= xNewY
.cap(2);
963 typesForVariable
[x
].insert(y
);
965 pos
+= xNewY
.matchedLength() + insertTagAround(result
,
972 Insert some stuff that cannot harm.
974 typesForVariable
["qApp"].insert("QApplication");
977 Add link to ': Class'.
980 while ((pos
= classX
.indexIn(result
, pos
)) != -1)
981 pos
+= classX
.matchedLength()
982 + insertTagAround(result
,
984 classX
.cap(1).length(),
992 var, SIGNAL(method())
996 while ((pos
= xDotY
.indexIn(result
, pos
)) != -1) {
997 QString x
= xDotY
.cap(1);
998 QString y
= xDotY
.cap(2);
1000 QSet
<QString
> types
= typesForVariable
.value(x
);
1001 pos
+= xDotY
.matchedLength()
1002 + insertTagAround(result
,
1004 xDotY
.cap(2).length(),
1006 (types
.count() == 1) ? "target=\""
1007 + protect(*types
.begin() + "::" + y
)
1008 + "()\"" : QString());
1012 Add link to 'Class::method()'.
1015 while ((pos
= xIsStaticZOfY
.indexIn(result
, pos
)) != -1) {
1016 QString x
= xIsStaticZOfY
.cap(1);
1017 QString z
= xIsStaticZOfY
.cap(3);
1019 pos
+= insertTagAround(result
,
1020 xIsStaticZOfY
.pos(3),
1023 "target=\"" + protect(x
) + "()\"");
1024 pos
+= insertTagAround(result
,
1025 xIsStaticZOfY
.pos(2),
1026 xIsStaticZOfY
.cap(2).length(),
1028 pos
+= xIsStaticZOfY
.matchedLength() - 1;
1032 Add link to 'globalFunction()'.
1035 while ((pos
= globalX
.indexIn(result
, pos
)) != -1) {
1036 QString x
= globalX
.cap(1);
1037 if (x
!= "QT_FORWARD_DECLARE_CLASS") {
1038 pos
+= globalX
.matchedLength()
1039 + insertTagAround(result
,
1043 "target=\"" + protect(x
) + "()\"") - 1;
1046 pos
+= globalX
.matchedLength();
1051 Do syntax highlighting of comments. Also alter the code in a
1052 minor way, so that we can include comments in documentation
1060 int sllpos
= singleLineCommentLine
.indexIn(result
, pos
);
1061 slpos
= sllpos
== -1 ? -1 : singleLineComment
.indexIn(result
, sllpos
);
1062 mlpos
= multiLineComment
.indexIn(result
, pos
);
1064 if (slpos
== -1 && mlpos
== -1)
1069 len
= multiLineComment
.matchedLength();
1071 else if (mlpos
== -1) {
1073 len
= singleLineComment
.matchedLength();
1076 if (slpos
< mlpos
) {
1078 len
= singleLineComment
.matchedLength();
1082 len
= multiLineComment
.matchedLength();
1086 if (result
.at(pos
+ 1) == QLatin1Char(' ')) {
1087 result
.remove(pos
+ len
- 2, 1);
1088 result
.remove(pos
+ 1, 1);
1092 int endcodePos
= result
.indexOf("\\ endcode", pos
);
1093 if (endcodePos
== -1 || endcodePos
>= pos
+ len
)
1095 result
.remove(endcodePos
+ 1, 1);
1099 pos
+= len
+ insertTagAround(result
, pos
, len
, "@comment");
1107 This function is for documenting QML properties. It returns
1108 the list of documentation sections for the children of the
1111 Currently, it only handles QML property groups.
1113 QList
<Section
> CppCodeMarker::qmlSections(const QmlClassNode
* qmlClassNode
,
1114 SynopsisStyle style
)
1116 QList
<Section
> sections
;
1118 if (style
== Summary
) {
1119 FastSection
qmlproperties(qmlClassNode
,
1123 FastSection
qmlattachedproperties(qmlClassNode
,
1124 "Attached Properties",
1127 FastSection
qmlsignals(qmlClassNode
,
1131 FastSection
qmlattachedsignals(qmlClassNode
,
1132 "QML Attached Signals",
1135 FastSection
qmlmethods(qmlClassNode
,
1139 FastSection
qmlattachedmethods(qmlClassNode
,
1140 "QML Attached Methods",
1144 NodeList::ConstIterator c
= qmlClassNode
->childNodes().begin();
1145 while (c
!= qmlClassNode
->childNodes().end()) {
1146 if ((*c
)->subType() == Node::QmlPropertyGroup
) {
1147 const QmlPropGroupNode
* qpgn
= static_cast<const QmlPropGroupNode
*>(*c
);
1148 NodeList::ConstIterator p
= qpgn
->childNodes().begin();
1149 while (p
!= qpgn
->childNodes().end()) {
1150 if ((*p
)->type() == Node::QmlProperty
) {
1151 const QmlPropertyNode
* pn
= static_cast<const QmlPropertyNode
*>(*p
);
1152 if (pn
->isAttached())
1153 insert(qmlattachedproperties
,*p
,style
,Okay
);
1155 insert(qmlproperties
,*p
,style
,Okay
);
1160 else if ((*c
)->type() == Node::QmlSignal
) {
1161 const FunctionNode
* sn
= static_cast<const FunctionNode
*>(*c
);
1162 if (sn
->isAttached())
1163 insert(qmlattachedsignals
,*c
,style
,Okay
);
1165 insert(qmlsignals
,*c
,style
,Okay
);
1167 else if ((*c
)->type() == Node::QmlMethod
) {
1168 const FunctionNode
* mn
= static_cast<const FunctionNode
*>(*c
);
1169 if (mn
->isAttached())
1170 insert(qmlattachedmethods
,*c
,style
,Okay
);
1172 insert(qmlmethods
,*c
,style
,Okay
);
1176 append(sections
,qmlproperties
);
1177 append(sections
,qmlattachedproperties
);
1178 append(sections
,qmlsignals
);
1179 append(sections
,qmlattachedsignals
);
1180 append(sections
,qmlmethods
);
1181 append(sections
,qmlattachedmethods
);
1183 else if (style
== Detailed
) {
1184 FastSection
qmlproperties(qmlClassNode
, "Property Documentation");
1185 FastSection
qmlattachedproperties(qmlClassNode
,"Attached Property Documentation");
1186 FastSection
qmlsignals(qmlClassNode
,"Signal Documentation");
1187 FastSection
qmlattachedsignals(qmlClassNode
,"Attached Signal Documentation");
1188 FastSection
qmlmethods(qmlClassNode
,"Method Documentation");
1189 FastSection
qmlattachedmethods(qmlClassNode
,"Attached Method Documentation");
1190 NodeList::ConstIterator c
= qmlClassNode
->childNodes().begin();
1191 while (c
!= qmlClassNode
->childNodes().end()) {
1192 if ((*c
)->subType() == Node::QmlPropertyGroup
) {
1193 const QmlPropGroupNode
* pgn
= static_cast<const QmlPropGroupNode
*>(*c
);
1194 if (pgn
->isAttached())
1195 insert(qmlattachedproperties
,*c
,style
,Okay
);
1197 insert(qmlproperties
,*c
,style
,Okay
);
1199 else if ((*c
)->type() == Node::QmlSignal
) {
1200 const FunctionNode
* sn
= static_cast<const FunctionNode
*>(*c
);
1201 if (sn
->isAttached())
1202 insert(qmlattachedsignals
,*c
,style
,Okay
);
1204 insert(qmlsignals
,*c
,style
,Okay
);
1206 else if ((*c
)->type() == Node::QmlMethod
) {
1207 const FunctionNode
* mn
= static_cast<const FunctionNode
*>(*c
);
1208 if (mn
->isAttached())
1209 insert(qmlattachedmethods
,*c
,style
,Okay
);
1211 insert(qmlmethods
,*c
,style
,Okay
);
1215 append(sections
,qmlproperties
);
1216 append(sections
,qmlattachedproperties
);
1217 append(sections
,qmlsignals
);
1218 append(sections
,qmlattachedsignals
);
1219 append(sections
,qmlmethods
);
1220 append(sections
,qmlattachedmethods
);