1 | // Copyright (C) 2021 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 | |
4 | #ifndef QQMLDOMELEMENTS_P_H |
5 | #define QQMLDOMELEMENTS_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 | |
18 | #include "qqmldomitem_p.h" |
19 | #include "qqmldomconstants_p.h" |
20 | #include "qqmldomcomments_p.h" |
21 | #include "qqmldomlinewriter_p.h" |
22 | |
23 | #include <QtQml/private/qqmljsast_p.h> |
24 | #include <QtQml/private/qqmljsengine_p.h> |
25 | #include <QtQml/private/qqmlsignalnames_p.h> |
26 | |
27 | #include <QtCore/QCborValue> |
28 | #include <QtCore/QCborMap> |
29 | #include <QtCore/QMutexLocker> |
30 | #include <QtCore/QPair> |
31 | |
32 | #include <memory> |
33 | #include <private/qqmljsscope_p.h> |
34 | |
35 | #include <functional> |
36 | #include <limits> |
37 | |
38 | QT_BEGIN_NAMESPACE |
39 | |
40 | namespace QQmlJS { |
41 | namespace Dom { |
42 | |
43 | // namespace for utility methods building specific paths |
44 | // using a namespace one can reopen it and add more methods in other places |
45 | namespace Paths { |
46 | Path moduleIndexPath( |
47 | const QString &uri, int majorVersion, const ErrorHandler &errorHandler = nullptr); |
48 | Path moduleScopePath( |
49 | const QString &uri, Version version, const ErrorHandler &errorHandler = nullptr); |
50 | Path moduleScopePath( |
51 | const QString &uri, const QString &version, const ErrorHandler &errorHandler = nullptr); |
52 | inline Path moduleScopePath( |
53 | const QString &uri, const ErrorHandler &errorHandler = nullptr) |
54 | { |
55 | return moduleScopePath(uri, version: QString(), errorHandler); |
56 | } |
57 | inline Path qmlDirInfoPath(const QString &path) |
58 | { |
59 | return Path::Root(r: PathRoot::Top).field(name: Fields::qmldirWithPath).key(name: path); |
60 | } |
61 | inline Path qmlDirPath(const QString &path) |
62 | { |
63 | return qmlDirInfoPath(path).field(name: Fields::currentItem); |
64 | } |
65 | inline Path qmldirFileInfoPath(const QString &path) |
66 | { |
67 | return Path::Root(r: PathRoot::Top).field(name: Fields::qmldirFileWithPath).key(name: path); |
68 | } |
69 | inline Path qmldirFilePath(const QString &path) |
70 | { |
71 | return qmldirFileInfoPath(path).field(name: Fields::currentItem); |
72 | } |
73 | inline Path qmlFileInfoPath(const QString &canonicalFilePath) |
74 | { |
75 | return Path::Root(r: PathRoot::Top).field(name: Fields::qmlFileWithPath).key(name: canonicalFilePath); |
76 | } |
77 | inline Path qmlFilePath(const QString &canonicalFilePath) |
78 | { |
79 | return qmlFileInfoPath(canonicalFilePath).field(name: Fields::currentItem); |
80 | } |
81 | inline Path qmlFileObjectPath(const QString &canonicalFilePath) |
82 | { |
83 | return qmlFilePath(canonicalFilePath) |
84 | .field(name: Fields::components) |
85 | .key(name: QString()) |
86 | .index(i: 0) |
87 | .field(name: Fields::objects) |
88 | .index(i: 0); |
89 | } |
90 | inline Path qmltypesFileInfoPath(const QString &path) |
91 | { |
92 | return Path::Root(r: PathRoot::Top).field(name: Fields::qmltypesFileWithPath).key(name: path); |
93 | } |
94 | inline Path qmltypesFilePath(const QString &path) |
95 | { |
96 | return qmltypesFileInfoPath(path).field(name: Fields::currentItem); |
97 | } |
98 | inline Path jsFileInfoPath(const QString &path) |
99 | { |
100 | return Path::Root(r: PathRoot::Top).field(name: Fields::jsFileWithPath).key(name: path); |
101 | } |
102 | inline Path jsFilePath(const QString &path) |
103 | { |
104 | return jsFileInfoPath(path).field(name: Fields::currentItem); |
105 | } |
106 | inline Path qmlDirectoryInfoPath(const QString &path) |
107 | { |
108 | return Path::Root(r: PathRoot::Top).field(name: Fields::qmlDirectoryWithPath).key(name: path); |
109 | } |
110 | inline Path qmlDirectoryPath(const QString &path) |
111 | { |
112 | return qmlDirectoryInfoPath(path).field(name: Fields::currentItem); |
113 | } |
114 | inline Path globalScopeInfoPath(const QString &name) |
115 | { |
116 | return Path::Root(r: PathRoot::Top).field(name: Fields::globalScopeWithName).key(name); |
117 | } |
118 | inline Path globalScopePath(const QString &name) |
119 | { |
120 | return globalScopeInfoPath(name).field(name: Fields::currentItem); |
121 | } |
122 | inline Path lookupCppTypePath(const QString &name) |
123 | { |
124 | return Path::Current(c: PathCurrent::Lookup).field(name: Fields::cppType).key(name); |
125 | } |
126 | inline Path lookupPropertyPath(const QString &name) |
127 | { |
128 | return Path::Current(c: PathCurrent::Lookup).field(name: Fields::propertyDef).key(name); |
129 | } |
130 | inline Path lookupSymbolPath(const QString &name) |
131 | { |
132 | return Path::Current(c: PathCurrent::Lookup).field(name: Fields::symbol).key(name); |
133 | } |
134 | inline Path lookupTypePath(const QString &name) |
135 | { |
136 | return Path::Current(c: PathCurrent::Lookup).field(name: Fields::type).key(name); |
137 | } |
138 | inline Path loadInfoPath(const Path &el) |
139 | { |
140 | return Path::Root(r: PathRoot::Env).field(name: Fields::loadInfo).key(name: el.toString()); |
141 | } |
142 | } // end namespace Paths |
143 | |
144 | class QMLDOM_EXPORT CommentableDomElement : public DomElement |
145 | { |
146 | public: |
147 | CommentableDomElement(const Path &pathFromOwner = Path()) : DomElement(pathFromOwner) { } |
148 | CommentableDomElement(const CommentableDomElement &o) : DomElement(o), m_comments(o.m_comments) |
149 | { |
150 | } |
151 | CommentableDomElement &operator=(const CommentableDomElement &o) = default; |
152 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override; |
153 | RegionComments &comments() { return m_comments; } |
154 | const RegionComments &comments() const { return m_comments; } |
155 | |
156 | private: |
157 | RegionComments m_comments; |
158 | }; |
159 | |
160 | class QMLDOM_EXPORT Version |
161 | { |
162 | public: |
163 | constexpr static DomType kindValue = DomType::Version; |
164 | constexpr static qint32 Undefined = -1; |
165 | constexpr static qint32 Latest = -2; |
166 | |
167 | Version(qint32 majorVersion = Undefined, qint32 minorVersion = Undefined); |
168 | static Version fromString(QStringView v); |
169 | |
170 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const; |
171 | |
172 | bool isLatest() const; |
173 | bool isValid() const; |
174 | QString stringValue() const; |
175 | QString majorString() const |
176 | { |
177 | if (majorVersion >= 0 || majorVersion == Undefined) |
178 | return QString::number(majorVersion); |
179 | return QString(); |
180 | } |
181 | QString majorSymbolicString() const |
182 | { |
183 | if (majorVersion == Version::Latest) |
184 | return QLatin1String("Latest"); |
185 | if (majorVersion >= 0 || majorVersion == Undefined) |
186 | return QString::number(majorVersion); |
187 | return QString(); |
188 | } |
189 | QString minorString() const |
190 | { |
191 | if (minorVersion >= 0 || minorVersion == Undefined) |
192 | return QString::number(minorVersion); |
193 | return QString(); |
194 | } |
195 | int compare(const Version &o) const |
196 | { |
197 | int c = majorVersion - o.majorVersion; |
198 | if (c != 0) |
199 | return c; |
200 | return minorVersion - o.minorVersion; |
201 | } |
202 | |
203 | qint32 majorVersion; |
204 | qint32 minorVersion; |
205 | }; |
206 | inline bool operator==(const Version &v1, const Version &v2) |
207 | { |
208 | return v1.compare(o: v2) == 0; |
209 | } |
210 | inline bool operator!=(const Version &v1, const Version &v2) |
211 | { |
212 | return v1.compare(o: v2) != 0; |
213 | } |
214 | inline bool operator<(const Version &v1, const Version &v2) |
215 | { |
216 | return v1.compare(o: v2) < 0; |
217 | } |
218 | inline bool operator<=(const Version &v1, const Version &v2) |
219 | { |
220 | return v1.compare(o: v2) <= 0; |
221 | } |
222 | inline bool operator>(const Version &v1, const Version &v2) |
223 | { |
224 | return v1.compare(o: v2) > 0; |
225 | } |
226 | inline bool operator>=(const Version &v1, const Version &v2) |
227 | { |
228 | return v1.compare(o: v2) >= 0; |
229 | } |
230 | |
231 | class QMLDOM_EXPORT QmlUri |
232 | { |
233 | public: |
234 | enum class Kind { Invalid, ModuleUri, DirectoryUrl, RelativePath, AbsolutePath }; |
235 | QmlUri() = default; |
236 | static QmlUri fromString(const QString &importStr); |
237 | static QmlUri fromUriString(const QString &importStr); |
238 | static QmlUri fromDirectoryString(const QString &importStr); |
239 | bool isValid() const; |
240 | bool isDirectory() const; |
241 | bool isModule() const; |
242 | QString moduleUri() const; |
243 | QString localPath() const; |
244 | QString absoluteLocalPath(const QString &basePath = QString()) const; |
245 | QUrl directoryUrl() const; |
246 | QString directoryString() const; |
247 | QString toString() const; |
248 | Kind kind() const; |
249 | |
250 | friend bool operator==(const QmlUri &i1, const QmlUri &i2) |
251 | { |
252 | return i1.m_kind == i2.m_kind && i1.m_value == i2.m_value; |
253 | } |
254 | friend bool operator!=(const QmlUri &i1, const QmlUri &i2) { return !(i1 == i2); } |
255 | |
256 | private: |
257 | QmlUri(const QUrl &url) : m_kind(Kind::DirectoryUrl), m_value(url) { } |
258 | QmlUri(Kind kind, const QString &value) : m_kind(kind), m_value(value) { } |
259 | Kind m_kind = Kind::Invalid; |
260 | std::variant<QString, QUrl> m_value; |
261 | }; |
262 | |
263 | class QMLDOM_EXPORT Import |
264 | { |
265 | Q_DECLARE_TR_FUNCTIONS(Import) |
266 | public: |
267 | constexpr static DomType kindValue = DomType::Import; |
268 | |
269 | static Import fromUriString( |
270 | const QString &importStr, Version v = Version(), const QString &importId = QString(), |
271 | const ErrorHandler &handler = nullptr); |
272 | static Import fromFileString( |
273 | const QString &importStr, const QString &importId = QString(), |
274 | const ErrorHandler &handler = nullptr); |
275 | |
276 | Import(const QmlUri &uri = QmlUri(), Version version = Version(), |
277 | const QString &importId = QString()) |
278 | : uri(uri), version(version), importId(importId) |
279 | { |
280 | } |
281 | |
282 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const; |
283 | Path importedPath() const |
284 | { |
285 | if (uri.isDirectory()) { |
286 | QString path = uri.absoluteLocalPath(); |
287 | if (!path.isEmpty()) { |
288 | return Paths::qmlDirPath(path); |
289 | } else { |
290 | Q_ASSERT_X(false, "Import", "url imports not supported"); |
291 | return Paths::qmldirFilePath(path: uri.directoryString()); |
292 | } |
293 | } else { |
294 | return Paths::moduleScopePath(uri: uri.moduleUri(), version); |
295 | } |
296 | } |
297 | Import baseImport() const { return Import { uri, version }; } |
298 | |
299 | friend bool operator==(const Import &i1, const Import &i2) |
300 | { |
301 | return i1.uri == i2.uri && i1.version == i2.version && i1.importId == i2.importId |
302 | && i1.comments == i2.comments && i1.implicit == i2.implicit; |
303 | } |
304 | friend bool operator!=(const Import &i1, const Import &i2) { return !(i1 == i2); } |
305 | |
306 | void writeOut(const DomItem &self, OutWriter &ow) const; |
307 | |
308 | static QRegularExpression importRe(); |
309 | |
310 | QmlUri uri; |
311 | Version version; |
312 | QString importId; |
313 | RegionComments comments; |
314 | bool implicit = false; |
315 | }; |
316 | |
317 | class QMLDOM_EXPORT ModuleAutoExport |
318 | { |
319 | public: |
320 | constexpr static DomType kindValue = DomType::ModuleAutoExport; |
321 | |
322 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const |
323 | { |
324 | bool cont = true; |
325 | cont = cont && self.dvWrapField(visitor, f: Fields::import, obj: import); |
326 | cont = cont && self.dvValueField(visitor, f: Fields::inheritVersion, value: inheritVersion); |
327 | return cont; |
328 | } |
329 | |
330 | friend bool operator==(const ModuleAutoExport &i1, const ModuleAutoExport &i2) |
331 | { |
332 | return i1.import == i2.import && i1.inheritVersion == i2.inheritVersion; |
333 | } |
334 | friend bool operator!=(const ModuleAutoExport &i1, const ModuleAutoExport &i2) |
335 | { |
336 | return !(i1 == i2); |
337 | } |
338 | |
339 | Import import; |
340 | bool inheritVersion = false; |
341 | }; |
342 | |
343 | class QMLDOM_EXPORT Pragma |
344 | { |
345 | public: |
346 | constexpr static DomType kindValue = DomType::Pragma; |
347 | |
348 | Pragma(const QString &pragmaName = QString(), const QStringList &pragmaValues = {}) |
349 | : name(pragmaName), values{ pragmaValues } |
350 | { |
351 | } |
352 | |
353 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const |
354 | { |
355 | bool cont = self.dvValueField(visitor, f: Fields::name, value: name); |
356 | cont = cont && self.dvValueField(visitor, f: Fields::values, value: values); |
357 | cont = cont && self.dvWrapField(visitor, f: Fields::comments, obj: comments); |
358 | return cont; |
359 | } |
360 | |
361 | void writeOut(const DomItem &self, OutWriter &ow) const; |
362 | |
363 | QString name; |
364 | QStringList values; |
365 | RegionComments comments; |
366 | }; |
367 | |
368 | class QMLDOM_EXPORT Id |
369 | { |
370 | public: |
371 | constexpr static DomType kindValue = DomType::Id; |
372 | |
373 | Id(const QString &idName = QString(), const Path &referredObject = Path()); |
374 | |
375 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const; |
376 | void updatePathFromOwner(const Path &pathFromOwner); |
377 | Path addAnnotation(const Path &selfPathFromOwner, const QmlObject &ann, QmlObject **aPtr = nullptr); |
378 | |
379 | QString name; |
380 | Path referredObjectPath; |
381 | RegionComments comments; |
382 | QList<QmlObject> annotations; |
383 | std::shared_ptr<ScriptExpression> value; |
384 | }; |
385 | |
386 | // TODO: rename? it may contain statements and stuff, not only expressions |
387 | // TODO QTBUG-121933 |
388 | class QMLDOM_EXPORT ScriptExpression final : public OwningItem |
389 | { |
390 | Q_GADGET |
391 | Q_DECLARE_TR_FUNCTIONS(ScriptExpression) |
392 | public: |
393 | enum class ExpressionType { |
394 | BindingExpression, |
395 | FunctionBody, |
396 | ArgInitializer, |
397 | ArgumentStructure, |
398 | ReturnType, |
399 | JSCode, // Used for storing the content of the whole .js file as "one" Expression |
400 | ESMCode, // Used for storing the content of the whole ECMAScript module (.mjs) as "one" |
401 | // Expression |
402 | }; |
403 | Q_ENUM(ExpressionType); |
404 | constexpr static DomType kindValue = DomType::ScriptExpression; |
405 | DomType kind() const override { return kindValue; } |
406 | |
407 | explicit ScriptExpression( |
408 | QStringView code, const std::shared_ptr<QQmlJS::Engine> &engine, AST::Node *ast, |
409 | const std::shared_ptr<AstComments> &comments, ExpressionType expressionType, |
410 | SourceLocation localOffset = SourceLocation(), int derivedFrom = 0, |
411 | QStringView preCode = QStringView(), QStringView postCode = QStringView()); |
412 | |
413 | ScriptExpression() |
414 | : ScriptExpression(QStringView(), std::shared_ptr<QQmlJS::Engine>(), nullptr, |
415 | std::shared_ptr<AstComments>(), ExpressionType::BindingExpression, |
416 | SourceLocation(), 0) |
417 | { |
418 | } |
419 | |
420 | explicit ScriptExpression( |
421 | const QString &code, ExpressionType expressionType, int derivedFrom = 0, |
422 | const QString &preCode = QString(), const QString &postCode = QString()) |
423 | : OwningItem(derivedFrom), m_expressionType(expressionType) |
424 | { |
425 | setCode(code, preCode, postCode); |
426 | } |
427 | |
428 | ScriptExpression(const ScriptExpression &e); |
429 | |
430 | std::shared_ptr<ScriptExpression> makeCopy(const DomItem &self) const |
431 | { |
432 | return std::static_pointer_cast<ScriptExpression>(r: doCopy(self)); |
433 | } |
434 | |
435 | std::shared_ptr<ScriptExpression> copyWithUpdatedCode(const DomItem &self, const QString &code) const; |
436 | |
437 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const override; |
438 | |
439 | Path canonicalPath(const DomItem &self) const override { return self.m_ownerPath; } |
440 | // parsed and created if not available |
441 | AST::Node *ast() const { return m_ast; } |
442 | // dump of the ast (without locations) |
443 | void astDumper(const Sink &s, AstDumperOptions options) const; |
444 | QString astRelocatableDump() const; |
445 | |
446 | // definedSymbols name, value, from |
447 | // usedSymbols name, locations |
448 | QStringView code() const |
449 | { |
450 | QMutexLocker l(mutex()); |
451 | return m_code; |
452 | } |
453 | |
454 | ExpressionType expressionType() const |
455 | { |
456 | QMutexLocker l(mutex()); |
457 | return m_expressionType; |
458 | } |
459 | |
460 | bool isNull() const |
461 | { |
462 | QMutexLocker l(mutex()); |
463 | return m_code.isNull(); |
464 | } |
465 | std::shared_ptr<QQmlJS::Engine> engine() const |
466 | { |
467 | QMutexLocker l(mutex()); |
468 | return m_engine; |
469 | } |
470 | std::shared_ptr<AstComments> astComments() const { return m_astComments; } |
471 | void writeOut(const DomItem &self, OutWriter &lw) const override; |
472 | SourceLocation globalLocation(const DomItem &self) const; |
473 | SourceLocation localOffset() const { return m_localOffset; } |
474 | QStringView preCode() const { return m_preCode; } |
475 | QStringView postCode() const { return m_postCode; } |
476 | void setScriptElement(const ScriptElementVariant &p); |
477 | ScriptElementVariant scriptElement() { return m_element; } |
478 | |
479 | protected: |
480 | std::shared_ptr<OwningItem> doCopy(const DomItem &) const override |
481 | { |
482 | return std::make_shared<ScriptExpression>(args: *this); |
483 | } |
484 | |
485 | std::function<SourceLocation(SourceLocation)> locationToGlobalF(const DomItem &self) const |
486 | { |
487 | SourceLocation loc = globalLocation(self); |
488 | return [loc, this](SourceLocation x) { |
489 | return SourceLocation(x.offset - m_localOffset.offset + loc.offset, x.length, |
490 | x.startLine - m_localOffset.startLine + loc.startLine, |
491 | ((x.startLine == m_localOffset.startLine) ? x.startColumn |
492 | - m_localOffset.startColumn + loc.startColumn |
493 | : x.startColumn)); |
494 | }; |
495 | } |
496 | |
497 | SourceLocation locationToLocal(SourceLocation x) const |
498 | { |
499 | return SourceLocation( |
500 | x.offset - m_localOffset.offset, x.length, x.startLine - m_localOffset.startLine, |
501 | ((x.startLine == m_localOffset.startLine) |
502 | ? x.startColumn - m_localOffset.startColumn |
503 | : x.startColumn)); // are line and column 1 based? then we should + 1 |
504 | } |
505 | |
506 | std::function<SourceLocation(SourceLocation)> locationToLocalF(const DomItem &) const |
507 | { |
508 | return [this](SourceLocation x) { return locationToLocal(x); }; |
509 | } |
510 | |
511 | private: |
512 | enum class ParseMode { |
513 | QML, |
514 | JS, |
515 | ESM, // ECMAScript module |
516 | }; |
517 | |
518 | inline ParseMode resolveParseMode() |
519 | { |
520 | switch (m_expressionType) { |
521 | case ExpressionType::BindingExpression: |
522 | // unfortunately there are no documentation explaining this resolution |
523 | // this was just moved from the original implementation |
524 | return ParseMode::QML; |
525 | case ExpressionType::ESMCode: |
526 | return ParseMode::ESM; |
527 | default: |
528 | return ParseMode::JS; |
529 | } |
530 | } |
531 | void setCode(const QString &code, const QString &preCode, const QString &postCode); |
532 | [[nodiscard]] AST::Node *parse(ParseMode mode); |
533 | |
534 | ExpressionType m_expressionType; |
535 | QString m_codeStr; |
536 | QStringView m_code; |
537 | QStringView m_preCode; |
538 | QStringView m_postCode; |
539 | mutable std::shared_ptr<QQmlJS::Engine> m_engine; |
540 | mutable AST::Node *m_ast; |
541 | std::shared_ptr<AstComments> m_astComments; |
542 | SourceLocation m_localOffset; |
543 | ScriptElementVariant m_element; |
544 | }; |
545 | |
546 | class BindingValue; |
547 | |
548 | class QMLDOM_EXPORT Binding |
549 | { |
550 | public: |
551 | constexpr static DomType kindValue = DomType::Binding; |
552 | |
553 | Binding(const QString &m_name = QString()); |
554 | Binding(const QString &m_name, std::unique_ptr<BindingValue> value, |
555 | BindingType bindingType = BindingType::Normal); |
556 | Binding(const QString &m_name, const std::shared_ptr<ScriptExpression> &value, |
557 | BindingType bindingType = BindingType::Normal); |
558 | Binding(const QString &m_name, const QString &scriptCode, |
559 | BindingType bindingType = BindingType::Normal); |
560 | Binding(const QString &m_name, const QmlObject &value, |
561 | BindingType bindingType = BindingType::Normal); |
562 | Binding(const QString &m_name, const QList<QmlObject> &value, |
563 | BindingType bindingType = BindingType::Normal); |
564 | Binding(const Binding &o); |
565 | Binding(Binding &&o) = default; |
566 | ~Binding(); |
567 | Binding &operator=(const Binding &); |
568 | Binding &operator=(Binding &&) = default; |
569 | |
570 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const; |
571 | DomItem valueItem(const DomItem &self) const; // ### REVISIT: consider replacing return value with variant |
572 | BindingValueKind valueKind() const; |
573 | QString name() const { return m_name; } |
574 | BindingType bindingType() const { return m_bindingType; } |
575 | QmlObject const *objectValue() const; |
576 | QList<QmlObject> const *arrayValue() const; |
577 | std::shared_ptr<ScriptExpression> scriptExpressionValue() const; |
578 | QmlObject *objectValue(); |
579 | QList<QmlObject> *arrayValue(); |
580 | std::shared_ptr<ScriptExpression> scriptExpressionValue(); |
581 | QList<QmlObject> annotations() const { return m_annotations; } |
582 | void setAnnotations(const QList<QmlObject> &annotations) { m_annotations = annotations; } |
583 | void setValue(std::unique_ptr<BindingValue> &&value) { m_value = std::move(value); } |
584 | Path addAnnotation(const Path &selfPathFromOwner, const QmlObject &a, QmlObject **aPtr = nullptr); |
585 | const RegionComments &comments() const { return m_comments; } |
586 | RegionComments &comments() { return m_comments; } |
587 | void updatePathFromOwner(const Path &newPath); |
588 | void writeOut(const DomItem &self, OutWriter &lw) const; |
589 | void writeOutValue(const DomItem &self, OutWriter &lw) const; |
590 | bool isSignalHandler() const |
591 | { |
592 | QString baseName = m_name.split(sep: QLatin1Char('.')).last(); |
593 | return QQmlSignalNames::isHandlerName(signalName: baseName); |
594 | } |
595 | static QString preCodeForName(QStringView n) |
596 | { |
597 | return QStringLiteral(u"QtObject{\n %1: ").arg(a: n.split(sep: u'.').last()); |
598 | } |
599 | static QString postCodeForName(QStringView) { return QStringLiteral(u"\n}\n"); } |
600 | QString preCode() const { return preCodeForName(n: m_name); } |
601 | QString postCode() const { return postCodeForName(m_name); } |
602 | |
603 | ScriptElementVariant bindingIdentifiers() const { return m_bindingIdentifiers; } |
604 | void setBindingIdentifiers(const ScriptElementVariant &bindingIdentifiers) { m_bindingIdentifiers = bindingIdentifiers; } |
605 | |
606 | private: |
607 | friend class QQmlDomAstCreator; |
608 | BindingType m_bindingType; |
609 | QString m_name; |
610 | std::unique_ptr<BindingValue> m_value; |
611 | QList<QmlObject> m_annotations; |
612 | RegionComments m_comments; |
613 | ScriptElementVariant m_bindingIdentifiers; |
614 | }; |
615 | |
616 | class QMLDOM_EXPORT AttributeInfo |
617 | { |
618 | public: |
619 | enum Access { Private, Protected, Public }; |
620 | |
621 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const; |
622 | |
623 | Path addAnnotation(const Path &selfPathFromOwner, const QmlObject &annotation, |
624 | QmlObject **aPtr = nullptr); |
625 | void updatePathFromOwner(const Path &newPath); |
626 | |
627 | QQmlJSScope::ConstPtr semanticScope() const { return m_semanticScope; } |
628 | void setSemanticScope(const QQmlJSScope::ConstPtr &scope) { m_semanticScope = scope; } |
629 | |
630 | QString name; |
631 | Access access = Access::Public; |
632 | QString typeName; |
633 | bool isReadonly = false; |
634 | bool isList = false; |
635 | QList<QmlObject> annotations; |
636 | RegionComments comments; |
637 | QQmlJSScope::ConstPtr m_semanticScope; |
638 | }; |
639 | |
640 | struct QMLDOM_EXPORT LocallyResolvedAlias |
641 | { |
642 | enum class Status { Invalid, ResolvedProperty, ResolvedObject, Loop, TooDeep }; |
643 | bool valid() |
644 | { |
645 | switch (status) { |
646 | case Status::ResolvedProperty: |
647 | case Status::ResolvedObject: |
648 | return true; |
649 | default: |
650 | return false; |
651 | } |
652 | } |
653 | DomItem baseObject; |
654 | DomItem localPropertyDef; |
655 | QString typeName; |
656 | QStringList accessedPath; |
657 | Status status = Status::Invalid; |
658 | int nAliases = 0; |
659 | }; |
660 | |
661 | class QMLDOM_EXPORT PropertyDefinition : public AttributeInfo |
662 | { |
663 | public: |
664 | constexpr static DomType kindValue = DomType::PropertyDefinition; |
665 | |
666 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const |
667 | { |
668 | bool cont = AttributeInfo::iterateDirectSubpaths(self, visitor); |
669 | cont = cont && self.dvValueField(visitor, f: Fields::isPointer, value: isPointer); |
670 | cont = cont && self.dvValueField(visitor, f: Fields::isFinal, value: isFinal); |
671 | cont = cont && self.dvValueField(visitor, f: Fields::isAlias, value: isAlias()); |
672 | cont = cont && self.dvValueField(visitor, f: Fields::isDefaultMember, value: isDefaultMember); |
673 | cont = cont && self.dvValueField(visitor, f: Fields::isRequired, value: isRequired); |
674 | cont = cont && self.dvValueField(visitor, f: Fields::read, value: read); |
675 | cont = cont && self.dvValueField(visitor, f: Fields::write, value: write); |
676 | cont = cont && self.dvValueField(visitor, f: Fields::bindable, value: bindable); |
677 | cont = cont && self.dvValueField(visitor, f: Fields::notify, value: notify); |
678 | cont = cont && self.dvReferenceField(visitor, f: Fields::type, referencedObject: typePath()); |
679 | if (m_nameIdentifiers) { |
680 | cont = cont && self.dvItemField(visitor, f: Fields::nameIdentifiers, it: [this, &self]() { |
681 | return self.subScriptElementWrapperItem(obj: m_nameIdentifiers); |
682 | }); |
683 | } |
684 | return cont; |
685 | } |
686 | |
687 | Path typePath() const { return Paths::lookupTypePath(name: typeName); } |
688 | |
689 | bool isAlias() const { return typeName == u"alias"; } |
690 | bool isParametricType() const; |
691 | void writeOut(const DomItem &self, OutWriter &lw) const; |
692 | ScriptElementVariant nameIdentifiers() const { return m_nameIdentifiers; } |
693 | void setNameIdentifiers(const ScriptElementVariant &name) { m_nameIdentifiers = name; } |
694 | |
695 | QString read; |
696 | QString write; |
697 | QString bindable; |
698 | QString notify; |
699 | bool isFinal = false; |
700 | bool isPointer = false; |
701 | bool isDefaultMember = false; |
702 | bool isRequired = false; |
703 | ScriptElementVariant m_nameIdentifiers; |
704 | }; |
705 | |
706 | class QMLDOM_EXPORT PropertyInfo |
707 | { |
708 | public: |
709 | constexpr static DomType kindValue = DomType::PropertyInfo; // used to get the correct kind in ObjectWrapper |
710 | |
711 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const; |
712 | |
713 | QList<DomItem> propertyDefs; |
714 | QList<DomItem> bindings; |
715 | }; |
716 | |
717 | class QMLDOM_EXPORT MethodParameter |
718 | { |
719 | public: |
720 | constexpr static DomType kindValue = DomType::MethodParameter; |
721 | enum class TypeAnnotationStyle { |
722 | Prefix, // a(int x) |
723 | Suffix, // a(x : int) |
724 | }; |
725 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const; |
726 | |
727 | void writeOut(const DomItem &self, OutWriter &ow) const; |
728 | void writeOutSignal(const DomItem &self, OutWriter &ow) const; |
729 | |
730 | QString name; |
731 | QString typeName; |
732 | bool isPointer = false; |
733 | bool isReadonly = false; |
734 | bool isList = false; |
735 | bool isRestElement = false; |
736 | std::shared_ptr<ScriptExpression> defaultValue; |
737 | /*! |
738 | \internal |
739 | Contains the scriptElement representing this argument, inclusive default value, |
740 | deconstruction, etc. |
741 | */ |
742 | std::shared_ptr<ScriptExpression> value; |
743 | QList<QmlObject> annotations; |
744 | RegionComments comments; |
745 | TypeAnnotationStyle typeAnnotationStyle = TypeAnnotationStyle::Suffix; |
746 | }; |
747 | |
748 | class QMLDOM_EXPORT MethodInfo : public AttributeInfo |
749 | { |
750 | Q_GADGET |
751 | public: |
752 | enum MethodType { Signal, Method }; |
753 | Q_ENUM(MethodType) |
754 | |
755 | constexpr static DomType kindValue = DomType::MethodInfo; |
756 | |
757 | Path typePath(const DomItem &) const |
758 | { |
759 | return (typeName.isEmpty() ? Path() : Paths::lookupTypePath(name: typeName)); |
760 | } |
761 | |
762 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const; |
763 | QString preCode(const DomItem &) const; // ### REVISIT, might be simplified by using different toplevel production rules at usage site |
764 | QString postCode(const DomItem &) const; |
765 | void writePre(const DomItem &self, OutWriter &ow) const; |
766 | void writeOut(const DomItem &self, OutWriter &ow) const; |
767 | void setCode(const QString &code) |
768 | { |
769 | body = std::make_shared<ScriptExpression>( |
770 | args: code, args: ScriptExpression::ExpressionType::FunctionBody, args: 0, |
771 | args: QLatin1String("function foo(){\n"), args: QLatin1String( "\n}\n")); |
772 | } |
773 | MethodInfo() = default; |
774 | |
775 | // TODO: make private + add getters/setters |
776 | QList<MethodParameter> parameters; |
777 | MethodType methodType = Method; |
778 | std::shared_ptr<ScriptExpression> body; |
779 | std::shared_ptr<ScriptExpression> returnType; |
780 | bool isConstructor = false; |
781 | }; |
782 | |
783 | class QMLDOM_EXPORT EnumItem |
784 | { |
785 | public: |
786 | constexpr static DomType kindValue = DomType::EnumItem; |
787 | enum class ValueKind : quint8 { |
788 | ImplicitValue, |
789 | ExplicitValue |
790 | }; |
791 | EnumItem(const QString &name = QString(), int value = 0, ValueKind valueKind = ValueKind::ImplicitValue) |
792 | : m_name(name), m_value(value), m_valueKind(valueKind) |
793 | { |
794 | } |
795 | |
796 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const; |
797 | |
798 | QString name() const { return m_name; } |
799 | double value() const { return m_value; } |
800 | RegionComments &comments() { return m_comments; } |
801 | const RegionComments &comments() const { return m_comments; } |
802 | void writeOut(const DomItem &self, OutWriter &lw) const; |
803 | |
804 | private: |
805 | QString m_name; |
806 | double m_value; |
807 | ValueKind m_valueKind; |
808 | RegionComments m_comments; |
809 | }; |
810 | |
811 | class QMLDOM_EXPORT EnumDecl final : public CommentableDomElement |
812 | { |
813 | public: |
814 | constexpr static DomType kindValue = DomType::EnumDecl; |
815 | DomType kind() const override { return kindValue; } |
816 | |
817 | EnumDecl(const QString &name = QString(), QList<EnumItem> values = QList<EnumItem>(), |
818 | Path pathFromOwner = Path()) |
819 | : CommentableDomElement(pathFromOwner), m_name(name), m_values(values) |
820 | { |
821 | } |
822 | |
823 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const override; |
824 | |
825 | QString name() const { return m_name; } |
826 | void setName(const QString &name) { m_name = name; } |
827 | const QList<EnumItem> &values() const & { return m_values; } |
828 | bool isFlag() const { return m_isFlag; } |
829 | void setIsFlag(bool flag) { m_isFlag = flag; } |
830 | QString alias() const { return m_alias; } |
831 | void setAlias(const QString &aliasName) { m_alias = aliasName; } |
832 | void setValues(QList<EnumItem> values) { m_values = values; } |
833 | Path addValue(EnumItem value) |
834 | { |
835 | m_values.append(t: value); |
836 | return Path::Field(s: Fields::values).index(i: index_type(m_values.size() - 1)); |
837 | } |
838 | void updatePathFromOwner(const Path &newP) override; |
839 | |
840 | const QList<QmlObject> &annotations() const & { return m_annotations; } |
841 | void setAnnotations(const QList<QmlObject> &annotations); |
842 | Path addAnnotation(const QmlObject &child, QmlObject **cPtr = nullptr); |
843 | void writeOut(const DomItem &self, OutWriter &lw) const override; |
844 | |
845 | private: |
846 | QString m_name; |
847 | bool m_isFlag = false; |
848 | QString m_alias; |
849 | QList<EnumItem> m_values; |
850 | QList<QmlObject> m_annotations; |
851 | }; |
852 | |
853 | class QMLDOM_EXPORT QmlObject final : public CommentableDomElement |
854 | { |
855 | Q_DECLARE_TR_FUNCTIONS(QmlObject) |
856 | public: |
857 | constexpr static DomType kindValue = DomType::QmlObject; |
858 | DomType kind() const override { return kindValue; } |
859 | |
860 | QmlObject(const Path &pathFromOwner = Path()); |
861 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override; |
862 | bool iterateBaseDirectSubpaths(const DomItem &self, DirectVisitor) const; |
863 | QList<QString> fields() const; |
864 | QList<QString> fields(const DomItem &) const override { return fields(); } |
865 | DomItem field(const DomItem &self, QStringView name) const override; |
866 | void updatePathFromOwner(const Path &newPath) override; |
867 | QString localDefaultPropertyName() const; |
868 | QString defaultPropertyName(const DomItem &self) const; |
869 | virtual bool iterateSubOwners(const DomItem &self, function_ref<bool(const DomItem &owner)> visitor) const; |
870 | |
871 | QString idStr() const { return m_idStr; } |
872 | QString name() const { return m_name; } |
873 | const QList<Path> &prototypePaths() const & { return m_prototypePaths; } |
874 | Path nextScopePath() const { return m_nextScopePath; } |
875 | const QMultiMap<QString, PropertyDefinition> &propertyDefs() const & { return m_propertyDefs; } |
876 | const QMultiMap<QString, Binding> &bindings() const & { return m_bindings; } |
877 | const QMultiMap<QString, MethodInfo> &methods() const & { return m_methods; } |
878 | QList<QmlObject> children() const { return m_children; } |
879 | QList<QmlObject> annotations() const { return m_annotations; } |
880 | |
881 | void setIdStr(const QString &id) { m_idStr = id; } |
882 | void setName(const QString &name) { m_name = name; } |
883 | void setDefaultPropertyName(const QString &name) { m_defaultPropertyName = name; } |
884 | void setPrototypePaths(QList<Path> prototypePaths) { m_prototypePaths = prototypePaths; } |
885 | Path addPrototypePath(const Path &prototypePath) |
886 | { |
887 | index_type idx = index_type(m_prototypePaths.indexOf(t: prototypePath)); |
888 | if (idx == -1) { |
889 | idx = index_type(m_prototypePaths.size()); |
890 | m_prototypePaths.append(t: prototypePath); |
891 | } |
892 | return Path::Field(s: Fields::prototypes).index(i: idx); |
893 | } |
894 | void setNextScopePath(const Path &nextScopePath) { m_nextScopePath = nextScopePath; } |
895 | void setPropertyDefs(QMultiMap<QString, PropertyDefinition> propertyDefs) |
896 | { |
897 | m_propertyDefs = propertyDefs; |
898 | } |
899 | void setBindings(QMultiMap<QString, Binding> bindings) { m_bindings = bindings; } |
900 | void setMethods(QMultiMap<QString, MethodInfo> functionDefs) { m_methods = functionDefs; } |
901 | void setChildren(const QList<QmlObject> &children) |
902 | { |
903 | m_children = children; |
904 | if (pathFromOwner()) |
905 | updatePathFromOwner(newPath: pathFromOwner()); |
906 | } |
907 | void setAnnotations(const QList<QmlObject> &annotations) |
908 | { |
909 | m_annotations = annotations; |
910 | if (pathFromOwner()) |
911 | updatePathFromOwner(newPath: pathFromOwner()); |
912 | } |
913 | Path addPropertyDef(const PropertyDefinition &propertyDef, AddOption option, |
914 | PropertyDefinition **pDef = nullptr) |
915 | { |
916 | return insertUpdatableElementInMultiMap(mapPathFromOwner: pathFromOwner().field(name: Fields::propertyDefs), |
917 | mmap&: m_propertyDefs, key: propertyDef.name, value: propertyDef, |
918 | option, valuePtr: pDef); |
919 | } |
920 | MutableDomItem addPropertyDef(MutableDomItem &self, const PropertyDefinition &propertyDef, |
921 | AddOption option); |
922 | |
923 | Path addBinding(Binding binding, AddOption option, Binding **bPtr = nullptr) |
924 | { |
925 | return insertUpdatableElementInMultiMap(mapPathFromOwner: pathFromOwner().field(name: Fields::bindings), mmap&: m_bindings, |
926 | key: binding.name(), value: binding, option, valuePtr: bPtr); |
927 | } |
928 | MutableDomItem addBinding(MutableDomItem &self, Binding binding, AddOption option); |
929 | Path addMethod(const MethodInfo &functionDef, AddOption option, MethodInfo **mPtr = nullptr) |
930 | { |
931 | return insertUpdatableElementInMultiMap(mapPathFromOwner: pathFromOwner().field(name: Fields::methods), mmap&: m_methods, |
932 | key: functionDef.name, value: functionDef, option, valuePtr: mPtr); |
933 | } |
934 | MutableDomItem addMethod(MutableDomItem &self, const MethodInfo &functionDef, AddOption option); |
935 | Path addChild(QmlObject child, QmlObject **cPtr = nullptr) |
936 | { |
937 | return appendUpdatableElementInQList(listPathFromOwner: pathFromOwner().field(name: Fields::children), list&: m_children, |
938 | value: child, vPtr: cPtr); |
939 | } |
940 | MutableDomItem addChild(MutableDomItem &self, QmlObject child) |
941 | { |
942 | Path p = addChild(child); |
943 | return MutableDomItem(self.owner().item(), p); |
944 | } |
945 | Path addAnnotation(const QmlObject &annotation, QmlObject **aPtr = nullptr) |
946 | { |
947 | return appendUpdatableElementInQList(listPathFromOwner: pathFromOwner().field(name: Fields::annotations), |
948 | list&: m_annotations, value: annotation, vPtr: aPtr); |
949 | } |
950 | void writeOut(const DomItem &self, OutWriter &ow, const QString &onTarget) const; |
951 | void writeOut(const DomItem &self, OutWriter &lw) const override { writeOut(self, ow&: lw, onTarget: QString()); } |
952 | |
953 | LocallyResolvedAlias resolveAlias(const DomItem &self, |
954 | std::shared_ptr<ScriptExpression> accessSequence) const; |
955 | LocallyResolvedAlias resolveAlias(const DomItem &self, const QStringList &accessSequence) const; |
956 | |
957 | QQmlJSScope::ConstPtr semanticScope() const { return m_scope; } |
958 | void setSemanticScope(const QQmlJSScope::ConstPtr &scope) { m_scope = scope; } |
959 | |
960 | ScriptElementVariant nameIdentifiers() const { return m_nameIdentifiers; } |
961 | void setNameIdentifiers(const ScriptElementVariant &name) { m_nameIdentifiers = name; } |
962 | |
963 | private: |
964 | friend class QQmlDomAstCreator; |
965 | QString m_idStr; |
966 | QString m_name; |
967 | QList<Path> m_prototypePaths; |
968 | Path m_nextScopePath; |
969 | QString m_defaultPropertyName; |
970 | QMultiMap<QString, PropertyDefinition> m_propertyDefs; |
971 | QMultiMap<QString, Binding> m_bindings; |
972 | QMultiMap<QString, MethodInfo> m_methods; |
973 | QList<QmlObject> m_children; |
974 | QList<QmlObject> m_annotations; |
975 | QQmlJSScope::ConstPtr m_scope; |
976 | ScriptElementVariant m_nameIdentifiers; |
977 | }; |
978 | |
979 | class Export |
980 | { |
981 | Q_DECLARE_TR_FUNCTIONS(Export) |
982 | public: |
983 | constexpr static DomType kindValue = DomType::Export; |
984 | static Export fromString( |
985 | const Path &source, QStringView exp, const Path &typePath, const ErrorHandler &h); |
986 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const |
987 | { |
988 | bool cont = true; |
989 | cont = cont && self.dvValueField(visitor, f: Fields::uri, value: uri); |
990 | cont = cont && self.dvValueField(visitor, f: Fields::typeName, value: typeName); |
991 | cont = cont && self.dvWrapField(visitor, f: Fields::version, obj: version); |
992 | if (typePath) |
993 | cont = cont && self.dvReferenceField(visitor, f: Fields::type, referencedObject: typePath); |
994 | cont = cont && self.dvValueField(visitor, f: Fields::isInternal, value: isInternal); |
995 | cont = cont && self.dvValueField(visitor, f: Fields::isSingleton, value: isSingleton); |
996 | if (exportSourcePath) |
997 | cont = cont && self.dvReferenceField(visitor, f: Fields::exportSource, referencedObject: exportSourcePath); |
998 | return cont; |
999 | } |
1000 | |
1001 | Path exportSourcePath; |
1002 | QString uri; |
1003 | QString typeName; |
1004 | Version version; |
1005 | Path typePath; |
1006 | bool isInternal = false; |
1007 | bool isSingleton = false; |
1008 | }; |
1009 | |
1010 | class QMLDOM_EXPORT Component : public CommentableDomElement |
1011 | { |
1012 | public: |
1013 | Component(const QString &name); |
1014 | Component(const Path &pathFromOwner = Path()); |
1015 | Component(const Component &o) = default; |
1016 | Component &operator=(const Component &) = default; |
1017 | |
1018 | bool iterateDirectSubpaths(const DomItem &, DirectVisitor) const override; |
1019 | void updatePathFromOwner(const Path &newPath) override; |
1020 | DomItem field(const DomItem &self, QStringView name) const override; |
1021 | |
1022 | QString name() const { return m_name; } |
1023 | const QMultiMap<QString, EnumDecl> &enumerations() const & { return m_enumerations; } |
1024 | const QList<QmlObject> &objects() const & { return m_objects; } |
1025 | bool isSingleton() const { return m_isSingleton; } |
1026 | bool isCreatable() const { return m_isCreatable; } |
1027 | bool isComposite() const { return m_isComposite; } |
1028 | QString attachedTypeName() const { return m_attachedTypeName; } |
1029 | Path attachedTypePath(const DomItem &) const { return m_attachedTypePath; } |
1030 | |
1031 | void setName(const QString &name) { m_name = name; } |
1032 | void setEnumerations(QMultiMap<QString, EnumDecl> enumerations) |
1033 | { |
1034 | m_enumerations = enumerations; |
1035 | } |
1036 | Path addEnumeration(const EnumDecl &enumeration, AddOption option = AddOption::Overwrite, |
1037 | EnumDecl **ePtr = nullptr) |
1038 | { |
1039 | return insertUpdatableElementInMultiMap(mapPathFromOwner: pathFromOwner().field(name: Fields::enumerations), |
1040 | mmap&: m_enumerations, key: enumeration.name(), value: enumeration, |
1041 | option, valuePtr: ePtr); |
1042 | } |
1043 | void setObjects(const QList<QmlObject> &objects) { m_objects = objects; } |
1044 | Path addObject(const QmlObject &object, QmlObject **oPtr = nullptr); |
1045 | void setIsSingleton(bool isSingleton) { m_isSingleton = isSingleton; } |
1046 | void setIsCreatable(bool isCreatable) { m_isCreatable = isCreatable; } |
1047 | void setIsComposite(bool isComposite) { m_isComposite = isComposite; } |
1048 | void setAttachedTypeName(const QString &name) { m_attachedTypeName = name; } |
1049 | void setAttachedTypePath(const Path &p) { m_attachedTypePath = p; } |
1050 | |
1051 | private: |
1052 | friend class QQmlDomAstCreator; |
1053 | QString m_name; |
1054 | QMultiMap<QString, EnumDecl> m_enumerations; |
1055 | QList<QmlObject> m_objects; |
1056 | bool m_isSingleton = false; |
1057 | bool m_isCreatable = true; |
1058 | bool m_isComposite = true; |
1059 | QString m_attachedTypeName; |
1060 | Path m_attachedTypePath; |
1061 | }; |
1062 | |
1063 | class QMLDOM_EXPORT JsResource final : public Component |
1064 | { |
1065 | public: |
1066 | constexpr static DomType kindValue = DomType::JsResource; |
1067 | DomType kind() const override { return kindValue; } |
1068 | |
1069 | JsResource(const Path &pathFromOwner = Path()) : Component(pathFromOwner) { } |
1070 | bool iterateDirectSubpaths(const DomItem &, DirectVisitor) const override |
1071 | { // to do: complete |
1072 | return true; |
1073 | } |
1074 | // globalSymbols defined/exported, required/used |
1075 | }; |
1076 | |
1077 | class QMLDOM_EXPORT QmltypesComponent final : public Component |
1078 | { |
1079 | public: |
1080 | constexpr static DomType kindValue = DomType::QmltypesComponent; |
1081 | DomType kind() const override { return kindValue; } |
1082 | |
1083 | QmltypesComponent(const Path &pathFromOwner = Path()) : Component(pathFromOwner) { } |
1084 | bool iterateDirectSubpaths(const DomItem &, DirectVisitor) const override; |
1085 | const QList<Export> &exports() const & { return m_exports; } |
1086 | QString fileName() const { return m_fileName; } |
1087 | void setExports(QList<Export> exports) { m_exports = exports; } |
1088 | void addExport(const Export &exportedEntry) { m_exports.append(t: exportedEntry); } |
1089 | void setFileName(const QString &fileName) { m_fileName = fileName; } |
1090 | const QList<int> &metaRevisions() const & { return m_metaRevisions; } |
1091 | void setMetaRevisions(QList<int> metaRevisions) { m_metaRevisions = metaRevisions; } |
1092 | void setInterfaceNames(const QStringList& interfaces) { m_interfaceNames = interfaces; } |
1093 | const QStringList &interfaceNames() const & { return m_interfaceNames; } |
1094 | QString extensionTypeName() const { return m_extensionTypeName; } |
1095 | void setExtensionTypeName(const QString &name) { m_extensionTypeName = name; } |
1096 | QString valueTypeName() const { return m_valueTypeName; } |
1097 | void setValueTypeName(const QString &name) { m_valueTypeName = name; } |
1098 | bool hasCustomParser() const { return m_hasCustomParser; } |
1099 | void setHasCustomParser(bool v) { m_hasCustomParser = v; } |
1100 | bool extensionIsJavaScript() const { return m_extensionIsJavaScript; } |
1101 | void setExtensionIsJavaScript(bool v) { m_extensionIsJavaScript = v; } |
1102 | bool extensionIsNamespace() const { return m_extensionIsNamespace; } |
1103 | void setExtensionIsNamespace(bool v) { m_extensionIsNamespace = v; } |
1104 | QQmlJSScope::AccessSemantics accessSemantics() const { return m_accessSemantics; } |
1105 | void setAccessSemantics(QQmlJSScope::AccessSemantics v) { m_accessSemantics = v; } |
1106 | |
1107 | void setSemanticScope(const QQmlJSScope::ConstPtr &scope) { m_semanticScope = scope; } |
1108 | QQmlJSScope::ConstPtr semanticScope() const { return m_semanticScope; } |
1109 | |
1110 | private: |
1111 | QList<Export> m_exports; |
1112 | QList<int> m_metaRevisions; |
1113 | QString m_fileName; // remove? |
1114 | QStringList m_interfaceNames; |
1115 | bool m_hasCustomParser = false; |
1116 | bool m_extensionIsJavaScript = false; |
1117 | bool m_extensionIsNamespace = false; |
1118 | QString m_valueTypeName; |
1119 | QString m_extensionTypeName; |
1120 | QQmlJSScope::AccessSemantics m_accessSemantics = QQmlJSScope::AccessSemantics::None; |
1121 | QQmlJSScope::ConstPtr m_semanticScope; |
1122 | }; |
1123 | |
1124 | class QMLDOM_EXPORT QmlComponent final : public Component |
1125 | { |
1126 | public: |
1127 | constexpr static DomType kindValue = DomType::QmlComponent; |
1128 | DomType kind() const override { return kindValue; } |
1129 | |
1130 | QmlComponent(const QString &name = QString()) : Component(name) |
1131 | { |
1132 | setIsComposite(true); |
1133 | setIsCreatable(true); |
1134 | } |
1135 | |
1136 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override; |
1137 | |
1138 | const QMultiMap<QString, Id> &ids() const & { return m_ids; } |
1139 | Path nextComponentPath() const { return m_nextComponentPath; } |
1140 | void setIds(QMultiMap<QString, Id> ids) { m_ids = ids; } |
1141 | void setNextComponentPath(const Path &p) { m_nextComponentPath = p; } |
1142 | void updatePathFromOwner(const Path &newPath) override; |
1143 | Path addId(const Id &id, AddOption option = AddOption::Overwrite, Id **idPtr = nullptr) |
1144 | { |
1145 | // warning does nor remove old idStr when overwriting... |
1146 | return insertUpdatableElementInMultiMap(mapPathFromOwner: pathFromOwner().field(name: Fields::ids), mmap&: m_ids, key: id.name, |
1147 | value: id, option, valuePtr: idPtr); |
1148 | } |
1149 | void writeOut(const DomItem &self, OutWriter &) const override; |
1150 | QList<QString> subComponentsNames(const DomItem &self) const; |
1151 | QList<DomItem> subComponents(const DomItem &self) const; |
1152 | |
1153 | void setSemanticScope(const QQmlJSScope::ConstPtr &scope) { m_semanticScope = scope; } |
1154 | QQmlJSScope::ConstPtr semanticScope() const { return m_semanticScope; } |
1155 | ScriptElementVariant nameIdentifiers() const { return m_nameIdentifiers; } |
1156 | void setNameIdentifiers(const ScriptElementVariant &name) { m_nameIdentifiers = name; } |
1157 | |
1158 | private: |
1159 | friend class QQmlDomAstCreator; |
1160 | Path m_nextComponentPath; |
1161 | QMultiMap<QString, Id> m_ids; |
1162 | QQmlJSScope::ConstPtr m_semanticScope; |
1163 | // m_nameIdentifiers contains the name of the component as FieldMemberExpression, and therefore |
1164 | // only exists in inline components! |
1165 | ScriptElementVariant m_nameIdentifiers; |
1166 | }; |
1167 | |
1168 | class QMLDOM_EXPORT GlobalComponent final : public Component |
1169 | { |
1170 | public: |
1171 | constexpr static DomType kindValue = DomType::GlobalComponent; |
1172 | DomType kind() const override { return kindValue; } |
1173 | |
1174 | GlobalComponent(const Path &pathFromOwner = Path()) : Component(pathFromOwner) { } |
1175 | }; |
1176 | |
1177 | static ErrorGroups importErrors = { .groups: { DomItem::domErrorGroup, NewErrorGroup("importError") } }; |
1178 | |
1179 | class QMLDOM_EXPORT ImportScope |
1180 | { |
1181 | Q_DECLARE_TR_FUNCTIONS(ImportScope) |
1182 | public: |
1183 | constexpr static DomType kindValue = DomType::ImportScope; |
1184 | |
1185 | ImportScope() = default; |
1186 | ~ImportScope() = default; |
1187 | |
1188 | const QList<Path> &importSourcePaths() const & { return m_importSourcePaths; } |
1189 | |
1190 | const QMap<QString, ImportScope> &subImports() const & { return m_subImports; } |
1191 | |
1192 | QList<Path> allSources(const DomItem &self) const; |
1193 | |
1194 | QSet<QString> importedNames(const DomItem &self) const |
1195 | { |
1196 | QSet<QString> res; |
1197 | const auto sources = allSources(self); |
1198 | for (const Path &p : sources) { |
1199 | QSet<QString> ks = self.path(p: p.field(name: Fields::exports), h: self.errorHandler()).keys(); |
1200 | res += ks; |
1201 | } |
1202 | return res; |
1203 | } |
1204 | |
1205 | QList<DomItem> importedItemsWithName(const DomItem &self, const QString &name) const |
1206 | { |
1207 | QList<DomItem> res; |
1208 | const auto sources = allSources(self); |
1209 | for (const Path &p : sources) { |
1210 | DomItem source = self.path(p: p.field(name: Fields::exports), h: self.errorHandler()); |
1211 | DomItem els = source.key(name); |
1212 | int nEls = els.indexes(); |
1213 | for (int i = 0; i < nEls; ++i) |
1214 | res.append(t: els.index(i)); |
1215 | if (nEls == 0 && els) { |
1216 | self.addError(msg: importErrors.warning( |
1217 | message: tr(sourceText: "Looking up '%1' expected a list of exports, not %2") |
1218 | .arg(args: name, args: els.toString()))); |
1219 | } |
1220 | } |
1221 | return res; |
1222 | } |
1223 | |
1224 | QList<Export> importedExportsWithName(const DomItem &self, const QString &name) const |
1225 | { |
1226 | QList<Export> res; |
1227 | for (const DomItem &i : importedItemsWithName(self, name)) |
1228 | if (const Export *e = i.as<Export>()) |
1229 | res.append(t: *e); |
1230 | else |
1231 | self.addError(msg: importErrors.warning( |
1232 | message: tr(sourceText: "Expected Export looking up '%1', not %2").arg(args: name, args: i.toString()))); |
1233 | return res; |
1234 | } |
1235 | |
1236 | bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const; |
1237 | |
1238 | void addImport(QStringList p, const Path &targetExports) |
1239 | { |
1240 | if (!p.isEmpty()) { |
1241 | const QString current = p.takeFirst(); |
1242 | m_subImports[current].addImport(p: std::move(p), targetExports); |
1243 | } else if (!m_importSourcePaths.contains(t: targetExports)) { |
1244 | m_importSourcePaths.append(t: targetExports); |
1245 | } |
1246 | } |
1247 | |
1248 | private: |
1249 | QList<Path> m_importSourcePaths; |
1250 | QMap<QString, ImportScope> m_subImports; |
1251 | }; |
1252 | |
1253 | class BindingValue |
1254 | { |
1255 | public: |
1256 | BindingValue(); |
1257 | BindingValue(const QmlObject &o); |
1258 | BindingValue(const std::shared_ptr<ScriptExpression> &o); |
1259 | BindingValue(const QList<QmlObject> &l); |
1260 | ~BindingValue(); |
1261 | BindingValue(const BindingValue &o); |
1262 | BindingValue &operator=(const BindingValue &o); |
1263 | |
1264 | DomItem value(const DomItem &binding) const; |
1265 | void updatePathFromOwner(const Path &newPath); |
1266 | |
1267 | private: |
1268 | friend class Binding; |
1269 | void clearValue(); |
1270 | |
1271 | BindingValueKind kind; |
1272 | union { |
1273 | int dummy; |
1274 | QmlObject object; |
1275 | std::shared_ptr<ScriptExpression> scriptExpression; |
1276 | QList<QmlObject> array; |
1277 | }; |
1278 | }; |
1279 | |
1280 | } // end namespace Dom |
1281 | } // end namespace QQmlJS |
1282 | QT_END_NAMESPACE |
1283 | #endif // QQMLDOMELEMENTS_P_H |
1284 |
Definitions
- moduleScopePath
- qmlDirInfoPath
- qmlDirPath
- qmldirFileInfoPath
- qmldirFilePath
- qmlFileInfoPath
- qmlFilePath
- qmlFileObjectPath
- qmltypesFileInfoPath
- qmltypesFilePath
- jsFileInfoPath
- jsFilePath
- qmlDirectoryInfoPath
- qmlDirectoryPath
- globalScopeInfoPath
- globalScopePath
- lookupCppTypePath
- lookupPropertyPath
- lookupSymbolPath
- lookupTypePath
- loadInfoPath
- CommentableDomElement
- CommentableDomElement
- CommentableDomElement
- operator=
- comments
- comments
- Version
- kindValue
- Undefined
- Latest
- majorString
- majorSymbolicString
- minorString
- compare
- operator==
- operator!=
- operator<
- operator<=
- operator>
- operator>=
- QmlUri
- Kind
- QmlUri
- operator==
- operator!=
- QmlUri
- QmlUri
- Import
- kindValue
- Import
- importedPath
- baseImport
- operator==
- operator!=
- ModuleAutoExport
- kindValue
- iterateDirectSubpaths
- operator==
- operator!=
- Pragma
- kindValue
- Pragma
- iterateDirectSubpaths
- Id
- kindValue
- ScriptExpression
- ExpressionType
- kindValue
- kind
- ScriptExpression
- ScriptExpression
- makeCopy
- canonicalPath
- ast
- code
- expressionType
- isNull
- engine
- astComments
- localOffset
- preCode
- postCode
- scriptElement
- doCopy
- locationToGlobalF
- locationToLocal
- locationToLocalF
- ParseMode
- resolveParseMode
- Binding
- kindValue
- Binding
- operator=
- name
- bindingType
- annotations
- setAnnotations
- setValue
- comments
- comments
- isSignalHandler
- preCodeForName
- postCodeForName
- preCode
- postCode
- bindingIdentifiers
- setBindingIdentifiers
- AttributeInfo
- Access
- semanticScope
- setSemanticScope
- LocallyResolvedAlias
- Status
- valid
- PropertyDefinition
- kindValue
- iterateDirectSubpaths
- typePath
- isAlias
- nameIdentifiers
- setNameIdentifiers
- PropertyInfo
- kindValue
- MethodParameter
- kindValue
- TypeAnnotationStyle
- MethodInfo
- MethodType
- kindValue
- typePath
- setCode
- MethodInfo
- EnumItem
- kindValue
- ValueKind
- EnumItem
- name
- value
- comments
- comments
- EnumDecl
- kindValue
- kind
- EnumDecl
- name
- setName
- values
- isFlag
- setIsFlag
- alias
- setAlias
- setValues
- addValue
- annotations
- QmlObject
- kindValue
- kind
- fields
- idStr
- name
- prototypePaths
- nextScopePath
- propertyDefs
- bindings
- methods
- children
- annotations
- setIdStr
- setName
- setDefaultPropertyName
- setPrototypePaths
- addPrototypePath
- setNextScopePath
- setPropertyDefs
- setBindings
- setMethods
- setChildren
- setAnnotations
- addPropertyDef
- addBinding
- addMethod
- addChild
- addChild
- addAnnotation
- writeOut
- semanticScope
- setSemanticScope
- nameIdentifiers
- setNameIdentifiers
- Export
- kindValue
- iterateDirectSubpaths
- Component
- Component
- operator=
- name
- enumerations
- objects
- isSingleton
- isCreatable
- isComposite
- attachedTypeName
- attachedTypePath
- setName
- setEnumerations
- addEnumeration
- setObjects
- setIsSingleton
- setIsCreatable
- setIsComposite
- setAttachedTypeName
- setAttachedTypePath
- JsResource
- kindValue
- kind
- JsResource
- iterateDirectSubpaths
- QmltypesComponent
- kindValue
- kind
- QmltypesComponent
- exports
- fileName
- setExports
- addExport
- setFileName
- metaRevisions
- setMetaRevisions
- setInterfaceNames
- interfaceNames
- extensionTypeName
- setExtensionTypeName
- valueTypeName
- setValueTypeName
- hasCustomParser
- setHasCustomParser
- extensionIsJavaScript
- setExtensionIsJavaScript
- extensionIsNamespace
- setExtensionIsNamespace
- accessSemantics
- setAccessSemantics
- setSemanticScope
- semanticScope
- QmlComponent
- kindValue
- kind
- QmlComponent
- ids
- nextComponentPath
- setIds
- setNextComponentPath
- addId
- setSemanticScope
- semanticScope
- nameIdentifiers
- setNameIdentifiers
- GlobalComponent
- kindValue
- kind
- GlobalComponent
- importErrors
- ImportScope
- kindValue
- ImportScope
- ~ImportScope
- importSourcePaths
- subImports
- importedNames
- importedItemsWithName
- importedExportsWithName
- addImport
Start learning QML with our Intro Training
Find out more