15#include <QtCore/qfileinfo.h>
16#include <QtCore/qobjectdefs.h>
20using namespace Qt::StringLiterals;
27
28
29
30
31
32
35 s_markers.prepend(
this);
39
40
41
44 s_markers.removeAll(
this);
48
49
50
54
55
62
63
64
68 for (
const auto &marker : std::as_const(s_markers))
69 marker->initializeMarker();
73
74
77 for (
const auto &marker : std::as_const(s_markers))
78 marker->terminateMarker();
83 CodeMarker *defaultMarker = markerForLanguage(s_defaultLang);
84 if (defaultMarker !=
nullptr && defaultMarker->recognizeCode(code))
87 for (
const auto &marker : std::as_const(s_markers)) {
88 if (marker->recognizeCode(code))
96
97
98
99
100
103 CodeMarker *defaultMarker = markerForLanguage(s_defaultLang);
105 while ((dot = fileName.lastIndexOf(QLatin1Char(
'.'), dot)) != -1) {
106 QString ext = fileName.mid(dot + 1);
107 if (defaultMarker !=
nullptr && defaultMarker->recognizeExtension(ext))
108 return defaultMarker;
109 for (
const auto &marker : std::as_const(s_markers)) {
110 if (marker->recognizeExtension(ext))
116 QString name = QFileInfo(fileName).fileName();
117 for (
const auto &marker : std::as_const(s_markers)) {
118 if (marker->recognizeFileName(name))
121 return defaultMarker;
126 for (
const auto &marker : std::as_const(s_markers)) {
127 if (marker->recognizeLanguage(lang.toLower()))
135 return (name ==
"qmldir"_L1);
140 return (language ==
"text"_L1);
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
164 if (node->isPreliminary())
165 return std::optional(Config::instance().get(
CONFIG_PRELIMINARY).asString().toLower());
168 if (
const auto &since = node->since(); !since.isEmpty())
169 result <<
"since %1"_L1.arg(since);
170 if (
const auto &deprecated = node->deprecatedSince(); !deprecated.isEmpty()) {
171 if (node->isDeprecated())
172 result <<
"deprecated in %1"_L1.arg(deprecated);
174 result <<
"until %1"_L1.arg(deprecated);
176 result << u"deprecated"_s;
179 return result.isEmpty() ?
std::nullopt :
std::optional(result.join(u", "_s));
183
184
185
195 if (
static_cast<
const EnumNode *>(node)->isAnonymous())
196 extra <<
"anonymous";
201 if (
static_cast<
const ClassNode *>(node)->isAnonymous())
202 extra <<
"anonymous";
205 const auto *func =
static_cast<
const FunctionNode *>(node);
206 if (func->isStatic()) {
208 }
else if (!func->isNonvirtual()) {
211 if (func->isOverride())
213 if (func->isPureVirtual())
218 if (func->isExplicit()) extra <<
"explicit";
219 if (func->isConstexpr()) extra <<
"constexpr";
220 if (
auto noexcept_info = func->getNoexcept()) {
221 extra << (QString(
"noexcept") + (!(*noexcept_info).isEmpty() ?
"(...)" :
""));
225 extra <<
"protected";
229 if (func->isSignal()) {
230 if (func->parameters().isPrivateSignal())
233 }
else if (func->isSlot())
235 else if (func->isImplicitlyGenerated())
237 else if (func->isExplicitlyDefaulted())
238 extra <<
"<@extref target=\"cpp-explicitly-defaulted\">default</@extref>";
239 else if (func->isDeletedAsWritten())
240 extra <<
"<@extref target=\"cpp-deleted-functions\">delete</@extref>";
241 else if (func->isInvokable())
242 extra <<
"invokable";
249 auto propertyNode =
static_cast<
const PropertyNode *>(node);
252 if (!propertyNode->isWritable())
253 extra <<
"read-only";
257 auto qmlProperty =
static_cast<
const QmlPropertyNode *>(node);
258 extra << qmlProperty->hints();
260 if (!qmlProperty->isDefault() && !qmlProperty->defaultValue().isEmpty())
261 extra << u"default: "_s + qmlProperty->defaultValue();
270 if (
auto status = nodeStatusAsString(node)) {
271 if (!extra.isEmpty())
272 extra.last() +=
','_L1;
276 QString extraStr = extra.join(QLatin1Char(
' '));
277 if (!extraStr.isEmpty()) {
287 return Utilities::protect(str);
290void CodeMarker::appendProtectedString(QString *output, QStringView str)
292 qsizetype n = str.size();
293 output->reserve(output->size() + n * 2 + 30);
294 const QChar *data = str.constData();
295 for (
int i = 0; i != n; ++i) {
296 switch (data[i].unicode()) {
298 *output += Utilities::samp;
301 *output += Utilities::slt;
304 *output += Utilities::sgt;
307 *output += Utilities::squot;
320 for (
int i = 0; i <= string.size(); ++i) {
322 if (i != string.size())
325 QChar lower = ch.toLower();
326 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
327 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
330 if (!pendingWord.isEmpty()) {
331 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
333 result += QLatin1String(
"<@type>");
334 result += pendingWord;
336 result += QLatin1String(
"</@type>");
340 switch (ch.unicode()) {
344 result += QLatin1String(
"&");
347 result += QLatin1String(
"<");
350 result += QLatin1String(
">");
357 if (trailingSpace && string.size()) {
358 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
359 result += QLatin1Char(
' ');
367 const QString &name = node->name();
371 tag = QLatin1String(
"@namespace");
376 tag = QLatin1String(
"@class");
379 tag = QLatin1String(
"@enum");
383 tag = QLatin1String(
"@typedef");
386 tag = QLatin1String(
"@function");
389 tag = QLatin1String(
"@property");
392 tag = QLatin1String(
"@property");
395 tag = QLatin1String(
"@property");
398 tag = QLatin1String(
"@unknown");
401 return (QLatin1Char(
'<') + tag + QLatin1Char(
'>') + protect(name) + QLatin1String(
"</") + tag
409 const auto *fn =
static_cast<
const FunctionNode *>(node);
410 switch (fn->metaness()) {
412 tag = QLatin1String(
"@signal");
415 tag = QLatin1String(
"@signalhandler");
418 tag = QLatin1String(
"@method");
421 tag = QLatin1String(
"@unknown");
425 tag = QLatin1String(
"@property");
427 tag = QLatin1String(
"@unknown");
429 return QLatin1Char(
'<') + tag + QLatin1Char(
'>') + protect(node->name()) + QLatin1String(
"</")
430 + tag + QLatin1Char(
'>');
435 return QLatin1String(
"<@link node=\"") + Utilities::stringForNode(node) + QLatin1String(
"\">") + body
436 + QLatin1String(
"</@link>");
QString typified(const QString &string, bool trailingSpace=false)
CodeMarker()
When a code marker constructs itself, it puts itself into the static list of code markers.
virtual void initializeMarker()
A code market performs no initialization by default.
static void initialize()
All the code markers in the static list are initialized here, after the qdoc configuration file has b...
QString taggedQmlNode(const Node *node)
virtual ~CodeMarker()
When a code marker destroys itself, it removes itself from the static list of code markers.
virtual void terminateMarker()
Terminating a code marker is trivial.
static void terminate()
All the code markers in the static list are terminated here.
virtual bool recognizeFileName(const QString &name)
QString linkTag(const Node *node, const QString &body)
virtual bool recognizeLanguage(const QString &language)
QString taggedNode(const Node *node)
This node is used to represent any kind of function being documented.
This class describes one instance of using the Q_PROPERTY macro.
A class for containing the elements of one documentation section.
static std::optional< QString > nodeStatusAsString(const Node *node)
Returns a string representing the node status, set using \preliminary,.
#define CONFIG_PRELIMINARY
Combined button and popup list for selecting options.
The Node class is the base class for all the nodes in QDoc's parse tree.
NodeType nodeType() const override
Returns this node's type.
virtual bool isDeprecated() const
Returns true if this node's status is Deprecated.
bool isFunction(Genus g=Genus::DontCare) const
Returns true if this is a FunctionNode and its Genus is set to g.
bool isQmlProperty() const
Returns true if the node type is QmlProperty.