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
qqmljsimporter_p.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:significant
4
5#ifndef QQMLJSIMPORTER_P_H
6#define QQMLJSIMPORTER_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#include <qtqmlcompilerexports.h>
19
21#include "qqmljsscope_p.h"
23#include <QtQml/private/qqmldirparser_p.h>
24#include <QtQml/private/qqmljsast_p.h>
25
27
28namespace QQmlJS {
29class Import
30{
31public:
32 Import() = default;
33 Import(QString prefix, QString name, QTypeRevision version, bool isFile, bool isDependency);
34
35 bool isValid() const;
36
37 QString prefix() const { return m_prefix; }
38 QString name() const { return m_name; }
39 QTypeRevision version() const { return m_version; }
40 bool isFile() const { return m_isFile; }
41 bool isDependency() const { return m_isDependency; }
42
43private:
44 QString m_prefix;
45 QString m_name;
46 QTypeRevision m_version;
47 bool m_isFile = false;
48 bool m_isDependency = false;
49
50 friend inline size_t qHash(const Import &key, size_t seed = 0) noexcept
51 {
52 return qHashMulti(seed, key.m_prefix, key.m_name, key.m_version,
53 key.m_isFile, key.m_isDependency);
54 }
55
56 friend inline bool operator==(const Import &a, const Import &b)
57 {
58 return a.m_prefix == b.m_prefix && a.m_name == b.m_name && a.m_version == b.m_version
59 && a.m_isFile == b.m_isFile && a.m_isDependency == b.m_isDependency;
60 }
61};
62}
63
67 TolerateFileSelectors = 0x4, // if we find a type "twice", check if one looks like it's from a file selector and use the other
68};
69Q_DECLARE_FLAGS(QQmlJSImporterFlags, QQmlJSImporterFlag)
70
71class QQmlJSImportVisitor;
72class QQmlJSLogger;
73class Q_QMLCOMPILER_EXPORT QQmlJSImporter
74{
75public:
76 struct ImportedTypes {
77 ImportedTypes(QQmlJS::ContextualTypes &&types, QList<QQmlJS::DiagnosticMessage> &&warnings)
78 : m_types(std::move(types)), m_warnings(std::move(warnings))
79 {}
80
81 ImportedTypes(const ImportedTypes &) = default;
82 ImportedTypes(ImportedTypes &&) = default;
83 ImportedTypes &operator=(const ImportedTypes &) = default;
84 ImportedTypes &operator=(ImportedTypes &&) = default;
85 ~ImportedTypes() = default;
86
87 void clear()
88 {
89 m_types.clearTypes();
90 m_warnings.clear();
91 }
92
93 const QQmlJS::ContextualTypes &contextualTypes() const { return m_types; }
94 const QList<QQmlJS::DiagnosticMessage> &warnings() const { return m_warnings; };
95
96 bool isEmpty() const { return m_types.types().isEmpty(); }
97
98 bool hasType(const QString &name) const { return m_types.hasType(name); }
99 QQmlJS::ImportedScope<QQmlJSScope::ConstPtr> type(const QString &name) const
100 {
101 return m_types.type(name);
102 }
103 QString name(const QQmlJSScope::ConstPtr &type) const { return m_types.name(type); }
104 void setType(const QString &name, const QQmlJS::ImportedScope<QQmlJSScope::ConstPtr> &type)
105 {
106 m_types.setType(name, type);
107 }
108 bool isNullType(const QString &name) const { return m_types.isNullType(name); }
109 const QHash<QString, QQmlJS::ImportedScope<QQmlJSScope::ConstPtr>> &types() const
110 {
111 return m_types.types();
112 }
113
114 void add(ImportedTypes &&other)
115 {
116 m_types.addTypes(std::move(other.m_types));
117 m_warnings.append(std::move(other.m_warnings));
118 }
119
120 void addWarnings(QList<QQmlJS::DiagnosticMessage> &&warnings)
121 {
122 m_warnings.append(std::move(warnings));
123 }
124
125 private:
126 QQmlJS::ContextualTypes m_types;
127 QList<QQmlJS::DiagnosticMessage> m_warnings;
128 };
129
130 QQmlJSImporter(const QStringList &importPaths, QQmlJSResourceFileMapper *mapper,
131 QQmlJSImporterFlags flags = QQmlJSImporterFlags{});
132
133 QQmlJSResourceFileMapper *resourceFileMapper() const { return m_mapper; }
134 void setResourceFileMapper(QQmlJSResourceFileMapper *mapper) { m_mapper = mapper; }
135
136 QQmlJSResourceFileMapper *metaDataMapper() const { return m_metaDataMapper; }
137 void setMetaDataMapper(QQmlJSResourceFileMapper *mapper) { m_metaDataMapper = mapper; }
138
139 ImportedTypes importHardCodedBuiltins();
140 QList<QQmlJS::DiagnosticMessage> importQmldirs(const QStringList &qmltypesFiles);
141
142 bool registerScope(const QQmlJSScope::Ptr &scope);
143 QQmlJSScope::Ptr importFile(const QString &file);
144 ImportedTypes importDirectory(const QString &directory, const QString &prefix = QString());
145
146 // ### qmltc needs this. once re-written, we no longer need to expose this
147 QHash<QString, QQmlJSScope::Ptr> importedFiles() const { return m_importedFiles; }
148
149 ImportedTypes importModule(const QString &module, const QString &prefix = QString(),
150 QTypeRevision version = QTypeRevision(),
151 QStringList *staticModuleList = nullptr);
152
153 ImportedTypes builtinInternalNames();
154
155 QList<QQmlJS::DiagnosticMessage> takeGlobalWarnings()
156 {
157 const auto result = std::move(m_globalWarnings);
158 m_globalWarnings.clear();
159 return result;
160 }
161
162 QStringList importPaths() const { return m_importPaths; }
163 void setImportPaths(const QStringList &importPaths);
164
165 void clearCache();
166
167 QQmlJSScope::ConstPtr jsGlobalObject();
168
169 struct ImportVisitorPrerequisites
170 {
171 ImportVisitorPrerequisites(QQmlJSScope::Ptr target, QQmlJSLogger *logger,
172 const QString &implicitImportDirectory = {},
173 const QStringList &qmldirFiles = {})
174 : m_target(target),
175 m_logger(logger),
176 m_implicitImportDirectory(implicitImportDirectory),
177 m_qmldirFiles(qmldirFiles)
178 {
179 Q_ASSERT(target && logger);
180 }
181
182 QQmlJSScope::Ptr m_target;
183 QQmlJSLogger *m_logger;
184 QString m_implicitImportDirectory;
185 QStringList m_qmldirFiles;
186 };
187 void runImportVisitor(QQmlJS::AST::Node *rootNode,
188 const ImportVisitorPrerequisites &prerequisites);
189
190 /*!
191 \internal
192 When a qml file gets lazily loaded, it will be lexed and parsed and finally be constructed
193 via an ImportVisitor. By default, this is done via the QQmlJSImportVisitor, but can also be done
194 via other import visitors like QmltcVisitor, which is used by qmltc to compile a QML file, or
195 QQmlDomAstCreatorWithQQmlJSScope, which is used to construct the Dom of lazily loaded QML files.
196 */
197 using ImportVisitor = std::function<void(QQmlJS::AST::Node *rootNode, QQmlJSImporter *self,
198 const ImportVisitorPrerequisites &prerequisites)>;
199
200 void setImportVisitor(ImportVisitor visitor) { m_importVisitor = visitor; }
201
202private:
203 friend class QDeferredFactory<QQmlJSScope>;
204
205 struct AvailableTypes
206 {
207 AvailableTypes(QQmlJS::ContextualTypes builtins)
208 : cppNames(std::move(builtins))
209 , qmlNames(QQmlJS::ContextualTypes::QML, {}, {}, cppNames.arrayType())
210 {
211 }
212
213 // C++ names used in qmltypes files for non-composite types
214 QQmlJS::ContextualTypes cppNames;
215
216 // Names the importing component sees, including any prefixes
217 QQmlJS::ContextualTypes qmlNames;
218
219 // Static modules included here
220 QStringList staticModules;
221
222 // Warnings produced when importing
223 QList<QQmlJS::DiagnosticMessage> warnings;
224
225 // Whether a system module has been imported
226 bool hasSystemModule = false;
227 };
228
229 struct Import {
230 QString name;
231 bool isStaticModule = false;
232 bool isSystemModule = false;
233
234 QList<QQmlJSExportedScope> objects;
235 QHash<QString, QQmlJSExportedScope> scripts;
236 QList<QQmlDirParser::Import> imports;
237 QList<QQmlDirParser::Import> dependencies;
238
239 // Warnings produced when importing
240 QList<QQmlJS::DiagnosticMessage> warnings;
241 };
242
243 AvailableTypes builtinImportHelper();
244 bool importHelper(const QString &module, AvailableTypes *types,
245 const QString &prefix = QString(), QTypeRevision version = QTypeRevision(),
246 bool isDependency = false, bool isFile = false);
247 void processImport(
248 const QQmlJS::Import &importDescription, const Import &import, AvailableTypes *types);
249 void importDependencies(
250 const Import &import, AvailableTypes *types, const QString &prefix = QString(),
251 QTypeRevision version = QTypeRevision(), bool isDependency = false);
252 QQmlDirParser createQmldirParserForFile(const QString &filename, Import *import);
253 void readQmltypes(const QString &filename, Import *result);
254 Import readQmldir(const QString &dirname);
255 Import readDirectory(const QString &directory);
256
257 QQmlJSScope::Ptr localFile2QQmlJSScope(const QString &filePath);
258 static void setQualifiedNamesOn(const Import &import);
259
260 QStringList m_importPaths;
261
262 QHash<std::pair<QString, QTypeRevision>, QString> m_seenImports;
263 QHash<QQmlJS::Import, QSharedPointer<AvailableTypes>> m_cachedImportTypes;
264 QHash<QString, Import> m_seenQmldirFiles;
265
266 QHash<QString, QQmlJSScope::Ptr> m_importedFiles;
267 QList<QQmlJS::DiagnosticMessage> m_globalWarnings;
268 std::optional<AvailableTypes> m_builtins;
269
270 QQmlJSResourceFileMapper *m_mapper = nullptr;
271 QQmlJSResourceFileMapper *m_metaDataMapper = nullptr;
272 QQmlJSImporterFlags m_flags;
273 bool useOptionalImports() const { return m_flags.testFlag(UseOptionalImports); };
274 bool preferQmlFilesFromSourceFolder() const
275 {
276 return m_flags.testFlag(PreferQmlFilesFromSourceFolder);
277 };
278
279 ImportVisitor m_importVisitor;
280};
281
282QT_END_NAMESPACE
283
284#endif // QQMLJSIMPORTER_P_H
friend bool operator==(const Import &a, const Import &b)
QString prefix() const
bool isValid() const
QTypeRevision version() const
QString name() const
bool isDependency() const
Import()=default
bool isFile() const
friend size_t qHash(const Import &key, size_t seed=0) noexcept
Import(QString prefix, QString name, QTypeRevision version, bool isFile, bool isDependency)
static QStringList aliases(const QQmlJSScope::ConstPtr &scope)
static const QLatin1String JsrootDotQmltypes
static bool isVersionAllowed(const QQmlJSScope::Export &exportEntry, const QQmlJS::Import &importDescription)
static bool isComposite(const QQmlJSScope::ConstPtr &scope)
static QString resolvePreferredPath(const QString &qmldirPath, const QString &prefer, QQmlJSResourceFileMapper *mapper)
static const QString prefixedName(const QString &prefix, const QString &name)
static const QLatin1String SlashQmldir
static QString internalName(const QQmlJSScope::ConstPtr &scope)
static bool fileSelectedScopesAreCompatibleHeuristic(const QQmlJSScope::ConstPtr &scope1, const QQmlJSScope::ConstPtr &scope2)
static const QLatin1String PluginsDotQmltypes
QQmlJSImporterFlag
@ UseOptionalImports
@ PreferQmlFilesFromSourceFolder
@ TolerateFileSelectors