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
qqmlimport_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 QQMLIMPORT_P_H
6#define QQMLIMPORT_P_H
7
8#include <QtCore/qurl.h>
9#include <QtCore/qcoreapplication.h>
10#include <QtCore/qloggingcategory.h>
11#include <QtCore/qset.h>
12#include <QtCore/qstringlist.h>
13
14#include <QtQml/qqmlabstracturlinterceptor.h>
15#include <QtQml/qqmlerror.h>
16#include <QtQml/qqmlfile.h>
17
18#include <private/qfieldlist_p.h>
19#include <private/qqmldirparser_p.h>
20#include <private/qqmltype_p.h>
21#include <private/qstringhash_p.h>
22
23//
24// W A R N I N G
25// -------------
26//
27// This file is not part of the Qt API. It exists purely as an
28// implementation detail. This header file may change from version to
29// version without notice, or even be removed.
30//
31// We mean it.
32//
33
34QT_BEGIN_NAMESPACE
35
36class QQmlTypeNameCache;
37class QDir;
39class QQmlTypeLoader;
41class QTypeRevision;
42class QQmlTypeLoader;
43
45
49
51{
57
58 QString uri; // e.g. QtQuick
59 QString url; // the base path of the import
60 QTypeRevision version; // the version imported
61
62 bool isLibrary; // true means that this is not a file import
63
64 // not covered by precedence. You can set a component as implicitly imported after the fact.
65 bool implicitlyImported = false;
66 bool isInlineComponent = false;
67
69
70 QQmlDirComponents qmlDirComponents; // a copy of the components listed in the qmldir
71 QQmlDirScripts qmlDirScripts; // a copy of the scripts in the qmldir
72
73 bool setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoaderQmldirContent &qmldir,
74 QQmlImportNamespace *nameSpace, QList<QQmlError> *errors);
75
76 static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts,
77 QTypeRevision version);
78
79 bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
80 QTypeRevision *version_return, QQmlType* type_return,
81 const QString *base = nullptr, bool *typeRecursionDetected = nullptr,
82 QQmlType::RegistrationType = QQmlType::AnyRegistrationType,
84 QList<QQmlError> *errors = nullptr) const;
85};
86
88{
89public:
91 ~QQmlImportNamespace() { qDeleteAll(imports); }
92
94
96 const QString &moduleUri, QTypeRevision version) const;
98 const QString &location, QTypeRevision version) const;
99
100 bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type,
101 QTypeRevision *version_return, QQmlType* type_return,
102 const QString *base = nullptr, QList<QQmlError> *errors = nullptr,
103 QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType,
104 bool *typeRecursionDeteced = nullptr);
105
106 // Prefix when used as a qualified import. Otherwise empty.
108
109 // Used by QQmlImports::m_qualifiedSets
110 // set to this in unqualifiedSet to indicate that the lists of imports needs
111 // to be sorted when an inline component import was added
112 // We can't use flag pointer, as that does not work with QFieldList
114 bool needsSorting() const { return nextNamespace == this; }
115 void setNeedsSorting(bool needsSorting)
116 {
117 Q_ASSERT(nextNamespace == this || nextNamespace == nullptr);
118 nextNamespace = needsSorting ? this : nullptr;
119 }
120};
121
122class Q_QML_EXPORT QQmlImports final : public QQmlRefCounted<QQmlImports>
123{
124 Q_DISABLE_COPY_MOVE(QQmlImports)
125 Q_DECLARE_TR_FUNCTIONS(QQmlImports)
126public:
127 enum ImportVersion { FullyVersioned, PartiallyVersioned, Unversioned };
128
129 enum ImportFlag : quint8 {
130 ImportNoFlag = 0x0,
131 ImportIncomplete = 0x1,
132 };
133 Q_DECLARE_FLAGS(ImportFlags, ImportFlag)
134
135 QQmlImports() = default;
136 ~QQmlImports()
137 {
138 while (QQmlImportNamespace *ns = m_qualifiedSets.takeFirst())
139 delete ns;
140 }
141
142 void setBaseUrl(const QUrl &url, const QString &urlString = QString());
143 QUrl baseUrl() const { return m_baseUrl; }
144
145 bool resolveType(
146 QQmlTypeLoader *typeLoader, const QHashedStringRef &type, QQmlType *type_return,
147 QTypeRevision *version_return, QQmlImportNamespace **ns_return,
148 QList<QQmlError> *errors = nullptr,
149 QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType,
150 bool *typeRecursionDetected = nullptr) const;
151
152 QTypeRevision addImplicitImport(
153 QQmlTypeLoader *typeLoader, QString *localQmldir, QList<QQmlError> *errors)
154 {
155 Q_ASSERT(errors);
156 qCDebug(lcQmlImport) << "addImplicitImport:" << qPrintable(baseUrl().toString());
157
158 const ImportFlags flags =
159 ImportFlags(!isLocal(baseUrl()) ? ImportIncomplete : ImportNoFlag);
160 return addFileImport(
161 typeLoader, QLatin1String("."), QString(), QTypeRevision(), flags,
162 QQmlImportInstance::Implicit, localQmldir, errors);
163 }
164
165 bool addInlineComponentImport(
166 QQmlImportInstance *const importInstance, const QString &name, const QUrl &importUrl);
167
168 QTypeRevision addFileImport(
169 QQmlTypeLoader *typeLoader, const QString &uri, const QString &prefix,
170 QTypeRevision requestedVersion, ImportFlags flags, quint8 precedence,
171 QString *localQmldir, QList<QQmlError> *errors);
172
173 QTypeRevision addLibraryImport(
174 QQmlTypeLoader *typeLoader, const QString &uri, const QString &prefix,
175 QTypeRevision requestedVersion, const QString &qmldirIdentifier,
176 const QString &qmldirUrl, ImportFlags flags, quint8 precedence,
177 QList<QQmlError> *errors);
178
179 QTypeRevision updateQmldirContent(
180 QQmlTypeLoader *typeLoader, const QString &uri, QTypeRevision version,
181 const QString &prefix, const QString &qmldirIdentifier, const QString &qmldirUrl,
182 QList<QQmlError> *errors);
183
184 void populateCache(QQmlTypeNameCache *cache) const;
185
186 struct ScriptReference
187 {
188 QString nameSpace;
189 QString qualifier;
190 QUrl fileName;
191 QUrl location;
192 };
193
194 QList<ScriptReference> resolvedScripts() const;
195
196 struct CompositeSingletonReference
197 {
198 QString typeName;
199 QString prefix;
200 QTypeRevision version;
201 };
202
203 QList<CompositeSingletonReference> resolvedCompositeSingletons() const;
204
205 static QStringList completeQmldirPaths(
206 const QString &uri, const QStringList &basePaths, QTypeRevision version);
207
208 static QString versionString(QTypeRevision version, ImportVersion importVersion);
209
210 static bool isLocal(const QString &url)
211 {
212 return !QQmlFile::urlToLocalFileOrQrc(url).isEmpty();
213 }
214
215 static bool isLocal(const QUrl &url)
216 {
217 return !QQmlFile::urlToLocalFileOrQrc(url).isEmpty();
218 }
219
220 static QUrl urlFromLocalFileOrQrcOrUrl(const QString &);
221
222 static void setDesignerSupportRequired(bool b);
223
224 static QTypeRevision validVersion(QTypeRevision version = QTypeRevision());
225
226 static QQmlError moduleNotFoundError(const QString &uri, QTypeRevision version);
227
228private:
229 enum class IsLibrary : bool { No = false, Yes = true };
230
231 static void insertImport(QQmlImportNamespace *nameSpace, QQmlImportInstance *import)
232 {
233 for (auto it = nameSpace->imports.cbegin(), end = nameSpace->imports.cend();
234 it != end; ++it) {
235 if ((*it)->precedence < import->precedence)
236 continue;
237
238 nameSpace->imports.insert(it, import);
239 return;
240 }
241 nameSpace->imports.append(import);
242 }
243
244 template<IsLibrary isLibrary>
245 static QQmlImportInstance *addImportToNamespace(
246 QQmlImportNamespace *nameSpace, const QString &uri, const QString &url,
247 QTypeRevision version, quint8 precedence)
248 {
249 Q_ASSERT(nameSpace);
250 Q_ASSERT(url.isEmpty() || url.endsWith(QLatin1Char('/')));
251
252 QQmlImportInstance *import = new QQmlImportInstance;
253 import->uri = uri;
254 import->url = url;
255 import->version = version;
256 import->isLibrary = bool(isLibrary);
257 import->precedence = precedence;
258 import->implicitlyImported = precedence >= QQmlImportInstance::Implicit;
259
260 insertImport(nameSpace, import);
261 return import;
262 }
263
264 QQmlImportNamespace *importNamespace(const QString &prefix);
265
266 bool resolveType(
267 QQmlTypeLoader *typeLoader, const QHashedStringRef &type, QTypeRevision *version_return,
268 QQmlType *type_return, QList<QQmlError> *errors,
269 QQmlType::RegistrationType registrationType,
270 bool *typeRecursionDetected = nullptr) const;
271
272 QQmlImportNamespace *findQualifiedNamespace(const QHashedStringRef &) const;
273
274 QTypeRevision importExtension(
275 QQmlTypeLoader *typeLoader, const QString &uri, QTypeRevision version,
276 const QQmlTypeLoaderQmldirContent *qmldir, QList<QQmlError> *errors);
277
278 void registerBuiltinModuleTypes(
279 const QQmlTypeLoaderQmldirContent &qmldir, QTypeRevision version);
280
281 QString redirectQmldirContent(
282 QQmlTypeLoader *typeLoader, QQmlTypeLoaderQmldirContent *qmldir);
283
284 bool getQmldirContent(
285 QQmlTypeLoader *typeLoader, const QString &qmldirIdentifier, const QString &uri,
286 QQmlTypeLoaderQmldirContent *qmldir, QList<QQmlError> *errors);
287
288 QString resolvedUri(const QString &dir_arg, QQmlTypeLoader *typeLoader);
289
290 template<IsLibrary isLibrary, typename Handler>
291 QTypeRevision finalizeImport(
292 QQmlImportNamespace *nameSpace, const QQmlTypeLoaderQmldirContent &qmldir,
293 const QString &importUri, const QString &url, quint8 precedence,
294 QTypeRevision requestedVersion, QTypeRevision importedVersion,
295 QList<QQmlError> *errors, Handler &&handler)
296 {
297 QQmlImportInstance *inserted = addImportToNamespace<isLibrary>(
298 nameSpace, importUri, url, requestedVersion, precedence);
299 Q_ASSERT(inserted);
300
301 registerBuiltinModuleTypes(qmldir, importedVersion);
302
303 if (!inserted->setQmldirContent(url, qmldir, nameSpace, errors))
304 return QTypeRevision();
305
306 return handler(inserted);
307 }
308
309 template<IsLibrary isLibrary>
310 QTypeRevision finalizeImport(
311 QQmlImportNamespace *nameSpace, const QQmlTypeLoaderQmldirContent &qmldir,
312 const QString &importUri, const QString &url, quint8 precedence,
313 QTypeRevision requestedVersion, QTypeRevision importedVersion,
314 QList<QQmlError> *errors)
315 {
316 return finalizeImport<isLibrary>(
317 nameSpace, qmldir, importUri, url, precedence, requestedVersion, importedVersion,
318 errors, [importedVersion](QQmlImportInstance *inserted) {
319 Q_UNUSED(inserted);
320 Q_ASSERT(importedVersion.isValid());
321 return importedVersion;
322 });
323 }
324
325 QUrl m_baseUrl;
326 QString m_base;
327
328 // storage of data related to imports without a namespace
329 // TODO: This needs to be mutable because QQmlImportNamespace likes to sort itself on
330 // resolveType(). Therefore, QQmlImportNamespace::resolveType() is not const.
331 // There should be a better way to do this.
332 mutable QQmlImportNamespace m_unqualifiedset;
333
334 // storage of data related to imports with a namespace
335 QFieldList<QQmlImportNamespace, &QQmlImportNamespace::nextNamespace> m_qualifiedSets;
336};
337
338Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlImports::ImportFlags)
339
340void qmlClearEnginePlugins();// For internal use by qmlClearRegisteredProperties
341
342QT_END_NAMESPACE
343
344#endif // QQMLIMPORT_P_H
QQmlImportInstance * findImportByModuleUri(const QString &moduleUri, QTypeRevision version) const
bool needsSorting() const
QQmlImportNamespace * nextNamespace
QQmlImportInstance * findImportByLocation(const QString &location, QTypeRevision version) const
QHashedString prefix
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, QTypeRevision *version_return, QQmlType *type_return, const QString *base=nullptr, QList< QQmlError > *errors=nullptr, QQmlType::RegistrationType registrationType=QQmlType::AnyRegistrationType, bool *typeRecursionDeteced=nullptr)
QList< QQmlImportInstance * > imports
void setNeedsSorting(bool needsSorting)
\inmodule QtCore
const QLoggingCategory & category() const
~QmlImportCategoryHolder()=default
static const QLatin1String String_qmldir("qmldir")
#define RESOLVE_TYPE_DEBUG
static const QString dotuidotqml_string(QStringLiteral(".ui.qml"))
static const QLatin1Char Colon(':')
static QTypeRevision qmldirContentError(const QString &uri, QList< QQmlError > *errors)
static const QString dotqml_string(QStringLiteral(".qml"))
static bool designerSupportRequired
void findCompositeSingletons(const QQmlImportNamespace &set, QList< QQmlImports::CompositeSingletonReference > &resultList, const QUrl &baseUrl)
static QTypeRevision matchingModuleVersionForLibraryImport(const QString &uri, QTypeRevision version, QList< QQmlError > *errors)
static QString getVersionInfo(QTypeRevision version)
static const QLatin1Char Dot('.')
static QTypeRevision matchingQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri, QTypeRevision version, QList< QQmlError > *errors)
bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QString &baseUrl)
static const QLatin1Char Slash('/')
static const QLatin1Char Backslash('\\')
static const QLatin1String Slash_qmldir("/qmldir")
static QTypeRevision finalizeLibraryImport(const QString &uri, QTypeRevision version, const QQmlTypeLoaderQmldirContent &qmldir, QQmlImportInstance *inserted, QList< QQmlError > *errors)
const QLoggingCategory & lcQmlImport()
DEFINE_BOOL_CONFIG_OPTION(forceDiskCache, QML_FORCE_DISK_CACHE)
QQmlDirComponents qmlDirComponents
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, QTypeRevision *version_return, QQmlType *type_return, const QString *base=nullptr, bool *typeRecursionDetected=nullptr, QQmlType::RegistrationType=QQmlType::AnyRegistrationType, QQmlImport::RecursionRestriction recursionRestriction=QQmlImport::PreventRecursion, QList< QQmlError > *errors=nullptr) const
bool setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoaderQmldirContent &qmldir, QQmlImportNamespace *nameSpace, QList< QQmlError > *errors)
QQmlDirScripts qmlDirScripts
QTypeRevision version
static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts, QTypeRevision version)