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_default(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_explicit{false},
57 m_constexpr{false},
58 m_metaness(Plain),
59 m_virtualness(NonVirtual),
60 m_overloadNumber(0)
61{
62 // nothing
63}
64
65/*!
66 Construct a function node for a QML method or signal, specified
67 by ther Metaness value \a type. It's parent is \a parent, and
68 it's name is \a name. If \a attached is true, it is an attached
69 method or signal.
70
71 \note The function node's overload flag is set to false, and
72 its overload number is set to 0. These data members are set
73 in normalizeOverloads(), when all the overloads are known.
74 */
75FunctionNode::FunctionNode(Metaness kind, Aggregate *parent, const QString &name, bool attached)
76 : Node(NodeType::Function, parent, name),
77 m_const(false),
78 m_default(false),
79 m_static(false),
80 m_reimpFlag(false),
81 m_attached(attached),
82 m_overloadFlag(false),
83 m_primaryOverloadFlag(false),
84 m_isFinal(false),
85 m_isOverride(false),
86 m_isRef(false),
87 m_isRefRef(false),
88 m_isInvokable(false),
89 m_explicit{false},
90 m_constexpr{false},
91 m_metaness(kind),
92 m_virtualness(NonVirtual),
93 m_overloadNumber(0)
94{
95 setGenus(getGenus(m_metaness));
96 if (!isCppNode() && name.startsWith("__"))
98}
99
100/*!
101 Clone this node on the heap and make the clone a child of
102 \a parent. Return the pointer to the clone.
103 */
104Node *FunctionNode::clone(Aggregate *parent)
105{
106 auto *fn = new FunctionNode(*this); // shallow copy
107 fn->setParent(nullptr);
108 parent->addChild(fn);
109 return fn;
110}
111
112/*!
113 Returns this function's virtualness value as a string
114 for use as an attribute value in index files.
115 */
117{
118 switch (m_virtualness) {
120 return QLatin1String("virtual");
122 return QLatin1String("pure");
124 default:
125 break;
126 }
127 return QLatin1String("non");
128}
129
130/*!
131 Sets the function node's virtualness value based on the value
132 of string \a value, which is the value of the function's \e{virtual}
133 attribute in an index file. If \a value is \e{pure}, and if the
134 parent() is a C++ class, set the parent's \e abstract flag to
135 \c {true}.
136 */
137void FunctionNode::setVirtualness(const QString &value)
138{
139 if (value == QLatin1String("pure")) {
140 m_virtualness = PureVirtual;
141 if (parent() && parent()->isClassNode())
142 parent()->setAbstract(true);
143 return;
144 }
145
146 m_virtualness = (value == QLatin1String("virtual")) ? NormalVirtual : NonVirtual;
147}
148
150static void buildMetanessMap()
151{
155 metanessMap_["constructor"] = FunctionNode::Ctor;
156 metanessMap_["copy-constructor"] = FunctionNode::CCtor;
157 metanessMap_["move-constructor"] = FunctionNode::MCtor;
158 metanessMap_["destructor"] = FunctionNode::Dtor;
160 metanessMap_["macrowithparams"] = FunctionNode::MacroWithParams;
161 metanessMap_["macrowithoutparams"] = FunctionNode::MacroWithoutParams;
162 metanessMap_["copy-assign"] = FunctionNode::CAssign;
163 metanessMap_["move-assign"] = FunctionNode::MAssign;
166 metanessMap_["qmlsignalhandler"] = FunctionNode::QmlSignalHandler;
168}
169
179
180/*!
181 Determines the Genus value for this FunctionNode given the
182 Metaness value \a metaness. Returns the Genus value. \a metaness must be
183 one of the values of Metaness. If not, Node::DontCare is
184 returned.
185 */
187{
188 switch (metaness) {
201 return Genus::CPP;
205 return Genus::QML;
206 }
207
208 return Genus::DontCare;
209}
210
211/*!
212 This static function converts the string \a value to an enum
213 value for the kind of function named by \a value.
214 */
215FunctionNode::Metaness FunctionNode::getMetaness(const QString &value)
216{
217 if (metanessMap_.isEmpty())
219 return metanessMap_[value];
220}
221
222/*!
223 This static function converts the topic string \a topic to an enum
224 value for the kind of function this FunctionNode represents.
225 */
226FunctionNode::Metaness FunctionNode::getMetanessFromTopic(const QString &topic)
227{
228 if (topicMetanessMap_.isEmpty())
230 return topicMetanessMap_[topic];
231}
232
233/*!
234 Sets the function node's overload number to \a number. If \a number
235 is 0, the function node's overload flag is set to false. If
236 \a number is greater than 0, the overload flag is set to true.
237 */
238void FunctionNode::setOverloadNumber(signed short number)
239{
240 m_overloadNumber = number;
241 m_overloadFlag = (number > 0);
242}
243
244/*!
245 \fn void FunctionNode::setReimpFlag()
246
247 Sets the function node's reimp flag to \c true, which means
248 the \e {\\reimp} command was used in the qdoc comment. It is
249 supposed to mean that the function reimplements a virtual
250 function in a base class.
251 */
252
253/*!
254 Returns a string representing the kind of function this
255 Function node represents, which depends on the Metaness
256 value.
257 */
259{
260 switch (m_metaness) {
262 return "QML signal";
264 return "QML signal handler";
266 return "QML method";
267 default:
268 return "function";
269 }
270}
271
272/*!
273 Returns a string representing the Metaness enum value for
274 this function. It is used in index files.
275 */
277{
278 switch (m_metaness) {
280 return "plain";
282 return "signal";
284 return "slot";
286 return "constructor";
288 return "copy-constructor";
290 return "move-constructor";
292 return "destructor";
294 return "macrowithparams";
296 return "macrowithoutparams";
298 return "native";
300 return "copy-assign";
302 return "move-assign";
304 return "qmlsignal";
306 return "qmlsignalhandler";
308 return "qmlmethod";
309 default:
310 return "plain";
311 }
312}
313
314/*!
315 Adds the "associated" property \a p to this function node.
316 The function might be the setter or getter for a property,
317 for example.
318 */
319void FunctionNode::addAssociatedProperty(PropertyNode *p)
320{
321 m_associatedProperties.append(p);
322}
323
324/*!
325 Returns the \e primary associated property, if this is an
326 access function for one or more properties.
327
328 An associated property is considered a primary if this
329 function's name starts with the property name. If there's
330 no such property, return the first one available as a
331 fallback.
332
333 If no associated properties exist, returns \nullptr.
334 */
336{
337 if (m_associatedProperties.isEmpty())
338 return nullptr;
339 if (m_associatedProperties.size() == 1)
340 return m_associatedProperties[0];
341
342 auto it = std::find_if(
343 m_associatedProperties.cbegin(), m_associatedProperties.cend(),
344 [this](const PropertyNode *p) {
345 return name().startsWith(p->name());
346 });
347
348 return it != m_associatedProperties.cend() ? *it : m_associatedProperties[0];
349}
350
351/*!
352 \reimp
353
354 Returns \c true if this is an access function for an obsolete property,
355 otherwise calls the base implementation of isDeprecated().
356*/
358{
359 return status() == Node::Deprecated;
360}
361
362/*! \fn unsigned char FunctionNode::overloadNumber() const
363 Returns the overload number for this function.
364 */
365
366/*!
367 Reconstructs and returns the function's signature.
368
369 Specific parts of the signature are included according to
370 flags in \a options:
371
372 \value Node::SignaturePlain
373 Plain signature
374 \value Node::SignatureDefaultValues
375 Include any default argument values
376 \value Node::SignatureReturnType
377 Include return type
378 \value Node::SignatureTemplateParams
379 Include \c {template <parameter_list>} if one exists
380 */
381QString FunctionNode::signature(Node::SignatureOptions options) const
382{
383 QStringList elements;
384
385 if (options & Node::SignatureTemplateParams && templateDecl())
386 elements << (*templateDecl()).to_qstring();
387 if (options & Node::SignatureReturnType)
388 elements << m_returnType.first;
389 elements.removeAll(QString());
390
391 if (!isMacroWithoutParams()) {
392 elements << name() + QLatin1Char('(')
393 + m_parameters.signature(options & Node::SignatureDefaultValues)
394 + QLatin1Char(')');
395 if (!isMacro()) {
396 if (isConst())
397 elements << QStringLiteral("const");
398 if (isRef())
399 elements << QStringLiteral("&");
400 else if (isRefRef())
401 elements << QStringLiteral("&&");
402 }
403 } else {
404 elements << name();
405 }
406 return elements.join(QLatin1Char(' '));
407}
408
409/*!
410 \fn int FunctionNode::compare(const FunctionNode *f1, const FunctionNode *f2)
411
412 Compares FunctionNode \a f1 with \a f2, assumed to have identical names.
413 Returns an integer less than, equal to, or greater than zero if f1 is
414 considered less than, equal to, or greater than f2.
415
416 The main purpose is to provide stable ordering for function overloads.
417 */
418[[nodiscard]] int compare(const FunctionNode *f1, const FunctionNode *f2)
419{
420 // Compare parameter count
421 int param_count{f1->parameters().count()};
422
423 if (int param_diff = param_count - f2->parameters().count(); param_diff != 0)
424 return param_diff;
425
426 // Constness
427 if (f1->isConst() != f2->isConst())
428 return f1->isConst() ? 1 : -1;
429
430 // Reference qualifiers
431 if (f1->isRef() != f2->isRef())
432 return f1->isRef() ? 1 : -1;
433 if (f1->isRefRef() != f2->isRefRef())
434 return f1->isRefRef() ? 1 : -1;
435
436 // Attachedness (applies to QML methods)
438 return f1->isAttached() ? 1 : -1;
439
440 // Parameter types
441 const Parameters &p1{f1->parameters()};
442 const Parameters &p2{f2->parameters()};
443 for (qsizetype i = 0; i < param_count; ++i) {
444 if (int type_comp = QString::compare(p1.at(i).type(), p2.at(i).type());
445 type_comp != 0) {
446 return type_comp;
447 }
448 }
449
450 // Template declarations
451 const auto &t1{f1->templateDecl()};
452 const auto &t2{f2->templateDecl()};
453 if (!t1 && !t2)
454 return 0;
455
456 if (t1 && t2)
457 return (*t1).to_std_string().compare((*t2).to_std_string());
458
459 return t1 ? 1 : -1;
460}
461
462/*!
463 In some cases, it is ok for a public function to be not documented.
464 For example, the macro Q_OBJECT adds several functions to the API of
465 a class, but these functions are normally not meant to be documented.
466 So if a function node doesn't have documentation, then if its name is
467 in the list of functions that it is ok not to document, this function
468 returns true. Otherwise, it returns false.
469
470 These are the member function names added by macros. Usually they
471 are not documented, but they can be documented, so this test avoids
472 reporting an error if they are not documented.
473
474 But maybe we should generate a standard text for each of them?
475 */
477{
478 if (!hasDoc()) {
479 if (name().startsWith(QLatin1String("qt_")) || name() == QLatin1String("metaObject")
480 || name() == QLatin1String("tr") || name() == QLatin1String("trUtf8")
481 || name() == QLatin1String("d_func")) {
482 return true;
483 }
484 QString s = signature(Node::SignatureReturnType);
485 if (s.contains(QLatin1String("enum_type")) && s.contains(QLatin1String("operator|")))
486 return true;
487 }
488 return false;
489}
490
491/*!
492 \fn bool FunctionNode::hasOverloads() const
493 Returns \c true if this function has overloads.
494 */
495
496/*!
497 \internal
498 \brief Returns the type of the function as a string.
499
500 The returned string is either the type as declared in the header, or `auto`
501 if that's the return type in the `\\fn` command for the function.
502 */
504{
505 if (m_returnType.second.has_value())
506 return m_returnType.second.value();
507 return m_returnType.first;
508}
509
510/*!
511 Returns the status of the function, taking the status of any associated
512 properties into account.
513*/
515{
516 auto it = std::find_if_not(m_associatedProperties.begin(), m_associatedProperties.end(),
517 [](const Node *p) -> bool { return p->isDeprecated(); });
518
519 if (!m_associatedProperties.isEmpty() && it == m_associatedProperties.end())
520 return Node::Deprecated;
521 else
522 return Node::status();
523}
524
525QT_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 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.
void setVirtualness(const QString &value)
Sets the function node's virtualness value based on the value of string value, which is the value of ...
virtual Status status() const override
Returns the status of the function, taking the status of any associated properties into account.
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.
static void buildTopicMetanessMap()
static void buildMetanessMap()
static QMap< QString, FunctionNode::Metaness > metanessMap_
static QMap< QString, FunctionNode::Metaness > topicMetanessMap_
NodeType
Definition genustypes.h:150
The Node class is the base class for all the nodes in QDoc's parse tree.
void setGenus(Genus t)
Definition node.h:93
virtual Status status() const
Returns the node's status value.
Definition node.h:249
Aggregate * parent() const
Returns the node's parent pointer.
Definition node.h:215
const std::optional< RelaxedTemplateDeclaration > & templateDecl() const
Definition node.h:253
bool hasDoc() const
Returns true if this node is documented, or it represents a documented node read from the index ('had...
Definition node.cpp:859
bool isCppNode() const
Returns true if this node's Genus value is CPP.
Definition node.h:98
void setStatus(Status t)
Sets the node's status to t.
Definition node.cpp:510
Status
An unsigned char that specifies the status of the documentation element in the documentation set.
Definition node.h:57
@ Internal
Definition node.h:61
@ Deprecated
Definition node.h:58
@ SignatureReturnType
Definition node.h:75
A class for parsing and managing a function parameter list.
Definition main.cpp:28
int count() const
Definition parameters.h:72