21#include "ir/contentbuilder.h"
22#include "ir/signaturespan.h"
42#include <QRegularExpression>
49using namespace Qt::Literals;
54 return [loc](QtMsgType type,
const QString &message) {
70 auto result = resolver->hrefForNode(target, relative);
71 if (
const auto *href = std::get_if<QString>(&result))
80 QString deprecatedSince;
82 QString deprecatedSinceQualified;
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101std::optional<DeprecationData> extractDeprecationData(
const Node *node)
104 const auto &version = node->deprecatedSince();
108 DeprecationData data{version, NodeText::nodeTypeDescription(node), version};
109 if (!version.isEmpty() && node->isQmlNode() && !node->logicalModuleName().isEmpty())
110 data.deprecatedSinceQualified = node->logicalModuleName() +
' '_L1 + version;
118const Node *findConceptNodeForRelative(
const Node *relative,
const QString &name)
124 return qdb->findConceptNode(name);
145void appendRequiresSpansWithLinks(QList<IR::SignatureSpan> &out,
146 const QString &requiresText,
147 const QStringList &conceptNames,
148 const HrefResolver *hrefResolver,
149 const Node *relative)
151 auto emitFallback = [&out, &requiresText]() {
154 req.text =
" requires "_L1 + requiresText;
158 if (conceptNames.isEmpty() || requiresText.isEmpty()) {
163 QStringList sorted = conceptNames;
164 std::sort(sorted.begin(), sorted.end(),
165 [](
const QString &a,
const QString &b) {
return a.size() > b.size(); });
172 QHash<QString, QString> targetForDisplay;
173 QStringList escapedAlternatives;
174 escapedAlternatives.reserve(sorted.size() * 2);
175 for (
const QString &name : sorted) {
176 if (!targetForDisplay.contains(name)) {
177 targetForDisplay.insert(name, name);
178 escapedAlternatives.append(QRegularExpression::escape(name));
180 const QString tail = name.section(
"::"_L1, -1);
181 if (tail != name && !targetForDisplay.contains(tail)) {
182 targetForDisplay.insert(tail, name);
183 escapedAlternatives.append(QRegularExpression::escape(tail));
186 const QRegularExpression conceptRegex(
187 u"\\b("_s + escapedAlternatives.join(u"|"_s) + u")\\b"_s);
188 if (!conceptRegex.isValid()) {
193 auto it = conceptRegex.globalMatch(requiresText);
203 lead.text =
" requires "_L1;
207 while (it.hasNext()) {
208 const auto match = it.next();
209 if (match.capturedStart() > pos) {
212 textSpan.text = requiresText.mid(pos, match.capturedStart() - pos);
213 out.append(textSpan);
215 const QString matched = match.captured(1);
216 const QString target = targetForDisplay.value(matched, matched);
217 const Node *cn = findConceptNodeForRelative(relative, target);
218 const QString href = cn ? resolveHref(hrefResolver, cn, relative) : QString();
222 if (href.isEmpty()) {
231 pos = match.capturedEnd();
233 if (pos < requiresText.size()) {
236 tail.text = requiresText.mid(pos);
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
289 SemanticOrigins *origins)
291 Q_ASSERT_X(pn,
"NodeExtractor::extractPageMetadata",
292 "PageNode pointer must be non-null");
301 const auto *qcn =
static_cast<
const QmlTypeNode *>(pn);
302 QString suffix = qcn->isQmlBasicType() ?
" QML Value Type"_L1 :
" QML Type"_L1;
303 pm.title = pn->name() + suffix;
304 pm.fullTitle = pm.title;
309 const auto *aggregate =
static_cast<
const Aggregate *>(pn);
310 pm.fullTitle = aggregate->plainFullName();
311 pm.title = pm.fullTitle;
313 pm.title = pn->title();
314 pm.fullTitle = pn->fullTitle();
317 pm.url = hrefResolver->fileName(pn);
318 const QString baseUrl = Config::instance().get(
CONFIG_URL).asString();
319 if (!baseUrl.isEmpty() && !pm.url.isEmpty() && !pm.url.contains(
"://"_L1)) {
321 + (baseUrl.endsWith(u'/') ? QString{} : QStringLiteral(
"/"))
324 pm.since = pn->since();
325 pm.deprecatedSince = pn->deprecatedSince();
326 if (
const auto deprecation = extractDeprecationData(pn)) {
327 pm.typeNoun = deprecation->typeNoun;
328 pm.deprecatedSinceQualified = deprecation->deprecatedSinceQualified;
330 pm.brief = pn
->doc().briefText().toString();
338 const int headingOffset = [&] {
357 diagnosticHandlerFor(pn));
358 pm.body = contentBuilder.build(firstAtom);
362 const auto *aggregate =
static_cast<
const Aggregate *>(pn);
363 pm.summarySections = extractSummarySections(aggregate, hrefResolver);
364 pm.detailSections = extractDetailSections(aggregate, hrefResolver, origins);
368 const auto *qcn =
static_cast<
const QmlTypeNode *>(pn);
369 pm.qmlTypeData = extractQmlTypeData(qcn, hrefResolver);
373 const auto *cn =
static_cast<
const CollectionNode *>(pn);
374 pm.collectionData = extractCollectionData(cn, hrefResolver);
378 const auto *aggregate =
static_cast<
const Aggregate *>(pn);
379 pm.cppReferenceData = extractCppReferenceData(aggregate, hrefResolver);
388
389
390
391
392
393
394
395
396
397
398
399
400
404 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
406 if (!qcn->logicalModuleName().isEmpty()) {
407 bool includeImport =
true;
414 QStringList parts = QStringList()
415 <<
"import"_L1 << qcn->logicalModuleName() << qcn->logicalModuleVersion();
416 data.importStatement = parts.join(
' '_L1).trimmed();
436 inheritsInfo.name = base->name();
437 inheritsInfo.href = resolveHref(hrefResolver, base, qcn);
442 inheritsInfo.moduleName = base->logicalModuleName();
444 data.inherits = inheritsInfo;
447 if (!subs.isEmpty()) {
448 QList<IR::QmlTypeData::InheritedByEntry> filteredSubs;
449 for (
const auto *sub : std::as_const(subs)) {
450 const NodeContext context = sub->createContext();
451 if (InclusionFilter::isIncluded(policy, context))
452 filteredSubs.append({sub->name(), resolveHref(hrefResolver, sub, qcn)});
454 std::sort(filteredSubs.begin(), filteredSubs.end(),
457 return a.name < b.name;
459 data.inheritedBy = filteredSubs;
465 if (InclusionFilter::isIncluded(policy, context))
466 data.nativeType = IR::QmlTypeData::NativeTypeInfo{cn->name(), resolveHref(hrefResolver, cn, qcn)};
478
479
480
481
482
483
484
485
486
487
488
489
494 data.logicalModuleName = cn->logicalModuleName();
495 data.logicalModuleVersion = cn->logicalModuleVersion();
496 data.qtVariable = cn->qtVariable();
513 const QString rawCmakePackage = cn->cmakePackage();
514 const QString rawCmakeComponent = cn->cmakeComponent();
515 const QString rawCmakeTargetItem = cn->cmakeTargetItem();
516 if (!rawCmakePackage.isEmpty() || !rawCmakeComponent.isEmpty()) {
517 const QString package = rawCmakePackage.isEmpty()
518 ?
"Qt"_L1 + QString::number(QT_VERSION_MAJOR)
520 data.cmakePackage = package;
521 data.cmakeComponent = rawCmakeComponent;
522 if (!rawCmakeTargetItem.isEmpty())
523 data.cmakeTargetItem = rawCmakeTargetItem;
524 else if (!rawCmakeComponent.isEmpty())
525 data.cmakeTargetItem = package +
"::"_L1 + rawCmakeComponent;
528 data.state = cn->state();
539 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
542 return { node->name(), resolveHref(hrefResolver, node, cn), node->doc().briefText().toString() };
545 auto sortEntries = [](QList<IR::CollectionData::MemberEntry> &entries) {
546 std::sort(entries.begin(), entries.end(),
549 return a.name.compare(b.name, Qt::CaseInsensitive) < 0;
555 for (
auto *node : nsMap.values()) {
556 const NodeContext context = node->createContext();
557 if (InclusionFilter::isIncluded(policy, context) && !node->isDeprecated())
558 data.namespaces.append(makeMemberEntry(node));
560 sortEntries(data.namespaces);
563 for (
auto *node : classMap.values()) {
564 const NodeContext context = node->createContext();
565 if (InclusionFilter::isIncluded(policy, context) && !node->isDeprecated())
566 data.classes.append(makeMemberEntry(node));
568 sortEntries(data.classes);
570 for (
const auto *node : cn->members()) {
571 if (!node->isInAPI())
573 const NodeContext context = node->createContext();
574 if (InclusionFilter::isIncluded(policy, context) && !node->isDeprecated())
575 data.members.append(makeMemberEntry(node));
577 sortEntries(data.members);
584 const HrefResolver *hrefResolver,
585 const Node *relative);
588
589
590
591
592
593
594
595
596
597
598
599
600
609 data.typeWord = aggregate->typeWord(
false);
612 auto ancestors = aggregate->plainFullName().split(
"::"_L1);
613 ancestors.pop_back();
614 data.ancestorNames = ancestors;
616 if (aggregate->includeFile())
617 data.headerInclude = *aggregate->includeFile();
619 if (!aggregate->physicalModuleName().isEmpty()) {
622 if (cn && (!cn->cmakeComponent().isEmpty() || !cn->cmakePackage().isEmpty())) {
623 const QString package = cn->cmakePackage().isEmpty()
624 ?
"Qt"_L1 + QString::number(QT_VERSION_MAJOR)
625 : cn->cmakePackage();
627 if (cn->cmakeComponent().isEmpty())
628 findPkg =
"find_package("_L1 + package +
" REQUIRED)"_L1;
630 findPkg =
"find_package("_L1 + package +
" REQUIRED COMPONENTS "_L1
631 + cn->cmakeComponent() +
")"_L1;
634 if (!cn->cmakeTargetItem().isEmpty()) {
635 target = cn->cmakeTargetItem();
636 }
else if (cn->cmakeComponent().isEmpty()) {
637 target = package +
"::"_L1 + package;
639 target = package +
"::"_L1 + cn->cmakeComponent();
642 data.cmakeFindPackage = findPkg;
643 data.cmakeTargetLinkLibraries =
644 "target_link_libraries(mytarget PRIVATE "_L1 + target +
")"_L1;
646 if (cn && !cn->qtVariable().isEmpty())
647 data.qmakeVariable =
"QT += "_L1 + cn->qtVariable();
650 auto statusOpt = formatStatus(aggregate, qdb);
652 data.statusText = *statusOpt;
653 if (aggregate->status() == Status::Deprecated)
654 data.statusCssClass =
"deprecated"_L1;
655 else if (!aggregate->deprecatedSince().isEmpty())
656 data.statusCssClass =
"pending-deprecation"_L1;
657 else if (aggregate->status() == Status::Preliminary)
658 data.statusCssClass =
"preliminary"_L1;
660 data.statusCssClass =
"status"_L1;
664 auto *classNode =
const_cast<ClassNode *>(
static_cast<
const ClassNode *>(aggregate));
666 if (classNode->isQmlNativeType()) {
667 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
668 const NodeContext context = classNode->createContext();
670 QList<QmlTypeNode *> nativeTypes{classNode->qmlNativeTypes().cbegin(),
671 classNode->qmlNativeTypes().cend()};
672 if (!nativeTypes.isEmpty()) {
674 data.qmlNativeType = IR::CppReferenceData::QmlNativeTypeLink{
675 nativeTypes.first()->name(),
676 resolveHref(hrefResolver, nativeTypes.first(), aggregate)
682 const auto *metaTags = classNode->doc().metaTagMap();
683 if (metaTags && metaTags->contains(u"qdoc-suppress-inheritance"_s))
687 const auto &baseClasses = classNode->baseClasses();
688 for (
const auto &bc : baseClasses) {
690 data.baseClasses.append({
691 bc.m_node->plainFullName(),
692 resolveHref(hrefResolver, bc.m_node, aggregate),
698 const auto &derivedClasses = classNode->derivedClasses();
699 for (
const auto &dc : derivedClasses) {
701 data.derivedClasses.append({
702 dc.m_node->plainFullName(),
703 resolveHref(hrefResolver, dc.m_node, aggregate)
707 std::sort(data.derivedClasses.begin(), data.derivedClasses.end(),
710 return a.name.compare(b.name, Qt::CaseInsensitive) < 0;
717 data.templateDeclSpans = buildTemplateDeclSpans(&templateDecl, hrefResolver, aggregate);
718 data.referencedConcepts.reserve(
int(templateDecl.referenced_concepts.size()));
719 for (
const auto &s : templateDecl.referenced_concepts)
720 data.referencedConcepts.append(QString::fromStdString(s));
724 if (selfCategory != ComparisonCategory::None)
725 data.selfComparisonCategory = QString::fromStdString(comparisonCategoryAsString(selfCategory));
727 const auto *comparesMap = aggregate
->doc().comparesWithMap();
728 if (comparesMap && !comparesMap->isEmpty()) {
729 for (
auto [key, description] : comparesMap->asKeyValueRange()) {
730 IR::CppReferenceData::ComparisonEntry entry;
731 entry.category = QString::fromStdString(comparisonCategoryAsString(key));
733 const QStringList types{description.firstAtom()->string().split(
';'_L1)};
734 entry.comparableTypes = types;
736 if (description.firstAtom()->next() != description.lastAtom()) {
737 Text descText = Text::subText(description.firstAtom()->next(),
738 description.lastAtom());
739 entry.description = descText.toString();
741 data.comparisonEntries.append(entry);
749 case Node::NonReentrant:
750 tsInfo.level =
"non-reentrant"_L1;
752 case Node::Reentrant:
753 tsInfo.level =
"reentrant"_L1;
755 case Node::ThreadSafe:
756 tsInfo.level =
"thread-safe"_L1;
762 NodeList reentrant, threadsafe, nonreentrant;
763 bool hasExceptions =
false;
764 for (
const auto *child : aggregate->childNodes()) {
765 if (!child->isDeprecated()) {
766 switch (child->threadSafeness()) {
767 case Node::Reentrant:
768 reentrant.append(
const_cast<Node *>(child));
769 if (ts == Node::ThreadSafe) hasExceptions =
true;
771 case Node::ThreadSafe:
772 threadsafe.append(
const_cast<Node *>(child));
773 if (ts == Node::Reentrant) hasExceptions =
true;
775 case Node::NonReentrant:
776 nonreentrant.append(
const_cast<Node *>(child));
777 hasExceptions =
true;
785 for (
const auto *node : std::as_const(reentrant)) {
786 tsInfo.reentrantExceptions.append({
787 node->plainFullName(),
788 resolveHref(hrefResolver, node, aggregate)
791 for (
const auto *node : std::as_const(threadsafe)) {
792 tsInfo.threadSafeExceptions.append({
793 node->plainFullName(),
794 resolveHref(hrefResolver, node, aggregate)
797 for (
const auto *node : std::as_const(nonreentrant)) {
798 tsInfo.nonReentrantExceptions.append({
799 node->plainFullName(),
800 resolveHref(hrefResolver, node, aggregate)
804 data.threadSafety =
std::move(tsInfo);
807 const QStringList &groupNames = aggregate->groupNames();
808 if (!groupNames.isEmpty()) {
810 for (
const auto &groupName : groupNames) {
811 auto it = groupMap.find(groupName);
812 if (it == groupMap.end() || !*it)
814 CollectionNode *group = *it;
819 qdb->mergeCollections(group);
820 if (group->wasSeen()) {
823 resolveHref(hrefResolver, group, aggregate)
830 const auto *ns =
static_cast<
const NamespaceNode *>(aggregate);
831 if (!ns->hasDoc() && ns->docNode()) {
833 data.fullNamespaceHref = resolveHref(hrefResolver, ns->docNode(), aggregate);
834 data.fullNamespaceModuleName = ns->docNode()->tree()->camelCaseModuleName();
842
843
844
845
846
847
848
855 QList<IR::SectionIR> result;
856 for (
const auto §ion : sv) {
857 if (section.isEmpty())
860 IR::SectionIR irSection;
861 irSection.title = section.title();
862 irSection.id = TextUtils::asAsciiPrintable(section.title());
863 irSection.singular = section.singular();
864 irSection.plural = section.plural();
870 for (
const auto *member : section.members()) {
871 if (member->isSharedCommentNode()) {
872 const auto *scn =
static_cast<
const SharedCommentNode *>(member);
873 for (
const auto *child : scn->collective()) {
874 IR::MemberIR irMember = extractMemberIR(child, hrefResolver, aggregate);
875 irMember.href =
"#"_L1 + hrefResolver->anchorForNode(child);
876 irSection.members.append(irMember);
879 IR::MemberIR irMember = extractMemberIR(member, hrefResolver, aggregate);
880 irMember.href =
"#"_L1 + hrefResolver->anchorForNode(member);
881 irSection.members.append(irMember);
885 for (
const auto *reimpl : section.reimplementedMembers())
886 irSection.reimplementedMembers.append(extractMemberIR(reimpl, hrefResolver, aggregate));
888 for (
const auto &[base, count] : section.inheritedMembers()) {
889 IR::InheritedMembersIR inherited;
890 inherited.className = base->plainFullName();
891 inherited.count = count;
892 inherited.href = resolveHref(hrefResolver, base, aggregate);
893 irSection.inheritedMembers.append(inherited);
896 result.append(irSection);
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
920 SemanticOrigins *origins)
925 QList<IR::SectionIR> result;
926 for (
const auto §ion : sv) {
927 if (section.isEmpty())
930 IR::SectionIR irSection;
931 irSection.title = section.title();
932 irSection.id = TextUtils::asAsciiPrintable(section.title());
933 irSection.singular = section.singular();
934 irSection.plural = section.plural();
938 QList<
const Node *> sectionOrigins;
940 for (
const auto *member : section.members()) {
941 if (member->isSharedCommentNode()) {
942 const auto *scn =
static_cast<
const SharedCommentNode *>(member);
944 QList<IR::ContentBlock> sharedBody;
945 const Text &bodyText = scn->doc().body();
946 if (
const Atom *firstAtom = bodyText.firstAtom()) {
947 IR::ContentBuilder contentBuilder(IR::BriefHandling::Include, 0,
948 diagnosticHandlerFor(scn));
949 sharedBody = contentBuilder.build(firstAtom);
952 QList<IR::ContentBlock> sharedAlso;
953 const QList<Text> &alsoTexts = scn->doc().alsoList();
954 for (
const Text &alsoText : alsoTexts) {
955 if (
const Atom *firstAtom = alsoText.firstAtom()) {
956 IR::ContentBuilder contentBuilder(IR::BriefHandling::Include, 0,
957 diagnosticHandlerFor(scn));
958 sharedAlso.append(contentBuilder.build(firstAtom));
962 for (
const auto *child : scn->collective()) {
963 IR::MemberIR irMember = extractMemberIR(child, hrefResolver, aggregate, MemberExtractionLevel::Detail);
964 irMember.body = sharedBody;
965 irMember.alsoList = sharedAlso;
968 sectionOrigins.append(irMember.anchorId.isEmpty() ?
nullptr : scn);
969 irSection.members.append(irMember);
972 IR::MemberIR irMember = extractMemberIR(member, hrefResolver, aggregate, MemberExtractionLevel::Detail);
973 sectionOrigins.append(irMember.anchorId.isEmpty() ?
nullptr : member);
974 irSection.members.append(irMember);
979 origins->append(std::move(sectionOrigins));
980 result.append(irSection);
988 case Node::Reentrant:
989 return "reentrant"_L1;
990 case Node::ThreadSafe:
991 return "thread-safe"_L1;
998
999
1000
1001
1002
1003
1004
1007 for (
auto &block : blocks) {
1008 if (block.type == IR::BlockType::DefinitionList
1009 && block.attributes.value(QLatin1String(
"listType"))
1011 for (
auto &entry : block.children) {
1012 if (entry.type != IR::BlockType::DefinitionTerm || entry.inlineContent.isEmpty())
1015 for (
const IR::InlineContent &content : entry.inlineContent)
1016 raw += content.plainText();
1017 const QString qualified = en->qualifiedValueName(raw);
1018 if (qualified != raw) {
1019 IR::InlineContent text;
1020 text.type = IR::InlineType::Text;
1021 text.text = qualified;
1022 entry.inlineContent = { text };
1026 qualifyEnumValueTerms(en, block.children);
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1049 member.name = node->name();
1050 member.fullName = node->plainFullName();
1051 member.href = resolveHref(hrefResolver, node, relative);
1057 if (
const auto deprecation = extractDeprecationData(node)) {
1058 member.deprecatedSince = deprecation->deprecatedSince;
1059 member.typeNoun = deprecation->typeNoun;
1060 member.deprecatedSinceQualified = deprecation->deprecatedSinceQualified;
1064 const auto *fn =
static_cast<
const FunctionNode *>(node);
1065 member.signature = fn->signature(
1076 for (
int i = 0; i < params
.count(); ++i) {
1078 param.type = params
.at(i
).type();
1079 param.name = params
.at(i
).name();
1080 param.defaultValue = params
.at(i
).defaultValue();
1081 member.parameters.append(param);
1084 const auto *en =
static_cast<
const EnumNode *>(node);
1085 member.signature = en->isScoped()
1086 ?
"enum class %1"_L1.arg(en->name())
1087 :
"enum %1"_L1.arg(en->name());
1089 for (
const auto &item : en->items()) {
1091 ev.name = item.name();
1092 ev.value = item.value();
1093 ev.since = item.since();
1094 member.enumValues.append(ev);
1097 const auto *qpn =
static_cast<
const QmlPropertyNode *>(node);
1098 member.signature = qpn->name() +
" : "_L1 + qpn->dataType();
1099 member.dataType = qpn->dataType();
1105 const auto *pn =
static_cast<
const PropertyNode *>(node);
1106 member.signature = pn->name() +
" : "_L1 + pn->qualifiedDataType();
1108 const auto *td =
static_cast<
const TypedefNode *>(node);
1109 member.signature = td->associatedEnum()
1110 ?
"flags "_L1 + td->name()
1113 const auto *vn =
static_cast<
const VariableNode *>(node);
1114 member.signature = vn->leftType() + vn->name() + vn->rightType();
1116 member.signature = node->name();
1119 if (includeDetail) {
1120 member.anchorId = hrefResolver->anchorForNode(node);
1121 member.synopsis = member.signature;
1122 member.since = node->since();
1123 member.threadSafety = threadSafenessString(node->threadSafeness());
1126 if (!catStr.empty())
1127 member.comparisonCategory = QString::fromStdString(catStr);
1130 const auto *fn =
static_cast<
const FunctionNode *>(node);
1131 const auto &noexcept_ = fn->getNoexcept();
1134 member.noexceptNote = *noexcept_;
1141 diagnosticHandlerFor(node));
1142 member.body = contentBuilder.build(firstAtom);
1144 qualifyEnumValueTerms(
static_cast<
const EnumNode *>(node), member.body);
1147 const QList<Text> &alsoTexts = node
->doc().alsoList();
1148 for (
const Text &alsoText : alsoTexts) {
1149 if (
const Atom *firstAtom = alsoText.firstAtom()) {
1150 IR::ContentBuilder contentBuilder(IR::BriefHandling::Include, 0,
1151 diagnosticHandlerFor(node));
1152 QList<IR::ContentBlock> blocks = contentBuilder.build(firstAtom);
1153 member.alsoList.append(blocks);
1159 member.signatureSpans = buildSignatureSpans(node, hrefResolver, relative, spanStyle);
1166 QList<IR::SignatureSpan> spans;
1167 QString pendingWord;
1169 for (
int i = 0; i <= typeString.size(); ++i) {
1171 if (i != typeString.size())
1172 ch = typeString.at(i);
1174 QChar lower = ch.toLower();
1175 if ((lower >=
'a'_L1 && lower <=
'z'_L1) || ch.digitValue() >= 0
1176 || ch ==
'_'_L1 || ch ==
':'_L1) {
1179 if (!pendingWord.isEmpty()) {
1180 bool isProbablyType = (pendingWord !=
"const"_L1);
1183 span.text = pendingWord;
1186 pendingWord.clear();
1191 span.text = QString(ch);
1201 QString extraStr = CodeMarker::extraSynopsis(node, style);
1202 if (extraStr.isEmpty())
1208 static const QRegularExpression extrefRegex(
1209 u"<@extref target=\"([^\"]+)\">([^<]+)</@extref>"_s);
1211 QList<IR::SignatureSpan> spans;
1216 auto it = extrefRegex.globalMatch(extraStr);
1217 while (it.hasNext()) {
1218 auto match = it.next();
1219 if (match.capturedStart() > pos) {
1222 textSpan.text = extraStr.mid(pos, match.capturedStart() - pos);
1223 wrapper.children.append(textSpan);
1227 ref.text = match.captured(2);
1228 ref.href =
"https://en.cppreference.com/w/cpp/language/"_L1 + match.captured(1);
1229 wrapper.children.append(ref);
1230 pos = match.capturedEnd();
1232 if (pos < extraStr.size()) {
1235 textSpan.text = extraStr.mid(pos);
1236 wrapper.children.append(textSpan);
1239 if (wrapper.children.isEmpty()) {
1240 wrapper.text = extraStr;
1242 spans.append(wrapper);
1247 const HrefResolver *hrefResolver,
1248 const Node *relative)
1255 declSpan.text =
"template"_L1;
1260 declSpan.children.append(open);
1263 for (
const auto ¶m : templateDecl->parameters) {
1264 if (param.sfinae_constraint)
1267 IR::SignatureSpan comma;
1268 comma.role = IR::SpanRole::Text;
1269 comma.text =
", "_L1;
1270 declSpan.children.append(comma);
1273 switch (param.kind) {
1274 case RelaxedTemplateParameter::Kind::TypeTemplateParameter: {
1275 if (param.concept_name) {
1276 const QString fq = QString::fromStdString(*param.concept_name);
1277 const QString unqualified = fq.section(
"::"_L1, -1);
1280 const Node *conceptNode = findConceptNodeForRelative(relative, fq);
1281 IR::SignatureSpan link;
1282 link.role = IR::SpanRole::Link;
1283 link.text = unqualified;
1284 link.href = resolveHref(hrefResolver, conceptNode, relative);
1285 declSpan.children.append(link);
1287 IR::SignatureSpan kw;
1288 kw.role = IR::SpanRole::Text;
1289 kw.text =
"typename"_L1;
1290 declSpan.children.append(kw);
1294 case RelaxedTemplateParameter::Kind::TemplateTemplateParameter: {
1295 IR::SignatureSpan kw;
1296 kw.role = IR::SpanRole::Text;
1297 kw.text =
"typename"_L1;
1298 declSpan.children.append(kw);
1301 case RelaxedTemplateParameter::Kind::NonTypeTemplateParameter: {
1302 if (!param.valued_declaration.type.empty()) {
1303 auto typeSpans = buildTypeSpans(QString::fromStdString(param.valued_declaration.type));
1304 declSpan.children.append(typeSpans);
1310 if (param.is_parameter_pack) {
1311 IR::SignatureSpan dots;
1312 dots.role = IR::SpanRole::Text;
1313 dots.text =
"..."_L1;
1314 declSpan.children.append(dots);
1317 if (!param.valued_declaration.name.empty()) {
1318 IR::SignatureSpan space;
1319 space.role = IR::SpanRole::Text;
1320 space.text =
" "_L1;
1321 declSpan.children.append(space);
1323 IR::SignatureSpan nameSpan;
1324 nameSpan.role = IR::SpanRole::Parameter;
1325 nameSpan.text = QString::fromStdString(param.valued_declaration.name);
1326 declSpan.children.append(nameSpan);
1329 if (!param.valued_declaration.initializer.empty()) {
1330 IR::SignatureSpan eq;
1331 eq.role = IR::SpanRole::Text;
1333 declSpan.children.append(eq);
1335 if (param.kind == RelaxedTemplateParameter::Kind::TypeTemplateParameter
1336 || param.kind == RelaxedTemplateParameter::Kind::TemplateTemplateParameter) {
1337 auto typeSpans = buildTypeSpans(QString::fromStdString(param.valued_declaration.initializer));
1338 declSpan.children.append(typeSpans);
1340 IR::SignatureSpan val;
1341 val.role = IR::SpanRole::Text;
1342 val.text = QString::fromStdString(param.valued_declaration.initializer);
1343 declSpan.children.append(val);
1352 close.text =
">"_L1;
1353 declSpan.children.append(close);
1355 if (templateDecl->requires_clause && !templateDecl->requires_clause->empty()) {
1356 const QString reqText = QString::fromStdString(*templateDecl->requires_clause);
1357 QStringList conceptNames;
1358 conceptNames.reserve(
int(templateDecl->referenced_concepts.size()));
1359 for (
const auto &s : templateDecl->referenced_concepts)
1360 conceptNames.append(QString::fromStdString(s));
1361 appendRequiresSpansWithLinks(declSpan.children, reqText, conceptNames,
1362 hrefResolver, relative);
1365 return { declSpan };
1369 const HrefResolver *hrefResolver,
1370 const Node *relative,
1373 QList<IR::SignatureSpan> spans;
1375 auto appendText = [&spans](
const QString &text) {
1382 auto appendName = [&spans, node, hrefResolver, relative](
const QString &name) {
1386 span.href = resolveHref(hrefResolver, node, relative);
1390 auto appendTypeSpans = [&spans](
const QString &type,
bool trailingSpace) {
1391 auto typeSpans = buildTypeSpans(type);
1392 spans.append(typeSpans);
1393 if (trailingSpace && !type.isEmpty()
1394 && !type.endsWith(
'*'_L1) && !type.endsWith(
'&'_L1)) {
1397 space.text =
" "_L1;
1398 spans.append(space);
1404 auto extras = buildExtraSpans(node, style);
1405 if (!extras.isEmpty()) {
1406 spans.append(extras);
1412 QString nameText = node->name();
1419 nameText = node->parent()->name() +
"::"_L1 + nameText;
1428 appendText(Node::nodeTypeString(node->nodeType()) +
" "_L1);
1430 appendName(nameText);
1434 span.text = nameText;
1439 const auto *func =
static_cast<
const FunctionNode *>(node);
1442 if (
auto templateDecl = node->templateDecl()) {
1443 auto tmplSpans = buildTemplateDeclSpans(&*templateDecl, hrefResolver, relative);
1444 spans.append(tmplSpans);
1450 if (!func->isNonvirtual())
1451 appendText(
"virtual "_L1);
1455 appendTypeSpans(func->returnTypeString(),
true);
1458 appendName(nameText);
1462 span.text = nameText;
1466 if (!func->isMacroWithoutParams()) {
1468 if (!func->parameters().isEmpty()) {
1469 const Parameters ¶meters = func->parameters();
1470 for (
int i = 0; i < parameters
.count(); ++i) {
1472 appendText(
", "_L1);
1474 QString pName = param.name();
1475 QString type = param.type();
1476 QString value = param.defaultValue();
1477 qsizetype insertPos = param.nameInsertionPoint();
1479 appendTypeSpans(type.left(insertPos),
false);
1482 paramSpan.text = pName;
1483 spans.append(paramSpan);
1484 appendTypeSpans(type.mid(insertPos),
false);
1487 appendTypeSpans(type, trailingSpace);
1491 paramSpan.text = pName;
1492 spans.append(paramSpan);
1496 appendText(
" = "_L1 + value);
1502 if (func->isConst())
1503 appendText(
" const"_L1);
1506 if (func->isFinal())
1507 appendText(
" final"_L1);
1508 if (func->isOverride())
1509 appendText(
" override"_L1);
1510 if (func->isPureVirtual())
1511 appendText(
" = 0"_L1);
1513 appendText(
" &"_L1);
1514 else if (func->isRefRef())
1515 appendText(
" &&"_L1);
1517 if (!func->returnType().isEmpty() && func->returnType() !=
"void"_L1) {
1518 appendText(
" : "_L1);
1519 appendTypeSpans(func->returnTypeString(),
false);
1523 appendText(
" &"_L1);
1524 else if (func->isRefRef())
1525 appendText(
" &&"_L1);
1526 if (
const auto &req = func->trailingRequiresClause(); req && !req->isEmpty())
1527 appendRequiresSpansWithLinks(spans, *req, func->referencedConcepts(),
1528 hrefResolver, relative);
1533 const auto *enume =
static_cast<
const EnumNode *>(node);
1534 appendText(
"enum"_L1);
1535 if (enume->isScoped())
1536 appendText(
" class"_L1);
1537 if (!enume->isAnonymous()) {
1540 appendName(nameText);
1544 span.text = nameText;
1549 appendText(
" { "_L1);
1550 const int MaxEnumValues = 6;
1551 QStringList documentedItems = enume->doc().enumItemNames();
1552 if (documentedItems.isEmpty()) {
1553 const auto &enumItems = enume->items();
1554 for (
const auto &item : enumItems)
1555 documentedItems << item.name();
1557 const QStringList omitItems = enume->doc().omitEnumItemNames();
1558 for (
const auto &item : omitItems)
1559 documentedItems.removeAll(item);
1561 if (documentedItems.size() > MaxEnumValues) {
1562 const QString last = documentedItems.last();
1563 documentedItems = documentedItems.mid(0, MaxEnumValues - 1);
1564 documentedItems +=
"..."_L1;
1565 documentedItems += last;
1567 appendText(documentedItems.join(
", "_L1));
1568 if (!documentedItems.isEmpty())
1576 if (
auto templateDecl = node->templateDecl()) {
1577 auto tmplSpans = buildTemplateDeclSpans(&*templateDecl, hrefResolver, relative);
1578 spans.append(tmplSpans);
1583 appendName(nameText);
1587 span.text = nameText;
1593 if (
static_cast<
const TypedefNode *>(node)->associatedEnum())
1594 appendText(
"flags "_L1);
1596 appendName(nameText);
1600 span.text = nameText;
1606 const auto *property =
static_cast<
const PropertyNode *>(node);
1608 appendName(nameText);
1612 span.text = nameText;
1615 appendText(
" : "_L1);
1616 appendTypeSpans(property->qualifiedDataType(),
false);
1620 const auto *property =
static_cast<
const QmlPropertyNode *>(node);
1622 appendName(nameText);
1626 span.text = nameText;
1629 appendText(
" : "_L1);
1630 appendTypeSpans(property->dataType(),
false);
1634 const auto *variable =
static_cast<
const VariableNode *>(node);
1637 appendName(nameText);
1641 span.text = nameText;
1644 appendText(
" : "_L1);
1645 appendTypeSpans(variable->dataType(),
false);
1647 appendTypeSpans(variable->leftType(),
true);
1649 appendName(nameText);
1653 span.text = nameText;
1656 appendText(variable->rightType());
1662 appendName(nameText);
1666 span.text = nameText;
1676
1677
1678
1679
1680
1681
1682
1683
1685 const HrefResolver *hrefResolver,
1686 const Node *relative)
1688 QList<IR::SignatureSpan> spans;
1690 auto appendText = [&spans](
const QString &text) {
1697 auto appendTypeSpans = [&spans](
const QString &type,
bool trailingSpace) {
1698 auto typeSpans = buildTypeSpans(type);
1699 spans.append(typeSpans);
1700 if (trailingSpace && !type.isEmpty()
1701 && !type.endsWith(
'*'_L1) && !type.endsWith(
'&'_L1)) {
1704 space.text =
" "_L1;
1705 spans.append(space);
1711 nameSpan.text = node->name();
1712 nameSpan.href = resolveHref(hrefResolver, node, relative);
1715 const auto *pn =
static_cast<
const QmlPropertyNode *>(node);
1716 spans.append(nameSpan);
1717 appendText(
" : "_L1);
1718 appendTypeSpans(pn->dataType(),
false);
1720 const auto *func =
static_cast<
const FunctionNode *>(node);
1721 if (!func->returnType().isEmpty())
1722 appendTypeSpans(func->returnTypeString(),
true);
1723 spans.append(nameSpan);
1725 if (!func->parameters().isEmpty()) {
1726 const Parameters ¶meters = func->parameters();
1727 for (
int i = 0; i < parameters
.count(); ++i) {
1729 appendText(
", "_L1);
1730 QString pName = parameters
.at(i
).name();
1731 QString type = parameters
.at(i
).type();
1732 if (!pName.isEmpty()) {
1733 appendTypeSpans(type,
true);
1736 paramSpan.text = pName;
1737 spans.append(paramSpan);
1741 paramSpan.text = type;
1742 spans.append(paramSpan);
1748 spans.append(nameSpan);
1751 auto extras = buildExtraSpans(node, Section::Summary);
1752 if (!extras.isEmpty()) {
1754 spans.append(extras);
1763 for (
const auto &span : spans)
1764 result += span.plainText();
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1783 const HrefResolver *hrefResolver,
1784 const Node *relative,
1787 if (node->isQmlNode() && !node->isEnumType())
1788 return buildQmlItemSpans(node, hrefResolver, relative);
1789 return buildCppSynopsisSpans(node, hrefResolver, relative, style);
1793
1794
1795
1796
1797
1798
1799
1800
1804 result.typeName = qcn->name();
1805 result.typeHref = resolveHref(hrefResolver, qcn, qcn);
1810 if (groupedMembers.isEmpty())
1813 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1816 IR::AllMemberEntry entry;
1817 entry.signatureSpans = buildQmlItemSpans(node, hrefResolver, qcn);
1818 entry.signature = plainTextFromSpans(entry.signatureSpans);
1819 entry.href = resolveHref(hrefResolver, node, qcn);
1821 if (node->isQmlProperty()) {
1822 auto *qpn =
static_cast<QmlPropertyNode *>(node);
1823 QStringList qmlHints = qpn->hints();
1824 if (qpn->isAttached() && !qmlHints.contains(
"attached"_L1))
1825 qmlHints <<
"attached"_L1;
1826 for (
const auto &h : std::as_const(qmlHints))
1827 entry.hints.append(h);
1828 }
else if (node->isAttached()) {
1829 entry.hints.append(
"attached"_L1);
1832 if (node->isPropertyGroup()) {
1833 entry.isPropertyGroup =
true;
1834 const auto *scn =
static_cast<SharedCommentNode *>(node);
1835 for (
auto *child : scn->collective()) {
1836 const NodeContext childContext = child->createContext();
1837 if (!InclusionFilter::isIncluded(policy, childContext))
1839 entry.children.append(buildEntry(child));
1846 auto isVisible = [&policy](
Node *node) {
1848 return InclusionFilter::isIncluded(policy, context)
1849 && !(node->isSharingComment() && node->sharedCommentNode()->isPropertyGroup());
1852 for (
const auto &[originType, nodes] : groupedMembers) {
1853 Q_ASSERT(originType);
1854 if (nodes.isEmpty())
1857 IR::MemberGroup group;
1858 if (originType != qcn) {
1859 group.typeName = originType->name();
1860 group.typeHref = resolveHref(hrefResolver, originType, qcn);
1863 for (
auto *node : nodes) {
1864 if (isVisible(node))
1865 group.members.append(buildEntry(node));
1868 result.memberGroups.append(group);
1875
1876
1877
1878
1879
1880
1881
1885 result.typeName = aggregate->plainFullName();
1886 result.typeHref = resolveHref(hrefResolver, aggregate, aggregate);
1894 const InclusionPolicy policy = Config::instance().createInclusionPolicy();
1896 for (
const auto *node : allMembers.members()) {
1897 if (node->name().isEmpty())
1899 const NodeContext context = node->createContext();
1900 if (!InclusionFilter::isIncluded(policy, context))
1902 if (node->isFunction()
1903 &&
static_cast<
const FunctionNode *>(node)->isIgnored())
1906 IR::AllMemberEntry entry;
1907 entry.signatureSpans = buildSignatureSpans(node, hrefResolver, aggregate, Section::AllMembers);
1908 entry.signature = plainTextFromSpans(entry.signatureSpans);
1909 entry.href = resolveHref(hrefResolver, node, aggregate);
1910 result.members.append(entry);
1917
1918
1919
1920
1921
1922
1923
1924
1928 const auto *qcn =
static_cast<
const QmlTypeNode *>(pn);
1929 if (qcn->isQmlBasicType())
1930 return std::nullopt;
1931 auto result = extractQmlAllMembersIR(qcn, hrefResolver);
1932 bool hasMember =
false;
1933 for (
const auto &group : std::as_const(result.memberGroups)) {
1934 if (!group.members.isEmpty()) {
1940 return std::nullopt;
1945 const auto *aggregate =
static_cast<
const Aggregate *>(pn);
1946 auto result = extractCppAllMembersIR(aggregate, hrefResolver);
1947 if (result.members.isEmpty())
1948 return std::nullopt;
1952 return std::nullopt;
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1977 const Config &config = Config::instance();
1981 const QString homepage = config.get(navDot +
CONFIG_HOMEPAGE).asString();
1982 const QString hometitle = config.get(navDot +
CONFIG_HOMETITLE).asString(homepage);
1984 const QString landingtitle = config.get(navDot +
CONFIG_LANDINGTITLE).asString(landingpage);
1988 const QString qmltypestitle = config.get(navDot +
CONFIG_QMLTYPESTITLE).asString(
"QML Types"_L1);
1990 const QString pageTitle = pn->title();
1993 auto resolveCrumb = [&](
const QString &targetName)
1994 -> std::pair<QString, CrumbState> {
1995 const Node *target = qdb->findNodeForTarget(targetName, pn);
1997 return {{}, CrumbState::Unresolved};
1999 return {{}, CrumbState::Current};
2000 return {resolveHref(hrefResolver, target, pn), CrumbState::Link};
2003 if (!homepage.isEmpty()) {
2004 auto [href, state] = resolveCrumb(homepage);
2005 if (state == CrumbState::Current)
2007 nav.breadcrumbs.append({hometitle,
std::move(href), state});
2010 if (!landingpage.isEmpty()) {
2011 auto [href, state] = resolveCrumb(landingpage);
2012 if (state != CrumbState::Current)
2013 nav.breadcrumbs.append({landingtitle,
std::move(href), state});
2017 if (!cppclassespage.isEmpty() && !cppclassestitle.isEmpty()) {
2018 auto [href, state] = resolveCrumb(cppclassespage);
2019 nav.breadcrumbs.append({cppclassestitle,
std::move(href), state});
2023 QString moduleState;
2024 if (moduleNode && !moduleNode->state().isEmpty())
2025 moduleState = QStringLiteral(
" (%1)").arg(moduleNode->state());
2027 if (!pn->physicalModuleName().isEmpty() && moduleNode
2028 && (!moduleState.isEmpty() || moduleNode->title() != cppclassespage)) {
2029 nav.breadcrumbs.append({moduleNode->name() + moduleState,
2030 resolveHref(hrefResolver, moduleNode, pn),
2033 nav.breadcrumbs.append({pn->name(), {}, CrumbState
::Current});
2035 if (!qmltypespage.isEmpty() && !qmltypestitle.isEmpty()) {
2036 auto [href, state] = resolveCrumb(qmltypespage);
2037 nav.breadcrumbs.append({qmltypestitle,
std::move(href), state});
2041 QString moduleState;
2042 if (moduleNode && !moduleNode->state().isEmpty())
2043 moduleState = QStringLiteral(
" (%1)").arg(moduleNode->state());
2046 && (!moduleState.isEmpty() || moduleNode->title() != qmltypespage)) {
2047 nav.breadcrumbs.append({moduleNode->name() + moduleState,
2048 resolveHref(hrefResolver, moduleNode, pn),
2051 nav.breadcrumbs.append({pn->name(), {}, CrumbState
::Current});
2053 auto currentNode = pn;
2054 std::deque<
const Node *> navNodes;
2055 qsizetype navItems = 0;
2057 if (
std::find(navNodes.cbegin(), navNodes.cend(),
2062 if (navNodes.empty()) {
2063 const QStringList groups = pn->groupNames();
2064 for (
const auto &groupName : groups) {
2065 const auto *groupNode = qdb->findNodeByNameAndType(
2066 QStringList{groupName}, &Node::isGroup);
2067 if (groupNode && !groupNode->title().isEmpty()) {
2068 navNodes.push_front(groupNode);
2073 for (
const auto *navNode : navNodes) {
2074 if (navNode->isPageNode())
2075 nav.breadcrumbs.append({navNode->title(),
2076 resolveHref(hrefResolver, navNode, pn),
2079 if (!nav.breadcrumbs.isEmpty())
2080 nav.breadcrumbs.append({pageTitle, {}, CrumbState
::Current});
2083 const auto &linkMap = pn->links();
2084 if (linkMap.contains(Node::PreviousLink)) {
2085 const auto &linkPair = linkMap[Node::PreviousLink];
2086 const Node *target = qdb->findNodeForTarget(linkPair.first, pn);
2089 if (target && target != pn) {
2090 href = resolveHref(hrefResolver, target, pn);
2091 title = (linkPair.first == linkPair.second && !target->title().isEmpty())
2092 ? target->title() : linkPair.second;
2094 href = linkPair.first;
2095 title = linkPair.second;
2099 if (linkMap.contains(Node::NextLink)) {
2100 const auto &linkPair = linkMap[Node::NextLink];
2101 const Node *target = qdb->findNodeForTarget(linkPair.first, pn);
2104 if (target && target != pn) {
2105 href = resolveHref(hrefResolver, target, pn);
2106 title = (linkPair.first == linkPair.second && !target->title().isEmpty())
2107 ? target->title() : linkPair.second;
2109 href = linkPair.first;
2110 title = linkPair.second;
2114 if (linkMap.contains(Node::StartLink)) {
2115 const auto &linkPair = linkMap[Node::StartLink];
2116 const Node *target = qdb->findNodeForTarget(linkPair.first, pn);
2119 if (target && target != pn) {
2120 href = resolveHref(hrefResolver, target, pn);
2121 title = (linkPair.first == linkPair.second && !target->title().isEmpty())
2122 ? target->title() : linkPair.second;
2124 href = linkPair.first;
2125 title = linkPair.second;
2130 const QString formatDot =
"HTML"_L1 + Config::dot;
2131 nav
.tocDepth = config.get(formatDot +
"tocdepth"_L1).asInt();
bool hasObsoleteMembers() const
Returns true if this aggregate contains at least one child that is marked obsolete.
The Atom class is the fundamental unit for representing documents internally.
The ClassNode represents a C++ class.
A class for holding the members of a collection of doc pages.
NodeMap getMembers(NodeType type) const
The Config class contains the configuration variables for controlling how qdoc produces documentation...
const Location & location() const
Returns the starting location of a qdoc comment.
const Text & body() const
Text briefText(bool inclusive=false) const
Converts Atom chains to QList<IR::ContentBlock> trees.
static bool isIncluded(const InclusionPolicy &policy, const NodeContext &context)
The Location class provides a way to mark a location in a file.
A PageNode is a Node that generates a documentation page.
const PageNode * navigationParent() const
bool noAutoList() const
Returns the value of the no auto-list flag.
The Parameter class describes one function parameter.
This class provides exclusive access to the qdoc database, which consists of a forrest of trees and a...
static QDocDatabase * qdocDB()
Creates the singleton.
const CollectionNode * getModuleNode(const Node *relative)
Returns the collection node representing the module that relative node belongs to,...
const CNMap & groups()
Returns a const reference to the collection of all group nodes in the primary tree.
Status
Specifies the status of the QQmlIncubator.
ClassNode * classNode() const override
If this is a QmlTypeNode, this function returns the pointer to the C++ ClassNode that this QML type r...
static void subclasses(const Node *base, NodeList &subs, bool recurse=false)
Loads the list subs with the nodes of all the subclasses of base.
QmlTypeNode * qmlBaseNode() const override
If this Aggregate is a QmlTypeNode, this function returns a pointer to the QmlTypeNode that is its ba...
CollectionNode * logicalModule() const override
If this is a QmlTypeNode, a pointer to its QML module is returned, which is a pointer to a Collection...
A class for containing the elements of one documentation section.
ClassNodesList & classNodesList()
A class for creating vectors of collections for documentation.
SectionVector & summarySections()
Sections(const Aggregate *aggregate)
This constructor builds the section vectors based on the type of the aggregate node.
bool hasObsoleteMembers(SectionPtrVector *summary_spv, SectionPtrVector *details_spv) const
Returns true if any sections in this object contain obsolete members.
SectionVector & detailsSections()
Section & allMembersSection()
const Atom * firstAtom() const
static std::string comparisonCategoryAsString(ComparisonCategory category)
#define CONFIG_CPPCLASSESTITLE
#define CONFIG_QMLTYPESPAGE
#define CONFIG_CPPCLASSESPAGE
#define CONFIG_NAVIGATION
#define CONFIG_LANDINGPAGE
#define CONFIG_LANDINGTITLE
#define CONFIG_QMLTYPESTITLE
QMap< QString, Node * > NodeMap
QList< const Section * > SectionPtrVector
QList< ClassNodes > ClassNodesList
A single entry in an all-members listing page.
Intermediate representation of the all-members listing page.
Intermediate representation of a single documentable member.
Intermediate representation of a function parameter.
Represents a single span within a structured signature.
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 isGroup() const
Returns true if the node type is Group.
bool isNamespace() const
Returns true if the node type is Namespace.
bool isTypedef() const
Returns true if the node type is Typedef.
bool isQmlBasicType() const
Returns true if the node type is QmlBasicType.
ComparisonCategory comparisonCategory() const
bool isQmlType() const
Returns true if the node type is QmlType or QmlValueType.
bool isHeader() const
Returns true if the node type is HeaderFile.
NodeType nodeType() const override
Returns this node's type.
Genus genus() const override
Returns this node's Genus.
bool isEnumType() const
Returns true if the node type is Enum.
virtual Status status() const
Returns the node's status value.
Aggregate * parent() const
Returns the node's parent pointer, that is, the aggregate under which the node is documented.
virtual bool isAggregate() const
Returns true if this node is an aggregate, which means it inherits Aggregate and can therefore have c...
static bool nodeNameLessThan(const Node *first, const Node *second)
Returns true if the node n1 is less than node n2.
bool isProxyNode() const
Returns true if the node type is Proxy.
const std::optional< RelaxedTemplateDeclaration > & templateDecl() const
Access access() const
Returns the node's Access setting, which can be Public, Protected, or Private.
bool isFunction(Genus g=Genus::DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
ThreadSafeness threadSafeness() const
Returns the thread safeness value for whatever this node represents.
bool isProperty() const
Returns true if the node type is Property.
NodeContext createContext() const
bool isModule() const
Returns true if the node type is Module.
ThreadSafeness
An unsigned char that specifies the degree of thread-safeness of the element.
bool isRelatedNonmember() const
Returns true if this is a related nonmember of something.
virtual bool isClassNode() const
Returns true if this is an instance of ClassNode.
virtual bool isCollectionNode() const
Returns true if this is an instance of CollectionNode.
bool isQmlModule() const
Returns true if the node type is QmlModule.
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