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 QString pathOfModule(const QString &moduleName, QTypeRevision revision) const
169 {
170 const auto it = m_seenImports.constFind({ moduleName, revision });
171 return it != m_seenImports.constEnd() ? *it : QString();
172 }
173
174 struct ImportVisitorPrerequisites
175 {
176 ImportVisitorPrerequisites(QQmlJSScope::Ptr target, QQmlJSLogger *logger,
177 const QString &implicitImportDirectory = {},
178 const QStringList &qmldirFiles = {})
179 : m_target(target),
180 m_logger(logger),
181 m_implicitImportDirectory(implicitImportDirectory),
182 m_qmldirFiles(qmldirFiles)
183 {
184 Q_ASSERT(target && logger);
185 }
186
187 QQmlJSScope::Ptr m_target;
188 QQmlJSLogger *m_logger;
189 QString m_implicitImportDirectory;
190 QStringList m_qmldirFiles;
191 };
192 void runImportVisitor(QQmlJS::AST::Node *rootNode,
193 const ImportVisitorPrerequisites &prerequisites);
194
195 /*!
196 \internal
197 When a qml file gets lazily loaded, it will be lexed and parsed and finally be constructed
198 via an ImportVisitor. By default, this is done via the QQmlJSImportVisitor, but can also be done
199 via other import visitors like QmltcVisitor, which is used by qmltc to compile a QML file, or
200 QQmlDomAstCreatorWithQQmlJSScope, which is used to construct the Dom of lazily loaded QML files.
201 */
202 using ImportVisitor = std::function<void(QQmlJS::AST::Node *rootNode, QQmlJSImporter *self,
203 const ImportVisitorPrerequisites &prerequisites)>;
204
205 void setImportVisitor(ImportVisitor visitor) { m_importVisitor = visitor; }
206
207private:
208 friend class QDeferredFactory<QQmlJSScope>;
209
210 struct AvailableTypes
211 {
212 AvailableTypes(QQmlJS::ContextualTypes builtins)
213 : cppNames(std::move(builtins))
214 , qmlNames(QQmlJS::ContextualTypes::QML, {}, {}, cppNames.arrayType())
215 {
216 }
217
218 // C++ names used in qmltypes files for non-composite types
219 QQmlJS::ContextualTypes cppNames;
220
221 // Names the importing component sees, including any prefixes
222 QQmlJS::ContextualTypes qmlNames;
223
224 // Static modules included here
225 QStringList staticModules;
226
227 // Warnings produced when importing
228 QList<QQmlJS::DiagnosticMessage> warnings;
229
230 // Whether a system module has been imported
231 bool hasSystemModule = false;
232 };
233
234 struct Import {
235 QString name;
236 bool isStaticModule = false;
237 bool isSystemModule = false;
238
239 QList<QQmlJSExportedScope> objects;
240 QHash<QString, QQmlJSExportedScope> scripts;
241 QList<QQmlDirParser::Import> imports;
242 QList<QQmlDirParser::Import> dependencies;
243
244 // Warnings produced when importing
245 QList<QQmlJS::DiagnosticMessage> warnings;
246 };
247
248 AvailableTypes builtinImportHelper();
249 bool importHelper(const QString &module, AvailableTypes *types,
250 const QString &prefix = QString(), QTypeRevision version = QTypeRevision(),
251 bool isDependency = false, bool isFile = false);
252 void processImport(
253 const QQmlJS::Import &importDescription, const Import &import, AvailableTypes *types);
254 void importDependencies(
255 const Import &import, AvailableTypes *types, const QString &prefix = QString(),
256 QTypeRevision version = QTypeRevision(), bool isDependency = false);
257 QQmlDirParser createQmldirParserForFile(const QString &filename, Import *import);
258 void readQmltypes(const QString &filename, Import *result);
259 Import readQmldir(const QString &dirname);
260 Import readDirectory(const QString &directory);
261
262 QQmlJSScope::Ptr localFile2QQmlJSScope(const QString &filePath);
263 static void setQualifiedNamesOn(const Import &import);
264
265 QStringList m_importPaths;
266
267 QHash<std::pair<QString, QTypeRevision>, QString> m_seenImports;
268 QHash<QQmlJS::Import, QSharedPointer<AvailableTypes>> m_cachedImportTypes;
269 QHash<QString, Import> m_seenQmldirFiles;
270
271 QHash<QString, QQmlJSScope::Ptr> m_importedFiles;
272 QList<QQmlJS::DiagnosticMessage> m_globalWarnings;
273 std::optional<AvailableTypes> m_builtins;
274
275 QQmlJSResourceFileMapper *m_mapper = nullptr;
276 QQmlJSResourceFileMapper *m_metaDataMapper = nullptr;
277 QQmlJSImporterFlags m_flags;
278 bool useOptionalImports() const { return m_flags.testFlag(UseOptionalImports); };
279 bool preferQmlFilesFromSourceFolder() const
280 {
281 return m_flags.testFlag(PreferQmlFilesFromSourceFolder);
282 };
283
284 ImportVisitor m_importVisitor;
285};
286
287QT_END_NAMESPACE
288
289#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)
Combined button and popup list for selecting options.
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