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
qqmltypenamecache_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
5#ifndef QQMLTYPENAMECACHE_P_H
6#define QQMLTYPENAMECACHE_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qqmlrefcount_p.h>
20#include "qqmlmetatype_p.h"
21
22#include <private/qstringhash_p.h>
23#include <private/qqmlimport_p.h>
24#include <private/qqmltypemoduleversion_p.h>
25
26#include <QtCore/qvector.h>
27
29
32 : scriptIndex(-1)
33 {}
34 // Imported module
36
37 // Or, imported script
39
40 // Or, imported compositeSingletons
42
43 // The qualifier of this import
45};
46
47class QQmlType;
48class QQmlEngine;
49class Q_QML_EXPORT QQmlTypeNameCache final : public QQmlRefCounted<QQmlTypeNameCache>
50{
51public:
52 QQmlTypeNameCache(const QQmlRefPointer<QQmlImports> &imports) : m_imports(imports) {}
53 ~QQmlTypeNameCache() {}
54
55 inline bool isEmpty() const;
56
57 void add(const QHashedString &name, int sciptIndex = -1, const QHashedString &nameSpace = QHashedString());
58 void add(const QHashedString &name, const QUrl &url, const QHashedString &nameSpace = QHashedString());
59
60 struct Result {
61 inline Result();
62 inline Result(const QQmlImportRef *importNamespace);
63 inline Result(const QQmlType &type);
64 inline Result(int scriptIndex);
65
66 inline bool isValid() const;
67
68 QQmlType type;
69 const QQmlImportRef *importNamespace;
70 int scriptIndex;
71 };
72
73 enum class QueryNamespaced { No, Yes };
74
75 // Restrict the types allowed for key. We don't want QV4::ScopedString, for example.
76
77 template<QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion>
78 Result query(const QHashedStringRef &key, QQmlTypeLoader *typeLoader) const
79 {
80 return doQuery<const QHashedStringRef &, recursionRestriction>(key, typeLoader);
81 }
82
83 template<QueryNamespaced queryNamespaced = QueryNamespaced::Yes>
84 Result query(const QHashedStringRef &key, const QQmlImportRef *importNamespace,
85 QQmlTypeLoader *typeLoader) const
86 {
87 return doQuery<const QHashedStringRef &, queryNamespaced>(key, importNamespace, typeLoader);
88 }
89
90 template<QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion>
91 Result query(const QV4::String *key, QQmlTypeLoader *typeLoader) const
92 {
93 return doQuery<const QV4::String *, recursionRestriction>(key, typeLoader);
94 }
95
96 template<QueryNamespaced queryNamespaced = QueryNamespaced::Yes>
97 Result query(const QV4::String *key, const QQmlImportRef *importNamespace,
98 QQmlTypeLoader *typeLoader) const
99 {
100 return doQuery<const QV4::String *, queryNamespaced>(key, importNamespace, typeLoader);
101 }
102
103private:
104 friend class QQmlImports;
105
106 static QHashedStringRef toHashedStringRef(const QHashedStringRef &key) { return key; }
107 static QHashedStringRef toHashedStringRef(const QV4::String *key)
108 {
109 const QV4::Heap::String *heapString = key->d();
110
111 // toQString() would also do simplifyString(). Therefore, we can be sure that this
112 // is safe. Any other operation on the string data cannot keep references on the
113 // non-simplified pieces.
114 if (heapString->subtype >= QV4::Heap::String::StringType_Complex)
115 heapString->simplifyString();
116
117 // This is safe because the string data is backed by the QV4::String we got as
118 // parameter. The contract about passing V4 values as parameters is that you have to
119 // scope them first, so that they don't get gc'd while the callee is working on them.
120 const QStringPrivate &text = heapString->text();
121 return QHashedStringRef(QStringView(text.ptr, text.size));
122 }
123
124 static QString toQString(const QHashedStringRef &key) { return key.toString(); }
125 static QString toQString(const QV4::String *key) { return key->toQStringNoThrow(); }
126
127 template<typename Key, QQmlImport::RecursionRestriction recursionRestriction>
128 Result doQuery(Key name, QQmlTypeLoader *typeLoader) const
129 {
130 Result result = doQuery(m_namedImports, name);
131
132 if (!result.isValid())
133 result = typeSearch(m_anonymousImports, name);
134
135 if (!result.isValid())
136 result = doQuery(m_anonymousCompositeSingletons, name);
137
138 if (!result.isValid()) {
139 // Look up anonymous types from the imports of this document
140 // ### it would be nice if QQmlImports allowed us to resolve a namespace
141 // first, and then types on it.
142 QQmlImportNamespace *typeNamespace = nullptr;
143 QList<QQmlError> errors;
144 QQmlType t;
145 bool typeRecursionDetected = false;
146 const bool typeFound = m_imports->resolveType(
147 typeLoader, toHashedStringRef(name), &t, nullptr, &typeNamespace, &errors,
148 QQmlType::AnyRegistrationType,
149 recursionRestriction == QQmlImport::AllowRecursion
150 ? &typeRecursionDetected
151 : nullptr);
152 if (typeFound)
153 return Result(t);
154
155 }
156
157 return result;
158 }
159
160 template<typename Key, QueryNamespaced queryNamespaced>
161 Result doQuery(Key name, const QQmlImportRef *importNamespace, QQmlTypeLoader *typeLoader) const
162 {
163 Q_ASSERT(importNamespace && importNamespace->scriptIndex == -1);
164
165 if constexpr (queryNamespaced == QueryNamespaced::Yes) {
166 QMap<const QQmlImportRef *, QStringHash<QQmlImportRef> >::const_iterator it
167 = m_namespacedImports.constFind(importNamespace);
168 if (it != m_namespacedImports.constEnd()) {
169 Result r = doQuery(*it, name);
170 if (r.isValid())
171 return r;
172 }
173 }
174
175 Result result = typeSearch(importNamespace->modules, name);
176
177 if (!result.isValid())
178 result = doQuery(importNamespace->compositeSingletons, name);
179
180 if (!result.isValid()) {
181 // Look up types from the imports of this document
182 // ### it would be nice if QQmlImports allowed us to resolve a namespace
183 // first, and then types on it.
184 const QString qualifiedTypeName = importNamespace->m_qualifier + u'.' + toQString(name);
185 QQmlImportNamespace *typeNamespace = nullptr;
186 QList<QQmlError> errors;
187 QQmlType t;
188 bool typeFound = m_imports->resolveType(
189 typeLoader, qualifiedTypeName, &t, nullptr, &typeNamespace, &errors);
190 if (typeFound)
191 return Result(t);
192 }
193
194 return result;
195 }
196
197 template<typename Key>
198 Result doQuery(const QStringHash<QQmlImportRef> &imports, Key key) const
199 {
200 QQmlImportRef *i = imports.value(key);
201 if (i) {
202 Q_ASSERT(!i->m_qualifier.isEmpty());
203 if (i->scriptIndex != -1) {
204 return Result(i->scriptIndex);
205 } else {
206 return Result(i);
207 }
208 }
209
210 return Result();
211 }
212
213 template<typename Key>
214 Result doQuery(const QStringHash<QUrl> &urls, Key key) const
215 {
216 QUrl *url = urls.value(key);
217 if (url) {
218 QQmlType type = QQmlMetaType::qmlType(*url);
219 return Result(type);
220 }
221
222 return Result();
223 }
224
225 template<typename Key>
226 Result typeSearch(const QList<QQmlTypeModuleVersion> &modules, Key key) const
227 {
228 for (auto it = modules.crbegin(), end = modules.crend(); it != end; ++it) {
229 QQmlType type = it->type(key);
230 if (type.isValid())
231 return Result(type);
232 }
233
234 return Result();
235 }
236
237 QStringHash<QQmlImportRef> m_namedImports;
238 QMap<const QQmlImportRef *, QStringHash<QQmlImportRef> > m_namespacedImports;
239 QList<QQmlTypeModuleVersion> m_anonymousImports;
240 QStringHash<QUrl> m_anonymousCompositeSingletons;
241 QQmlRefPointer<QQmlImports> m_imports;
242};
243
244QQmlTypeNameCache::Result::Result()
245: importNamespace(nullptr), scriptIndex(-1)
246{
247}
248
249QQmlTypeNameCache::Result::Result(const QQmlImportRef *importNamespace)
250: importNamespace(importNamespace), scriptIndex(-1)
251{
252}
253
254QQmlTypeNameCache::Result::Result(const QQmlType &type)
255: type(type), importNamespace(nullptr), scriptIndex(-1)
256{
257}
258
259QQmlTypeNameCache::Result::Result(int scriptIndex)
260: importNamespace(nullptr), scriptIndex(scriptIndex)
261{
262}
263
264bool QQmlTypeNameCache::Result::isValid() const
265{
266 return type.isValid() || importNamespace || scriptIndex != -1;
267}
268
269bool QQmlTypeNameCache::isEmpty() const
270{
271 return m_namedImports.isEmpty() && m_anonymousImports.isEmpty()
272 && m_anonymousCompositeSingletons.isEmpty();
273}
274
275QT_END_NAMESPACE
276
277#endif // QQMLTYPENAMECACHE_P_H
Combined button and popup list for selecting options.
QList< QQmlTypeModuleVersion > modules
QStringHash< QUrl > compositeSingletons