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
4#ifndef QQMLJSIMPORTER_P_H
5#define QQMLJSIMPORTER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16
17#include <qtqmlcompilerexports.h>
18
19#include "qqmljscontextualtypes_p.h"
20#include "qqmljsscope_p.h"
21#include "qqmljsresourcefilemapper_p.h"
22#include <QtQml/private/qqmldirparser_p.h>
23#include <QtQml/private/qqmljsast_p.h>
24
25#include <memory>
26
27QT_BEGIN_NAMESPACE
28
29namespace QQmlJS {
30class Import
31{
32public:
33 Import() = default;
34 Import(QString prefix, QString name, QTypeRevision version, bool isFile, bool isDependency);
35
36 bool isValid() const;
37
38 QString prefix() const { return m_prefix; }
39 QString name() const { return m_name; }
40 QTypeRevision version() const { return m_version; }
41 bool isFile() const { return m_isFile; }
42 bool isDependency() const { return m_isDependency; }
43
44private:
45 QString m_prefix;
46 QString m_name;
47 QTypeRevision m_version;
48 bool m_isFile = false;
49 bool m_isDependency = false;
50
51 friend inline size_t qHash(const Import &key, size_t seed = 0) noexcept
52 {
53 return qHashMulti(seed, args: key.m_prefix, args: key.m_name, args: key.m_version,
54 args: key.m_isFile, args: key.m_isDependency);
55 }
56
57 friend inline bool operator==(const Import &a, const Import &b)
58 {
59 return a.m_prefix == b.m_prefix && a.m_name == b.m_name && a.m_version == b.m_version
60 && a.m_isFile == b.m_isFile && a.m_isDependency == b.m_isDependency;
61 }
62};
63}
64
65enum QQmlJSImporterFlag {
66 UseOptionalImports = 0x1,
67 PreferQmlFilesFromSourceFolder = 0x2
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(types: std::move(other.m_types));
117 m_warnings.append(l: std::move(other.m_warnings));
118 }
119
120 void addWarnings(QList<QQmlJS::DiagnosticMessage> &&warnings)
121 {
122 m_warnings.append(l: 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 importBuiltins();
140 QList<QQmlJS::DiagnosticMessage> importQmldirs(const QStringList &qmltypesFiles);
141
142 QQmlJSScope::Ptr importFile(const QString &file);
143 ImportedTypes importDirectory(const QString &directory, const QString &prefix = QString());
144
145 // ### qmltc needs this. once re-written, we no longer need to expose this
146 QHash<QString, QQmlJSScope::Ptr> importedFiles() const { return m_importedFiles; }
147
148 ImportedTypes importModule(const QString &module, const QString &prefix = QString(),
149 QTypeRevision version = QTypeRevision(),
150 QStringList *staticModuleList = nullptr);
151
152 ImportedTypes builtinInternalNames();
153
154 QList<QQmlJS::DiagnosticMessage> takeGlobalWarnings()
155 {
156 const auto result = std::move(m_globalWarnings);
157 m_globalWarnings.clear();
158 return result;
159 }
160
161 QStringList importPaths() const { return m_importPaths; }
162 void setImportPaths(const QStringList &importPaths);
163
164 void clearCache();
165
166 QQmlJSScope::ConstPtr jsGlobalObject() const;
167
168 struct ImportVisitorPrerequisites
169 {
170 ImportVisitorPrerequisites(QQmlJSScope::Ptr target, QQmlJSLogger *logger,
171 const QString &implicitImportDirectory = {},
172 const QStringList &qmldirFiles = {})
173 : m_target(target),
174 m_logger(logger),
175 m_implicitImportDirectory(implicitImportDirectory),
176 m_qmldirFiles(qmldirFiles)
177 {
178 Q_ASSERT(target && logger);
179 }
180
181 QQmlJSScope::Ptr m_target;
182 QQmlJSLogger *m_logger;
183 QString m_implicitImportDirectory;
184 QStringList m_qmldirFiles;
185 };
186 void runImportVisitor(QQmlJS::AST::Node *rootNode,
187 const ImportVisitorPrerequisites &prerequisites);
188
189 /*!
190 \internal
191 When a qml file gets lazily loaded, it will be lexed and parsed and finally be constructed
192 via an ImportVisitor. By default, this is done via the QQmlJSImportVisitor, but can also be done
193 via other import visitors like QmltcVisitor, which is used by qmltc to compile a QML file, or
194 QQmlDomAstCreatorWithQQmlJSScope, which is used to construct the Dom of lazily loaded QML files.
195 */
196 using ImportVisitor = std::function<void(QQmlJS::AST::Node *rootNode, QQmlJSImporter *self,
197 const ImportVisitorPrerequisites &prerequisites)>;
198
199 void setImportVisitor(ImportVisitor visitor) { m_importVisitor = visitor; }
200
201private:
202 friend class QDeferredFactory<QQmlJSScope>;
203
204 struct AvailableTypes
205 {
206 AvailableTypes(QQmlJS::ContextualTypes builtins)
207 : cppNames(std::move(builtins))
208 , qmlNames(QQmlJS::ContextualTypes::QML, {}, cppNames.arrayType())
209 {
210 }
211
212 // C++ names used in qmltypes files for non-composite types
213 QQmlJS::ContextualTypes cppNames;
214
215 // Names the importing component sees, including any prefixes
216 QQmlJS::ContextualTypes qmlNames;
217
218 // Static modules included here
219 QStringList staticModules;
220
221 // Warnings produced when importing
222 QList<QQmlJS::DiagnosticMessage> warnings;
223
224 // Whether a system module has been imported
225 bool hasSystemModule = false;
226 };
227
228 struct Import {
229 QString name;
230 bool isStaticModule = false;
231 bool isSystemModule = false;
232
233 QList<QQmlJSExportedScope> objects;
234 QHash<QString, QQmlJSExportedScope> scripts;
235 QList<QQmlDirParser::Import> imports;
236 QList<QQmlDirParser::Import> dependencies;
237
238 // Warnings produced when importing
239 QList<QQmlJS::DiagnosticMessage> warnings;
240 };
241
242 AvailableTypes builtinImportHelper();
243 bool importHelper(const QString &module, AvailableTypes *types,
244 const QString &prefix = QString(), QTypeRevision version = QTypeRevision(),
245 bool isDependency = false, bool isFile = false);
246 void processImport(
247 const QQmlJS::Import &importDescription, const Import &import, AvailableTypes *types);
248 void importDependencies(
249 const Import &import, AvailableTypes *types, const QString &prefix = QString(),
250 QTypeRevision version = QTypeRevision(), bool isDependency = false);
251 QQmlDirParser createQmldirParserForFile(const QString &filename, Import *import);
252 void readQmltypes(const QString &filename, Import *result);
253 Import readQmldir(const QString &dirname);
254 Import readDirectory(const QString &directory);
255
256 QQmlJSScope::Ptr localFile2ScopeTree(const QString &filePath);
257 static void setQualifiedNamesOn(const Import &import);
258
259 QStringList m_importPaths;
260
261 QHash<QPair<QString, QTypeRevision>, QString> m_seenImports;
262 QHash<QQmlJS::Import, QSharedPointer<AvailableTypes>> m_cachedImportTypes;
263 QHash<QString, Import> m_seenQmldirFiles;
264
265 QHash<QString, QQmlJSScope::Ptr> m_importedFiles;
266 QList<QQmlJS::DiagnosticMessage> m_globalWarnings;
267 std::optional<AvailableTypes> m_builtins;
268
269 QQmlJSResourceFileMapper *m_mapper = nullptr;
270 QQmlJSResourceFileMapper *m_metaDataMapper = nullptr;
271 QQmlJSImporterFlags m_flags;
272 bool useOptionalImports() const { return m_flags.testFlag(flag: UseOptionalImports); };
273 bool preferQmlFilesFromSourceFolder() const
274 {
275 return m_flags.testFlag(flag: PreferQmlFilesFromSourceFolder);
276 };
277
278 ImportVisitor m_importVisitor;
279};
280
281QT_END_NAMESPACE
282
283#endif // QQMLJSIMPORTER_P_H
284

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtdeclarative/src/qmlcompiler/qqmljsimporter_p.h