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 | |
13 | QT_BEGIN_NAMESPACE |
14 | |
15 | /*! |
16 | Constructor for the QML property node. |
17 | */ |
18 | QmlPropertyNode::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 | */ |
48 | bool 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 | */ |
78 | bool 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 | */ |
91 | PropertyNode *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 | |
137 | QT_END_NAMESPACE |
138 | |