summaryrefslogtreecommitdiffstats
path: root/src/qdoc/qdoc/src/qdoc/qmlpropertynode.cpp
blob: 335b7d870c8db03f77066a128e1852772805a526 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#include "qmlpropertynode.h"

#include "classnode.h"
#include "propertynode.h"
#include "enumnode.h"

#include <utility>
#include "qdocdatabase.h"
#include "utilities.h"

QT_BEGIN_NAMESPACE

/*!
  Constructor for the QML property node.
 */
QmlPropertyNode::QmlPropertyNode(Aggregate *parent, const QString &name, QString type,
                                 bool attached)
    : Node(QmlProperty, parent, name),
      m_type(std::move(type)),
      m_attached(attached)
{
    if (m_type == "alias")
        m_isAlias = true;
    if (name.startsWith("__"))
        setStatus(Internal);
}

/*!
  \fn bool QmlPropertyNode::isReadOnly() const

  Returns \c true if this QML property node is marked as a
  read-only property.
*/

/*!
    \fn const EnumNode *QmlPropertyNode::enumNode() const

    Returns the node representing the C++ enumeration associated
    with this property, or \nullptr.
*/

/*!
    Returns the prefix to use for documentated enumerators from
    the associated C++ enum for this property.
*/
const QString &QmlPropertyNode::enumPrefix() const
{
    return !m_enumNode.second.isEmpty() ?
            m_enumNode.second : parent()->name();
}

/*!
    Locates the node specified by \a path and sets it as the C++ enumeration
    associated with this property.

    \a registeredQmlName is used as the prefix in the generated enum value
    documentation.

    \note The target EnumNode is searched under the primary tree only.

    Returns \c true on success.
*/
bool QmlPropertyNode::setEnumNode(const QString &path, const QString &registeredQmlName)
{
    m_enumNode.first = static_cast<EnumNode*>(
        QDocDatabase::qdocDB()->primaryTree()->findNodeByNameAndType(path.split("::"), &Node::isEnumType)
    );
    m_enumNode.second = registeredQmlName;
    return m_enumNode.first != nullptr;
}

/*!
  Returns \c true if this QML property or attached property is
  read-only. If the read-only status is not set explicitly
  using the \\readonly command, QDoc attempts to resolve it
  from the associated C++ class instantiated by the QML type
  that this property belongs to.

  \note Depending on how the QML type is implemented, this
  information may not be available to QDoc. If so, add a debug
  line but do not treat it as a warning.
 */
bool QmlPropertyNode::isReadOnly()
{
    if (m_readOnly != FlagValueDefault)
        return fromFlagValue(m_readOnly, false);

    // Find the parent QML type node
    auto *parent{this->parent()};
    while (parent && !(parent->isQmlType()))
        parent = parent->parent();

    bool readonly{false};
    if (auto qcn = static_cast<QmlTypeNode *>(parent); qcn && qcn->classNode()) {
        if (auto propertyNode = findCorrespondingCppProperty(); propertyNode)
            readonly = !propertyNode->isWritable();
        else
            qCDebug(lcQdoc).nospace()
                    << qPrintable(defLocation().toString())
                    << ": Automatic resolution of QML property attributes failed for "
                    << name()
                    << " (Q_PROPERTY not found in the C++ class hierarchy known to QDoc. "
                    << "Likely, the type is replaced with a private implementation.)";
    }
    markReadOnly(readonly);
    return readonly;
}

/*!
    Returns \c true if this QML property is marked with \required or the
    corresponding C++ property uses the REQUIRED keyword.
*/
bool QmlPropertyNode::isRequired()
{
    if (m_required != FlagValueDefault)
        return fromFlagValue(m_required, false);

    PropertyNode *pn = findCorrespondingCppProperty();
    return pn != nullptr && pn->isRequired();
}

/*!
  Returns a pointer this QML property's corresponding C++
  property, if it has one.
 */
PropertyNode *QmlPropertyNode::findCorrespondingCppProperty()
{
    PropertyNode *pn;
    Node *n = parent();
    while (n && !(n->isQmlType()))
        n = n->parent();
    if (n) {
        auto *qcn = static_cast<QmlTypeNode *>(n);
        ClassNode *cn = qcn->classNode();
        if (cn) {
            /*
              If there is a dot in the property name, first
              find the C++ property corresponding to the QML
              property group.
             */
            QStringList dotSplit = name().split(QChar('.'));
            pn = cn->findPropertyNode(dotSplit[0]);
            if (pn) {
                /*
                  Now find the C++ property corresponding to
                  the QML property in the QML property group,
                  <group>.<property>.
                 */
                if (dotSplit.size() > 1) {
                    QStringList path(extractClassName(pn->qualifiedDataType()));
                    Node *nn = QDocDatabase::qdocDB()->findClassNode(path);
                    if (nn) {
                        auto *cn = static_cast<ClassNode *>(nn);
                        PropertyNode *pn2 = cn->findPropertyNode(dotSplit[1]);
                        /*
                          If found, return the C++ property
                          corresponding to the QML property.
                          Otherwise, return the C++ property
                          corresponding to the QML property
                          group.
                         */
                        return (pn2 ? pn2 : pn);
                    }
                } else
                    return pn;
            }
        }
    }
    return nullptr;
}

QT_END_NAMESPACE