Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
functionnode.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "functionnode.h"
5#include "propertynode.h"
6
7#include <string>
8
10
11using namespace Qt::StringLiterals;
12
13/*!
14 \class FunctionNode
15
16 This node is used to represent any kind of function being
17 documented. It can represent a C++ class member function, a C++
18 global function, a QML method, or a macro, with or without
19 parameters.
20
21 A C++ function can be a signal, a slot, a constructor of any
22 kind, a destructor, a copy or move assignment operator, or
23 just a plain old member function or a global function.
24
25 A QML method can be a plain old method, or a
26 signal or signal handler.
27
28 If the function is an overload, its overload flag is
29 true.
30
31 The function node also has an overload number. If the
32 node's overload flag is set, this overload number is
33 positive; otherwise, the overload number is 0.
34 */
35
36/*!
37 Construct a function node for a C++ function. It's parent
38 is \a parent, and it's name is \a name.
39
40 \note The function node's overload flag is set to false, and
41 its overload number is set to 0. These data members are set
42 in normalizeOverloads(), when all the overloads are known.
43 */
44FunctionNode::FunctionNode(Aggregate *parent, const QString &name)
45 : Node(NodeType::Function, parent, name),
46 m_const(false),
47 m_implicitlyGenerated(false),
48 m_static(false),
49 m_reimpFlag(false),
50 m_attached(false),
51 m_overloadFlag(false),
52 m_primaryOverloadFlag(false),
53 m_isFinal(false),
54 m_isOverride(false),
55 m_isRef(false),
56 m_isRefRef(false),
57 m_isInvokable(false),
58 m_explicitlyDefaulted(false),
59 m_deleted(false),
60 m_hiddenFriend(false),
61 m_explicit{false},
62 m_constexpr{false},
63 m_metaness(Metaness::Plain),
64 m_virtualness(NonVirtual),
65 m_overloadNumber(0)
66{
67 // nothing
68}
69
70/*!
71 Construct a function node for a QML method or signal, specified
72 by ther Metaness value \a type. It's parent is \a parent, and
73 it's name is \a name. If \a attached is true, it is an attached
74 method or signal.
75
76 \note The function node's overload flag is set to false, and
77 its overload number is set to 0. These data members are set
78 in normalizeOverloads(), when all the overloads are known.
79 */
80FunctionNode::FunctionNode(Metaness kind, Aggregate *parent, const QString &name, bool attached)
81 : Node(NodeType::Function, parent, name),
82 m_const(false),
83 m_implicitlyGenerated(false),
84 m_static(false),
85 m_reimpFlag(false),
86 m_attached(attached),
87 m_overloadFlag(false),
88 m_primaryOverloadFlag(false),
89 m_isFinal(false),
90 m_isOverride(false),
91 m_isRef(false),
92 m_isRefRef(false),
93 m_isInvokable(false),
94 m_explicitlyDefaulted(false),
95 m_deleted(false),
96 m_hiddenFriend(false),
97 m_explicit{false},
98 m_constexpr{false},
99 m_metaness(kind),
100 m_virtualness(NonVirtual),
101 m_overloadNumber(0)
102{
103 setGenus(getGenus(m_metaness));
104 if (!isCppNode() && name.startsWith("__"))
106}
107
108/*!
109 Clone this node on the heap and make the clone a child of
110 \a parent. Return the pointer to the clone.
111 */
113{
114 auto *fn = new FunctionNode(*this); // shallow copy
115 fn->setParent(nullptr);
116 parent->addChild(fn);
117 return fn;
118}
119
120/*!
121 Returns this function's virtualness value as a string
122 for use as an attribute value in index files.
123 */
125{
126 switch (m_virtualness) {
128 return QLatin1String("virtual");
130 return QLatin1String("pure");
132 default:
133 break;
134 }
135 return QLatin1String("non");
136}
137
138/*!
139 Sets the function node's virtualness value based on the value
140 of string \a value, which is the value of the function's \e{virtual}
141 attribute in an index file. If \a value is \e{pure}, and if the
142 parent() is a C++ class, set the parent's \e abstract flag to
143 \c {true}.
144 */
145void FunctionNode::setVirtualness(const QString &value)
146{
147 if (value == QLatin1String("pure")) {
148 m_virtualness = PureVirtual;
149 if (parent() && parent()->isClassNode())
150 parent()->setAbstract(true);
151 return;
152 }
153
154 m_virtualness = (value == QLatin1String("virtual")) ? NormalVirtual : NonVirtual;
155}
156
158static void buildMetanessMap()
159{
160 metanessMap_["plain"] = Metaness::Plain;
161 metanessMap_["signal"] = Metaness::Signal;
163 metanessMap_["constructor"] = Metaness::Ctor;
164 metanessMap_["copy-constructor"] = Metaness::CCtor;
165 metanessMap_["move-constructor"] = Metaness::MCtor;
166 metanessMap_["destructor"] = Metaness::Dtor;
168 metanessMap_["macrowithparams"] = Metaness::MacroWithParams;
169 metanessMap_["macrowithoutparams"] = Metaness::MacroWithoutParams;
170 metanessMap_["copy-assign"] = Metaness::CAssign;
171 metanessMap_["move-assign"] = Metaness::MAssign;
172 metanessMap_["native"] = Metaness::Native;
173 metanessMap_["qmlsignal"] = Metaness::QmlSignal;
174 metanessMap_["qmlsignalhandler"] = Metaness::QmlSignalHandler;
175 metanessMap_["qmlmethod"] = Metaness::QmlMethod;
176}
177
180{
183 topicMetanessMap_["qmlattachedsignal"] = Metaness::QmlSignal;
185 topicMetanessMap_["qmlattachedmethod"] = Metaness::QmlMethod;
186}
187
188/*!
189 Determines the Genus value for this FunctionNode given the
190 Metaness value \a metaness. Returns the Genus value. \a metaness must be
191 one of the values of Metaness. If not, Node::DontCare is
192 returned.
193 */
195{
196 switch (metaness) {
197 case Metaness::Plain:
198 case Metaness::Signal:
199 case Metaness::Slot:
200 case Metaness::Ctor:
201 case Metaness::Dtor:
202 case Metaness::CCtor:
203 case Metaness::MCtor:
206 case Metaness::Native:
209 return Genus::CPP;
213 return Genus::QML;
214 }
215
216 return Genus::DontCare;
217}
218
219/*!
220 This static function converts the string \a value to an enum
221 value for the kind of function named by \a value.
222 */
223Metaness FunctionNode::getMetaness(const QString &value)
224{
225 if (metanessMap_.isEmpty())
227 return metanessMap_[value];
228}
229
230/*!
231 This static function converts the topic string \a topic to an enum
232 value for the kind of function this FunctionNode represents.
233 */
234Metaness FunctionNode::getMetanessFromTopic(const QString &topic)
235{
236 if (topicMetanessMap_.isEmpty())
238 return topicMetanessMap_[topic];
239}
240
241/*!
242 Extends the base implementation to test whether an associated enum
243 is in the API.
244*/
246{
247 if (Node::isInAPI())
248 return true;
249
250 for (auto *property : m_associatedProperties) {
251 if (property->isInAPI())
252 return true;
253 }
254
255 return false;
256}
257
258/*!
259 Sets the function node's overload number to \a number. If \a number
260 is 0, the function node's overload flag is set to false. If
261 \a number is greater than 0, the overload flag is set to true.
262 */
263void FunctionNode::setOverloadNumber(signed short number)
264{
265 m_overloadNumber = number;
266 m_overloadFlag = (number > 0);
267}
268
269/*!
270 \fn void FunctionNode::setReimpFlag()
271
272 Sets the function node's reimp flag to \c true, which means
273 the \e {\\reimp} command was used in the qdoc comment. It is
274 supposed to mean that the function reimplements a virtual
275 function in a base class.
276 */
277
278/*!
279 Returns a string representing the kind of function this
280 Function node represents, which depends on the Metaness
281 value.
282 */
284{
285 switch (m_metaness) {
286 case Metaness::Signal:
287 return "signal";
288 case Metaness::Slot:
289 return "slot";
291 return "QML signal";
293 return "QML signal handler";
295 return "QML method";
296 default:
297 return "function";
298 }
299}
300
301/*!
302 Returns a string representing the Metaness enum value for
303 this function. It is used in index files.
304 */
306{
307 switch (m_metaness) {
308 case Metaness::Plain:
309 return "plain";
310 case Metaness::Signal:
311 return "signal";
312 case Metaness::Slot:
313 return "slot";
314 case Metaness::Ctor:
315 return "constructor";
316 case Metaness::CCtor:
317 return "copy-constructor";
318 case Metaness::MCtor:
319 return "move-constructor";
320 case Metaness::Dtor:
321 return "destructor";
323 return "macrowithparams";
325 return "macrowithoutparams";
326 case Metaness::Native:
327 return "native";
329 return "copy-assign";
331 return "move-assign";
333 return "qmlsignal";
335 return "qmlsignalhandler";
337 return "qmlmethod";
338 default:
339 return "plain";
340 }
341}
342
343/*!
344 Adds the "associated" property \a p to this function node.
345 The function might be the setter or getter for a property,
346 for example.
347 */
349{
350 if (p->isInAPI())
351 m_associatedProperties.append(p);
352}
353
354/*!
355 Returns the \e primary associated property, if this is an
356 access function for one or more properties.
357
358 Non-deprecated properties are preferred over deprecated properties.
359 Among properties with the same deprecation status, a property whose
360 name is a prefix of the function name is preferred, with the longest
361 matching prefix taking precedence. Otherwise, properties are ordered
362 alphabetically for deterministic output.
363
364 If no associated properties exist, returns \nullptr.
365 */
367{
368 if (m_associatedProperties.isEmpty())
369 return nullptr;
370 if (m_associatedProperties.size() == 1)
371 return m_associatedProperties[0];
372
373 return *std::min_element(
374 m_associatedProperties.cbegin(), m_associatedProperties.cend(),
375 [this](const PropertyNode *a, const PropertyNode *b) {
376 if (a->isDeprecated() != b->isDeprecated())
377 return !a->isDeprecated();
378
379 const bool aMatches = name().startsWith(a->name());
380 const bool bMatches = name().startsWith(b->name());
381
382 if (aMatches != bMatches)
383 return aMatches;
384
385 if (aMatches && a->name().size() != b->name().size())
386 return a->name().size() > b->name().size();
387
388 return a->name() < b->name();
389 });
390}
391
392/*!
393 \reimp
394
395 Returns \c true if this is an access function for an obsolete property,
396 otherwise calls the base implementation of isDeprecated().
397*/
399{
401}
402
403/*! \fn unsigned char FunctionNode::overloadNumber() const
404 Returns the overload number for this function.
405 */
406
407/*!
408 Reconstructs and returns the function's signature.
409
410 Specific parts of the signature are included according to
411 flags in \a options:
412
413 \value Node::SignaturePlain
414 Plain signature
415 \value Node::SignatureDefaultValues
416 Include any default argument values
417 \value Node::SignatureReturnType
418 Include return type
419 \value Node::SignatureTemplateParams
420 Include \c {template <parameter_list>} if one exists
421 */
422QString FunctionNode::signature(Node::SignatureOptions options) const
423{
424 QStringList elements;
425
426 if (options & Node::SignatureTemplateParams && templateDecl())
427 elements << (*templateDecl()).to_qstring();
428 if (options & Node::SignatureReturnType)
429 elements << m_returnType.first;
430 elements.removeAll(QString());
431
432 if (!isMacroWithoutParams()) {
433 elements << name() + QLatin1Char('(')
434 + m_parameters.signature(options & Node::SignatureDefaultValues)
435 + QLatin1Char(')');
436 if (!isMacro()) {
437 if (isConst())
438 elements << QStringLiteral("const");
439 if (isRef())
440 elements << QStringLiteral("&");
441 else if (isRefRef())
442 elements << QStringLiteral("&&");
443 }
444 } else {
445 elements << name();
446 }
447 return elements.join(QLatin1Char(' '));
448}
449
450/*!
451 \fn int FunctionNode::compare(const FunctionNode *f1, const FunctionNode *f2)
452
453 Compares FunctionNode \a f1 with \a f2, assumed to have identical names.
454 Returns an integer less than, equal to, or greater than zero if f1 is
455 considered less than, equal to, or greater than f2.
456
457 The main purpose is to provide stable ordering for function overloads.
458 */
459[[nodiscard]] int compare(const FunctionNode *f1, const FunctionNode *f2)
460{
461 // Compare parameter count
462 int param_count{f1->parameters().count()};
463
464 if (int param_diff = param_count - f2->parameters().count(); param_diff != 0)
465 return param_diff;
466
467 // Constness
468 if (f1->isConst() != f2->isConst())
469 return f1->isConst() ? 1 : -1;
470
471 // Reference qualifiers
472 if (f1->isRef() != f2->isRef())
473 return f1->isRef() ? 1 : -1;
474 if (f1->isRefRef() != f2->isRefRef())
475 return f1->isRefRef() ? 1 : -1;
476
477 // Attachedness (applies to QML methods)
479 return f1->isAttached() ? 1 : -1;
480
481 // Parameter types
482 const Parameters &p1{f1->parameters()};
483 const Parameters &p2{f2->parameters()};
484 for (qsizetype i = 0; i < param_count; ++i) {
485 if (int type_comp = QString::compare(p1.at(i).type(), p2.at(i).type());
486 type_comp != 0) {
487 return type_comp;
488 }
489 }
490
491 // Template declarations
492 const auto &t1{f1->templateDecl()};
493 const auto &t2{f2->templateDecl()};
494 if (!t1 && !t2)
495 return 0;
496
497 if (t1 && t2)
498 return (*t1).to_std_string().compare((*t2).to_std_string());
499
500 return t1 ? 1 : -1;
501}
502
503/*!
504 In some cases, it is ok for a public function to be not documented.
505 For example, the macro Q_OBJECT adds several functions to the API of
506 a class, but these functions are normally not meant to be documented.
507 So if a function node doesn't have documentation, then if its name is
508 in the list of functions that it is ok not to document, this function
509 returns true. Otherwise, it returns false.
510
511 These are the member function names added by macros. Usually they
512 are not documented, but they can be documented, so this test avoids
513 reporting a warning if they are not documented.
514
515 But maybe we should generate a standard text for each of them?
516 */
518{
519 if (!hasDoc()) {
520 if (name().startsWith(QLatin1String("qt_")) || name().startsWith(QLatin1String("_q_"))
521 || name() == QLatin1String("metaObject") || name() == QLatin1String("tr")
522 || name() == QLatin1String("trUtf8") || name() == QLatin1String("d_func")) {
523 return true;
524 }
525 QString s = signature(Node::SignatureReturnType);
526 if (s.contains(QLatin1String("enum_type")) && s.contains(QLatin1String("operator|")))
527 return true;
528 }
529 return false;
530}
531
532/*!
533 \fn bool FunctionNode::hasOverloads() const
534 Returns \c true if this function has overloads.
535 */
536
537/*!
538 \internal
539 \brief Returns the type of the function as a string.
540
541 The returned string is either the type as declared in the header, or `auto`
542 if that's the return type in the `\\fn` command for the function.
543 */
545{
546 if (m_returnType.second.has_value())
547 return m_returnType.second.value();
548 return m_returnType.first;
549}
550
551/*!
552 Returns the status of the function, taking the status of any associated
553 properties into account.
554*/
556{
557 auto it = std::find_if_not(m_associatedProperties.begin(), m_associatedProperties.end(),
558 [](const Node *p) -> bool { return p->isDeprecated(); });
559
560 if (!m_associatedProperties.isEmpty() && it == m_associatedProperties.end())
561 return Status::Deprecated;
562 else
563 return Node::status();
564}
565
566/*!
567 \internal
568 Auto-generates documentation for explicitly defaulted or deleted
569 special member functions that don't already have documentation.
570*/
571void FunctionNode::autoGenerateSmfDoc(const QString &className)
572{
573 if (hasDoc())
574 return;
576 return;
578 return;
579
580 QString docSource;
581 if (isDtor()) {
582 docSource = u"Destroys the instance of \\notranslate %1."_s.arg(className);
583 if (isVirtual())
584 docSource += u" This destructor is virtual."_s;
585 } else if (isCtor()) {
586 docSource = u"Default-constructs an instance of \\notranslate %1."_s.arg(className);
587 } else if (isCCtor()) {
588 docSource = u"Copy-constructs an instance of \\notranslate %1."_s.arg(className);
589 } else if (isMCtor()) {
590 docSource = u"Move-constructs an instance of \\notranslate %1."_s.arg(className);
591 } else if (isCAssign() || isMAssign()) {
592 const auto &params = parameters();
593 const QString other = (!params.isEmpty() && !params.at(0).name().isEmpty())
594 ? params.at(0).name()
595 : u"other"_s;
596 docSource = isCAssign()
597 ? u"Copy-assigns \\a %1 to this \\notranslate %2 instance."_s.arg(other, className)
598 : u"Move-assigns \\a %1 to this \\notranslate %2 instance."_s.arg(other, className);
599 }
600
601 if (docSource.isEmpty())
602 return;
603
604 if (isDeletedAsWritten())
605 docSource += u" This function is deleted."_s;
606
607 static const QSet<QString> noMetaCommands;
608 static const QSet<QString> noTopics;
609 Doc doc(location(), location(), docSource, noMetaCommands, noTopics);
611 setDoc(doc);
612}
613
614QT_END_NAMESPACE
void addChild(Node *child)
Adds the child to this node's child list and sets the child's parent pointer to this Aggregate.
Definition doc.h:32
void markAutoGenerated()
Marks this documentation as auto-generated by QDoc.
Definition doc.cpp:252
This node is used to represent any kind of function being documented.
QString metanessString() const
Returns a string representing the Metaness enum value for this function.
QString kindString() const
Returns a string representing the kind of function this Function node represents, which depends on th...
FunctionNode(Metaness type, Aggregate *parent, const QString &name, bool attached=false)
Construct a function node for a QML method or signal, specified by ther Metaness value type.
const Parameters & parameters() const
bool isRef() const
bool isInAPI() const override
Extends the base implementation to test whether an associated enum is in the API.
bool isMAssign() const
bool isCAssign() const
Node * clone(Aggregate *parent) override
Clone this node on the heap and make the clone a child of parent.
bool isDeprecated() const override
\reimp
void autoGenerateSmfDoc(const QString &className)
void addAssociatedProperty(PropertyNode *property)
Adds the "associated" property p to this function node.
bool isDtor() const
bool isSpecialMemberFunction() const
static Genus getGenus(Metaness metaness)
Determines the Genus value for this FunctionNode given the Metaness value metaness.
bool isConst() const
bool isRefRef() const
FunctionNode(Aggregate *parent, const QString &name)
Construct a function node for a C++ function.
bool isAttached() const override
Returns true if the QML property or QML method node is marked as attached.
bool isDeletedAsWritten() const
void setOverloadNumber(signed short number)
Sets the function node's overload number to number.
bool isIgnored() const
In some cases, it is ok for a public function to be not documented.
bool isCCtor() const
bool isMCtor() const
friend int compare(const FunctionNode *f1, const FunctionNode *f2)
Compares FunctionNode f1 with f2, assumed to have identical names.
bool isCtor() const
QString returnTypeString() const
Returns the type of the function as a string.
bool isExplicitlyDefaulted() const
virtual Status status() const override
Returns the status of the function, taking the status of any associated properties into account.
Parameters & parameters()
void setVirtualness(const QString &value)
Sets the function node's virtualness value based on the value of string value, which is the value of ...
const PropertyNode * primaryAssociatedProperty() const
Returns the primary associated property, if this is an access function for one or more properties.
QString virtualness() const
Returns this function's virtualness value as a string for use as an attribute value in index files.
This class describes one instance of using the Q_PROPERTY macro.
Status
Specifies the status of the QQmlIncubator.
static void buildTopicMetanessMap()
static QMap< QString, Metaness > topicMetanessMap_
static QMap< QString, Metaness > metanessMap_
static void buildMetanessMap()
NodeType
Definition genustypes.h:165
Metaness
Specifies the kind of function a FunctionNode represents.
Definition genustypes.h:242
@ MacroWithParams
Definition genustypes.h:250
@ MacroWithoutParams
Definition genustypes.h:251
@ QmlSignalHandler
Definition genustypes.h:256
Combined button and popup list for selecting options.
@ Deprecated
Definition status.h:12
@ Internal
Definition status.h:15
The Node class is the base class for all the nodes in QDoc's parse tree.
void setGenus(Genus t)
Definition node.h:86
virtual Status status() const
Returns the node's status value.
Definition node.h:241
Aggregate * parent() const
Returns the node's parent pointer.
Definition node.h:210
virtual bool isDeprecated() const
Returns true if this node's status is Deprecated.
Definition node.h:136
const Location & location() const
If this node's definition location is empty, this function returns this node's declaration location.
Definition node.h:233
const std::optional< RelaxedTemplateDeclaration > & templateDecl() const
Definition node.h:245
virtual bool isInAPI() const
Returns true if this node is considered to be part of the API as per the InclusionPolicy retrieved fr...
Definition node.cpp:927
void setDoc(const Doc &doc, bool replace=false)
Sets this Node's Doc to doc.
Definition node.cpp:560
bool hasDoc() const
Returns true if this node is documented, or it represents a documented node read from the index ('had...
Definition node.cpp:942
void setParent(Aggregate *n)
Sets the node's parent pointer to n.
Definition node.h:182
bool isCppNode() const
Returns true if this node's Genus value is CPP.
Definition node.h:92
virtual void setStatus(Status t)
Sets the node's status to t.
Definition node.cpp:574
@ SignatureReturnType
Definition node.h:68
A class for parsing and managing a function parameter list.
Definition main.cpp:28
int count() const
Definition parameters.h:34