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
11/*!
12 \class FunctionNode
13
14 This node is used to represent any kind of function being
15 documented. It can represent a C++ class member function, a C++
16 global function, a QML method, or a macro, with or without
17 parameters.
18
19 A C++ function can be a signal, a slot, a constructor of any
20 kind, a destructor, a copy or move assignment operator, or
21 just a plain old member function or a global function.
22
23 A QML method can be a plain old method, or a
24 signal or signal handler.
25
26 If the function is an overload, its overload flag is
27 true.
28
29 The function node also has an overload number. If the
30 node's overload flag is set, this overload number is
31 positive; otherwise, the overload number is 0.
32 */
33
34/*!
35 Construct a function node for a C++ function. It's parent
36 is \a parent, and it's name is \a name.
37
38 \note The function node's overload flag is set to false, and
39 its overload number is set to 0. These data members are set
40 in normalizeOverloads(), when all the overloads are known.
41 */
42FunctionNode::FunctionNode(Aggregate *parent, const QString &name)
43 : Node(NodeType::Function, parent, name),
44 m_const(false),
45 m_implicitlyGenerated(false),
46 m_static(false),
47 m_reimpFlag(false),
48 m_attached(false),
49 m_overloadFlag(false),
50 m_primaryOverloadFlag(false),
51 m_isFinal(false),
52 m_isOverride(false),
53 m_isRef(false),
54 m_isRefRef(false),
55 m_isInvokable(false),
56 m_explicitlyDefaulted(false),
57 m_deleted(false),
58 m_hiddenFriend(false),
59 m_explicit{false},
60 m_constexpr{false},
61 m_metaness(Plain),
62 m_virtualness(NonVirtual),
63 m_overloadNumber(0)
64{
65 // nothing
66}
67
68/*!
69 Construct a function node for a QML method or signal, specified
70 by ther Metaness value \a type. It's parent is \a parent, and
71 it's name is \a name. If \a attached is true, it is an attached
72 method or signal.
73
74 \note The function node's overload flag is set to false, and
75 its overload number is set to 0. These data members are set
76 in normalizeOverloads(), when all the overloads are known.
77 */
78FunctionNode::FunctionNode(Metaness kind, Aggregate *parent, const QString &name, bool attached)
79 : Node(NodeType::Function, parent, name),
80 m_const(false),
81 m_implicitlyGenerated(false),
82 m_static(false),
83 m_reimpFlag(false),
84 m_attached(attached),
85 m_overloadFlag(false),
86 m_primaryOverloadFlag(false),
87 m_isFinal(false),
88 m_isOverride(false),
89 m_isRef(false),
90 m_isRefRef(false),
91 m_isInvokable(false),
92 m_explicitlyDefaulted(false),
93 m_deleted(false),
94 m_hiddenFriend(false),
95 m_explicit{false},
96 m_constexpr{false},
97 m_metaness(kind),
98 m_virtualness(NonVirtual),
99 m_overloadNumber(0)
100{
101 setGenus(getGenus(m_metaness));
102 if (!isCppNode() && name.startsWith("__"))
104}
105
106/*!
107 Clone this node on the heap and make the clone a child of
108 \a parent. Return the pointer to the clone.
109 */
110Node *FunctionNode::clone(Aggregate *parent)
111{
112 auto *fn = new FunctionNode(*this); // shallow copy
113 fn->setParent(nullptr);
114 parent->addChild(fn);
115 return fn;
116}
117
118/*!
119 Returns this function's virtualness value as a string
120 for use as an attribute value in index files.
121 */
123{
124 switch (m_virtualness) {
126 return QLatin1String("virtual");
128 return QLatin1String("pure");
130 default:
131 break;
132 }
133 return QLatin1String("non");
134}
135
136/*!
137 Sets the function node's virtualness value based on the value
138 of string \a value, which is the value of the function's \e{virtual}
139 attribute in an index file. If \a value is \e{pure}, and if the
140 parent() is a C++ class, set the parent's \e abstract flag to
141 \c {true}.
142 */
143void FunctionNode::setVirtualness(const QString &value)
144{
145 if (value == QLatin1String("pure")) {
146 m_virtualness = PureVirtual;
147 if (parent() && parent()->isClassNode())
148 parent()->setAbstract(true);
149 return;
150 }
151
152 m_virtualness = (value == QLatin1String("virtual")) ? NormalVirtual : NonVirtual;
153}
154
156static void buildMetanessMap()
157{
161 metanessMap_["constructor"] = FunctionNode::Ctor;
162 metanessMap_["copy-constructor"] = FunctionNode::CCtor;
163 metanessMap_["move-constructor"] = FunctionNode::MCtor;
164 metanessMap_["destructor"] = FunctionNode::Dtor;
166 metanessMap_["macrowithparams"] = FunctionNode::MacroWithParams;
167 metanessMap_["macrowithoutparams"] = FunctionNode::MacroWithoutParams;
168 metanessMap_["copy-assign"] = FunctionNode::CAssign;
169 metanessMap_["move-assign"] = FunctionNode::MAssign;
172 metanessMap_["qmlsignalhandler"] = FunctionNode::QmlSignalHandler;
174}
175
185
186/*!
187 Determines the Genus value for this FunctionNode given the
188 Metaness value \a metaness. Returns the Genus value. \a metaness must be
189 one of the values of Metaness. If not, Node::DontCare is
190 returned.
191 */
193{
194 switch (metaness) {
207 return Genus::CPP;
211 return Genus::QML;
212 }
213
214 return Genus::DontCare;
215}
216
217/*!
218 This static function converts the string \a value to an enum
219 value for the kind of function named by \a value.
220 */
221FunctionNode::Metaness FunctionNode::getMetaness(const QString &value)
222{
223 if (metanessMap_.isEmpty())
225 return metanessMap_[value];
226}
227
228/*!
229 This static function converts the topic string \a topic to an enum
230 value for the kind of function this FunctionNode represents.
231 */
232FunctionNode::Metaness FunctionNode::getMetanessFromTopic(const QString &topic)
233{
234 if (topicMetanessMap_.isEmpty())
236 return topicMetanessMap_[topic];
237}
238
239/*!
240 Extends the base implementation to test whether an associated enum
241 is in the API.
242*/
244{
245 if (Node::isInAPI())
246 return true;
247
248 for (auto *property : m_associatedProperties) {
249 if (property->isInAPI())
250 return true;
251 }
252
253 return false;
254}
255
256/*!
257 Sets the function node's overload number to \a number. If \a number
258 is 0, the function node's overload flag is set to false. If
259 \a number is greater than 0, the overload flag is set to true.
260 */
261void FunctionNode::setOverloadNumber(signed short number)
262{
263 m_overloadNumber = number;
264 m_overloadFlag = (number > 0);
265}
266
267/*!
268 \fn void FunctionNode::setReimpFlag()
269
270 Sets the function node's reimp flag to \c true, which means
271 the \e {\\reimp} command was used in the qdoc comment. It is
272 supposed to mean that the function reimplements a virtual
273 function in a base class.
274 */
275
276/*!
277 Returns a string representing the kind of function this
278 Function node represents, which depends on the Metaness
279 value.
280 */
282{
283 switch (m_metaness) {
285 return "QML signal";
287 return "QML signal handler";
289 return "QML method";
290 default:
291 return "function";
292 }
293}
294
295/*!
296 Returns a string representing the Metaness enum value for
297 this function. It is used in index files.
298 */
300{
301 switch (m_metaness) {
303 return "plain";
305 return "signal";
307 return "slot";
309 return "constructor";
311 return "copy-constructor";
313 return "move-constructor";
315 return "destructor";
317 return "macrowithparams";
319 return "macrowithoutparams";
321 return "native";
323 return "copy-assign";
325 return "move-assign";
327 return "qmlsignal";
329 return "qmlsignalhandler";
331 return "qmlmethod";
332 default:
333 return "plain";
334 }
335}
336
337/*!
338 Adds the "associated" property \a p to this function node.
339 The function might be the setter or getter for a property,
340 for example.
341 */
342void FunctionNode::addAssociatedProperty(PropertyNode *p)
343{
344 m_associatedProperties.append(p);
345}
346
347/*!
348 Returns the \e primary associated property, if this is an
349 access function for one or more properties.
350
351 An associated property is considered primary if this
352 function's name starts with the property name. If no
353 prefix match exists, the property with the alphabetically
354 first name is returned for deterministic output.
355
356 If no associated properties exist, returns \nullptr.
357 */
359{
360 if (m_associatedProperties.isEmpty())
361 return nullptr;
362 if (m_associatedProperties.size() == 1)
363 return m_associatedProperties[0];
364
365 auto it = std::find_if(
366 m_associatedProperties.cbegin(), m_associatedProperties.cend(),
367 [this](const PropertyNode *p) {
368 return name().startsWith(p->name());
369 });
370 if (it != m_associatedProperties.cend())
371 return *it;
372
373 // No prefix match: multiple properties share this signal but none
374 // match by name. Pick alphabetically for deterministic output
375 // regardless of tree traversal order.
376 return *std::min_element(
377 m_associatedProperties.cbegin(), m_associatedProperties.cend(),
378 [](const PropertyNode *a, const PropertyNode *b) { return a->name() < b->name(); });
379}
380
381/*!
382 \reimp
383
384 Returns \c true if this is an access function for an obsolete property,
385 otherwise calls the base implementation of isDeprecated().
386*/
388{
390}
391
392/*! \fn unsigned char FunctionNode::overloadNumber() const
393 Returns the overload number for this function.
394 */
395
396/*!
397 Reconstructs and returns the function's signature.
398
399 Specific parts of the signature are included according to
400 flags in \a options:
401
402 \value Node::SignaturePlain
403 Plain signature
404 \value Node::SignatureDefaultValues
405 Include any default argument values
406 \value Node::SignatureReturnType
407 Include return type
408 \value Node::SignatureTemplateParams
409 Include \c {template <parameter_list>} if one exists
410 */
411QString FunctionNode::signature(Node::SignatureOptions options) const
412{
413 QStringList elements;
414
415 if (options & Node::SignatureTemplateParams && templateDecl())
416 elements << (*templateDecl()).to_qstring();
417 if (options & Node::SignatureReturnType)
418 elements << m_returnType.first;
419 elements.removeAll(QString());
420
421 if (!isMacroWithoutParams()) {
422 elements << name() + QLatin1Char('(')
423 + m_parameters.signature(options & Node::SignatureDefaultValues)
424 + QLatin1Char(')');
425 if (!isMacro()) {
426 if (isConst())
427 elements << QStringLiteral("const");
428 if (isRef())
429 elements << QStringLiteral("&");
430 else if (isRefRef())
431 elements << QStringLiteral("&&");
432 }
433 } else {
434 elements << name();
435 }
436 return elements.join(QLatin1Char(' '));
437}
438
439/*!
440 \fn int FunctionNode::compare(const FunctionNode *f1, const FunctionNode *f2)
441
442 Compares FunctionNode \a f1 with \a f2, assumed to have identical names.
443 Returns an integer less than, equal to, or greater than zero if f1 is
444 considered less than, equal to, or greater than f2.
445
446 The main purpose is to provide stable ordering for function overloads.
447 */
448[[nodiscard]] int compare(const FunctionNode *f1, const FunctionNode *f2)
449{
450 // Compare parameter count
451 int param_count{f1->parameters().count()};
452
453 if (int param_diff = param_count - f2->parameters().count(); param_diff != 0)
454 return param_diff;
455
456 // Constness
457 if (f1->isConst() != f2->isConst())
458 return f1->isConst() ? 1 : -1;
459
460 // Reference qualifiers
461 if (f1->isRef() != f2->isRef())
462 return f1->isRef() ? 1 : -1;
463 if (f1->isRefRef() != f2->isRefRef())
464 return f1->isRefRef() ? 1 : -1;
465
466 // Attachedness (applies to QML methods)
468 return f1->isAttached() ? 1 : -1;
469
470 // Parameter types
471 const Parameters &p1{f1->parameters()};
472 const Parameters &p2{f2->parameters()};
473 for (qsizetype i = 0; i < param_count; ++i) {
474 if (int type_comp = QString::compare(p1.at(i).type(), p2.at(i).type());
475 type_comp != 0) {
476 return type_comp;
477 }
478 }
479
480 // Template declarations
481 const auto &t1{f1->templateDecl()};
482 const auto &t2{f2->templateDecl()};
483 if (!t1 && !t2)
484 return 0;
485
486 if (t1 && t2)
487 return (*t1).to_std_string().compare((*t2).to_std_string());
488
489 return t1 ? 1 : -1;
490}
491
492/*!
493 In some cases, it is ok for a public function to be not documented.
494 For example, the macro Q_OBJECT adds several functions to the API of
495 a class, but these functions are normally not meant to be documented.
496 So if a function node doesn't have documentation, then if its name is
497 in the list of functions that it is ok not to document, this function
498 returns true. Otherwise, it returns false.
499
500 These are the member function names added by macros. Usually they
501 are not documented, but they can be documented, so this test avoids
502 reporting an error if they are not documented.
503
504 But maybe we should generate a standard text for each of them?
505 */
507{
508 if (!hasDoc()) {
509 if (name().startsWith(QLatin1String("qt_")) || name() == QLatin1String("metaObject")
510 || name() == QLatin1String("tr") || name() == QLatin1String("trUtf8")
511 || name() == QLatin1String("d_func")) {
512 return true;
513 }
514 QString s = signature(Node::SignatureReturnType);
515 if (s.contains(QLatin1String("enum_type")) && s.contains(QLatin1String("operator|")))
516 return true;
517 }
518 return false;
519}
520
521/*!
522 \fn bool FunctionNode::hasOverloads() const
523 Returns \c true if this function has overloads.
524 */
525
526/*!
527 \internal
528 \brief Returns the type of the function as a string.
529
530 The returned string is either the type as declared in the header, or `auto`
531 if that's the return type in the `\\fn` command for the function.
532 */
534{
535 if (m_returnType.second.has_value())
536 return m_returnType.second.value();
537 return m_returnType.first;
538}
539
540/*!
541 Returns the status of the function, taking the status of any associated
542 properties into account.
543*/
545{
546 auto it = std::find_if_not(m_associatedProperties.begin(), m_associatedProperties.end(),
547 [](const Node *p) -> bool { return p->isDeprecated(); });
548
549 if (!m_associatedProperties.isEmpty() && it == m_associatedProperties.end())
550 return Status::Deprecated;
551 else
552 return Node::status();
553}
554
555QT_END_NAMESPACE
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 isDeprecated() const override
\reimp
static Genus getGenus(Metaness metaness)
Determines the Genus value for this FunctionNode given the Metaness value metaness.
bool isConst() const
bool isRefRef() const
bool isAttached() const override
Returns true if the QML property or QML method node is marked as attached.
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.
friend int compare(const FunctionNode *f1, const FunctionNode *f2)
Compares FunctionNode f1 with f2, assumed to have identical names.
QString returnTypeString() const
Returns the type of the function as a string.
virtual Status status() const override
Returns the status of the function, taking the status of any associated properties into account.
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 void buildMetanessMap()
static QMap< QString, FunctionNode::Metaness > metanessMap_
static QMap< QString, FunctionNode::Metaness > topicMetanessMap_
NodeType
Definition genustypes.h:150
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:239
Aggregate * parent() const
Returns the node's parent pointer.
Definition node.h:208
virtual bool isDeprecated() const
Returns true if this node's status is Deprecated.
Definition node.h:134
const std::optional< RelaxedTemplateDeclaration > & templateDecl() const
Definition node.h:243
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:918
bool hasDoc() const
Returns true if this node is documented, or it represents a documented node read from the index ('had...
Definition node.cpp:933
bool isCppNode() const
Returns true if this node's Genus value is CPP.
Definition node.h:91
virtual void setStatus(Status t)
Sets the node's status to t.
Definition node.cpp:571
@ 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