19#include <QtCore/qdebug.h>
20#include <QtCore/qregularexpression.h>
24using namespace Qt::StringLiterals;
27
28
29
30
31
32
33
34
35
41 if (param.template_declaration)
42 result += formatTemplateDeclStorage(*param.template_declaration, TemplateFormat::SingleLine) +
' '_L1;
47 case RelaxedTemplateParameter::Kind::TypeTemplateParameter:
48 result +=
"typename"_L1;
50 case RelaxedTemplateParameter::Kind::NonTypeTemplateParameter:
51 if (!decl.type.empty())
52 result += typified(QString::fromStdString(decl.type),
false);
54 case RelaxedTemplateParameter::Kind::TemplateTemplateParameter:
55 result +=
"typename"_L1;
59 if (param.is_parameter_pack)
62 if (!decl
.name.empty()) {
63 if (!result.isEmpty() && !result.endsWith(
' '_L1))
65 result += protect(QString::fromStdString(decl.name));
72 result += typified(QString::fromStdString(decl.initializer),
false);
74 result += protect(QString::fromStdString(decl.initializer));
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
99 TemplateFormat format)
101 const bool multiline = (format == TemplateFormat::MultiLine);
103 QString result =
"template <"_L1;
108 for (qsizetype i = 0; i <
static_cast<qsizetype>(templateDecl.parameters.size()); ++i) {
110 result += multiline ?
",\n"_L1 :
", "_L1;
114 result += formatTemplateParameter(templateDecl.parameters[i]);
126
127
128
129
130
131
132
133
137 const auto format = multiline ? TemplateFormat::MultiLine : TemplateFormat::SingleLine;
139 QString content = formatTemplateDeclStorage(*templateDecl, format);
143 result =
"<@template-block>"_L1;
147 if (templateDecl->requires_clause && !templateDecl->requires_clause->empty())
148 result +=
" requires "_L1 + protect(QString::fromStdString(*templateDecl->requires_clause));
151 result +=
'\n'_L1 +
"</@template-block>"_L1;
159
160
161bool CppCodeMarker::recognizeCode(
const QString & )
167
168
169
170bool CppCodeMarker::recognizeExtension(
const QString &extension)
172 QByteArray ext = extension.toLatin1();
173 return ext ==
"c" || ext ==
"c++" || ext ==
"qdoc" || ext ==
"qtt" || ext ==
"qtx"
174 || ext ==
"cc" || ext ==
"cpp" || ext ==
"cxx" || ext ==
"ch" || ext ==
"h"
175 || ext ==
"h++" || ext ==
"hh" || ext ==
"hpp" || ext ==
"hxx";
179
180
181bool CppCodeMarker::recognizeLanguage(
const QString &lang)
183 return lang == QLatin1String(
"c") || lang == QLatin1String(
"cpp");
187
188
194QString CppCodeMarker::markedUpCode(
const QString &code,
const Node *relative,
197 return addMarkUp(code, relative, location);
200QString CppCodeMarker::markedUpSynopsis(
const Node *node,
const Node * ,
203 const int MaxEnumValues = 6;
210 name = taggedNode(node);
211 if (style != Section::Details)
212 name = linkTag(node, name);
213 name =
"<@name>" + name +
"</@name>";
218 name.prepend(taggedNode(node->parent()) +
"::");
228 synopsis += QLatin1Char(
' ') + name;
233 if (
auto templateDecl = node->templateDecl())
234 synopsis = formatTemplateDecl(&*templateDecl);
236 if (style != Section::AllMembers && !func->returnType().isEmpty())
237 synopsis += typified(func->returnTypeString(),
true);
240 synopsis += QLatin1Char(
'(');
243 for (
int i = 0; i < parameters
.count(); ++i) {
246 QString name = parameters
.at(i
).name();
247 QString type = parameters
.at(i
).type();
248 QString value = parameters
.at(i
).defaultValue();
250 synopsis += typified(type, trailingSpace);
252 synopsis +=
"<@param>" + protect(name) +
"</@param>";
254 synopsis +=
" = " + protect(value);
257 synopsis += QLatin1Char(
')');
260 synopsis +=
" const";
264 synopsis.prepend(
"virtual ");
266 synopsis.append(
" final");
268 synopsis.append(
" override");
270 synopsis.append(
" = 0");
272 synopsis.append(
" &");
274 synopsis.append(
" &&");
276 if (!func->returnType().isEmpty() && func->returnType() !=
"void")
277 synopsis +=
" : " + typified(func->returnTypeString());
280 synopsis.append(
" &");
282 synopsis.append(
" &&");
283 if (
const auto &req = func->trailingRequiresClause(); req && !req->isEmpty())
284 synopsis.append(
" requires " + protect(*req));
288 enume =
static_cast<
const EnumNode *>(node);
291 synopsis +=
" class";
292 if (!enume->isAnonymous())
293 synopsis +=
" %1"_L1.arg(name);
294 else if (style != Section::Details)
295 synopsis = linkTag(node, synopsis);
299 QStringList documentedItems = enume
->doc().enumItemNames();
300 if (documentedItems.isEmpty()) {
301 const auto &enumItems = enume->items();
302 for (
const auto &item : enumItems)
303 documentedItems << item.name();
305 const QStringList omitItems = enume
->doc().omitEnumItemNames();
306 for (
const auto &item : omitItems)
307 documentedItems.removeAll(item);
309 if (documentedItems.size() > MaxEnumValues) {
311 const QString last = documentedItems.last();
312 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
313 documentedItems +=
"…";
314 documentedItems += last;
316 synopsis += documentedItems.join(QLatin1String(
", "));
318 if (!documentedItems.isEmpty())
319 synopsis += QLatin1Char(
' ');
320 synopsis += QLatin1Char(
'}');
325 if (
auto templateDecl = node->templateDecl())
326 synopsis += formatTemplateDecl(&*templateDecl);
331 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
336 auto property =
static_cast<
const PropertyNode *>(node);
337 synopsis = name +
" : " + typified(property->qualifiedDataType());
341 auto property =
static_cast<
const QmlPropertyNode *>(node);
342 synopsis = name +
" : " + typified(property->dataType());
345 case NodeType::Variable:
346 variable =
static_cast<
const VariableNode *>(node);
348 synopsis = name +
" : " + typified(variable->dataType());
350 synopsis = typified(variable->leftType(),
true) + name + protect(variable->rightType());
354 synopsis =
std::move(name);
357 QString extra = CodeMarker::extraSynopsis(node, style);
358 if (!extra.isEmpty()) {
359 extra.prepend(u"<@extra>"_s);
360 extra.append(u"</@extra> "_s);
363 return extra + synopsis;
367
368QString CppCodeMarker::markedUpQmlItem(
const Node *node,
bool summary)
370 QString name = taggedQmlNode(node);
374 name = linkTag(node, name);
376 const auto *pn =
static_cast<
const QmlPropertyNode *>(node);
377 if (pn->isAttached())
378 name.prepend(pn->element() + QLatin1Char(
'.'));
380 name =
"<@name>" + name +
"</@name>";
382 const auto *pn =
static_cast<
const QmlPropertyNode *>(node);
383 synopsis = name +
" : " + typified(pn->dataType());
385 const auto *func =
static_cast<
const FunctionNode *>(node);
386 if (!func->returnType().isEmpty())
387 synopsis = typified(func->returnTypeString(),
true) + name;
390 synopsis += QLatin1Char(
'(');
391 if (!func->parameters().isEmpty()) {
392 const Parameters ¶meters = func->parameters();
393 for (
int i = 0; i < parameters
.count(); ++i) {
396 QString name = parameters
.at(i
).name();
397 QString type = parameters
.at(i
).type();
399 if (!name.isEmpty()) {
400 synopsis += typified(type,
true);
401 paramName =
std::move(name);
403 paramName =
std::move(type);
405 synopsis +=
"<@param>" + protect(paramName) +
"</@param>";
408 synopsis += QLatin1Char(
')');
410 synopsis =
std::move(name);
414 if (!extra.isEmpty()) {
415 extra.prepend(u" <@extra>"_s);
416 extra.append(u"</@extra>"_s);
419 return synopsis + extra;
422QString CppCodeMarker::markedUpName(
const Node *node)
424 QString name = linkTag(node, taggedNode(node));
430QString CppCodeMarker::markedUpEnumValue(
const QString &enumValue,
const Node *relative)
438 if (nativeEnum && nativeEnum->enumNode()
439 && !enumValue.startsWith(
"%1."_L1.arg(nativeEnum->prefix())))
440 return "%1<@op>.</@op>%2"_L1.arg(nativeEnum->prefix(), enumValue);
444 && enumValue.section(
' ', 0, 0).contains(
'.'_L1)) {
445 return "<@op>%1</@op>"_L1.arg(enumValue);
453 parts.prepend(markedUpName(node));
458 if (
static_cast<
const EnumNode *>(relative)->isScoped())
459 parts.append(relative->name());
461 parts.append(enumValue);
462 const auto &delim = (relative->genus() == Genus::QML) ?
"."_L1 :
"::"_L1;
463 return parts.join(
"<@op>%1</@op>"_L1.arg(delim));
466QString CppCodeMarker::addMarkUp(
const QString &in,
const Node * ,
469 static QSet<QString> types{
470 QLatin1String(
"bool"), QLatin1String(
"char"), QLatin1String(
"double"),
471 QLatin1String(
"float"), QLatin1String(
"int"), QLatin1String(
"long"),
472 QLatin1String(
"short"), QLatin1String(
"signed"), QLatin1String(
"unsigned"),
473 QLatin1String(
"uint"), QLatin1String(
"ulong"), QLatin1String(
"ushort"),
474 QLatin1String(
"uchar"), QLatin1String(
"void"), QLatin1String(
"qlonglong"),
475 QLatin1String(
"qulonglong"), QLatin1String(
"qint"), QLatin1String(
"qint8"),
476 QLatin1String(
"qint16"), QLatin1String(
"qint32"), QLatin1String(
"qint64"),
477 QLatin1String(
"quint"), QLatin1String(
"quint8"), QLatin1String(
"quint16"),
478 QLatin1String(
"quint32"), QLatin1String(
"quint64"), QLatin1String(
"qreal"),
479 QLatin1String(
"cond")
482 static QSet<QString> keywords{
483 QLatin1String(
"and"), QLatin1String(
"and_eq"), QLatin1String(
"asm"), QLatin1String(
"auto"),
484 QLatin1String(
"bitand"), QLatin1String(
"bitor"), QLatin1String(
"break"),
485 QLatin1String(
"case"), QLatin1String(
"catch"), QLatin1String(
"class"),
486 QLatin1String(
"compl"), QLatin1String(
"const"), QLatin1String(
"const_cast"),
487 QLatin1String(
"continue"), QLatin1String(
"default"), QLatin1String(
"delete"),
488 QLatin1String(
"do"), QLatin1String(
"dynamic_cast"), QLatin1String(
"else"),
489 QLatin1String(
"enum"), QLatin1String(
"explicit"), QLatin1String(
"export"),
490 QLatin1String(
"extern"), QLatin1String(
"false"), QLatin1String(
"for"),
491 QLatin1String(
"friend"), QLatin1String(
"goto"), QLatin1String(
"if"),
492 QLatin1String(
"include"), QLatin1String(
"inline"), QLatin1String(
"monitor"),
493 QLatin1String(
"mutable"), QLatin1String(
"namespace"), QLatin1String(
"new"),
494 QLatin1String(
"not"), QLatin1String(
"not_eq"), QLatin1String(
"operator"),
495 QLatin1String(
"or"), QLatin1String(
"or_eq"), QLatin1String(
"private"),
496 QLatin1String(
"protected"), QLatin1String(
"public"), QLatin1String(
"register"),
497 QLatin1String(
"reinterpret_cast"), QLatin1String(
"return"), QLatin1String(
"sizeof"),
498 QLatin1String(
"static"), QLatin1String(
"static_cast"), QLatin1String(
"struct"),
499 QLatin1String(
"switch"), QLatin1String(
"template"), QLatin1String(
"this"),
500 QLatin1String(
"throw"), QLatin1String(
"true"), QLatin1String(
"try"),
501 QLatin1String(
"typedef"), QLatin1String(
"typeid"), QLatin1String(
"typename"),
502 QLatin1String(
"union"), QLatin1String(
"using"), QLatin1String(
"virtual"),
503 QLatin1String(
"volatile"), QLatin1String(
"wchar_t"), QLatin1String(
"while"),
504 QLatin1String(
"xor"), QLatin1String(
"xor_eq"), QLatin1String(
"synchronized"),
506 QLatin1String(
"signals"), QLatin1String(
"slots"), QLatin1String(
"emit")
518 static const QRegularExpression classRegExp(QRegularExpression::anchoredPattern(
"Qt?(?:[A-Z3]+[a-z][A-Za-z]*|t)"));
519 static const QRegularExpression functionRegExp(QRegularExpression::anchoredPattern(
"q([A-Z][a-z]+)+"));
520 static const QRegularExpression findFunctionRegExp(QStringLiteral(
"^\\s*\\("));
523 auto readChar = [&]() {
535 if (ch.isLetter() || ch ==
'_') {
541 }
while (!atEOF && (ch.isLetterOrNumber() || ch ==
'_'));
543 if (classRegExp.match(ident).hasMatch()) {
544 tag = QStringLiteral(
"type");
545 }
else if (functionRegExp.match(ident).hasMatch()) {
546 tag = QStringLiteral(
"func");
548 }
else if (types.contains(ident)) {
549 tag = QStringLiteral(
"type");
550 }
else if (keywords.contains(ident)) {
551 tag = QStringLiteral(
"keyword");
552 }
else if (braceDepth == 0 && parenDepth == 0) {
553 if (code.indexOf(findFunctionRegExp, i - 1) == i - 1)
554 tag = QStringLiteral(
"func");
557 }
else if (ch.isDigit()) {
561 }
while (!atEOF && (ch.isLetterOrNumber() || ch ==
'.' || ch ==
'\''));
562 tag = QStringLiteral(
"number");
564 switch (ch.unicode()) {
584 tag = QStringLiteral(
"op");
590 while (!atEOF && ch !=
'"') {
597 tag = QStringLiteral(
"string");
602 while (!atEOF && ch !=
'\n') {
608 tag = QStringLiteral(
"preprocessor");
614 while (!atEOF && ch !=
'\'') {
621 tag = QStringLiteral(
"char");
636 if (!atEOF && ch ==
':') {
639 tag = QStringLiteral(
"op");
645 if (!atEOF && ch ==
'/') {
649 }
while (!atEOF && ch !=
'\n');
650 tag = QStringLiteral(
"comment");
651 }
else if (ch ==
'*') {
652 bool metAster =
false;
653 bool metAsterSlash =
false;
658 while (!metAsterSlash) {
663 else if (metAster && ch ==
'/')
664 metAsterSlash =
true;
670 tag = QStringLiteral(
"comment");
672 tag = QStringLiteral(
"op");
691 text = QStringView{code}.mid(start, finish - start);
694 if (!tag.isEmpty()) {
695 out += QStringLiteral(
"<@");
698 out += QStringLiteral(
" target=\"");
700 out += QStringLiteral(
"()\"");
702 out += QStringLiteral(
">");
705 appendProtectedString(&out, text);
707 if (!tag.isEmpty()) {
708 out += QStringLiteral(
"</@");
710 out += QStringLiteral(
">");
714 if (start < code.size()) {
715 appendProtectedString(&out, QStringView{code}.mid(start));
The Atom class is the fundamental unit for representing documents internally.
AtomType
\value AnnotatedList \value AutoLink \value BaseName \value BriefLeft \value BriefRight \value C \val...
This node is used to represent any kind of function being documented.
bool isMacroWithoutParams() const
const Parameters & parameters() const
bool isPureVirtual() const override
bool isNonvirtual() const
The Location class provides a way to mark a location in a file.
Interface implemented by Node subclasses that can refer to a C++ enum.
virtual const NativeEnum * nativeEnum() const =0
Encapsulates information about native (C++) enum values.
A class for containing the elements of one documentation section.
constexpr std::size_t MultilineTemplateParamThreshold
Combined button and popup list for selecting options.
The Node class is the base class for all the nodes in QDoc's parse tree.
const Doc & doc() const
Returns a reference to the node's Doc data member.
bool isQmlNode() const
Returns true if this node's Genus value is QML.
bool isEnumType(Genus g) const
bool isHeader() const
Returns true if the node type is HeaderFile.
NodeType nodeType() const override
Returns this node's type.
virtual bool isMacro() const
returns true if either FunctionNode::isMacroWithParams() or FunctionNode::isMacroWithoutParams() retu...
bool isEnumType() const
Returns true if the node type is Enum.
Aggregate * parent() const
Returns the node's parent pointer.
bool isProxyNode() const
Returns true if the node type is Proxy.
bool isFunction(Genus g=Genus::DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
bool isProperty() const
Returns true if the node type is Property.
bool isRelatedNonmember() const
Returns true if this is a related nonmember of something.
bool isQmlProperty() const
Returns true if the node type is QmlProperty.
A class for parsing and managing a function parameter list.
const Parameter & at(int i) const
ValuedDeclaration valued_declaration
@ TemplateTemplateParameter