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 An associated property is considered primary if this
359 function's name starts with the property name. If no
360 prefix match exists, the property with the alphabetically
361 first name is returned for deterministic output.
362
363 If no associated properties exist, returns \nullptr.
364 */
366{
367 if (m_associatedProperties.isEmpty())
368 return nullptr;
369 if (m_associatedProperties.size() == 1)
370 return m_associatedProperties[0];
371
372 auto it = std::find_if(
373 m_associatedProperties.cbegin(), m_associatedProperties.cend(),
374 [this](const PropertyNode *p) {
375 return name().startsWith(p->name());
376 });
377 if (it != m_associatedProperties.cend())
378 return *it;
379
380 // No prefix match: multiple properties share this signal but none
381 // match by name. Pick alphabetically for deterministic output
382 // regardless of tree traversal order.
383 return *std::min_element(
384 m_associatedProperties.cbegin(), m_associatedProperties.cend(),
385 [](const PropertyNode *a, const PropertyNode *b) { return a->name() < b->name(); });
386}
387
388/*!
389 \reimp
390
391 Returns \c true if this is an access function for an obsolete property,
392 otherwise calls the base implementation of isDeprecated().
393*/
395{
397}
398
399/*! \fn unsigned char FunctionNode::overloadNumber() const
400 Returns the overload number for this function.
401 */
402
403/*!
404 Reconstructs and returns the function's signature.
405
406 Specific parts of the signature are included according to
407 flags in \a options:
408
409 \value Node::SignaturePlain
410 Plain signature
411 \value Node::SignatureDefaultValues
412 Include any default argument values
413 \value Node::SignatureReturnType
414 Include return type
415 \value Node::SignatureTemplateParams
416 Include \c {template <parameter_list>} if one exists
417 */
418QString FunctionNode::signature(Node::SignatureOptions options) const
419{
420 QStringList elements;
421
422 if (options & Node::SignatureTemplateParams && templateDecl())
423 elements << (*templateDecl()).to_qstring();
424 if (options & Node::SignatureReturnType)
425 elements << m_returnType.first;
426 elements.removeAll(QString());
427
428 if (!isMacroWithoutParams()) {
429 elements << name() + QLatin1Char('(')
430 + m_parameters.signature(options & Node::SignatureDefaultValues)
431 + QLatin1Char(')');
432 if (!isMacro()) {
433 if (isConst())
434 elements << QStringLiteral("const");
435 if (isRef())
436 elements << QStringLiteral("&");
437 else if (isRefRef())
438 elements << QStringLiteral("&&");
439 }
440 } else {
441 elements << name();
442 }
443 return elements.join(QLatin1Char(' '));
444}
445
446/*!
447 \fn int FunctionNode::compare(const FunctionNode *f1, const FunctionNode *f2)
448
449 Compares FunctionNode \a f1 with \a f2, assumed to have identical names.
450 Returns an integer less than, equal to, or greater than zero if f1 is
451 considered less than, equal to, or greater than f2.
452
453 The main purpose is to provide stable ordering for function overloads.
454 */
455[[nodiscard]] int compare(const FunctionNode *f1, const FunctionNode *f2)
456{
457 // Compare parameter count
458 int param_count{f1->parameters().count()};
459
460 if (int param_diff = param_count - f2->parameters().count(); param_diff != 0)
461 return param_diff;
462
463 // Constness
464 if (f1->isConst() != f2->isConst())
465 return f1->isConst() ? 1 : -1;
466
467 // Reference qualifiers
468 if (f1->isRef() != f2->isRef())
469 return f1->isRef() ? 1 : -1;
470 if (f1->isRefRef() != f2->isRefRef())
471 return f1->isRefRef() ? 1 : -1;
472
473 // Attachedness (applies to QML methods)
475 return f1->isAttached() ? 1 : -1;
476
477 // Parameter types
478 const Parameters &p1{f1->parameters()};
479 const Parameters &p2{f2->parameters()};
480 for (qsizetype i = 0; i < param_count; ++i) {
481 if (int type_comp = QString::compare(p1.at(i).type(), p2.at(i).type());
482 type_comp != 0) {
483 return type_comp;
484 }
485 }
486
487 // Template declarations
488 const auto &t1{f1->templateDecl()};
489 const auto &t2{f2->templateDecl()};
490 if (!t1 && !t2)
491 return 0;
492
493 if (t1 && t2)
494 return (*t1).to_std_string().compare((*t2).to_std_string());
495
496 return t1 ? 1 : -1;
497}
498
499/*!
500 In some cases, it is ok for a public function to be not documented.
501 For example, the macro Q_OBJECT adds several functions to the API of
502 a class, but these functions are normally not meant to be documented.
503 So if a function node doesn't have documentation, then if its name is
504 in the list of functions that it is ok not to document, this function
505 returns true. Otherwise, it returns false.
506
507 These are the member function names added by macros. Usually they
508 are not documented, but they can be documented, so this test avoids
509 reporting a warning if they are not documented.
510
511 But maybe we should generate a standard text for each of them?
512 */
514{
515 if (!hasDoc()) {
516 if (name().startsWith(QLatin1String("qt_")) || name().startsWith(QLatin1String("_q_"))
517 || name() == QLatin1String("metaObject") || name() == QLatin1String("tr")
518 || name() == QLatin1String("trUtf8") || name() == QLatin1String("d_func")) {
519 return true;
520 }
521 QString s = signature(Node::SignatureReturnType);
522 if (s.contains(QLatin1String("enum_type")) && s.contains(QLatin1String("operator|")))
523 return true;
524 }
525 return false;
526}
527
528/*!
529 \fn bool FunctionNode::hasOverloads() const
530 Returns \c true if this function has overloads.
531 */
532
533/*!
534 \internal
535 \brief Returns the type of the function as a string.
536
537 The returned string is either the type as declared in the header, or `auto`
538 if that's the return type in the `\\fn` command for the function.
539 */
541{
542 if (m_returnType.second.has_value())
543 return m_returnType.second.value();
544 return m_returnType.first;
545}
546
547/*!
548 Returns the status of the function, taking the status of any associated
549 properties into account.
550*/
552{
553 auto it = std::find_if_not(m_associatedProperties.begin(), m_associatedProperties.end(),
554 [](const Node *p) -> bool { return p->isDeprecated(); });
555
556 if (!m_associatedProperties.isEmpty() && it == m_associatedProperties.end())
557 return Status::Deprecated;
558 else
559 return Node::status();
560}
561
562/*!
563 \internal
564 Auto-generates documentation for explicitly defaulted or deleted
565 special member functions that don't already have documentation.
566*/
567void FunctionNode::autoGenerateSmfDoc(const QString &className)
568{
569 if (hasDoc())
570 return;
572 return;
574 return;
575
576 QString docSource;
577 if (isDtor()) {
578 docSource = u"Destroys the instance of \\notranslate %1."_s.arg(className);
579 if (isVirtual())
580 docSource += u" This destructor is virtual."_s;
581 } else if (isCtor()) {
582 docSource = u"Default-constructs an instance of \\notranslate %1."_s.arg(className);
583 } else if (isCCtor()) {
584 docSource = u"Copy-constructs an instance of \\notranslate %1."_s.arg(className);
585 } else if (isMCtor()) {
586 docSource = u"Move-constructs an instance of \\notranslate %1."_s.arg(className);
587 } else if (isCAssign() || isMAssign()) {
588 const auto &params = parameters();
589 const QString other = (!params.isEmpty() && !params.at(0).name().isEmpty())
590 ? params.at(0).name()
591 : u"other"_s;
592 docSource = isCAssign()
593 ? u"Copy-assigns \\a %1 to this \\notranslate %2 instance."_s.arg(other, className)
594 : u"Move-assigns \\a %1 to this \\notranslate %2 instance."_s.arg(other, className);
595 }
596
597 if (docSource.isEmpty())
598 return;
599
600 if (isDeletedAsWritten())
601 docSource += u" This function is deleted."_s;
602
603 static const QSet<QString> noMetaCommands;
604 static const QSet<QString> noTopics;
605 Doc doc(location(), location(), docSource, noMetaCommands, noTopics);
607 setDoc(doc);
608}
609
610QT_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:154
Metaness
Specifies the kind of function a FunctionNode represents.
Definition genustypes.h:231
@ MacroWithParams
Definition genustypes.h:239
@ MacroWithoutParams
Definition genustypes.h:240
@ QmlSignalHandler
Definition genustypes.h:245
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:930
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:945
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