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
38QT_BEGIN_NAMESPACE
39
40namespace QQmlJS {
41namespace 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
45namespace Paths {
46Path moduleIndexPath(
47 const QString &uri, int majorVersion, const ErrorHandler &errorHandler = nullptr);
48Path moduleScopePath(
49 const QString &uri, Version version, const ErrorHandler &errorHandler = nullptr);
50Path moduleScopePath(
51 const QString &uri, const QString &version, const ErrorHandler &errorHandler = nullptr);
52inline Path moduleScopePath(
53 const QString &uri, const ErrorHandler &errorHandler = nullptr)
54{
55 return moduleScopePath(uri, version: QString(), errorHandler);
56}
57inline Path qmlDirInfoPath(const QString &path)
58{
59 return Path::Root(r: PathRoot::Top).field(name: Fields::qmldirWithPath).key(name: path);
60}
61inline Path qmlDirPath(const QString &path)
62{
63 return qmlDirInfoPath(path).field(name: Fields::currentItem);
64}
65inline Path qmldirFileInfoPath(const QString &path)
66{
67 return Path::Root(r: PathRoot::Top).field(name: Fields::qmldirFileWithPath).key(name: path);
68}
69inline Path qmldirFilePath(const QString &path)
70{
71 return qmldirFileInfoPath(path).field(name: Fields::currentItem);
72}
73inline Path qmlFileInfoPath(const QString &canonicalFilePath)
74{
75 return Path::Root(r: PathRoot::Top).field(name: Fields::qmlFileWithPath).key(name: canonicalFilePath);
76}
77inline Path qmlFilePath(const QString &canonicalFilePath)
78{
79 return qmlFileInfoPath(canonicalFilePath).field(name: Fields::currentItem);
80}
81inline 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}
90inline Path qmltypesFileInfoPath(const QString &path)
91{
92 return Path::Root(r: PathRoot::Top).field(name: Fields::qmltypesFileWithPath).key(name: path);
93}
94inline Path qmltypesFilePath(const QString &path)
95{
96 return qmltypesFileInfoPath(path).field(name: Fields::currentItem);
97}
98inline Path jsFileInfoPath(const QString &path)
99{
100 return Path::Root(r: PathRoot::Top).field(name: Fields::jsFileWithPath).key(name: path);
101}
102inline Path jsFilePath(const QString &path)
103{
104 return jsFileInfoPath(path).field(name: Fields::currentItem);
105}
106inline Path qmlDirectoryInfoPath(const QString &path)
107{
108 return Path::Root(r: PathRoot::Top).field(name: Fields::qmlDirectoryWithPath).key(name: path);
109}
110inline Path qmlDirectoryPath(const QString &path)
111{
112 return qmlDirectoryInfoPath(path).field(name: Fields::currentItem);
113}
114inline Path globalScopeInfoPath(const QString &name)
115{
116 return Path::Root(r: PathRoot::Top).field(name: Fields::globalScopeWithName).key(name);
117}
118inline Path globalScopePath(const QString &name)
119{
120 return globalScopeInfoPath(name).field(name: Fields::currentItem);
121}
122inline Path lookupCppTypePath(const QString &name)
123{
124 return Path::Current(c: PathCurrent::Lookup).field(name: Fields::cppType).key(name);
125}
126inline Path lookupPropertyPath(const QString &name)
127{
128 return Path::Current(c: PathCurrent::Lookup).field(name: Fields::propertyDef).key(name);
129}
130inline Path lookupSymbolPath(const QString &name)
131{
132 return Path::Current(c: PathCurrent::Lookup).field(name: Fields::symbol).key(name);
133}
134inline Path lookupTypePath(const QString &name)
135{
136 return Path::Current(c: PathCurrent::Lookup).field(name: Fields::type).key(name);
137}
138inline 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
144class QMLDOM_EXPORT CommentableDomElement : public DomElement
145{
146public:
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
156private:
157 RegionComments m_comments;
158};
159
160class QMLDOM_EXPORT Version
161{
162public:
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};
206inline bool operator==(const Version &v1, const Version &v2)
207{
208 return v1.compare(o: v2) == 0;
209}
210inline bool operator!=(const Version &v1, const Version &v2)
211{
212 return v1.compare(o: v2) != 0;
213}
214inline bool operator<(const Version &v1, const Version &v2)
215{
216 return v1.compare(o: v2) < 0;
217}
218inline bool operator<=(const Version &v1, const Version &v2)
219{
220 return v1.compare(o: v2) <= 0;
221}
222inline bool operator>(const Version &v1, const Version &v2)
223{
224 return v1.compare(o: v2) > 0;
225}
226inline bool operator>=(const Version &v1, const Version &v2)
227{
228 return v1.compare(o: v2) >= 0;
229}
230
231class QMLDOM_EXPORT QmlUri
232{
233public:
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
256private:
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
263class QMLDOM_EXPORT Import
264{
265 Q_DECLARE_TR_FUNCTIONS(Import)
266public:
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
317class QMLDOM_EXPORT ModuleAutoExport
318{
319public:
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
343class QMLDOM_EXPORT Pragma
344{
345public:
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
368class QMLDOM_EXPORT Id
369{
370public:
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
388class QMLDOM_EXPORT ScriptExpression final : public OwningItem
389{
390 Q_GADGET
391 Q_DECLARE_TR_FUNCTIONS(ScriptExpression)
392public:
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
479protected:
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
511private:
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
546class BindingValue;
547
548class QMLDOM_EXPORT Binding
549{
550public:
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
606private:
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
616class QMLDOM_EXPORT AttributeInfo
617{
618public:
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
640struct 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
661class QMLDOM_EXPORT PropertyDefinition : public AttributeInfo
662{
663public:
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
706class QMLDOM_EXPORT PropertyInfo
707{
708public:
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
717class QMLDOM_EXPORT MethodParameter
718{
719public:
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
748class QMLDOM_EXPORT MethodInfo : public AttributeInfo
749{
750 Q_GADGET
751public:
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
783class QMLDOM_EXPORT EnumItem
784{
785public:
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
804private:
805 QString m_name;
806 double m_value;
807 ValueKind m_valueKind;
808 RegionComments m_comments;
809};
810
811class QMLDOM_EXPORT EnumDecl final : public CommentableDomElement
812{
813public:
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
845private:
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
853class QMLDOM_EXPORT QmlObject final : public CommentableDomElement
854{
855 Q_DECLARE_TR_FUNCTIONS(QmlObject)
856public:
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
963private:
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
979class Export
980{
981 Q_DECLARE_TR_FUNCTIONS(Export)
982public:
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
1010class QMLDOM_EXPORT Component : public CommentableDomElement
1011{
1012public:
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
1051private:
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
1063class QMLDOM_EXPORT JsResource final : public Component
1064{
1065public:
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
1077class QMLDOM_EXPORT QmltypesComponent final : public Component
1078{
1079public:
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
1110private:
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
1124class QMLDOM_EXPORT QmlComponent final : public Component
1125{
1126public:
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
1158private:
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
1168class QMLDOM_EXPORT GlobalComponent final : public Component
1169{
1170public:
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
1177static ErrorGroups importErrors = { .groups: { DomItem::domErrorGroup, NewErrorGroup("importError") } };
1178
1179class QMLDOM_EXPORT ImportScope
1180{
1181 Q_DECLARE_TR_FUNCTIONS(ImportScope)
1182public:
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
1248private:
1249 QList<Path> m_importSourcePaths;
1250 QMap<QString, ImportScope> m_subImports;
1251};
1252
1253class BindingValue
1254{
1255public:
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
1267private:
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
1282QT_END_NAMESPACE
1283#endif // QQMLDOMELEMENTS_P_H
1284

Provided by KDAB

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

source code of qtdeclarative/src/qmldom/qqmldomelements_p.h