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 "qmltypenode.h"
5#include "collectionnode.h"
6#include "qdocdatabase.h"
7
8#include <QtCore/qdebug.h>
9
10QT_BEGIN_NAMESPACE
11
12QMultiMap<const Node *, Node *> QmlTypeNode::s_inheritedBy;
13
14/*!
15 Constructs a Qml type.
16
17 The new node has the given \a parent, name \a name, and a specific node
18 \a type. Valid types are Node::QmlType and Node::QmlValueType.
19 */
20QmlTypeNode::QmlTypeNode(Aggregate *parent, const QString &name, Node::NodeType type)
21 : Aggregate(type, parent, name)
22{
23 Q_ASSERT(type == Node::QmlType || type == Node::QmlValueType);
24 setTitle(name);
25}
26
27/*!
28 Clear the static maps so that subsequent runs don't try to use
29 contents from a previous run.
30 */
31void QmlTypeNode::terminate()
32{
33 s_inheritedBy.clear();
34}
35
36/*!
37 Record the fact that QML class \a base is inherited by
38 QML class \a sub.
39 */
40void QmlTypeNode::addInheritedBy(const Node *base, Node *sub)
41{
42 if (sub->isInternal())
43 return;
44 if (!s_inheritedBy.contains(key: base, value: sub))
45 s_inheritedBy.insert(key: base, value: sub);
46}
47
48/*!
49 Loads the list \a subs with the nodes of all the subclasses of \a base.
50 */
51void QmlTypeNode::subclasses(const Node *base, NodeList &subs)
52{
53 subs.clear();
54 if (s_inheritedBy.count(key: base) > 0) {
55 subs = s_inheritedBy.values(key: base);
56 }
57}
58
59/*!
60 If this QML type node has a base type node,
61 return the fully qualified name of that QML
62 type, i.e. <QML-module-name>::<QML-type-name>.
63 */
64QString QmlTypeNode::qmlFullBaseName() const
65{
66 QString result;
67 if (m_qmlBaseNode) {
68 result = m_qmlBaseNode->logicalModuleName() + "::" + m_qmlBaseNode->name();
69 }
70 return result;
71}
72
73/*!
74 If the QML type's QML module pointer is set, return the QML
75 module name from the QML module node. Otherwise, return the
76 empty string.
77 */
78QString QmlTypeNode::logicalModuleName() const
79{
80 return (m_logicalModule ? m_logicalModule->logicalModuleName() : QString());
81}
82
83/*!
84 If the QML type's QML module pointer is set, return the QML
85 module version from the QML module node. Otherwise, return
86 the empty string.
87 */
88QString QmlTypeNode::logicalModuleVersion() const
89{
90 return (m_logicalModule ? m_logicalModule->logicalModuleVersion() : QString());
91}
92
93/*!
94 If the QML type's QML module pointer is set, return the QML
95 module identifier from the QML module node. Otherwise, return
96 the empty string.
97 */
98QString QmlTypeNode::logicalModuleIdentifier() const
99{
100 return (m_logicalModule ? m_logicalModule->logicalModuleIdentifier() : QString());
101}
102
103/*!
104 Returns true if this QML type inherits \a type.
105 */
106bool QmlTypeNode::inherits(Aggregate *type)
107{
108 QmlTypeNode *qtn = qmlBaseNode();
109 while (qtn != nullptr) {
110 if (qtn == type)
111 return true;
112 qtn = qtn->qmlBaseNode();
113 }
114 return false;
115}
116
117/*!
118 Recursively resolves the base node for this QML type when only the name of
119 the base type is known.
120
121 \a previousSearches is used for speeding up the process.
122*/
123void QmlTypeNode::resolveInheritance(NodeMap &previousSearches)
124{
125 if (m_qmlBaseNode || m_qmlBaseName.isEmpty())
126 return;
127
128 auto *base = static_cast<QmlTypeNode *>(previousSearches.value(key: m_qmlBaseName));
129 if (!previousSearches.contains(key: m_qmlBaseName)) {
130 for (const auto &import : std::as_const(t&: m_importList)) {
131 base = QDocDatabase::qdocDB()->findQmlType(import, name: m_qmlBaseName);
132 if (base)
133 break;
134 }
135 if (!base) {
136 if (m_qmlBaseName.contains(c: ':'))
137 base = QDocDatabase::qdocDB()->findQmlType(name: m_qmlBaseName);
138 else
139 base = QDocDatabase::qdocDB()->findQmlType(qmid: QString(), name: m_qmlBaseName);
140 }
141 previousSearches.insert(key: m_qmlBaseName, value: base);
142 }
143
144 if (base && base != this) {
145 m_qmlBaseNode = base;
146 QmlTypeNode::addInheritedBy(base, sub: this);
147 // Base types read from the index need resolving as they only have the name set
148 if (base->isIndexNode())
149 base->resolveInheritance(previousSearches);
150 }
151}
152
153QT_END_NAMESPACE
154

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