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