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;
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;
109 for (
const auto ¶m : templateDecl.parameters) {
110 if (param.sfinae_constraint)
113 result += multiline ?
",\n"_L1 :
", "_L1;
117 result += formatTemplateParameter(param);
130
131
132
133
134
135
136
137
141 const auto format = multiline ? TemplateFormat::MultiLine : TemplateFormat::SingleLine;
143 QString content = formatTemplateDeclStorage(*templateDecl, format);
147 result =
"<@template-block>"_L1;
151 if (templateDecl->requires_clause && !templateDecl->requires_clause->empty())
152 result +=
" requires "_L1 + protect(QString::fromStdString(*templateDecl->requires_clause));
155 result +=
'\n'_L1 +
"</@template-block>"_L1;
163
164
165bool CppCodeMarker::recognizeCode(
const QString & )
171
172
173
174bool CppCodeMarker::recognizeExtension(
const QString &extension)
176 QByteArray ext = extension.toLatin1();
177 return ext ==
"c" || ext ==
"c++" || ext ==
"qdoc" || ext ==
"qtt" || ext ==
"qtx"
178 || ext ==
"cc" || ext ==
"cpp" || ext ==
"cxx" || ext ==
"ch" || ext ==
"h"
179 || ext ==
"h++" || ext ==
"hh" || ext ==
"hpp" || ext ==
"hxx";
183
184
185bool CppCodeMarker::recognizeLanguage(
const QString &lang)
187 return lang == QLatin1String(
"c") || lang == QLatin1String(
"cpp");
191
192
198QString CppCodeMarker::markedUpCode(
const QString &code,
const Node *relative,
201 return addMarkUp(code, relative, location);
204QString CppCodeMarker::markedUpSynopsis(
const Node *node,
const Node * ,
207 const int MaxEnumValues = 6;
214 name = taggedNode(node);
215 if (style != Section::Details)
216 name = linkTag(node, name);
217 name =
"<@name>" + name +
"</@name>";
222 name.prepend(taggedNode(node->parent()) +
"::");
232 synopsis += QLatin1Char(
' ') + name;
237 if (
auto templateDecl = node->templateDecl())
238 synopsis = formatTemplateDecl(&*templateDecl);
241 synopsis += typified(func->returnTypeString(),
true);
244 synopsis += QLatin1Char(
'(');
247 for (
int i = 0; i < parameters
.count(); ++i) {
251 QString name = param.name();
252 QString type = param.type();
253 QString value = param.defaultValue();
254 qsizetype insertPos = param.nameInsertionPoint();
257 synopsis += typified(type.left(insertPos),
false);
258 synopsis +=
"<@param>" + protect(name) +
"</@param>";
259 synopsis += typified(type.mid(insertPos),
false);
262 synopsis += typified(type, trailingSpace);
264 synopsis +=
"<@param>" + protect(name) +
"</@param>";
267 synopsis +=
" = " + protect(value);
270 synopsis += QLatin1Char(
')');
273 synopsis +=
" const";
277 synopsis.prepend(
"virtual ");
279 synopsis.append(
" final");
281 synopsis.append(
" override");
283 synopsis.append(
" = 0");
285 synopsis.append(
" &");
287 synopsis.append(
" &&");
289 if (!func->returnType().isEmpty() && func->returnType() !=
"void")
290 synopsis +=
" : " + typified(func->returnTypeString());
293 synopsis.append(
" &");
295 synopsis.append(
" &&");
296 if (
const auto &req = func->trailingRequiresClause(); req && !req->isEmpty())
297 synopsis.append(
" requires " + protect(*req));
301 enume =
static_cast<
const EnumNode *>(node);
304 synopsis +=
" class";
305 if (!enume->isAnonymous())
306 synopsis +=
" %1"_L1.arg(name);
307 else if (style != Section::Details)
308 synopsis = linkTag(node, synopsis);
312 QStringList documentedItems = enume
->doc().enumItemNames();
313 if (documentedItems.isEmpty()) {
314 const auto &enumItems = enume->items();
315 for (
const auto &item : enumItems)
316 documentedItems << item.name();
318 const QStringList omitItems = enume
->doc().omitEnumItemNames();
319 for (
const auto &item : omitItems)
320 documentedItems.removeAll(item);
322 if (documentedItems.size() > MaxEnumValues) {
324 const QString last = documentedItems.last();
325 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
326 documentedItems +=
"…";
327 documentedItems += last;
329 synopsis += documentedItems.join(QLatin1String(
", "));
331 if (!documentedItems.isEmpty())
332 synopsis += QLatin1Char(
' ');
333 synopsis += QLatin1Char(
'}');
338 if (
auto templateDecl = node->templateDecl())
339 synopsis += formatTemplateDecl(&*templateDecl);
344 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
349 auto property =
static_cast<
const PropertyNode *>(node);
350 synopsis = name +
" : " + typified(property->qualifiedDataType());
354 auto property =
static_cast<
const QmlPropertyNode *>(node);
355 synopsis = name +
" : " + typified(property->dataType());
358 case NodeType::Variable:
359 variable =
static_cast<
const VariableNode *>(node);
361 synopsis = name +
" : " + typified(variable->dataType());
363 synopsis = typified(variable->leftType(),
true) + name + protect(variable->rightType());
367 synopsis =
std::move(name);
370 QString extra = CodeMarker::extraSynopsis(node, style);
371 if (!extra.isEmpty()) {
372 extra.prepend(u"<@extra>"_s);
373 extra.append(u"</@extra> "_s);
376 return extra + synopsis;
380
381QString CppCodeMarker::markedUpQmlItem(
const Node *node,
bool summary)
383 QString name = taggedQmlNode(node);
387 name = linkTag(node, name);
389 const auto *pn =
static_cast<
const QmlPropertyNode *>(node);
390 if (pn->isAttached())
391 name.prepend(pn->element() + QLatin1Char(
'.'));
393 name =
"<@name>" + name +
"</@name>";
395 const auto *pn =
static_cast<
const QmlPropertyNode *>(node);
396 synopsis = name +
" : " + typified(pn->dataType());
398 const auto *func =
static_cast<
const FunctionNode *>(node);
399 if (!func->returnType().isEmpty())
400 synopsis = typified(func->returnTypeString(),
true) + name;
403 synopsis += QLatin1Char(
'(');
404 if (!func->parameters().isEmpty()) {
405 const Parameters ¶meters = func->parameters();
406 for (
int i = 0; i < parameters
.count(); ++i) {
409 QString name = parameters
.at(i
).name();
410 QString type = parameters
.at(i
).type();
412 if (!name.isEmpty()) {
413 synopsis += typified(type,
true);
414 paramName =
std::move(name);
416 paramName =
std::move(type);
418 synopsis +=
"<@param>" + protect(paramName) +
"</@param>";
421 synopsis += QLatin1Char(
')');
423 synopsis =
std::move(name);
427 if (!extra.isEmpty()) {
428 extra.prepend(u" <@extra>"_s);
429 extra.append(u"</@extra>"_s);
432 return synopsis + extra;
435QString CppCodeMarker::markedUpName(
const Node *node)
437 QString name = linkTag(node, taggedNode(node));
443QString CppCodeMarker::markedUpEnumValue(
const QString &enumValue,
const Node *relative)
451 if (nativeEnum && nativeEnum->enumNode()
452 && !enumValue.startsWith(
"%1."_L1.arg(nativeEnum->prefix())))
453 return "%1<@op>.</@op>%2"_L1.arg(nativeEnum->prefix(), enumValue);
457 && enumValue.section(
' ', 0, 0).contains(
'.'_L1)) {
458 return "<@op>%1</@op>"_L1.arg(enumValue);
466 parts.prepend(markedUpName(node));
471 if (
static_cast<
const EnumNode *>(relative)->isScoped())
472 parts.append(relative->name());
474 parts.append(enumValue);
475 const auto &delim = (relative->genus() == Genus::QML) ?
"."_L1 :
"::"_L1;
476 return parts.join(
"<@op>%1</@op>"_L1.arg(delim));
479QString CppCodeMarker::addMarkUp(
const QString &in,
const Node * ,
482 static QSet<QString> types{
483 QLatin1String(
"bool"), QLatin1String(
"char"), QLatin1String(
"double"),
484 QLatin1String(
"float"), QLatin1String(
"int"), QLatin1String(
"long"),
485 QLatin1String(
"short"), QLatin1String(
"signed"), QLatin1String(
"unsigned"),
486 QLatin1String(
"uint"), QLatin1String(
"ulong"), QLatin1String(
"ushort"),
487 QLatin1String(
"uchar"), QLatin1String(
"void"), QLatin1String(
"qlonglong"),
488 QLatin1String(
"qulonglong"), QLatin1String(
"qint"), QLatin1String(
"qint8"),
489 QLatin1String(
"qint16"), QLatin1String(
"qint32"), QLatin1String(
"qint64"),
490 QLatin1String(
"quint"), QLatin1String(
"quint8"), QLatin1String(
"quint16"),
491 QLatin1String(
"quint32"), QLatin1String(
"quint64"), QLatin1String(
"qreal"),
492 QLatin1String(
"cond")
495 static QSet<QString> keywords{
496 QLatin1String(
"and"), QLatin1String(
"and_eq"), QLatin1String(
"asm"), QLatin1String(
"auto"),
497 QLatin1String(
"bitand"), QLatin1String(
"bitor"), QLatin1String(
"break"),
498 QLatin1String(
"case"), QLatin1String(
"catch"), QLatin1String(
"class"),
499 QLatin1String(
"compl"), QLatin1String(
"const"), QLatin1String(
"const_cast"),
500 QLatin1String(
"continue"), QLatin1String(
"default"), QLatin1String(
"delete"),
501 QLatin1String(
"do"), QLatin1String(
"dynamic_cast"), QLatin1String(
"else"),
502 QLatin1String(
"enum"), QLatin1String(
"explicit"), QLatin1String(
"export"),
503 QLatin1String(
"extern"), QLatin1String(
"false"), QLatin1String(
"for"),
504 QLatin1String(
"friend"), QLatin1String(
"goto"), QLatin1String(
"if"),
505 QLatin1String(
"include"), QLatin1String(
"inline"), QLatin1String(
"monitor"),
506 QLatin1String(
"mutable"), QLatin1String(
"namespace"), QLatin1String(
"new"),
507 QLatin1String(
"not"), QLatin1String(
"not_eq"), QLatin1String(
"operator"),
508 QLatin1String(
"or"), QLatin1String(
"or_eq"), QLatin1String(
"private"),
509 QLatin1String(
"protected"), QLatin1String(
"public"), QLatin1String(
"register"),
510 QLatin1String(
"reinterpret_cast"), QLatin1String(
"return"), QLatin1String(
"sizeof"),
511 QLatin1String(
"static"), QLatin1String(
"static_cast"), QLatin1String(
"struct"),
512 QLatin1String(
"switch"), QLatin1String(
"template"), QLatin1String(
"this"),
513 QLatin1String(
"throw"), QLatin1String(
"true"), QLatin1String(
"try"),
514 QLatin1String(
"typedef"), QLatin1String(
"typeid"), QLatin1String(
"typename"),
515 QLatin1String(
"union"), QLatin1String(
"using"), QLatin1String(
"virtual"),
516 QLatin1String(
"volatile"), QLatin1String(
"wchar_t"), QLatin1String(
"while"),
517 QLatin1String(
"xor"), QLatin1String(
"xor_eq"), QLatin1String(
"synchronized"),
519 QLatin1String(
"signals"), QLatin1String(
"slots"), QLatin1String(
"emit")
531 static const QRegularExpression classRegExp(QRegularExpression::anchoredPattern(
"Qt?(?:[A-Z3]+[a-z][A-Za-z]*|t)"));
532 static const QRegularExpression functionRegExp(QRegularExpression::anchoredPattern(
"q([A-Z][a-z]+)+"));
533 static const QRegularExpression findFunctionRegExp(QStringLiteral(
"^\\s*\\("));
536 auto readChar = [&]() {
548 if (ch.isLetter() || ch ==
'_') {
554 }
while (!atEOF && (ch.isLetterOrNumber() || ch ==
'_'));
556 if (classRegExp.match(ident).hasMatch()) {
557 tag = QStringLiteral(
"type");
558 }
else if (functionRegExp.match(ident).hasMatch()) {
559 tag = QStringLiteral(
"func");
561 }
else if (types.contains(ident)) {
562 tag = QStringLiteral(
"type");
563 }
else if (keywords.contains(ident)) {
564 tag = QStringLiteral(
"keyword");
565 }
else if (braceDepth == 0 && parenDepth == 0) {
566 if (code.indexOf(findFunctionRegExp, i - 1) == i - 1)
567 tag = QStringLiteral(
"func");
570 }
else if (ch.isDigit()) {
574 }
while (!atEOF && (ch.isLetterOrNumber() || ch ==
'.' || ch ==
'\''));
575 tag = QStringLiteral(
"number");
577 switch (ch.unicode()) {
597 tag = QStringLiteral(
"op");
603 while (!atEOF && ch !=
'"') {
610 tag = QStringLiteral(
"string");
615 while (!atEOF && ch !=
'\n') {
621 tag = QStringLiteral(
"preprocessor");
627 while (!atEOF && ch !=
'\'') {
634 tag = QStringLiteral(
"char");
649 if (!atEOF && ch ==
':') {
652 tag = QStringLiteral(
"op");
658 if (!atEOF && ch ==
'/') {
662 }
while (!atEOF && ch !=
'\n');
663 tag = QStringLiteral(
"comment");
664 }
else if (ch ==
'*') {
665 bool metAster =
false;
666 bool metAsterSlash =
false;
671 while (!metAsterSlash) {
676 else if (metAster && ch ==
'/')
677 metAsterSlash =
true;
683 tag = QStringLiteral(
"comment");
685 tag = QStringLiteral(
"op");
704 text = QStringView{code}.mid(start, finish - start);
707 if (!tag.isEmpty()) {
708 out += QStringLiteral(
"<@");
711 out += QStringLiteral(
" target=\"");
713 out += QStringLiteral(
"()\"");
715 out += QStringLiteral(
">");
718 appendProtectedString(&out, text);
720 if (!tag.isEmpty()) {
721 out += QStringLiteral(
"</@");
723 out += QStringLiteral(
">");
727 if (start < code.size()) {
728 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.
The Parameter class describes one function parameter.
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
std::size_t visibleParameterCount() const
Returns the number of template parameters that are visible in rendered output — SFINAE-annotated para...
ValuedDeclaration valued_declaration
@ NonTypeTemplateParameter
@ TemplateTemplateParameter