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
31#include <memory>
32#include <private/qqmljsscope_p.h>
33
34#include <functional>
35#include <limits>
36#include <utility>
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::fromRoot(r: PathRoot::Top).withField(name: Fields::qmldirWithPath).withKey(name: path);
60}
61inline Path qmlDirPath(const QString &path)
62{
63 return qmlDirInfoPath(path).withField(name: Fields::currentItem);
64}
65inline Path qmldirFileInfoPath(const QString &path)
66{
67 return Path::fromRoot(r: PathRoot::Top).withField(name: Fields::qmldirFileWithPath).withKey(name: path);
68}
69inline Path qmldirFilePath(const QString &path)
70{
71 return qmldirFileInfoPath(path).withField(name: Fields::currentItem);
72}
73inline Path qmlFileInfoPath(const QString &canonicalFilePath)
74{
75 return Path::fromRoot(r: PathRoot::Top).withField(name: Fields::qmlFileWithPath).withKey(name: canonicalFilePath);
76}
77inline Path qmlFilePath(const QString &canonicalFilePath)
78{
79 return qmlFileInfoPath(canonicalFilePath).withField(name: Fields::currentItem);
80}
81inline Path qmlFileObjectPath(const QString &canonicalFilePath)
82{
83 return qmlFilePath(canonicalFilePath)
84 .withField(name: Fields::components)
85 .withKey(name: QString())
86 .withIndex(i: 0)
87 .withField(name: Fields::objects)
88 .withIndex(i: 0);
89}
90inline Path qmltypesFileInfoPath(const QString &path)
91{
92 return Path::fromRoot(r: PathRoot::Top).withField(name: Fields::qmltypesFileWithPath).withKey(name: path);
93}
94inline Path qmltypesFilePath(const QString &path)
95{
96 return qmltypesFileInfoPath(path).withField(name: Fields::currentItem);
97}
98inline Path jsFileInfoPath(const QString &path)
99{
100 return Path::fromRoot(r: PathRoot::Top).withField(name: Fields::jsFileWithPath).withKey(name: path);
101}
102inline Path jsFilePath(const QString &path)
103{
104 return jsFileInfoPath(path).withField(name: Fields::currentItem);
105}
106inline Path qmlDirectoryInfoPath(const QString &path)
107{
108 return Path::fromRoot(r: PathRoot::Top).withField(name: Fields::qmlDirectoryWithPath).withKey(name: path);
109}
110inline Path qmlDirectoryPath(const QString &path)
111{
112 return qmlDirectoryInfoPath(path).withField(name: Fields::currentItem);
113}
114inline Path globalScopeInfoPath(const QString &name)
115{
116 return Path::fromRoot(r: PathRoot::Top).withField(name: Fields::globalScopeWithName).withKey(name);
117}
118inline Path globalScopePath(const QString &name)
119{
120 return globalScopeInfoPath(name).withField(name: Fields::currentItem);
121}
122inline Path lookupCppTypePath(const QString &name)
123{
124 return Path::fromCurrent(c: PathCurrent::Lookup).withField(name: Fields::cppType).withKey(name);
125}
126inline Path lookupPropertyPath(const QString &name)
127{
128 return Path::fromCurrent(c: PathCurrent::Lookup).withField(name: Fields::propertyDef).withKey(name);
129}
130inline Path lookupSymbolPath(const QString &name)
131{
132 return Path::fromCurrent(c: PathCurrent::Lookup).withField(name: Fields::symbol).withKey(name);
133}
134inline Path lookupTypePath(const QString &name)
135{
136 return Path::fromCurrent(c: PathCurrent::Lookup).withField(name: Fields::type).withKey(name);
137}
138inline Path loadInfoPath(const Path &el)
139{
140 return Path::fromRoot(r: PathRoot::Env).withField(name: Fields::loadInfo).withKey(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 QStringView loc2Str(SourceLocation) const;
471 std::shared_ptr<AstComments> astComments() const { return m_astComments; }
472 void writeOut(const DomItem &self, OutWriter &lw) const override;
473 SourceLocation globalLocation(const DomItem &self) const;
474 SourceLocation localOffset() const { return m_localOffset; }
475 QStringView preCode() const { return m_preCode; }
476 QStringView postCode() const { return m_postCode; }
477 void setScriptElement(const ScriptElementVariant &p);
478 ScriptElementVariant scriptElement() { return m_element; }
479
480protected:
481 std::shared_ptr<OwningItem> doCopy(const DomItem &) const override
482 {
483 return std::make_shared<ScriptExpression>(args: *this);
484 }
485
486 std::function<SourceLocation(SourceLocation)> locationToGlobalF(const DomItem &self) const
487 {
488 SourceLocation loc = globalLocation(self);
489 return [loc, this](SourceLocation x) {
490 return SourceLocation(x.offset - m_localOffset.offset + loc.offset, x.length,
491 x.startLine - m_localOffset.startLine + loc.startLine,
492 ((x.startLine == m_localOffset.startLine) ? x.startColumn
493 - m_localOffset.startColumn + loc.startColumn
494 : x.startColumn));
495 };
496 }
497
498 SourceLocation locationToLocal(SourceLocation x) const
499 {
500 return SourceLocation(
501 x.offset - m_localOffset.offset, x.length, x.startLine - m_localOffset.startLine,
502 ((x.startLine == m_localOffset.startLine)
503 ? x.startColumn - m_localOffset.startColumn
504 : x.startColumn)); // are line and column 1 based? then we should + 1
505 }
506
507 std::function<SourceLocation(SourceLocation)> locationToLocalF(const DomItem &) const
508 {
509 return [this](SourceLocation x) { return locationToLocal(x); };
510 }
511
512private:
513 enum class ParseMode {
514 QML,
515 JS,
516 ESM, // ECMAScript module
517 };
518
519 inline ParseMode resolveParseMode()
520 {
521 switch (m_expressionType) {
522 case ExpressionType::BindingExpression:
523 // unfortunately there are no documentation explaining this resolution
524 // this was just moved from the original implementation
525 return ParseMode::QML;
526 case ExpressionType::ESMCode:
527 return ParseMode::ESM;
528 default:
529 return ParseMode::JS;
530 }
531 }
532 void setCode(const QString &code, const QString &preCode, const QString &postCode);
533 [[nodiscard]] AST::Node *parse(ParseMode mode);
534
535 ExpressionType m_expressionType;
536 QString m_codeStr;
537 QStringView m_code;
538 QStringView m_preCode;
539 QStringView m_postCode;
540 mutable std::shared_ptr<QQmlJS::Engine> m_engine;
541 mutable AST::Node *m_ast;
542 std::shared_ptr<AstComments> m_astComments;
543 SourceLocation m_localOffset;
544 ScriptElementVariant m_element;
545};
546
547class BindingValue;
548
549class QMLDOM_EXPORT Binding
550{
551public:
552 constexpr static DomType kindValue = DomType::Binding;
553
554 Binding(const QString &m_name = QString());
555 Binding(const QString &m_name, std::unique_ptr<BindingValue> value,
556 BindingType bindingType = BindingType::Normal);
557 Binding(const QString &m_name, const std::shared_ptr<ScriptExpression> &value,
558 BindingType bindingType = BindingType::Normal);
559 Binding(const QString &m_name, const QString &scriptCode,
560 BindingType bindingType = BindingType::Normal);
561 Binding(const QString &m_name, const QmlObject &value,
562 BindingType bindingType = BindingType::Normal);
563 Binding(const QString &m_name, const QList<QmlObject> &value,
564 BindingType bindingType = BindingType::Normal);
565 Binding(const Binding &o);
566 Binding(Binding &&o) = default;
567 ~Binding();
568 Binding &operator=(const Binding &);
569 Binding &operator=(Binding &&) = default;
570
571 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const;
572 DomItem valueItem(const DomItem &self) const; // ### REVISIT: consider replacing return value with variant
573 BindingValueKind valueKind() const;
574 QString name() const { return m_name; }
575 BindingType bindingType() const { return m_bindingType; }
576 QmlObject const *objectValue() const;
577 QList<QmlObject> const *arrayValue() const;
578 std::shared_ptr<ScriptExpression> scriptExpressionValue() const;
579 QmlObject *objectValue();
580 QList<QmlObject> *arrayValue();
581 std::shared_ptr<ScriptExpression> scriptExpressionValue();
582 QList<QmlObject> annotations() const { return m_annotations; }
583 void setAnnotations(const QList<QmlObject> &annotations) { m_annotations = annotations; }
584 void setValue(std::unique_ptr<BindingValue> &&value);
585 Path addAnnotation(const Path &selfPathFromOwner, const QmlObject &a, QmlObject **aPtr = nullptr);
586 const RegionComments &comments() const { return m_comments; }
587 RegionComments &comments() { return m_comments; }
588 void updatePathFromOwner(const Path &newPath);
589 void writeOut(const DomItem &self, OutWriter &lw) const;
590 void writeOutValue(const DomItem &self, OutWriter &lw) const;
591 bool isSignalHandler() const
592 {
593 QString baseName = m_name.split(sep: QLatin1Char('.')).last();
594 return QQmlSignalNames::isHandlerName(signalName: baseName);
595 }
596 static QString preCodeForName(QStringView n)
597 {
598 return QStringLiteral(u"QtObject{\n %1: ").arg(a: n.split(sep: u'.').last());
599 }
600 static QString postCodeForName(QStringView) { return QStringLiteral(u"\n}\n"); }
601 QString preCode() const { return preCodeForName(n: m_name); }
602 QString postCode() const { return postCodeForName(m_name); }
603
604 ScriptElementVariant bindingIdentifiers() const { return m_bindingIdentifiers; }
605 void setBindingIdentifiers(const ScriptElementVariant &bindingIdentifiers) { m_bindingIdentifiers = bindingIdentifiers; }
606
607private:
608 friend class QQmlDomAstCreator;
609 BindingType m_bindingType;
610 QString m_name;
611 std::unique_ptr<BindingValue> m_value;
612 QList<QmlObject> m_annotations;
613 RegionComments m_comments;
614 ScriptElementVariant m_bindingIdentifiers;
615};
616
617class QMLDOM_EXPORT AttributeInfo
618{
619public:
620 enum Access { Private, Protected, Public };
621
622 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const;
623
624 Path addAnnotation(const Path &selfPathFromOwner, const QmlObject &annotation,
625 QmlObject **aPtr = nullptr);
626 void updatePathFromOwner(const Path &newPath);
627
628 QQmlJSScope::ConstPtr semanticScope() const { return m_semanticScope; }
629 void setSemanticScope(const QQmlJSScope::ConstPtr &scope) { m_semanticScope = scope; }
630
631 QString name;
632 Access access = Access::Public;
633 QString typeName;
634 bool isReadonly = false;
635 bool isList = false;
636 QList<QmlObject> annotations;
637 RegionComments comments;
638 QQmlJSScope::ConstPtr m_semanticScope;
639};
640
641struct QMLDOM_EXPORT LocallyResolvedAlias
642{
643 enum class Status { Invalid, ResolvedProperty, ResolvedObject, Loop, TooDeep };
644 bool valid()
645 {
646 switch (status) {
647 case Status::ResolvedProperty:
648 case Status::ResolvedObject:
649 return true;
650 default:
651 return false;
652 }
653 }
654 DomItem baseObject;
655 DomItem localPropertyDef;
656 QString typeName;
657 QStringList accessedPath;
658 Status status = Status::Invalid;
659 int nAliases = 0;
660};
661
662class QMLDOM_EXPORT PropertyDefinition : public AttributeInfo
663{
664public:
665 constexpr static DomType kindValue = DomType::PropertyDefinition;
666
667 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
668 {
669 bool cont = AttributeInfo::iterateDirectSubpaths(self, visitor);
670 cont = cont && self.dvValueField(visitor, f: Fields::isPointer, value: isPointer);
671 cont = cont && self.dvValueField(visitor, f: Fields::isFinal, value: isFinal);
672 cont = cont && self.dvValueField(visitor, f: Fields::isAlias, value: isAlias());
673 cont = cont && self.dvValueField(visitor, f: Fields::isDefaultMember, value: isDefaultMember);
674 cont = cont && self.dvValueField(visitor, f: Fields::isRequired, value: isRequired);
675 cont = cont && self.dvValueField(visitor, f: Fields::read, value: read);
676 cont = cont && self.dvValueField(visitor, f: Fields::write, value: write);
677 cont = cont && self.dvValueField(visitor, f: Fields::bindable, value: bindable);
678 cont = cont && self.dvValueField(visitor, f: Fields::notify, value: notify);
679 cont = cont && self.dvReferenceField(visitor, f: Fields::type, referencedObject: typePath());
680 if (m_nameIdentifiers) {
681 cont = cont && self.dvItemField(visitor, f: Fields::nameIdentifiers, it: [this, &self]() {
682 return self.subScriptElementWrapperItem(obj: m_nameIdentifiers);
683 });
684 }
685 return cont;
686 }
687
688 Path typePath() const { return Paths::lookupTypePath(name: typeName); }
689
690 bool isAlias() const { return typeName == u"alias"; }
691 bool isParametricType() const;
692 void writeOut(const DomItem &self, OutWriter &lw) const;
693 ScriptElementVariant nameIdentifiers() const { return m_nameIdentifiers; }
694 void setNameIdentifiers(const ScriptElementVariant &name) { m_nameIdentifiers = name; }
695
696 QString read;
697 QString write;
698 QString bindable;
699 QString notify;
700 bool isFinal = false;
701 bool isPointer = false;
702 bool isDefaultMember = false;
703 bool isRequired = false;
704 ScriptElementVariant m_nameIdentifiers;
705};
706
707class QMLDOM_EXPORT PropertyInfo
708{
709public:
710 constexpr static DomType kindValue = DomType::PropertyInfo; // used to get the correct kind in ObjectWrapper
711
712 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const;
713
714 QList<DomItem> propertyDefs;
715 QList<DomItem> bindings;
716};
717
718class QMLDOM_EXPORT MethodParameter
719{
720public:
721 constexpr static DomType kindValue = DomType::MethodParameter;
722 enum class TypeAnnotationStyle {
723 Prefix, // a(int x)
724 Suffix, // a(x : int)
725 };
726 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const;
727
728 void writeOut(const DomItem &self, OutWriter &ow) const;
729 void writeOutSignal(const DomItem &self, OutWriter &ow) const;
730
731 QString name;
732 QString typeName;
733 bool isPointer = false;
734 bool isReadonly = false;
735 bool isList = false;
736 bool isRestElement = false;
737 std::shared_ptr<ScriptExpression> defaultValue;
738 /*!
739 \internal
740 Contains the scriptElement representing this argument, inclusive default value,
741 deconstruction, etc.
742 */
743 std::shared_ptr<ScriptExpression> value;
744 QList<QmlObject> annotations;
745 RegionComments comments;
746 TypeAnnotationStyle typeAnnotationStyle = TypeAnnotationStyle::Suffix;
747};
748
749// TODO (QTBUG-128423)
750// Refactor to differentiate between Signals and Methods easily,
751// considering their distinct handling and formatting needs.
752// Explore separating Signal functionality or unifying shared methods.
753class QMLDOM_EXPORT MethodInfo : public AttributeInfo
754{
755 Q_GADGET
756public:
757 enum MethodType { Signal, Method };
758 Q_ENUM(MethodType)
759
760 constexpr static DomType kindValue = DomType::MethodInfo;
761
762 Path typePath(const DomItem &) const
763 {
764 return (typeName.isEmpty() ? Path() : Paths::lookupTypePath(name: typeName));
765 }
766
767 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const;
768 QString preCode(const DomItem &) const; // ### REVISIT, might be simplified by using different toplevel production rules at usage site
769 QString postCode(const DomItem &) const;
770 void writePre(const DomItem &self, OutWriter &ow) const;
771 void writeOut(const DomItem &self, OutWriter &ow) const;
772 QString signature(const DomItem &self) const;
773
774 void setCode(const QString &code)
775 {
776 body = std::make_shared<ScriptExpression>(
777 args: code, args: ScriptExpression::ExpressionType::FunctionBody, args: 0,
778 args: QLatin1String("function foo(){\n"), args: QLatin1String("\n}\n"));
779 }
780 MethodInfo() = default;
781
782 // TODO: make private + add getters/setters
783 QList<MethodParameter> parameters;
784 MethodType methodType = Method;
785 std::shared_ptr<ScriptExpression> body;
786 std::shared_ptr<ScriptExpression> returnType;
787 bool isConstructor = false;
788
789private:
790 void writeOutArguments(const DomItem &self, OutWriter &ow) const;
791 void writeOutReturnType(OutWriter &ow) const;
792 void writeOutBody(const DomItem &self, OutWriter &ow) const;
793};
794
795class QMLDOM_EXPORT EnumItem
796{
797public:
798 constexpr static DomType kindValue = DomType::EnumItem;
799 enum class ValueKind : quint8 {
800 ImplicitValue,
801 ExplicitValue
802 };
803 EnumItem(const QString &name = QString(), int value = 0, ValueKind valueKind = ValueKind::ImplicitValue)
804 : m_name(name), m_value(value), m_valueKind(valueKind)
805 {
806 }
807
808 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const;
809
810 QString name() const { return m_name; }
811 double value() const { return m_value; }
812 RegionComments &comments() { return m_comments; }
813 const RegionComments &comments() const { return m_comments; }
814 void writeOut(const DomItem &self, OutWriter &lw) const;
815
816private:
817 QString m_name;
818 double m_value;
819 ValueKind m_valueKind;
820 RegionComments m_comments;
821};
822
823class QMLDOM_EXPORT EnumDecl final : public CommentableDomElement
824{
825public:
826 constexpr static DomType kindValue = DomType::EnumDecl;
827 DomType kind() const override { return kindValue; }
828
829 EnumDecl(const QString &name = QString(), QList<EnumItem> values = QList<EnumItem>(),
830 Path pathFromOwner = Path())
831 : CommentableDomElement(pathFromOwner), m_name(name), m_values(values)
832 {
833 }
834
835 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const override;
836
837 QString name() const { return m_name; }
838 void setName(const QString &name) { m_name = name; }
839 const QList<EnumItem> &values() const & { return m_values; }
840 bool isFlag() const { return m_isFlag; }
841 void setIsFlag(bool flag) { m_isFlag = flag; }
842 QString alias() const { return m_alias; }
843 void setAlias(const QString &aliasName) { m_alias = aliasName; }
844 void setValues(QList<EnumItem> values) { m_values = values; }
845 Path addValue(EnumItem value)
846 {
847 m_values.append(t: value);
848 return Path::fromField(s: Fields::values).withIndex(i: index_type(m_values.size() - 1));
849 }
850 void updatePathFromOwner(const Path &newP) override;
851
852 const QList<QmlObject> &annotations() const & { return m_annotations; }
853 void setAnnotations(const QList<QmlObject> &annotations);
854 Path addAnnotation(const QmlObject &child, QmlObject **cPtr = nullptr);
855 void writeOut(const DomItem &self, OutWriter &lw) const override;
856
857private:
858 QString m_name;
859 bool m_isFlag = false;
860 QString m_alias;
861 QList<EnumItem> m_values;
862 QList<QmlObject> m_annotations;
863};
864
865class QMLDOM_EXPORT QmlObject final : public CommentableDomElement
866{
867 Q_DECLARE_TR_FUNCTIONS(QmlObject)
868public:
869 constexpr static DomType kindValue = DomType::QmlObject;
870 DomType kind() const override { return kindValue; }
871
872 QmlObject(const Path &pathFromOwner = Path());
873 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
874 bool iterateBaseDirectSubpaths(const DomItem &self, DirectVisitor) const;
875 QList<QString> fields() const;
876 QList<QString> fields(const DomItem &) const override { return fields(); }
877 DomItem field(const DomItem &self, QStringView name) const override;
878 void updatePathFromOwner(const Path &newPath) override;
879 QString localDefaultPropertyName() const;
880 QString defaultPropertyName(const DomItem &self) const;
881 virtual bool iterateSubOwners(const DomItem &self, function_ref<bool(const DomItem &owner)> visitor) const;
882
883 QString idStr() const { return m_idStr; }
884 QString name() const { return m_name; }
885 const QList<Path> &prototypePaths() const & { return m_prototypePaths; }
886 Path nextScopePath() const { return m_nextScopePath; }
887 const QMultiMap<QString, PropertyDefinition> &propertyDefs() const & { return m_propertyDefs; }
888 const QMultiMap<QString, Binding> &bindings() const & { return m_bindings; }
889 const QMultiMap<QString, MethodInfo> &methods() const & { return m_methods; }
890 QList<QmlObject> children() const { return m_children; }
891 QList<QmlObject> annotations() const { return m_annotations; }
892
893 void setIdStr(const QString &id) { m_idStr = id; }
894 void setName(const QString &name) { m_name = name; }
895 void setDefaultPropertyName(const QString &name) { m_defaultPropertyName = name; }
896 void setPrototypePaths(QList<Path> prototypePaths) { m_prototypePaths = prototypePaths; }
897 Path addPrototypePath(const Path &prototypePath)
898 {
899 index_type idx = index_type(m_prototypePaths.indexOf(t: prototypePath));
900 if (idx == -1) {
901 idx = index_type(m_prototypePaths.size());
902 m_prototypePaths.append(t: prototypePath);
903 }
904 return Path::fromField(s: Fields::prototypes).withIndex(i: idx);
905 }
906 void setNextScopePath(const Path &nextScopePath) { m_nextScopePath = nextScopePath; }
907 void setPropertyDefs(QMultiMap<QString, PropertyDefinition> propertyDefs)
908 {
909 m_propertyDefs = propertyDefs;
910 }
911 void setBindings(QMultiMap<QString, Binding> bindings) { m_bindings = bindings; }
912 void setMethods(QMultiMap<QString, MethodInfo> functionDefs) { m_methods = functionDefs; }
913 void setChildren(const QList<QmlObject> &children)
914 {
915 m_children = children;
916 if (pathFromOwner())
917 updatePathFromOwner(newPath: pathFromOwner());
918 }
919 void setAnnotations(const QList<QmlObject> &annotations)
920 {
921 m_annotations = annotations;
922 if (pathFromOwner())
923 updatePathFromOwner(newPath: pathFromOwner());
924 }
925 Path addPropertyDef(const PropertyDefinition &propertyDef, AddOption option,
926 PropertyDefinition **pDef = nullptr)
927 {
928 return insertUpdatableElementInMultiMap(mapPathFromOwner: pathFromOwner().withField(name: Fields::propertyDefs),
929 mmap&: m_propertyDefs, key: propertyDef.name, value: propertyDef,
930 option, valuePtr: pDef);
931 }
932 MutableDomItem addPropertyDef(MutableDomItem &self, const PropertyDefinition &propertyDef,
933 AddOption option);
934
935 Path addBinding(Binding binding, AddOption option, Binding **bPtr = nullptr)
936 {
937 return insertUpdatableElementInMultiMap(mapPathFromOwner: pathFromOwner().withField(name: Fields::bindings), mmap&: m_bindings,
938 key: binding.name(), value: binding, option, valuePtr: bPtr);
939 }
940 MutableDomItem addBinding(MutableDomItem &self, Binding binding, AddOption option);
941 Path addMethod(const MethodInfo &functionDef, AddOption option, MethodInfo **mPtr = nullptr)
942 {
943 return insertUpdatableElementInMultiMap(mapPathFromOwner: pathFromOwner().withField(name: Fields::methods), mmap&: m_methods,
944 key: functionDef.name, value: functionDef, option, valuePtr: mPtr);
945 }
946 MutableDomItem addMethod(MutableDomItem &self, const MethodInfo &functionDef, AddOption option);
947 Path addChild(QmlObject child, QmlObject **cPtr = nullptr)
948 {
949 return appendUpdatableElementInQList(listPathFromOwner: pathFromOwner().withField(name: Fields::children), list&: m_children,
950 value: child, vPtr: cPtr);
951 }
952 MutableDomItem addChild(MutableDomItem &self, QmlObject child)
953 {
954 Path p = addChild(child);
955 return MutableDomItem(self.owner().item(), p);
956 }
957 Path addAnnotation(const QmlObject &annotation, QmlObject **aPtr = nullptr)
958 {
959 return appendUpdatableElementInQList(listPathFromOwner: pathFromOwner().withField(name: Fields::annotations),
960 list&: m_annotations, value: annotation, vPtr: aPtr);
961 }
962
963 QList<std::pair<SourceLocation, DomItem>> orderOfAttributes(const DomItem &self,
964 const DomItem &component) const;
965 void writeOutAttributes(const DomItem &self, OutWriter &ow, const DomItem &component,
966 const QString &code) const;
967
968 void writeOutSortedEnumerations(const DomItem &component, OutWriter &ow) const;
969 void writeOutSortedAttributes(const DomItem &self, OutWriter &ow,
970 const DomItem &component) const;
971 void writeOutSortedPropertyDefinition(const DomItem &self, OutWriter &ow,
972 QSet<QString> &mergedDefBinding) const;
973
974 void writeOutId(const DomItem &self, OutWriter &ow) const;
975 void writeOut(const DomItem &self, OutWriter &ow, const QString &onTarget) const;
976 void writeOut(const DomItem &self, OutWriter &lw) const override { writeOut(self, ow&: lw, onTarget: QString()); }
977
978 LocallyResolvedAlias resolveAlias(const DomItem &self,
979 std::shared_ptr<ScriptExpression> accessSequence) const;
980 LocallyResolvedAlias resolveAlias(const DomItem &self, const QStringList &accessSequence) const;
981
982 QQmlJSScope::ConstPtr semanticScope() const { return m_scope; }
983 void setSemanticScope(const QQmlJSScope::ConstPtr &scope) { m_scope = scope; }
984
985 ScriptElementVariant nameIdentifiers() const { return m_nameIdentifiers; }
986 void setNameIdentifiers(const ScriptElementVariant &name) { m_nameIdentifiers = name; }
987
988private:
989 friend class QQmlDomAstCreator;
990 QString m_idStr;
991 QString m_name;
992 QList<Path> m_prototypePaths;
993 Path m_nextScopePath;
994 QString m_defaultPropertyName;
995 QMultiMap<QString, PropertyDefinition> m_propertyDefs;
996 QMultiMap<QString, Binding> m_bindings;
997 QMultiMap<QString, MethodInfo> m_methods;
998 QList<QmlObject> m_children;
999 QList<QmlObject> m_annotations;
1000 QQmlJSScope::ConstPtr m_scope;
1001 ScriptElementVariant m_nameIdentifiers;
1002
1003 static constexpr quint32 posOfNewElements = std::numeric_limits<quint32>::max();
1004};
1005
1006class Export
1007{
1008 Q_DECLARE_TR_FUNCTIONS(Export)
1009public:
1010 constexpr static DomType kindValue = DomType::Export;
1011 static Export fromString(
1012 const Path &source, QStringView exp, const Path &typePath, const ErrorHandler &h);
1013 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
1014 {
1015 bool cont = true;
1016 cont = cont && self.dvValueField(visitor, f: Fields::uri, value: uri);
1017 cont = cont && self.dvValueField(visitor, f: Fields::typeName, value: typeName);
1018 cont = cont && self.dvWrapField(visitor, f: Fields::version, obj: version);
1019 if (typePath)
1020 cont = cont && self.dvReferenceField(visitor, f: Fields::type, referencedObject: typePath);
1021 cont = cont && self.dvValueField(visitor, f: Fields::isInternal, value: isInternal);
1022 cont = cont && self.dvValueField(visitor, f: Fields::isSingleton, value: isSingleton);
1023 if (exportSourcePath)
1024 cont = cont && self.dvReferenceField(visitor, f: Fields::exportSource, referencedObject: exportSourcePath);
1025 return cont;
1026 }
1027
1028 Path exportSourcePath;
1029 QString uri;
1030 QString typeName;
1031 Version version;
1032 Path typePath;
1033 bool isInternal = false;
1034 bool isSingleton = false;
1035};
1036
1037class QMLDOM_EXPORT Component : public CommentableDomElement
1038{
1039public:
1040 Component(const QString &name);
1041 Component(const Path &pathFromOwner = Path());
1042 Component(const Component &o) = default;
1043 Component &operator=(const Component &) = default;
1044
1045 bool iterateDirectSubpaths(const DomItem &, DirectVisitor) const override;
1046 void updatePathFromOwner(const Path &newPath) override;
1047 DomItem field(const DomItem &self, QStringView name) const override;
1048
1049 QString name() const { return m_name; }
1050 const QMultiMap<QString, EnumDecl> &enumerations() const & { return m_enumerations; }
1051 const QList<QmlObject> &objects() const & { return m_objects; }
1052 bool isSingleton() const { return m_isSingleton; }
1053 bool isCreatable() const { return m_isCreatable; }
1054 bool isComposite() const { return m_isComposite; }
1055 QString attachedTypeName() const { return m_attachedTypeName; }
1056 Path attachedTypePath(const DomItem &) const { return m_attachedTypePath; }
1057
1058 void setName(const QString &name) { m_name = name; }
1059 void setEnumerations(QMultiMap<QString, EnumDecl> enumerations)
1060 {
1061 m_enumerations = enumerations;
1062 }
1063 Path addEnumeration(const EnumDecl &enumeration, AddOption option = AddOption::Overwrite,
1064 EnumDecl **ePtr = nullptr)
1065 {
1066 return insertUpdatableElementInMultiMap(mapPathFromOwner: pathFromOwner().withField(name: Fields::enumerations),
1067 mmap&: m_enumerations, key: enumeration.name(), value: enumeration,
1068 option, valuePtr: ePtr);
1069 }
1070 void setObjects(const QList<QmlObject> &objects) { m_objects = objects; }
1071 Path addObject(const QmlObject &object, QmlObject **oPtr = nullptr);
1072 void setIsSingleton(bool isSingleton) { m_isSingleton = isSingleton; }
1073 void setIsCreatable(bool isCreatable) { m_isCreatable = isCreatable; }
1074 void setIsComposite(bool isComposite) { m_isComposite = isComposite; }
1075 void setAttachedTypeName(const QString &name) { m_attachedTypeName = name; }
1076 void setAttachedTypePath(const Path &p) { m_attachedTypePath = p; }
1077
1078private:
1079 friend class QQmlDomAstCreator;
1080 QString m_name;
1081 QMultiMap<QString, EnumDecl> m_enumerations;
1082 QList<QmlObject> m_objects;
1083 bool m_isSingleton = false;
1084 bool m_isCreatable = true;
1085 bool m_isComposite = true;
1086 QString m_attachedTypeName;
1087 Path m_attachedTypePath;
1088};
1089
1090class QMLDOM_EXPORT JsResource final : public Component
1091{
1092public:
1093 constexpr static DomType kindValue = DomType::JsResource;
1094 DomType kind() const override { return kindValue; }
1095
1096 JsResource(const Path &pathFromOwner = Path()) : Component(pathFromOwner) { }
1097 bool iterateDirectSubpaths(const DomItem &, DirectVisitor) const override
1098 { // to do: complete
1099 return true;
1100 }
1101 // globalSymbols defined/exported, required/used
1102};
1103
1104class QMLDOM_EXPORT QmltypesComponent final : public Component
1105{
1106public:
1107 constexpr static DomType kindValue = DomType::QmltypesComponent;
1108 DomType kind() const override { return kindValue; }
1109
1110 QmltypesComponent(const Path &pathFromOwner = Path()) : Component(pathFromOwner) { }
1111 bool iterateDirectSubpaths(const DomItem &, DirectVisitor) const override;
1112 const QList<Export> &exports() const & { return m_exports; }
1113 QString fileName() const { return m_fileName; }
1114 void setExports(QList<Export> exports) { m_exports = exports; }
1115 void addExport(const Export &exportedEntry) { m_exports.append(t: exportedEntry); }
1116 void setFileName(const QString &fileName) { m_fileName = fileName; }
1117 const QList<int> &metaRevisions() const & { return m_metaRevisions; }
1118 void setMetaRevisions(QList<int> metaRevisions) { m_metaRevisions = metaRevisions; }
1119 void setInterfaceNames(const QStringList& interfaces) { m_interfaceNames = interfaces; }
1120 const QStringList &interfaceNames() const & { return m_interfaceNames; }
1121 QString extensionTypeName() const { return m_extensionTypeName; }
1122 void setExtensionTypeName(const QString &name) { m_extensionTypeName = name; }
1123 QString valueTypeName() const { return m_valueTypeName; }
1124 void setValueTypeName(const QString &name) { m_valueTypeName = name; }
1125 bool hasCustomParser() const { return m_hasCustomParser; }
1126 void setHasCustomParser(bool v) { m_hasCustomParser = v; }
1127 bool extensionIsJavaScript() const { return m_extensionIsJavaScript; }
1128 void setExtensionIsJavaScript(bool v) { m_extensionIsJavaScript = v; }
1129 bool extensionIsNamespace() const { return m_extensionIsNamespace; }
1130 void setExtensionIsNamespace(bool v) { m_extensionIsNamespace = v; }
1131 QQmlJSScope::AccessSemantics accessSemantics() const { return m_accessSemantics; }
1132 void setAccessSemantics(QQmlJSScope::AccessSemantics v) { m_accessSemantics = v; }
1133
1134 void setSemanticScope(const QQmlJSScope::ConstPtr &scope) { m_semanticScope = scope; }
1135 QQmlJSScope::ConstPtr semanticScope() const { return m_semanticScope; }
1136
1137private:
1138 QList<Export> m_exports;
1139 QList<int> m_metaRevisions;
1140 QString m_fileName; // remove?
1141 QStringList m_interfaceNames;
1142 bool m_hasCustomParser = false;
1143 bool m_extensionIsJavaScript = false;
1144 bool m_extensionIsNamespace = false;
1145 QString m_valueTypeName;
1146 QString m_extensionTypeName;
1147 QQmlJSScope::AccessSemantics m_accessSemantics = QQmlJSScope::AccessSemantics::None;
1148 QQmlJSScope::ConstPtr m_semanticScope;
1149};
1150
1151class QMLDOM_EXPORT QmlComponent final : public Component
1152{
1153public:
1154 constexpr static DomType kindValue = DomType::QmlComponent;
1155 DomType kind() const override { return kindValue; }
1156
1157 QmlComponent(const QString &name = QString()) : Component(name)
1158 {
1159 setIsComposite(true);
1160 setIsCreatable(true);
1161 }
1162
1163 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
1164
1165 const QMultiMap<QString, Id> &ids() const & { return m_ids; }
1166 Path nextComponentPath() const { return m_nextComponentPath; }
1167 void setIds(QMultiMap<QString, Id> ids) { m_ids = ids; }
1168 void setNextComponentPath(const Path &p) { m_nextComponentPath = p; }
1169 void updatePathFromOwner(const Path &newPath) override;
1170 Path addId(const Id &id, AddOption option = AddOption::Overwrite, Id **idPtr = nullptr)
1171 {
1172 // warning does nor remove old idStr when overwriting...
1173 return insertUpdatableElementInMultiMap(mapPathFromOwner: pathFromOwner().withField(name: Fields::ids), mmap&: m_ids, key: id.name,
1174 value: id, option, valuePtr: idPtr);
1175 }
1176 void writeOut(const DomItem &self, OutWriter &) const override;
1177 QList<QString> subComponentsNames(const DomItem &self) const;
1178 QList<DomItem> subComponents(const DomItem &self) const;
1179
1180 void setSemanticScope(const QQmlJSScope::ConstPtr &scope) { m_semanticScope = scope; }
1181 QQmlJSScope::ConstPtr semanticScope() const { return m_semanticScope; }
1182 ScriptElementVariant nameIdentifiers() const { return m_nameIdentifiers; }
1183 void setNameIdentifiers(const ScriptElementVariant &name) { m_nameIdentifiers = name; }
1184
1185private:
1186 friend class QQmlDomAstCreator;
1187 Path m_nextComponentPath;
1188 QMultiMap<QString, Id> m_ids;
1189 QQmlJSScope::ConstPtr m_semanticScope;
1190 // m_nameIdentifiers contains the name of the component as FieldMemberExpression, and therefore
1191 // only exists in inline components!
1192 ScriptElementVariant m_nameIdentifiers;
1193};
1194
1195class QMLDOM_EXPORT GlobalComponent final : public Component
1196{
1197public:
1198 constexpr static DomType kindValue = DomType::GlobalComponent;
1199 DomType kind() const override { return kindValue; }
1200
1201 GlobalComponent(const Path &pathFromOwner = Path()) : Component(pathFromOwner) { }
1202};
1203
1204static ErrorGroups importErrors = { .groups: { DomItem::domErrorGroup, NewErrorGroup("importError") } };
1205
1206class QMLDOM_EXPORT ImportScope
1207{
1208 Q_DECLARE_TR_FUNCTIONS(ImportScope)
1209public:
1210 constexpr static DomType kindValue = DomType::ImportScope;
1211
1212 ImportScope() = default;
1213
1214 const QList<Path> &importSourcePaths() const & { return m_importSourcePaths; }
1215
1216 const QMap<QString, ImportScope> &subImports() const & { return m_subImports; }
1217
1218 QList<Path> allSources(const DomItem &self) const;
1219
1220 QSet<QString> importedNames(const DomItem &self) const
1221 {
1222 QSet<QString> res;
1223 const auto sources = allSources(self);
1224 for (const Path &p : sources) {
1225 QSet<QString> ks = self.path(p: p.withField(name: Fields::exports), h: self.errorHandler()).keys();
1226 res += ks;
1227 }
1228 return res;
1229 }
1230
1231 QList<DomItem> importedItemsWithName(const DomItem &self, const QString &name) const
1232 {
1233 QList<DomItem> res;
1234 const auto sources = allSources(self);
1235 for (const Path &p : sources) {
1236 DomItem source = self.path(p: p.withField(name: Fields::exports), h: self.errorHandler());
1237 DomItem els = source.key(name);
1238 int nEls = els.indexes();
1239 for (int i = 0; i < nEls; ++i)
1240 res.append(t: els.index(i));
1241 if (nEls == 0 && els) {
1242 self.addError(msg: importErrors.warning(
1243 message: tr(sourceText: "Looking up '%1' expected a list of exports, not %2")
1244 .arg(args: name, args: els.toString())));
1245 }
1246 }
1247 return res;
1248 }
1249
1250 QList<Export> importedExportsWithName(const DomItem &self, const QString &name) const
1251 {
1252 QList<Export> res;
1253 for (const DomItem &i : importedItemsWithName(self, name))
1254 if (const Export *e = i.as<Export>())
1255 res.append(t: *e);
1256 else
1257 self.addError(msg: importErrors.warning(
1258 message: tr(sourceText: "Expected Export looking up '%1', not %2").arg(args: name, args: i.toString())));
1259 return res;
1260 }
1261
1262 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const;
1263
1264 void addImport(QStringList p, const Path &targetExports)
1265 {
1266 if (!p.isEmpty()) {
1267 const QString current = p.takeFirst();
1268 m_subImports[current].addImport(p: std::move(p), targetExports);
1269 } else if (!m_importSourcePaths.contains(t: targetExports)) {
1270 m_importSourcePaths.append(t: targetExports);
1271 }
1272 }
1273
1274private:
1275 QList<Path> m_importSourcePaths;
1276 QMap<QString, ImportScope> m_subImports;
1277};
1278
1279class BindingValue
1280{
1281public:
1282 BindingValue();
1283 BindingValue(const QmlObject &o);
1284 BindingValue(const std::shared_ptr<ScriptExpression> &o);
1285 BindingValue(const QList<QmlObject> &l);
1286 ~BindingValue();
1287 BindingValue(const BindingValue &o);
1288 BindingValue &operator=(const BindingValue &o);
1289
1290 DomItem value(const DomItem &binding) const;
1291 void updatePathFromOwner(const Path &newPath);
1292
1293private:
1294 friend class Binding;
1295 void clearValue();
1296
1297 BindingValueKind kind;
1298 union {
1299 int dummy;
1300 QmlObject object;
1301 std::shared_ptr<ScriptExpression> scriptExpression;
1302 QList<QmlObject> array;
1303 };
1304};
1305
1306} // end namespace Dom
1307} // end namespace QQmlJS
1308QT_END_NAMESPACE
1309#endif // QQMLDOMELEMENTS_P_H
1310

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