16#include <QtCore/qfileinfo.h>
17#include <QtCore/qobjectdefs.h>
21using namespace Qt::StringLiterals;
28
29
30
31
32
33
36 s_markers.prepend(
this);
40
41
42
45 s_markers.removeAll(
this);
49
50
51
55
56
63
64
65
69 for (
const auto &marker : std::as_const(s_markers))
70 marker->initializeMarker();
74
75
78 for (
const auto &marker : std::as_const(s_markers))
79 marker->terminateMarker();
84 CodeMarker *defaultMarker = markerForLanguage(s_defaultLang);
85 if (defaultMarker !=
nullptr && defaultMarker->recognizeCode(code))
88 for (
const auto &marker : std::as_const(s_markers)) {
89 if (marker->recognizeCode(code))
97
98
99
100
101
104 CodeMarker *defaultMarker = markerForLanguage(s_defaultLang);
106 while ((dot = fileName.lastIndexOf(QLatin1Char(
'.'), dot)) != -1) {
107 QString ext = fileName.mid(dot + 1);
108 if (defaultMarker !=
nullptr && defaultMarker->recognizeExtension(ext))
109 return defaultMarker;
110 for (
const auto &marker : std::as_const(s_markers)) {
111 if (marker->recognizeExtension(ext))
117 QString name = QFileInfo(fileName).fileName();
118 for (
const auto &marker : std::as_const(s_markers)) {
119 if (marker->recognizeFileName(name))
122 return defaultMarker;
127 for (
const auto &marker : std::as_const(s_markers)) {
128 if (marker->recognizeLanguage(lang.toLower()))
136 return (name ==
"qmldir"_L1);
141 return (language ==
"text"_L1);
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
165 if (node->isPreliminary())
166 return std::optional(Config::instance().get(
CONFIG_PRELIMINARY).asString().toLower());
169 if (
const auto &since = node->since(); !since.isEmpty())
170 result <<
"since %1"_L1.arg(since);
171 if (
const auto &deprecated = node->deprecatedSince(); !deprecated.isEmpty()) {
172 if (node->isDeprecated())
173 result <<
"deprecated in %1"_L1.arg(deprecated);
175 result <<
"until %1"_L1.arg(deprecated);
177 result << u"deprecated"_s;
180 return result.isEmpty() ?
std::nullopt :
std::optional(result.join(u", "_s));
184
185
186
196 if (
static_cast<
const EnumNode *>(node)->isAnonymous())
197 extra <<
"anonymous";
202 if (
static_cast<
const ClassNode *>(node)->isAnonymous())
203 extra <<
"anonymous";
206 const auto *func =
static_cast<
const FunctionNode *>(node);
207 if (func->isStatic()) {
209 }
else if (!func->isNonvirtual()) {
212 if (func->isOverride())
214 if (func->isPureVirtual())
219 if (func->isExplicit()) extra <<
"explicit";
220 if (func->isConstexpr()) extra <<
"constexpr";
221 if (
auto noexcept_info = func->getNoexcept()) {
222 extra << (QString(
"noexcept") + (!(*noexcept_info).isEmpty() ?
"(...)" :
""));
225 if (func->access() == Access::Protected)
226 extra <<
"protected";
227 else if (func->access() == Access::Private)
230 if (func->isSignal()) {
231 if (func->parameters().isPrivateSignal())
234 }
else if (func->isSlot())
236 else if (func->isImplicitlyGenerated())
238 else if (func->isExplicitlyDefaulted())
239 extra <<
"<@extref target=\"cpp-explicitly-defaulted\">default</@extref>";
240 else if (func->isDeletedAsWritten())
241 extra <<
"<@extref target=\"cpp-deleted-functions\">delete</@extref>";
242 else if (func->isInvokable())
243 extra <<
"invokable";
245 if (func->isAttached())
253 auto propertyNode =
static_cast<
const PropertyNode *>(node);
256 if (!propertyNode->isWritable())
257 extra <<
"read-only";
258 if (propertyNode->isAttached())
263 auto qmlProperty =
static_cast<
const QmlPropertyNode *>(node);
264 extra << qmlProperty->hints();
266 if (!qmlProperty->isDefault() && !qmlProperty->defaultValue().isEmpty())
267 extra << u"default: "_s + qmlProperty->defaultValue();
268 if (qmlProperty->isAttached())
278 if (
auto status = nodeStatusAsString(node)) {
279 if (!extra.isEmpty())
280 extra.last() +=
','_L1;
284 QString extraStr = extra.join(QLatin1Char(
' '));
285 if (!extraStr.isEmpty()) {
295 return TextUtils::protect(str);
298void CodeMarker::appendProtectedString(QString *output, QStringView str)
300 qsizetype n = str.size();
301 output->reserve(output->size() + n * 2 + 30);
302 const QChar *data = str.constData();
303 for (
int i = 0; i != n; ++i) {
304 switch (data[i].unicode()) {
306 *output += TextUtils::samp;
309 *output += TextUtils::slt;
312 *output += TextUtils::sgt;
315 *output += TextUtils::squot;
323QString
CodeMarker::typified(
const QString &string,
bool trailingSpace)
328 for (
int i = 0; i <= string.size(); ++i) {
330 if (i != string.size())
333 QChar lower = ch.toLower();
334 if ((lower >= QLatin1Char(
'a') && lower <= QLatin1Char(
'z')) || ch.digitValue() >= 0
335 || ch == QLatin1Char(
'_') || ch == QLatin1Char(
':')) {
338 if (!pendingWord.isEmpty()) {
339 bool isProbablyType = (pendingWord != QLatin1String(
"const"));
341 result += QLatin1String(
"<@type>");
342 result += pendingWord;
344 result += QLatin1String(
"</@type>");
348 switch (ch.unicode()) {
352 result += QLatin1String(
"&");
355 result += QLatin1String(
"<");
358 result += QLatin1String(
">");
365 if (trailingSpace && string.size()) {
366 if (!string.endsWith(QLatin1Char(
'*')) && !string.endsWith(QLatin1Char(
'&')))
367 result += QLatin1Char(
' ');
375 const QString &name = node->name();
379 tag = QLatin1String(
"@namespace");
384 tag = QLatin1String(
"@class");
387 tag = QLatin1String(
"@enum");
391 tag = QLatin1String(
"@typedef");
394 tag = QLatin1String(
"@function");
397 tag = QLatin1String(
"@property");
400 tag = QLatin1String(
"@property");
403 tag = QLatin1String(
"@property");
406 tag = QLatin1String(
"@unknown");
409 return (QLatin1Char(
'<') + tag + QLatin1Char(
'>') + protect(name) + QLatin1String(
"</") + tag
417 const auto *fn =
static_cast<
const FunctionNode *>(node);
418 switch (fn->metaness()) {
420 tag = QLatin1String(
"@signal");
423 tag = QLatin1String(
"@signalhandler");
426 tag = QLatin1String(
"@method");
429 tag = QLatin1String(
"@unknown");
433 tag = QLatin1String(
"@property");
435 tag = QLatin1String(
"@unknown");
437 return QLatin1Char(
'<') + tag + QLatin1Char(
'>') + protect(node->name()) + QLatin1String(
"</")
438 + tag + QLatin1Char(
'>');
443 return QLatin1String(
"<@link node=\"") + Utilities::stringForNode(node) + QLatin1String(
"\">") + body
444 + 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 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
Metaness
Specifies the kind of function a FunctionNode represents.
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.