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";
244 if (func->isAttached())
252 auto propertyNode =
static_cast<
const PropertyNode *>(node);
255 if (!propertyNode->isWritable())
256 extra <<
"read-only";
257 if (propertyNode->isAttached())
262 auto qmlProperty =
static_cast<
const QmlPropertyNode *>(node);
263 extra << qmlProperty->hints();
265 if (!qmlProperty->isDefault() && !qmlProperty->defaultValue().isEmpty())
266 extra << u"default: "_s + qmlProperty->defaultValue();
267 if (qmlProperty->isAttached())
277 if (
auto status = nodeStatusAsString(node)) {
278 if (!extra.isEmpty())
279 extra.last() +=
','_L1;
283 QString extraStr = extra.join(QLatin1Char(
' '));
284 if (!extraStr.isEmpty()) {
294 return Utilities::protect(str);
297void CodeMarker::appendProtectedString(QString *output, QStringView str)
299 qsizetype n = str.size();
300 output->reserve(output->size() + n * 2 + 30);
301 const QChar *data = str.constData();
302 for (
int i = 0; i != n; ++i) {
303 switch (data[i].unicode()) {
305 *output += Utilities::samp;
308 *output += Utilities::slt;
311 *output += Utilities::sgt;
314 *output += Utilities::squot;
322QString
CodeMarker::typified(
const QString &string,
bool trailingSpace)
327 for (
int i = 0; i <= string.size(); ++i) {
329 if (i != string.size())
332 QChar lower = ch.toLower();
333 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
334 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
337 if (!pendingWord.isEmpty()) {
338 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
340 result += QLatin1String(
"<@type>");
341 result += pendingWord;
343 result += QLatin1String(
"</@type>");
347 switch (ch.unicode()) {
351 result += QLatin1String(
"&");
354 result += QLatin1String(
"<");
357 result += QLatin1String(
">");
364 if (trailingSpace && string.size()) {
365 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
366 result += QLatin1Char(
' ');
374 const QString &name = node->name();
378 tag = QLatin1String(
"@namespace");
383 tag = QLatin1String(
"@class");
386 tag = QLatin1String(
"@enum");
390 tag = QLatin1String(
"@typedef");
393 tag = QLatin1String(
"@function");
396 tag = QLatin1String(
"@property");
399 tag = QLatin1String(
"@property");
402 tag = QLatin1String(
"@property");
405 tag = QLatin1String(
"@unknown");
408 return (QLatin1Char(
'<') + tag + QLatin1Char(
'>') + protect(name) + QLatin1String(
"</") + tag
416 const auto *fn =
static_cast<
const FunctionNode *>(node);
417 switch (fn->metaness()) {
419 tag = QLatin1String(
"@signal");
422 tag = QLatin1String(
"@signalhandler");
425 tag = QLatin1String(
"@method");
428 tag = QLatin1String(
"@unknown");
432 tag = QLatin1String(
"@property");
434 tag = QLatin1String(
"@unknown");
436 return QLatin1Char(
'<') + tag + QLatin1Char(
'>') + protect(node->name()) + QLatin1String(
"</")
437 + tag + QLatin1Char(
'>');
442 return QLatin1String(
"<@link node=\"") + Utilities::stringForNode(node) + QLatin1String(
"\">") + body
443 + QLatin1String(
"</@link>");
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.