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 "qmlpropertynode.h"
5
6#include "classnode.h"
7#include "propertynode.h"
8
9#include <utility>
10#include "qdocdatabase.h"
11#include "utilities.h"
12
13QT_BEGIN_NAMESPACE
14
15/*!
16 Constructor for the QML property node.
17 */
18QmlPropertyNode::QmlPropertyNode(Aggregate *parent, const QString &name, QString type,
19 bool attached)
20 : Node(QmlProperty, parent, name),
21 m_type(std::move(type)),
22 m_attached(attached)
23{
24 if (m_type == "alias")
25 m_isAlias = true;
26 if (name.startsWith(s: "__"))
27 setStatus(Internal);
28}
29
30/*!
31 \fn bool QmlPropertyNode::isReadOnly() const
32
33 Returns \c true if this QML property node is marked as a
34 read-only property.
35*/
36
37/*!
38 Returns \c true if this QML property or attached property is
39 read-only. If the read-only status is not set explicitly
40 using the \\readonly command, QDoc attempts to resolve it
41 from the associated C++ class instantiated by the QML type
42 that this property belongs to.
43
44 \note Depending on how the QML type is implemented, this
45 information may not be available to QDoc. If so, add a debug
46 line but do not treat it as a warning.
47 */
48bool QmlPropertyNode::isReadOnly()
49{
50 if (m_readOnly != FlagValueDefault)
51 return fromFlagValue(fv: m_readOnly, defaultValue: false);
52
53 // Find the parent QML type node
54 auto *parent{this->parent()};
55 while (parent && !(parent->isQmlType()))
56 parent = parent->parent();
57
58 bool readonly{false};
59 if (auto qcn = static_cast<QmlTypeNode *>(parent); qcn && qcn->classNode()) {
60 if (auto propertyNode = findCorrespondingCppProperty(); propertyNode)
61 readonly = !propertyNode->isWritable();
62 else
63 qCDebug(lcQdoc).nospace()
64 << qPrintable(defLocation().toString())
65 << ": Automatic resolution of QML property attributes failed for "
66 << name()
67 << " (Q_PROPERTY not found in the C++ class hierarchy known to QDoc. "
68 << "Likely, the type is replaced with a private implementation.)";
69 }
70 markReadOnly(flag: readonly);
71 return readonly;
72}
73
74/*!
75 Returns \c true if this QML property is marked with \required or the
76 corresponding C++ property uses the REQUIRED keyword.
77*/
78bool QmlPropertyNode::isRequired()
79{
80 if (m_required != FlagValueDefault)
81 return fromFlagValue(fv: m_required, defaultValue: false);
82
83 PropertyNode *pn = findCorrespondingCppProperty();
84 return pn != nullptr && pn->isRequired();
85}
86
87/*!
88 Returns a pointer this QML property's corresponding C++
89 property, if it has one.
90 */
91PropertyNode *QmlPropertyNode::findCorrespondingCppProperty()
92{
93 PropertyNode *pn;
94 Node *n = parent();
95 while (n && !(n->isQmlType()))
96 n = n->parent();
97 if (n) {
98 auto *qcn = static_cast<QmlTypeNode *>(n);
99 ClassNode *cn = qcn->classNode();
100 if (cn) {
101 /*
102 If there is a dot in the property name, first
103 find the C++ property corresponding to the QML
104 property group.
105 */
106 QStringList dotSplit = name().split(sep: QChar('.'));
107 pn = cn->findPropertyNode(name: dotSplit[0]);
108 if (pn) {
109 /*
110 Now find the C++ property corresponding to
111 the QML property in the QML property group,
112 <group>.<property>.
113 */
114 if (dotSplit.size() > 1) {
115 QStringList path(extractClassName(string: pn->qualifiedDataType()));
116 Node *nn = QDocDatabase::qdocDB()->findClassNode(path);
117 if (nn) {
118 auto *cn = static_cast<ClassNode *>(nn);
119 PropertyNode *pn2 = cn->findPropertyNode(name: dotSplit[1]);
120 /*
121 If found, return the C++ property
122 corresponding to the QML property.
123 Otherwise, return the C++ property
124 corresponding to the QML property
125 group.
126 */
127 return (pn2 ? pn2 : pn);
128 }
129 } else
130 return pn;
131 }
132 }
133 }
134 return nullptr;
135}
136
137QT_END_NAMESPACE
138

source code of qttools/src/qdoc/qdoc/qmlpropertynode.cpp