Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmldomitem_p.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QMLDOMITEM_H
5#define QMLDOMITEM_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 "qqmldom_global.h"
19#include "qqmldom_fwd_p.h"
23#include "qqmldompath_p.h"
29
30#include <QtCore/QMap>
31#include <QtCore/QMultiMap>
32#include <QtCore/QSet>
33#include <QtCore/QString>
34#include <QtCore/QStringView>
35#include <QtCore/QDebug>
36#include <QtCore/QDateTime>
37#include <QtCore/QMutex>
38#include <QtCore/QCborValue>
39#include <QtCore/QTimeZone>
40#include <QtQml/private/qqmljssourcelocation_p.h>
41#include <QtQmlCompiler/private/qqmljsscope_p.h>
42
43#include <memory>
44#include <typeinfo>
45#include <utility>
46#include <type_traits>
47#include <variant>
48#include <optional>
49#include <cstddef>
50
51QT_BEGIN_NAMESPACE
52
53QT_ENABLE_P0846_SEMANTICS_FOR(get_if)
54
55QT_DECLARE_EXPORTED_QT_LOGGING_CATEGORY(writeOutLog, QMLDOM_EXPORT);
56
57namespace QQmlJS {
58// we didn't have enough 'O's to properly name everything...
59namespace Dom {
60
61class Path;
62
63constexpr bool domTypeIsObjWrap(DomType k);
64constexpr bool domTypeIsValueWrap(DomType k);
65constexpr bool domTypeIsDomElement(DomType);
66constexpr bool domTypeIsOwningItem(DomType);
68constexpr bool domTypeIsScriptElement(DomType);
72constexpr bool domTypeCanBeInline(DomType k)
73{
74 switch (k) {
75 case DomType::Empty:
76 case DomType::Map:
77 case DomType::List:
78 case DomType::ListP:
83 return true;
84 default:
85 return false;
86 }
87}
89
94
95inline bool noFilter(const DomItem &, const PathEls::PathComponent &, const DomItem &)
96{
97 return true;
98}
99
101// using DirectVisitor = function_ref<bool(Path, const DomItem &)>;
102
103namespace {
104template<typename T>
105struct IsMultiMap : std::false_type
106{
107};
108
109template<typename Key, typename T>
110struct IsMultiMap<QMultiMap<Key, T>> : std::true_type
111{
112};
113
114template<typename T>
115struct IsMap : std::false_type
116{
117};
118
119template<typename Key, typename T>
120struct IsMap<QMap<Key, T>> : std::true_type
121{
122};
123
124template<typename... Ts>
125using void_t = void;
126
127template<typename T, typename = void>
128struct IsDomObject : std::false_type
129{
130};
131
132template<typename T>
133struct IsDomObject<T, void_t<decltype(T::kindValue)>> : std::true_type
134{
135};
136
137template<typename T, typename = void>
138struct IsInlineDom : std::false_type
139{
140};
141
142template<typename T>
143struct IsInlineDom<T, void_t<decltype(T::kindValue)>>
144 : std::integral_constant<bool, domTypeCanBeInline(T::kindValue)>
145{
146};
147
148template<typename T>
149struct IsInlineDom<T *, void_t<decltype(T::kindValue)>> : std::true_type
150{
151};
152
153template<typename T>
154struct IsInlineDom<std::shared_ptr<T>, void_t<decltype(T::kindValue)>> : std::true_type
155{
156};
157
158template<typename T>
159struct IsSharedPointerToDomObject : std::false_type
160{
161};
162
163template<typename T>
164struct IsSharedPointerToDomObject<std::shared_ptr<T>> : IsDomObject<T>
165{
166};
167
168template<typename T, typename = void>
169struct IsList : std::false_type
170{
171};
172
173template<typename T>
174struct IsList<T, void_t<typename T::value_type>> : std::true_type
175{
176};
177
178}
179
180template<typename T>
182 int i;
183 T lp;
184
185 // TODO: these are extremely nasty. What is this int doing in here?
186 T *data() { return reinterpret_cast<T *>(this); }
187 const T *data() const { return reinterpret_cast<const T *>(this); }
188
190 SubclassStorage(T &&el) { el.moveTo(data()); }
191 SubclassStorage(const T *el) { el->copyTo(data()); }
195 {
196 data()->~T();
197 o.data()->copyTo(data());
198 return *this;
199 }
200 ~SubclassStorage() { data()->~T(); }
201};
202
204{
205public:
206 using FilterT = function_ref<bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)>;
207
208 virtual ~DomBase() = default;
209
210 DomBase *domBase() { return this; }
211 const DomBase *domBase() const { return this; }
212
213 // minimal overload set:
214 virtual DomType kind() const = 0;
215 virtual DomKind domKind() const;
216 virtual Path pathFromOwner() const = 0;
217 virtual Path canonicalPath(const DomItem &self) const = 0;
218 virtual bool
220 DirectVisitor visitor) const = 0; // iterates the *direct* subpaths, returns
221 // false if a quick end was requested
222
224 const DomItem &self) const; // the DomItem corresponding to the canonicalSource source
225 virtual void dump(const DomItem &, const Sink &sink, int indent, FilterT filter) const;
226 virtual quintptr id() const;
227 QString typeName() const;
228
229 virtual QList<QString> fields(const DomItem &self) const;
230 virtual DomItem field(const DomItem &self, QStringView name) const;
231
232 virtual index_type indexes(const DomItem &self) const;
233 virtual DomItem index(const DomItem &self, index_type index) const;
234
235 virtual QSet<QString> const keys(const DomItem &self) const;
236 virtual DomItem key(const DomItem &self, const QString &name) const;
237
238 virtual QString canonicalFilePath(const DomItem &self) const;
239
240 virtual void writeOut(const DomItem &self, OutWriter &lw) const;
241
242 virtual QCborValue value() const {
243 return QCborValue();
244 }
245};
246
248{
249 switch (k) {
250 case DomType::Empty:
251 return DomKind::Empty;
252 case DomType::List:
253 case DomType::ListP:
254 return DomKind::List;
255 case DomType::Map:
256 return DomKind::Map;
257 case DomType::ConstantData:
258 return DomKind::Value;
259 default:
260 return DomKind::Object;
261 }
262}
263
264class QMLDOM_EXPORT Empty final : public DomBase
265{
266public:
267 constexpr static DomType kindValue = DomType::Empty;
268 DomType kind() const override { return kindValue; }
269
270 Empty *operator->() { return this; }
271 const Empty *operator->() const { return this; }
272 Empty &operator*() { return *this; }
273 const Empty &operator*() const { return *this; }
274
275 Empty();
276 quintptr id() const override { return ~quintptr(0); }
277 Path pathFromOwner() const override;
278 Path canonicalPath(const DomItem &self) const override;
279 DomItem containingObject(const DomItem &self) const override;
280 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
281 void dump(const DomItem &, const Sink &s, int indent,
282 function_ref<bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)> filter)
283 const override;
284};
285
287protected:
288 DomElement& operator=(const DomElement&) = default;
289public:
290 DomElement(const Path &pathFromOwner = Path());
291 DomElement(const DomElement &o) = default;
292 Path pathFromOwner() const override { return m_pathFromOwner; }
293 Path canonicalPath(const DomItem &self) const override;
294 DomItem containingObject(const DomItem &self) const override;
295 virtual void updatePathFromOwner(const Path &newPath);
296
297private:
298 Path m_pathFromOwner;
299};
300
301class QMLDOM_EXPORT Map final : public DomElement
302{
303public:
304 constexpr static DomType kindValue = DomType::Map;
305 DomType kind() const override { return kindValue; }
306
307 Map *operator->() { return this; }
308 const Map *operator->() const { return this; }
309 Map &operator*() { return *this; }
310 const Map &operator*() const { return *this; }
311
312 using LookupFunction = std::function<DomItem(const DomItem &, QString)>;
313 using Keys = std::function<QSet<QString>(const DomItem &)>;
314 Map(const Path &pathFromOwner, const LookupFunction &lookup,
315 const Keys &keys, const QString &targetType);
316 quintptr id() const override;
317 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
318 QSet<QString> const keys(const DomItem &self) const override;
319 DomItem key(const DomItem &self, const QString &name) const override;
320
321 template<typename T>
322 static Map fromMultiMapRef(const Path &pathFromOwner, const QMultiMap<QString, T> &mmap);
323 template<typename T>
324 static Map fromMultiMap(const Path &pathFromOwner, const QMultiMap<QString, T> &mmap);
325 template<typename T>
326 static Map
328 const Path &pathFromOwner, const QMap<QString, T> &mmap,
329 const std::function<DomItem(const DomItem &, const PathEls::PathComponent &, const T &)> &elWrapper);
330
331 template<typename T>
332 static Map fromFileRegionMap(
333 const Path &pathFromOwner, const QMap<FileLocationRegion, T> &map);
334
335private:
336 template<typename MapT>
337 static QSet<QString> fileRegionKeysFromMap(const MapT &map);
338 LookupFunction m_lookup;
339 Keys m_keys;
340 QString m_targetType;
341};
342
343class QMLDOM_EXPORT List final : public DomElement
344{
345public:
346 constexpr static DomType kindValue = DomType::List;
347 DomType kind() const override { return kindValue; }
348
349 List *operator->() { return this; }
350 const List *operator->() const { return this; }
351 List &operator*() { return *this; }
352 const List &operator*() const { return *this; }
353
354 using LookupFunction = std::function<DomItem(const DomItem &, index_type)>;
357 std::function<bool(const DomItem &, function_ref<bool(index_type, function_ref<DomItem()>)>)>;
358
359 List(const Path &pathFromOwner, const LookupFunction &lookup, const Length &length,
360 const IteratorFunction &iterator, const QString &elType);
361 quintptr id() const override;
362 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
363 void
364 dump(const DomItem &, const Sink &s, int indent,
365 function_ref<bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)>) const override;
366 index_type indexes(const DomItem &self) const override;
367 DomItem index(const DomItem &self, index_type index) const override;
368
369 template<typename T>
370 static List
371 fromQList(const Path &pathFromOwner, const QList<T> &list,
372 const std::function<DomItem(const DomItem &, const PathEls::PathComponent &, const T &)> &elWrapper,
374 template<typename T>
375 static List
376 fromQListRef(const Path &pathFromOwner, const QList<T> &list,
377 const std::function<DomItem(const DomItem &, const PathEls::PathComponent &, const T &)> &elWrapper,
379 void writeOut(const DomItem &self, OutWriter &ow, bool compact) const;
380 void writeOut(const DomItem &self, OutWriter &ow) const override { writeOut(self, ow, true); }
381
382private:
383 LookupFunction m_lookup;
384 Length m_length;
385 IteratorFunction m_iterator;
386 QString m_elType;
387};
388
390{
391public:
392 constexpr static DomType kindValue = DomType::ListP;
393 DomType kind() const override { return kindValue; }
394
395 ListPBase(const Path &pathFromOwner, const QList<const void *> &pList, const QString &elType)
396 : DomElement(pathFromOwner), m_pList(pList), m_elType(elType)
397 {
398 }
399 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor v) const override;
400 virtual void copyTo(ListPBase *) const { Q_ASSERT(false); };
401 virtual void moveTo(ListPBase *) const { Q_ASSERT(false); };
402 quintptr id() const override { return quintptr(0); }
403 index_type indexes(const DomItem &) const override { return index_type(m_pList.size()); }
404 void writeOut(const DomItem &self, OutWriter &ow, bool compact) const;
405 void writeOut(const DomItem &self, OutWriter &ow) const override { writeOut(self, ow, true); }
406
407protected:
408 QList<const void *> m_pList;
410};
411
412template<typename T>
413class ListPT final : public ListPBase
414{
415public:
416 constexpr static DomType kindValue = DomType::ListP;
417
418 ListPT(const Path &pathFromOwner, const QList<T *> &pList, const QString &elType = QString(),
420 : ListPBase(pathFromOwner, {},
421 (elType.isEmpty() ? QLatin1String(typeid(T).name()) : elType))
422 {
423 static_assert(sizeof(ListPBase) == sizeof(ListPT),
424 "ListPT does not have the same size as ListPBase");
425 static_assert(alignof(ListPBase) == alignof(ListPT),
426 "ListPT does not have the same size as ListPBase");
427 m_pList.reserve(pList.size());
428 if (options == ListOptions::Normal) {
429 for (const void *p : pList)
430 m_pList.append(p);
431 } else if (options == ListOptions::Reverse) {
432 for (qsizetype i = pList.size(); i-- != 0;)
433 // probably writing in reverse and reading sequentially would be better
434 m_pList.append(pList.at(i));
435 } else {
436 Q_ASSERT(false);
437 }
438 }
439 void copyTo(ListPBase *t) const override { new (t) ListPT(*this); }
440 void moveTo(ListPBase *t) const override { new (t) ListPT(std::move(*this)); }
441 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor v) const override;
442
443 DomItem index(const DomItem &self, index_type index) const override;
444};
445
447{
448public:
449 constexpr static DomType kindValue = DomType::ListP;
450 template<typename T>
451 ListP(const Path &pathFromOwner, const QList<T *> &pList, const QString &elType = QString(),
454 {
455 }
456 ListP() = delete;
457
458 ListPBase *operator->() { return list.data(); }
459 const ListPBase *operator->() const { return list.data(); }
460 ListPBase &operator*() { return *list.data(); }
461 const ListPBase &operator*() const { return *list.data(); }
462
463private:
465};
466
467class QMLDOM_EXPORT ConstantData final : public DomElement
468{
469public:
471 DomType kind() const override { return kindValue; }
472
477
478 ConstantData *operator->() { return this; }
479 const ConstantData *operator->() const { return this; }
480 ConstantData &operator*() { return *this; }
481 const ConstantData &operator*() const { return *this; }
482
483 ConstantData(const Path &pathFromOwner, const QCborValue &value,
484 Options options = Options::MapIsMap);
485 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
486 quintptr id() const override;
487 DomKind domKind() const override;
488 QCborValue value() const override { return m_value; }
489 Options options() const { return m_options; }
490private:
491 QCborValue m_value;
492 Options m_options;
493};
494
496{
497public:
499 DomType kind() const final override { return m_kind; }
500
501 quintptr id() const final override { return m_id; }
502 DomKind domKind() const final override { return m_domKind; }
503
504 template <typename T>
505 T const *as() const
506 {
507 if (m_options & SimpleWrapOption::ValueType) {
508 if (m_value.metaType() == QMetaType::fromType<T>())
509 return static_cast<const T *>(m_value.constData());
510 return nullptr;
511 } else {
512 return m_value.value<const T *>();
513 }
514 }
515
517 virtual void copyTo(SimpleObjectWrapBase *) const { Q_ASSERT(false); }
518 virtual void moveTo(SimpleObjectWrapBase *) const { Q_ASSERT(false); }
519 bool iterateDirectSubpaths(const DomItem &, DirectVisitor) const override
520 {
521 Q_ASSERT(false);
522 return true;
523 }
524
525protected:
526 friend class TestDomItem;
527 SimpleObjectWrapBase(const Path &pathFromOwner, const QVariant &value, quintptr idValue,
528 DomType kind = kindValue,
529 SimpleWrapOptions options = SimpleWrapOption::None)
530 : DomElement(pathFromOwner),
531 m_kind(kind),
533 m_value(value),
534 m_id(idValue),
536 {
537 }
538
544};
545
546template<typename T>
547class SimpleObjectWrapT final : public SimpleObjectWrapBase
548{
549public:
551
552 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const override
553 {
554 return asT()->iterateDirectSubpaths(self, visitor);
555 }
556
557 void writeOut(const DomItem &self, OutWriter &lw) const override;
558
559 const T *asT() const
560 {
561 if constexpr (domTypeIsValueWrap(T::kindValue)) {
562 if (m_value.metaType() == QMetaType::fromType<T>())
563 return static_cast<const T *>(m_value.constData());
564 return nullptr;
565 } else if constexpr (domTypeIsObjWrap(T::kindValue)) {
566 return m_value.value<const T *>();
567 } else {
568 // need dependent static assert to not unconditially trigger
569 static_assert(!std::is_same_v<T, T>, "wrapping of unexpected type");
570 return nullptr; // necessary to avoid warnings on INTEGRITY
571 }
572 }
573
574 void copyTo(SimpleObjectWrapBase *target) const override
575 {
576 static_assert(sizeof(SimpleObjectWrapBase) == sizeof(SimpleObjectWrapT),
577 "Size mismatch in SimpleObjectWrapT");
578 static_assert(alignof(SimpleObjectWrapBase) == alignof(SimpleObjectWrapT),
579 "Size mismatch in SimpleObjectWrapT");
580 new (target) SimpleObjectWrapT(*this);
581 }
582
583 void moveTo(SimpleObjectWrapBase *target) const override
584 {
585 static_assert(sizeof(SimpleObjectWrapBase) == sizeof(SimpleObjectWrapT),
586 "Size mismatch in SimpleObjectWrapT");
587 static_assert(alignof(SimpleObjectWrapBase) == alignof(SimpleObjectWrapT),
588 "Size mismatch in SimpleObjectWrapT");
589 new (target) SimpleObjectWrapT(std::move(*this));
590 }
591
592 SimpleObjectWrapT(const Path &pathFromOwner, const QVariant &v,
593 quintptr idValue, SimpleWrapOptions o)
594 : SimpleObjectWrapBase(pathFromOwner, v, idValue, T::kindValue, o)
595 {
596 Q_ASSERT(domTypeIsValueWrap(T::kindValue) == bool(o & SimpleWrapOption::ValueType));
597 }
598};
599
601{
602public:
604
605 SimpleObjectWrapBase *operator->() { return wrap.data(); }
606 const SimpleObjectWrapBase *operator->() const { return wrap.data(); }
607 SimpleObjectWrapBase &operator*() { return *wrap.data(); }
608 const SimpleObjectWrapBase &operator*() const { return *wrap.data(); }
609
610 template<typename T>
611 static SimpleObjectWrap fromObjectRef(const Path &pathFromOwner, T &value)
612 {
613 return SimpleObjectWrap(pathFromOwner, value);
614 }
616
617private:
618 template<typename T>
619 SimpleObjectWrap(const Path &pathFromOwner, T &value)
620 {
621 using BaseT = std::decay_t<T>;
622 if constexpr (domTypeIsObjWrap(BaseT::kindValue)) {
623 new (wrap.data()) SimpleObjectWrapT<BaseT>(pathFromOwner, QVariant::fromValue(&value),
624 quintptr(&value), SimpleWrapOption::None);
625 } else if constexpr (domTypeIsValueWrap(BaseT::kindValue)) {
626 new (wrap.data()) SimpleObjectWrapT<BaseT>(pathFromOwner, QVariant::fromValue(value),
627 quintptr(0), SimpleWrapOption::ValueType);
628 } else {
629 qCWarning(domLog) << "Unexpected object to wrap in SimpleObjectWrap: "
630 << domTypeToString(BaseT::kindValue);
631 Q_ASSERT_X(false, "SimpleObjectWrap",
632 "simple wrap of unexpected object"); // allow? (mocks for testing,...)
633 new (wrap.data())
634 SimpleObjectWrapT<BaseT>(pathFromOwner, nullptr, 0, SimpleWrapOption::None);
635 }
636 }
638};
639
641{
643public:
644 constexpr static DomType kindValue = DomType::Reference;
645 DomType kind() const override { return kindValue; }
646
647 Reference *operator->() { return this; }
648 const Reference *operator->() const { return this; }
649 Reference &operator*() { return *this; }
650 const Reference &operator*() const { return *this; }
651
652 bool shouldCache() const;
653 Reference(const Path &referredObject = Path(), const Path &pathFromOwner = Path(),
654 const SourceLocation &loc = SourceLocation());
655 quintptr id() const override;
656 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
657 DomItem field(const DomItem &self, QStringView name) const override;
658 QList<QString> fields(const DomItem &self) const override;
659 index_type indexes(const DomItem &) const override { return 0; }
660 DomItem index(const DomItem &, index_type) const override;
661 QSet<QString> const keys(const DomItem &) const override { return {}; }
662 DomItem key(const DomItem &, const QString &) const override;
663
664 DomItem get(const DomItem &self, const ErrorHandler &h = nullptr,
665 QList<Path> *visitedRefs = nullptr) const;
666 QList<DomItem> getAll(const DomItem &self, const ErrorHandler &h = nullptr,
667 QList<Path> *visitedRefs = nullptr) const;
668
670};
671
672namespace FileLocations {
673struct Info;
674}
675
676/*!
677 \internal
678 \brief A common base class for all the script elements.
679
680 This marker class allows to use all the script elements as a ScriptElement*, using virtual
681 dispatch. For now, it does not add any extra functionality, compared to a DomElement, but allows
682 to forbid DomElement* at the places where only script elements are required.
683 */
684// TODO: do we need another marker struct like this one to differentiate expressions from
685// statements? This would allow to avoid mismatchs between script expressions and script statements,
686// using type-safety.
688{
689 template<typename T>
690 using PointerType = std::shared_ptr<T>;
691
692 using DomElement::DomElement;
693 virtual void
694 createFileLocations(const std::shared_ptr<FileLocations::Node> &fileLocationOfOwner) = 0;
695
697 void setSemanticScope(const QQmlJSScope::ConstPtr &scope);
698
699private:
700 QQmlJSScope::ConstPtr m_scope;
701};
702
703/*!
704 \internal
705 \brief Use this to contain any script element.
706 */
708{
709private:
710 template<typename... T>
712
713 template<typename T, typename Variant>
714 struct TypeIsInVariant;
715
716 template<typename T, typename... Ts>
717 struct TypeIsInVariant<T, std::variant<Ts...>> : public std::disjunction<std::is_same<T, Ts>...>
718 {
719 };
720
721public:
728
729 template<typename T>
730 static ScriptElementVariant fromElement(const T &element)
731 {
732 static_assert(TypeIsInVariant<T, ScriptElementT>::value,
733 "Cannot construct ScriptElementVariant from T, as it is missing from the "
734 "ScriptElementT.");
736 p.m_data = element;
737 return p;
738 }
739
741
742 operator bool() const { return m_data.has_value(); }
743
744 template<typename F>
745 void visitConst(F &&visitor) const
746 {
747 if (m_data)
748 std::visit(std::forward<F>(visitor), *m_data);
749 }
750
751 template<typename F>
752 void visit(F &&visitor)
753 {
754 if (m_data)
755 std::visit(std::forward<F>(visitor), *m_data);
756 }
757 std::optional<ScriptElementT> data() { return m_data; }
758 void setData(const ScriptElementT &data) { m_data = data; }
759
760private:
761 std::optional<ScriptElementT> m_data;
762};
763
764/*!
765 \internal
766
767 To avoid cluttering the already unwieldy \l ElementT type below with all the types that the
768 different script elements can have, wrap them in an extra class. It will behave like an internal
769 Dom structure (e.g. like a List or a Map) and contain a pointer the the script element.
770 */
772{
773public:
775
777
778 DomBase *operator->() { return m_element.base().get(); }
779 const DomBase *operator->() const { return m_element.base().get(); }
780 DomBase &operator*() { return *m_element.base(); }
781 const DomBase &operator*() const { return *m_element.base(); }
782
783 ScriptElementVariant element() const { return m_element; }
784
785private:
786 ScriptElementVariant m_element;
787};
788
789// TODO: create more "groups" to simplify this variant? Maybe into Internal, ScriptExpression, ???
790using ElementT =
791 std::variant<ConstantData, Empty, List, ListP, Map, Reference, ScriptElementDomWrapper,
793 const DomEnvironment *, const DomUniverse *, const EnumDecl *,
795 const GlobalComponent *, const JsFile *, const JsResource *, const LoadInfo *,
796 const MockObject *, const MockOwner *, const QmlComponent *, const QmlFile *,
797 const QmlObject *, const ScriptExpression *>;
798
799using TopT = std::variant<
800 std::monostate,
801 std::shared_ptr<DomEnvironment>,
802 std::shared_ptr<DomUniverse>>;
803
804using OwnerT =
805 std::variant<std::monostate, std::shared_ptr<MockOwner>,
806 std::shared_ptr<ExternalItemInfoBase>, std::shared_ptr<ExternalItemPairBase>,
807 std::shared_ptr<JsFile>, std::shared_ptr<QmlFile>,
808 std::shared_ptr<ScriptExpression>, std::shared_ptr<AstComments>,
809 std::shared_ptr<LoadInfo>, std::shared_ptr<FileLocations::Node>,
810 std::shared_ptr<DomEnvironment>, std::shared_ptr<DomUniverse>>;
811
812inline bool emptyChildrenVisitor(Path, const DomItem &, bool)
813{
814 return true;
815}
816
817class MutableDomItem;
818
820{
821public:
827
828 FileToLoad(const std::weak_ptr<DomEnvironment> &environment, const QString &canonicalPath,
829 const QString &logicalPath, const std::optional<InMemoryContents> &content);
830 FileToLoad() = default;
831
832 static FileToLoad fromMemory(const std::weak_ptr<DomEnvironment> &environment,
833 const QString &path, const QString &data);
834 static FileToLoad fromFileSystem(const std::weak_ptr<DomEnvironment> &environment,
835 const QString &canonicalPath);
836
837 std::shared_ptr<DomEnvironment> environment() const { return m_environment.lock(); }
838 QString canonicalPath() const { return m_canonicalPath; }
839 QString logicalPath() const { return m_logicalPath; }
840 void setCanonicalPath(const QString &canonicalPath) { m_canonicalPath = canonicalPath; }
841 void setLogicalPath(const QString &logicalPath) { m_logicalPath = logicalPath; }
842 std::optional<InMemoryContents> content() const { return m_content; }
843
844private:
845 std::weak_ptr<DomEnvironment> m_environment;
846 QString m_canonicalPath;
847 QString m_logicalPath;
848 std::optional<InMemoryContents> m_content;
849};
850
853public:
854 using Callback = std::function<void(const Path &, const DomItem &, const DomItem &)>;
855
857 using Visitor = function_ref<bool(const Path &, const DomItem &)>;
858 using ChildrenVisitor = function_ref<bool(const Path &, const DomItem &, bool)>;
859
861 static ErrorGroups myErrors();
864
866
867 template<typename F>
868 auto visitEl(F f) const
869 {
870 return std::visit(f, this->m_element);
871 }
872
873 explicit operator bool() const { return m_kind != DomType::Empty; }
875 return m_kind;
876 }
877 QString internalKindStr() const { return domTypeToString(internalKind()); }
879 {
880 if (m_kind == DomType::ConstantData)
881 return std::get<ConstantData>(m_element).domKind();
882 else
883 return kind2domKind(m_kind);
884 }
885
886 Path canonicalPath() const;
887
888 DomItem filterUp(function_ref<bool(DomType k, const DomItem &)> filter, FilterUpOptions options) const;
890 DomItem container() const;
891 DomItem owner() const;
892 DomItem top() const;
893 DomItem environment() const;
894 DomItem universe() const;
895 DomItem containingFile() const;
897 DomItem goToFile(const QString &filePath) const;
898 DomItem goUp(int) const;
899 DomItem directParent() const;
900
901 DomItem qmlObject(GoTo option = GoTo::Strict,
903 DomItem fileObject(GoTo option = GoTo::Strict) const;
904 DomItem rootQmlObject(GoTo option = GoTo::Strict) const;
905 DomItem component(GoTo option = GoTo::Strict) const;
909
910 // convenience getters
911 DomItem get(const ErrorHandler &h = nullptr, QList<Path> *visitedRefs = nullptr) const;
912 QList<DomItem> getAll(const ErrorHandler &h = nullptr, QList<Path> *visitedRefs = nullptr) const;
918 bool isCanonicalChild(const DomItem &child) const;
919 bool hasAnnotations() const;
920 QString name() const { return field(Fields::name).value().toString(); }
921 DomItem pragmas() const { return field(Fields::pragmas); }
922 DomItem ids() const { return field(Fields::ids); }
923 QString idStr() const { return field(Fields::idStr).value().toString(); }
924 DomItem propertyInfos() const { return field(Fields::propertyInfos); }
925 PropertyInfo propertyInfoWithName(const QString &name) const;
927 DomItem propertyDefs() const { return field(Fields::propertyDefs); }
928 DomItem bindings() const { return field(Fields::bindings); }
929 DomItem methods() const { return field(Fields::methods); }
930 DomItem enumerations() const { return field(Fields::enumerations); }
931 DomItem children() const { return field(Fields::children); }
932 DomItem child(index_type i) const { return field(Fields::children).index(i); }
934 {
936 return field(Fields::annotations);
937 else
938 return DomItem();
939 }
940
941 bool resolve(const Path &path, Visitor visitor, const ErrorHandler &errorHandler,
942 ResolveOptions options = ResolveOption::None, const Path &fullPath = Path(),
943 QList<Path> *visitedRefs = nullptr) const;
944
945 DomItem operator[](const Path &path) const;
946 DomItem operator[](QStringView component) const;
947 DomItem operator[](const QString &component) const;
948 DomItem operator[](const char16_t *component) const
949 {
950 return (*this)[QStringView(component)];
951 } // to avoid clash with stupid builtin ptrdiff_t[DomItem&], coming from C
952 DomItem operator[](index_type i) const { return index(i); }
953 DomItem operator[](int i) const { return index(i); }
954 index_type size() const { return indexes() + keys().size(); }
955 index_type length() const { return size(); }
956
957 DomItem path(const Path &p, const ErrorHandler &h = &defaultErrorHandler) const;
958 DomItem path(const QString &p, const ErrorHandler &h = &defaultErrorHandler) const;
959 DomItem path(QStringView p, const ErrorHandler &h = &defaultErrorHandler) const;
960
961 QList<QString> fields() const;
962 DomItem field(QStringView name) const;
963
964 index_type indexes() const;
965 DomItem index(index_type) const;
966 bool visitIndexes(function_ref<bool(const DomItem &)> visitor) const;
967
968 QSet<QString> keys() const;
969 QStringList sortedKeys() const;
970 DomItem key(const QString &name) const;
971 DomItem key(QStringView name) const { return key(name.toString()); }
972 bool visitKeys(function_ref<bool(const QString &, const DomItem &)> visitor) const;
973
974 QList<DomItem> values() const;
975 void writeOutPre(OutWriter &lw) const;
976 void writeOut(OutWriter &lw) const;
977 void writeOutPost(OutWriter &lw) const;
978 bool writeOutForFile(OutWriter &ow, WriteOutChecks extraChecks) const;
979 bool writeOut(const QString &path, const LineWriterOptions &opt = LineWriterOptions(),
980 FileWriter *fw = nullptr,
981 WriteOutChecks extraChecks = WriteOutCheck::Default) const;
982
983 bool visitTree(const Path &basePath, ChildrenVisitor visitor,
984 VisitOptions options = VisitOption::Default,
985 ChildrenVisitor openingVisitor = emptyChildrenVisitor,
986 ChildrenVisitor closingVisitor = emptyChildrenVisitor,
987 const FieldFilter &filter = FieldFilter::noFilter()) const;
988 bool visitPrototypeChain(function_ref<bool(const DomItem &)> visitor,
989 VisitPrototypesOptions options = VisitPrototypesOption::Normal,
990 const ErrorHandler &h = nullptr, QSet<quintptr> *visited = nullptr,
991 QList<Path> *visitedRefs = nullptr) const;
992 bool visitDirectAccessibleScopes(function_ref<bool(const DomItem &)> visitor,
993 VisitPrototypesOptions options = VisitPrototypesOption::Normal,
994 const ErrorHandler &h = nullptr, QSet<quintptr> *visited = nullptr,
995 QList<Path> *visitedRefs = nullptr) const;
996 bool
997 visitStaticTypePrototypeChains(function_ref<bool(const DomItem &)> visitor,
998 VisitPrototypesOptions options = VisitPrototypesOption::Normal,
999 const ErrorHandler &h = nullptr, QSet<quintptr> *visited = nullptr,
1000 QList<Path> *visitedRefs = nullptr) const;
1001
1002 bool visitUp(function_ref<bool(const DomItem &)> visitor) const;
1003 bool visitScopeChain(
1004 function_ref<bool(const DomItem &)> visitor, LookupOptions = LookupOption::Normal,
1005 const ErrorHandler &h = nullptr, QSet<quintptr> *visited = nullptr,
1006 QList<Path> *visitedRefs = nullptr) const;
1008 const QString &name, function_ref<bool(const DomItem &)> visitor) const;
1009 bool visitLookup1(
1010 const QString &symbolName, function_ref<bool(const DomItem &)> visitor,
1011 LookupOptions = LookupOption::Normal, const ErrorHandler &h = nullptr,
1012 QSet<quintptr> *visited = nullptr, QList<Path> *visitedRefs = nullptr) const;
1013 bool visitLookup(
1014 const QString &symbolName, function_ref<bool(const DomItem &)> visitor,
1015 LookupType type = LookupType::Symbol, LookupOptions = LookupOption::Normal,
1016 const ErrorHandler &errorHandler = nullptr, QSet<quintptr> *visited = nullptr,
1017 QList<Path> *visitedRefs = nullptr) const;
1019 const QString &name, function_ref<bool(const DomItem &)> visitor) const;
1021 const ErrorHandler &h = nullptr, QList<Path> *visitedRefs = nullptr) const;
1023 const QString &symbolName, LookupType type = LookupType::Symbol,
1024 LookupOptions = LookupOption::Normal, const ErrorHandler &errorHandler = nullptr) const;
1026 const QString &symbolName, LookupType type = LookupType::Symbol,
1027 LookupOptions = LookupOption::Normal, const ErrorHandler &errorHandler = nullptr) const;
1028
1029 quintptr id() const;
1030 Path pathFromOwner() const;
1031 QString canonicalFilePath() const;
1033 bool commitToBase(const std::shared_ptr<DomEnvironment> &validPtr = nullptr) const;
1035 QCborValue value() const;
1036
1037 void dumpPtr(const Sink &sink) const;
1038 void dump(const Sink &, int indent = 0,
1039 function_ref<bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)> filter =
1040 noFilter) const;
1042 dump(const QString &path,
1043 function_ref<bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)>
1044 filter = noFilter,
1045 int indent = 0, FileWriter *fw = nullptr) const;
1046 QString toString() const;
1047
1048 // OwnigItem elements
1049 int derivedFrom() const;
1050 int revision() const;
1051 QDateTime createdAt() const;
1052 QDateTime frozenAt() const;
1054
1055 void addError(ErrorMessage &&msg) const;
1056 ErrorHandler errorHandler() const;
1057 void clearErrors(const ErrorGroups &groups = ErrorGroups({}), bool iterate = true) const;
1058 // return false if a quick exit was requested
1059 bool iterateErrors(
1060 function_ref<bool (const DomItem &, const ErrorMessage &)> visitor, bool iterate,
1061 Path inPath = Path()) const;
1062
1063 bool iterateSubOwners(function_ref<bool(const DomItem &owner)> visitor) const;
1064 bool iterateDirectSubpaths(DirectVisitor v) const;
1065
1066 template<typename T>
1067 DomItem subDataItem(const PathEls::PathComponent &c, const T &value,
1068 ConstantData::Options options = ConstantData::Options::MapIsMap) const;
1069 template<typename T>
1070 DomItem subValueItem(const PathEls::PathComponent &c, const T &value,
1071 ConstantData::Options options = ConstantData::Options::MapIsMap) const;
1072 template <typename T>
1073 bool invokeVisitorOnValue(DirectVisitor visitor, const PathEls::PathComponent &c, const T &value,
1074 ConstantData::Options options = ConstantData::Options::MapIsMap) const;
1075 template <typename F>
1076 bool invokeVisitorOnLazyField(DirectVisitor visitor, QStringView f, F valueF,
1077 ConstantData::Options options = ConstantData::Options::MapIsMap) const
1078 {
1079 PathEls::PathComponent c = PathEls::Field(f);
1080 auto lazyWrap = [this, &c, &valueF, options]() {
1081 return this->subValueItem<decltype(valueF())>(c, valueF(), options);
1082 };
1083 return visitor(c, lazyWrap);
1084 }
1085 DomItem subReferencesItem(const PathEls::PathComponent &c, const QList<Path> &paths) const;
1086 DomItem subReferenceItem(const PathEls::PathComponent &c, const Path &referencedObject) const;
1087 bool invokeVisitorOnReference(DirectVisitor visitor, QStringView f,
1088 const Path &referencedObject) const
1089 {
1090 PathEls::PathComponent c = PathEls::Field(f);
1091 return visitor(c, [c, this, referencedObject]() {
1092 return this->subReferenceItem(c, referencedObject);
1093 });
1094 }
1095 bool invokeVisitorOnReferences(DirectVisitor visitor, QStringView f,
1096 const QList<Path> &paths) const
1097 {
1098 PathEls::PathComponent c = PathEls::Field(f);
1099 return visitor(c, [c, this, paths]() { return this->subReferencesItem(c, paths); });
1100 }
1101 DomItem subListItem(const List &list) const;
1102 DomItem subMapItem(const Map &map) const;
1103
1105 {
1106 Q_ASSERT(obj);
1107 return DomItem(m_top, m_owner, m_ownerPath, ScriptElementDomWrapper(obj));
1108 }
1109
1110 template<typename Owner>
1111 DomItem subOwnerItem(const PathEls::PathComponent &c, Owner o) const
1112 {
1113 if constexpr (domTypeIsUnattachedOwningItem(Owner::element_type::kindValue))
1114 return DomItem(m_top, o, canonicalPath().withComponent(c), o.get());
1115 else
1116 return DomItem(m_top, o, Path(), o.get());
1117 }
1118 template <typename T>
1119 DomItem wrap(const PathEls::PathComponent &c, const T &obj) const;
1120 template <typename T>
1121 bool invokeVisitorOnField(DirectVisitor visitor, QStringView f, T &obj) const
1122 {
1123 PathEls::PathComponent c = PathEls::Field(f);
1124 auto lazyWrap = [this, &c, &obj]() { return this->wrap<T>(c, obj); };
1125 return visitor(c, lazyWrap);
1126 }
1127
1128 DomItem() = default;
1129 DomItem(const std::shared_ptr<DomEnvironment> &);
1130 DomItem(const std::shared_ptr<DomUniverse> &);
1131
1132 // TODO move to DomEnvironment?
1133 static DomItem fromCode(const QString &code, DomType fileType = DomType::QmlFile);
1134
1135 // --- start of potentially dangerous stuff, make private? ---
1136
1137 std::shared_ptr<DomTop> topPtr() const;
1138 std::shared_ptr<OwningItem> owningItemPtr() const;
1139
1140 // keep the DomItem around to ensure that it doesn't get deleted
1141 template<typename T, typename std::enable_if<std::is_base_of_v<DomBase, T>, bool>::type = true>
1142 T const *as() const
1143 {
1144 if (m_kind == T::kindValue) {
1145 if constexpr (domTypeIsObjWrap(T::kindValue) || domTypeIsValueWrap(T::kindValue))
1146 return std::get<SimpleObjectWrap>(m_element)->as<T>();
1147 else
1148 return static_cast<T const *>(base());
1149 }
1150 return nullptr;
1151 }
1152
1153 template<typename T, typename std::enable_if<!std::is_base_of_v<DomBase, T>, bool>::type = true>
1154 T const *as() const
1155 {
1156 if (m_kind == T::kindValue) {
1157 Q_ASSERT(domTypeIsObjWrap(m_kind) || domTypeIsValueWrap(m_kind));
1158 return std::get<SimpleObjectWrap>(m_element)->as<T>();
1159 }
1160 return nullptr;
1161 }
1162
1163 template<typename T>
1164 std::shared_ptr<T> ownerAs() const;
1165
1166 template<typename Owner, typename T>
1167 DomItem copy(const Owner &owner, const Path &ownerPath, const T &base) const
1168 {
1169 Q_ASSERT(!std::holds_alternative<std::monostate>(m_top));
1170 static_assert(IsInlineDom<std::decay_t<T>>::value, "Expected an inline item or pointer");
1171 return DomItem(m_top, owner, ownerPath, base);
1172 }
1173
1174 template<typename Owner>
1175 DomItem copy(const Owner &owner, const Path &ownerPath) const
1176 {
1177 Q_ASSERT(!std::holds_alternative<std::monostate>(m_top));
1178 return DomItem(m_top, owner, ownerPath, owner.get());
1179 }
1180
1181 template<typename T>
1182 DomItem copy(const T &base) const
1183 {
1184 Q_ASSERT(!std::holds_alternative<std::monostate>(m_top));
1185 using BaseT = std::decay_t<T>;
1186 static_assert(!std::is_same_v<BaseT, ElementT>,
1187 "variant not supported, pass in the stored types");
1188 static_assert(IsInlineDom<BaseT>::value || std::is_same_v<BaseT, std::monostate>,
1189 "expected either a pointer or an inline item");
1190
1191 if constexpr (IsSharedPointerToDomObject<BaseT>::value)
1192 return DomItem(m_top, base, Path(), base.get());
1193 else if constexpr (IsInlineDom<BaseT>::value)
1194 return DomItem(m_top, m_owner, m_ownerPath, base);
1195
1196 Q_UNREACHABLE_RETURN(DomItem(m_top, m_owner, m_ownerPath, nullptr));
1197 }
1198
1199private:
1200 template <typename T>
1201 std::shared_ptr<T> ownerAs_impl() const
1202 {
1203 if (auto p = get_if<std::shared_ptr<T>>(&m_owner))
1204 return *p;
1205 return nullptr;
1206 }
1207
1208 enum class WriteOutCheckResult { Success, Failed };
1209 WriteOutCheckResult performWriteOutChecks(const DomItem &, OutWriter &, WriteOutChecks) const;
1210 const DomBase *base() const;
1211
1212 template<typename Env, typename Owner>
1213 DomItem(Env, Owner, Path, std::nullptr_t) : DomItem()
1214 {
1215 }
1216
1217 template<typename Env, typename Owner, typename T,
1218 typename = std::enable_if_t<IsInlineDom<std::decay_t<T>>::value>>
1219 DomItem(Env env, Owner owner, const Path &ownerPath, const T &el)
1220 : m_top(env), m_owner(owner), m_ownerPath(ownerPath), m_element(el)
1221 {
1222 using BaseT = std::decay_t<T>;
1223 if constexpr (std::is_pointer_v<BaseT>) {
1224 if (!el || el->kind() == DomType::Empty) { // avoid null ptr, and allow only a
1225 // single kind of Empty
1226 m_kind = DomType::Empty;
1227 m_top = std::monostate();
1228 m_owner = std::monostate();
1229 m_ownerPath = Path();
1230 m_element = Empty();
1231 } else {
1232 using DomT = std::remove_pointer_t<BaseT>;
1233 m_element = el;
1234 m_kind = DomT::kindValue;
1235 }
1236 } else {
1237 static_assert(!std::is_same_v<BaseT, ElementT>,
1238 "variant not supported, pass in the internal type");
1239 m_kind = el->kind();
1240 }
1241 }
1242 friend class DomBase;
1243 friend class DomElement;
1244 friend class Map;
1245 friend class List;
1246 friend class QmlObject;
1247 friend class DomUniverse;
1248 friend class DomEnvironment;
1250 friend class ConstantData;
1251 friend class MutableDomItem;
1252 friend class ScriptExpression;
1253 friend class AstComments;
1254 friend class FileLocations::Node;
1255 friend class TestDomItem;
1256 friend QMLDOM_EXPORT bool operator==(const DomItem &, const DomItem &);
1257 DomType m_kind = DomType::Empty;
1258 TopT m_top;
1259 OwnerT m_owner;
1260 Path m_ownerPath;
1261 ElementT m_element = Empty();
1262};
1263
1264QMLDOM_EXPORT bool operator==(const DomItem &o1, const DomItem &o2);
1265
1266inline bool operator!=(const DomItem &o1, const DomItem &o2)
1267{
1268 return !(o1 == o2);
1269}
1270
1271template<typename T>
1272static DomItem keyMultiMapHelper(const DomItem &self, const QString &key,
1273 const QMultiMap<QString, T> &mmap)
1274{
1275 auto it = mmap.find(key);
1276 auto end = mmap.cend();
1277 if (it == end)
1278 return DomItem();
1279 else {
1280 // special case single element (++it == end || it.key() != key)?
1281 QList<const T *> values;
1282 while (it != end && it.key() == key)
1283 values.append(&(*it++));
1284 ListP ll(self.pathFromOwner().withComponent(PathEls::Key(key)), values, QString(),
1286 return self.copy(ll);
1287 }
1288}
1289
1290template<typename T>
1291Map Map::fromMultiMapRef(const Path &pathFromOwner, const QMultiMap<QString, T> &mmap)
1292{
1293 return Map(
1294 pathFromOwner,
1295 [&mmap](const DomItem &self, const QString &key) {
1296 return keyMultiMapHelper(self, key, mmap);
1297 },
1298 [&mmap](const DomItem &) { return QSet<QString>(mmap.keyBegin(), mmap.keyEnd()); },
1299 QLatin1String(typeid(T).name()));
1300}
1301
1302template<typename T>
1303Map Map::fromMapRef(
1304 const Path &pathFromOwner, const QMap<QString, T> &map,
1305 const std::function<DomItem(const DomItem &, const PathEls::PathComponent &, const T &)> &elWrapper)
1306{
1307 return Map(
1308 pathFromOwner,
1309 [&map, elWrapper](const DomItem &self, const QString &key) {
1310 const auto it = map.constFind(key);
1311 if (it == map.constEnd())
1312 return DomItem();
1313 return elWrapper(self, PathEls::Key(key), it.value());
1314 },
1315 [&map](const DomItem &) { return QSet<QString>(map.keyBegin(), map.keyEnd()); },
1316 QLatin1String(typeid(T).name()));
1317}
1318
1319template<typename MapT>
1320QSet<QString> Map::fileRegionKeysFromMap(const MapT &map)
1321{
1322 QSet<QString> keys;
1323 std::transform(map.keyBegin(), map.keyEnd(), std::inserter(keys, keys.begin()), fileLocationRegionName);
1324 return keys;
1325}
1326
1327template<typename T>
1328Map Map::fromFileRegionMap(const Path &pathFromOwner, const QMap<FileLocationRegion, T> &map)
1329{
1330 auto result = Map(
1331 pathFromOwner,
1332 [&map](const DomItem &mapItem, const QString &key) -> DomItem {
1333 auto it = map.constFind(fileLocationRegionValue(key));
1334 if (it == map.constEnd())
1335 return {};
1336
1337 return mapItem.wrap(PathEls::Key(key), *it);
1338 },
1339 [&map](const DomItem &) { return fileRegionKeysFromMap(map); },
1340 QString::fromLatin1(typeid(T).name()));
1341 return result;
1342}
1343
1344template<typename T>
1345List List::fromQList(
1346 const Path &pathFromOwner, const QList<T> &list,
1347 const std::function<DomItem(const DomItem &, const PathEls::PathComponent &, const T &)> &elWrapper,
1348 ListOptions options)
1349{
1350 index_type len = list.size();
1351 if (options == ListOptions::Reverse) {
1352 return List(
1353 pathFromOwner,
1354 [list, elWrapper](const DomItem &self, index_type i) mutable {
1355 if (i < 0 || i >= list.size())
1356 return DomItem();
1357 return elWrapper(self, PathEls::Index(i), list[list.size() - i - 1]);
1358 },
1359 [len](const DomItem &) { return len; }, nullptr, QLatin1String(typeid(T).name()));
1360 } else {
1361 return List(
1362 pathFromOwner,
1363 [list, elWrapper](const DomItem &self, index_type i) mutable {
1364 if (i < 0 || i >= list.size())
1365 return DomItem();
1366 return elWrapper(self, PathEls::Index(i), list[i]);
1367 },
1368 [len](const DomItem &) { return len; }, nullptr, QLatin1String(typeid(T).name()));
1369 }
1370}
1371
1372template<typename T>
1373List List::fromQListRef(
1374 const Path &pathFromOwner, const QList<T> &list,
1375 const std::function<DomItem(const DomItem &, const PathEls::PathComponent &, const T &)> &elWrapper,
1376 ListOptions options)
1377{
1378 if (options == ListOptions::Reverse) {
1379 return List(
1380 pathFromOwner,
1381 [&list, elWrapper](const DomItem &self, index_type i) {
1382 if (i < 0 || i >= list.size())
1383 return DomItem();
1384 return elWrapper(self, PathEls::Index(i), list[list.size() - i - 1]);
1385 },
1386 [&list](const DomItem &) { return list.size(); }, nullptr,
1387 QLatin1String(typeid(T).name()));
1388 } else {
1389 return List(
1390 pathFromOwner,
1391 [&list, elWrapper](const DomItem &self, index_type i) {
1392 if (i < 0 || i >= list.size())
1393 return DomItem();
1394 return elWrapper(self, PathEls::Index(i), list[i]);
1395 },
1396 [&list](const DomItem &) { return list.size(); }, nullptr,
1397 QLatin1String(typeid(T).name()));
1398 }
1399}
1400
1402protected:
1403 virtual std::shared_ptr<OwningItem> doCopy(const DomItem &self) const = 0;
1404
1405public:
1406 OwningItem(const OwningItem &o);
1407 OwningItem(int derivedFrom=0);
1408 OwningItem(int derivedFrom, const QDateTime &lastDataUpdateAt);
1409 OwningItem(const OwningItem &&) = delete;
1410 OwningItem &operator=(const OwningItem &&) = delete;
1411 static int nextRevision();
1412
1413 Path canonicalPath(const DomItem &self) const override = 0;
1414
1415 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override;
1416 std::shared_ptr<OwningItem> makeCopy(const DomItem &self) const { return doCopy(self); }
1417 Path pathFromOwner() const override final { return Path(); }
1418 DomItem containingObject(const DomItem &self) const override;
1419 int derivedFrom() const;
1420 virtual int revision() const;
1421
1422 QDateTime createdAt() const;
1423 virtual QDateTime lastDataUpdateAt() const;
1424 virtual void refreshedDataAt(QDateTime tNew);
1425
1426 // explicit freeze handling needed?
1427 virtual bool frozen() const;
1428 virtual bool freeze();
1429 QDateTime frozenAt() const;
1430
1431 virtual void addError(const DomItem &self, ErrorMessage &&msg);
1432 void addErrorLocal(ErrorMessage &&msg);
1433 void clearErrors(const ErrorGroups &groups = ErrorGroups({}));
1434 // return false if a quick exit was requested
1435 bool iterateErrors(
1436 const DomItem &self,
1437 function_ref<bool(const DomItem &source, const ErrorMessage &msg)> visitor,
1438 const Path &inPath = Path());
1440 QMutexLocker l(mutex());
1441 return m_errors;
1442 }
1443
1444 virtual bool iterateSubOwners(const DomItem &self, function_ref<bool(const DomItem &owner)> visitor);
1445
1446 QBasicMutex *mutex() const { return &m_mutex; }
1447private:
1448 mutable QBasicMutex m_mutex;
1449 int m_derivedFrom;
1450 int m_revision;
1451 QDateTime m_createdAt;
1452 QDateTime m_lastDataUpdateAt;
1453 QDateTime m_frozenAt;
1454 QMultiMap<Path, ErrorMessage> m_errors;
1455 QMap<ErrorMessage, quint32> m_errorsCounts;
1456};
1457
1458template<typename T>
1459std::shared_ptr<T> DomItem::ownerAs() const
1460{
1461 static_assert(domTypeIsOwningItem(T::kindValue),
1462 "unexpected non owning value in ownerAs");
1463 if constexpr (T::kindValue == DomType::FileLocationsNode)
1464 return std::static_pointer_cast<T>(ownerAs_impl<FileLocations::Node>());
1465 else if constexpr (T::kindValue == DomType::ExternalItemInfo)
1466 return std::static_pointer_cast<T>(ownerAs_impl<ExternalItemInfoBase>());
1467 else if constexpr (T::kindValue == DomType::ExternalItemPair)
1468 return std::static_pointer_cast<T>(ownerAs_impl<ExternalItemPairBase>());
1469 else
1470 return ownerAs_impl<T>();
1471}
1472
1473template<int I>
1474struct rank : rank<I - 1>
1475{
1476 static_assert(I > 0, "");
1477};
1478template<>
1479struct rank<0>
1480{
1481};
1482
1483template<typename T>
1484auto writeOutWrap(const T &t, const DomItem &self, OutWriter &lw, rank<1>)
1485 -> decltype(t.writeOut(self, lw))
1486{
1487 t.writeOut(self, lw);
1488}
1489
1490template<typename T>
1491auto writeOutWrap(const T &, const DomItem &, OutWriter &, rank<0>) -> void
1492{
1493 qCWarning(writeOutLog) << "Ignoring writeout to wrapped object not supporting it ("
1494 << typeid(T).name();
1495}
1496template<typename T>
1497auto writeOutWrap(const T &t, const DomItem &self, OutWriter &lw) -> void
1498{
1499 writeOutWrap(t, self, lw, rank<1>());
1500}
1501
1502template<typename T>
1503void SimpleObjectWrapT<T>::writeOut(const DomItem &self, OutWriter &lw) const
1504{
1505 writeOutWrap<T>(*asT(), self, lw);
1506}
1507
1508QMLDOM_EXPORT QDebug operator<<(QDebug debug, const DomItem &c);
1509
1510// TODO QTBUG-121518 quite some methods are used only in the "examples"
1511// Even though MutableDomItem provides some API for modifying internal data,
1512// de-facto it's not very helpful / convinient / intuitive to use
1513// Moreover it just amplifies and repeats issues of DomItem interface,
1514// a.k.a. abuse or misuse of type erasure technique
1516public:
1518
1519 explicit operator bool() const
1520 {
1521 return bool(m_owner);
1522 } // this is weaker than item(), but normally correct
1524 QString internalKindStr() { return domTypeToString(internalKind()); }
1525 DomKind domKind() { return kind2domKind(internalKind()); }
1526
1527 Path canonicalPath() const { return m_owner.canonicalPath().withPath(m_pathFromOwner); }
1529 {
1530 if (m_pathFromOwner)
1531 return MutableDomItem(m_owner, m_pathFromOwner.split().pathToSource);
1532 else {
1533 DomItem cObj = m_owner.containingObject();
1535 }
1536 }
1537
1539 {
1540 if (m_pathFromOwner)
1541 return MutableDomItem(m_owner, m_pathFromOwner.dropTail());
1542 else {
1544 }
1545 }
1546
1549 {
1550 return MutableDomItem(item().qmlObject(option, fOptions));
1551 }
1553 {
1554 return MutableDomItem(item().fileObject(option));
1555 }
1557 {
1558 return MutableDomItem(item().rootQmlObject(option));
1559 }
1561
1563 {
1564 return MutableDomItem { item().component(option) };
1565 }
1566 MutableDomItem owner() { return MutableDomItem(m_owner); }
1570 Path pathFromOwner() { return m_pathFromOwner; }
1572 MutableDomItem operator[](QStringView component) { return MutableDomItem(item()[component]); }
1573 MutableDomItem operator[](const QString &component)
1574 {
1575 return MutableDomItem(item()[component]);
1576 }
1577 MutableDomItem operator[](const char16_t *component)
1578 {
1579 // to avoid clash with stupid builtin ptrdiff_t[MutableDomItem&], coming from C
1580 return MutableDomItem(item()[QStringView(component)]);
1581 }
1582 MutableDomItem operator[](index_type i) { return MutableDomItem(item().index(i)); }
1583
1585 MutableDomItem path(const QString &p) { return path(Path::fromString(p)); }
1586 MutableDomItem path(QStringView p) { return path(Path::fromString(p)); }
1587
1588 QList<QString> const fields() { return item().fields(); }
1589 MutableDomItem field(QStringView name) { return MutableDomItem(item().field(name)); }
1590 index_type indexes() { return item().indexes(); }
1591 MutableDomItem index(index_type i) { return MutableDomItem(item().index(i)); }
1592
1593 QSet<QString> const keys() { return item().keys(); }
1594 MutableDomItem key(const QString &name) { return MutableDomItem(item().key(name)); }
1595 MutableDomItem key(QStringView name) { return key(name.toString()); }
1596
1597 void
1598 dump(const Sink &s, int indent = 0,
1599 function_ref<bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)> filter = noFilter)
1600 {
1601 item().dump(s, indent, filter);
1602 }
1604 dump(const QString &path,
1605 function_ref<bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)>
1606 filter = noFilter,
1607 int indent = 0, FileWriter *fw = nullptr)
1608 {
1609 return item().dump(path, filter, indent, fw);
1610 }
1611 void writeOut(OutWriter &lw) { return item().writeOut(lw); }
1612 bool writeOut(const QString &path, const LineWriterOptions &opt = LineWriterOptions(),
1613 FileWriter *fw = nullptr)
1614 {
1615 return item().writeOut(path, opt, fw);
1616 }
1617
1622 bool commitToBase(const std::shared_ptr<DomEnvironment> &validEnvPtr = nullptr)
1623 {
1624 return item().commitToBase(validEnvPtr);
1625 }
1626 QString canonicalFilePath() const { return item().canonicalFilePath(); }
1627
1629
1630 QCborValue value() { return item().value(); }
1631
1632 QString toString() { return item().toString(); }
1633
1634 // convenience getters
1635 QString name() { return item().name(); }
1638 QString idStr() { return item().idStr(); }
1643 MutableDomItem child(index_type i) { return MutableDomItem(item().child(i)); }
1645
1646 // // OwnigItem elements
1647 int derivedFrom() { return m_owner.derivedFrom(); }
1648 int revision() { return m_owner.revision(); }
1649 QDateTime createdAt() { return m_owner.createdAt(); }
1650 QDateTime frozenAt() { return m_owner.frozenAt(); }
1651 QDateTime lastDataUpdateAt() { return m_owner.lastDataUpdateAt(); }
1652
1653 void addError(ErrorMessage &&msg) { item().addError(std::move(msg)); }
1655
1656 // convenience setters
1661 const MethodInfo &functionDef, AddOption option = AddOption::Overwrite);
1663
1664 MutableDomItem() = default;
1665 MutableDomItem(const DomItem &owner, const Path &pathFromOwner):
1667 {}
1671
1672 std::shared_ptr<DomTop> topPtr() { return m_owner.topPtr(); }
1673 std::shared_ptr<OwningItem> owningItemPtr() { return m_owner.owningItemPtr(); }
1674
1675 template<typename T>
1676 T const *as()
1677 {
1678 return item().as<T>();
1679 }
1680
1681 template <typename T>
1683 Q_ASSERT(!m_owner || !m_owner.owningItemPtr()->frozen());
1684
1685 DomItem self = item();
1686 if (self.m_kind != T::kindValue)
1687 return nullptr;
1688
1689 const T *t = nullptr;
1690 if constexpr (domTypeIsObjWrap(T::kindValue) || domTypeIsValueWrap(T::kindValue))
1691 t = static_cast<const SimpleObjectWrapBase *>(self.base())->as<T>();
1692 else if constexpr (std::is_base_of<DomBase, T>::value)
1693 t = static_cast<const T *>(self.base());
1694 else
1695 Q_UNREACHABLE_RETURN(nullptr);
1696
1697 // Nasty. But since ElementT has to store the const pointers, we allow it in this one place.
1698 return const_cast<T *>(t);
1699 }
1700
1701 template<typename T>
1702 std::shared_ptr<T> ownerAs() const
1703 {
1704 return m_owner.ownerAs<T>();
1705 }
1706 // it is dangerous to assume it stays valid when updates are preformed...
1707 DomItem item() const { return m_owner.path(m_pathFromOwner); }
1708
1709 friend bool operator==(const MutableDomItem &o1, const MutableDomItem &o2)
1710 {
1711 return o1.m_owner == o2.m_owner && o1.m_pathFromOwner == o2.m_pathFromOwner;
1712 }
1713 friend bool operator!=(const MutableDomItem &o1, const MutableDomItem &o2)
1714 {
1715 return !(o1 == o2);
1716 }
1717
1718private:
1719 DomItem m_owner;
1720 Path m_pathFromOwner;
1721};
1722
1723QMLDOM_EXPORT QDebug operator<<(QDebug debug, const MutableDomItem &c);
1724
1725template<typename K, typename T>
1726Path insertUpdatableElementInMultiMap(const Path &mapPathFromOwner, QMultiMap<K, T> &mmap, K key,
1727 const T &value, AddOption option = AddOption::KeepExisting,
1728 T **valuePtr = nullptr)
1729{
1730 if (option == AddOption::Overwrite) {
1731 auto it = mmap.find(key);
1732 if (it != mmap.end()) {
1733 T &v = *it;
1734 v = value;
1735 if (++it != mmap.end() && it.key() == key) {
1736 qWarning() << " requested overwrite of " << key
1737 << " that contains aleready multiple entries in" << mapPathFromOwner;
1738 }
1739 Path newPath = mapPathFromOwner.withKey(key).withIndex(0);
1740 v.updatePathFromOwner(newPath);
1741 if (valuePtr)
1742 *valuePtr = &v;
1743 return newPath;
1744 }
1745 }
1746 mmap.insert(key, value);
1747 auto it = mmap.find(key);
1748 auto it2 = it;
1749 int nVal = 0;
1750 while (it2 != mmap.end() && it2.key() == key) {
1751 ++nVal;
1752 ++it2;
1753 }
1754 Path newPath = mapPathFromOwner.withKey(key).withIndex(nVal-1);
1755 T &v = *it;
1756 v.updatePathFromOwner(newPath);
1757 if (valuePtr)
1758 *valuePtr = &v;
1759 return newPath;
1760}
1761
1762template<typename T>
1763Path appendUpdatableElementInQList(const Path &listPathFromOwner, QList<T> &list, const T &value,
1764 T **vPtr = nullptr)
1765{
1766 int idx = list.size();
1767 list.append(value);
1768 Path newPath = listPathFromOwner.withIndex(idx);
1769 T &targetV = list[idx];
1770 targetV.updatePathFromOwner(newPath);
1771 if (vPtr)
1772 *vPtr = &targetV;
1773 return newPath;
1774}
1775
1776template <typename T, typename K = QString>
1777void updatePathFromOwnerMultiMap(QMultiMap<K, T> &mmap, const Path &newPath)
1778{
1779 auto it = mmap.begin();
1780 auto end = mmap.end();
1781 index_type i = 0;
1782 K name;
1783 QList<T*> els;
1784 while (it != end) {
1785 if (i > 0 && name != it.key()) {
1786 Path pName = newPath.withKey(QString(name));
1787 for (T *el : els)
1788 el->updatePathFromOwner(pName.withIndex(--i));
1789 els.clear();
1790 els.append(&(*it));
1791 name = it.key();
1792 i = 1;
1793 } else {
1794 els.append(&(*it));
1795 name = it.key();
1796 ++i;
1797 }
1798 ++it;
1799 }
1800 Path pName = newPath.withKey(name);
1801 for (T *el : els)
1802 el->updatePathFromOwner(pName.withIndex(--i));
1803}
1804
1805template <typename T>
1806void updatePathFromOwnerQList(QList<T> &list, const Path &newPath)
1807{
1808 auto it = list.begin();
1809 auto end = list.end();
1810 index_type i = 0;
1811 while (it != end)
1812 (it++)->updatePathFromOwner(newPath.withIndex(i++));
1813}
1814
1815constexpr bool domTypeIsObjWrap(DomType k)
1816{
1817 switch (k) {
1818 case DomType::Binding:
1819 case DomType::EnumItem:
1821 case DomType::Export:
1822 case DomType::Id:
1823 case DomType::Import:
1827 case DomType::Pragma:
1829 case DomType::Version:
1830 case DomType::Comment:
1834 return true;
1835 default:
1836 return false;
1837 }
1838}
1839
1841{
1842 switch (k) {
1844 return true;
1845 default:
1846 return false;
1847 }
1848}
1849
1851{
1852 switch (k) {
1853 case DomType::QmlObject:
1856 case DomType::Reference:
1857 case DomType::Map:
1858 case DomType::List:
1859 case DomType::ListP:
1860 case DomType::EnumDecl:
1865 return true;
1866 default:
1867 return false;
1868 }
1869}
1870
1872{
1873 switch (k) {
1874 case DomType::MockOwner:
1875
1878
1879 case DomType::JsFile:
1880 case DomType::QmlFile:
1881
1884
1885 case DomType::LoadInfo:
1887
1890 return true;
1891 default:
1892 return false;
1893 }
1894}
1895
1897{
1898 switch (k) {
1902 return true;
1903 default:
1904 return false;
1905 }
1906}
1907
1909{
1911}
1912
1913template<typename T>
1915 ConstantData::Options options) const
1916{
1917 using BaseT = std::remove_cv_t<std::remove_reference_t<T>>;
1918 if constexpr (
1919 std::is_base_of_v<
1920 QCborValue,
1921 BaseT> || std::is_base_of_v<QCborArray, BaseT> || std::is_base_of_v<QCborMap, BaseT>) {
1922 return DomItem(m_top, m_owner, m_ownerPath,
1923 ConstantData(pathFromOwner().withComponent(c), value, options));
1924 } else if constexpr (std::is_same_v<DomItem, BaseT>) {
1925 Q_UNUSED(options);
1926 return value;
1927 } else if constexpr (IsList<T>::value && !std::is_convertible_v<BaseT, QStringView>) {
1928 return subListItem(List::fromQList<typename BaseT::value_type>(
1929 pathFromOwner().withComponent(c), value,
1930 [options](const DomItem &list, const PathEls::PathComponent &p,
1931 const typename T::value_type &v) { return list.subValueItem(p, v, options); }));
1932 } else if constexpr (IsSharedPointerToDomObject<BaseT>::value) {
1933 Q_UNUSED(options);
1934 return subOwnerItem(c, value);
1935 } else {
1936 return subDataItem(c, value, options);
1937 }
1938}
1939
1940template<typename T>
1942 ConstantData::Options options) const
1943{
1944 using BaseT = std::remove_cv_t<std::remove_reference_t<T>>;
1945 if constexpr (std::is_same_v<BaseT, ConstantData>) {
1946 return this->copy(value);
1947 } else if constexpr (std::is_base_of_v<QCborValue, BaseT>) {
1948 return DomItem(m_top, m_owner, m_ownerPath,
1949 ConstantData(pathFromOwner().withComponent(c), value, options));
1950 } else {
1951 return DomItem(
1952 m_top, m_owner, m_ownerPath,
1953 ConstantData(pathFromOwner().withComponent(c), QCborValue(value), options));
1954 }
1955}
1956
1957template <typename T>
1958bool DomItem::invokeVisitorOnValue(DirectVisitor visitor, const PathEls::PathComponent &c,
1959 const T &value, ConstantData::Options options) const
1960{
1961 auto lazyWrap = [this, &c, &value, options]() {
1962 return this->subValueItem<T>(c, value, options);
1963 };
1964 return visitor(c, lazyWrap);
1965}
1966
1967template<typename T>
1968DomItem DomItem::wrap(const PathEls::PathComponent &c, const T &obj) const
1969{
1970 using BaseT = std::decay_t<T>;
1971 if constexpr (std::is_same_v<QString, BaseT> || std::is_arithmetic_v<BaseT>) {
1972 return this->subDataItem(c, QCborValue(obj));
1973 } else if constexpr (std::is_same_v<SourceLocation, BaseT>) {
1974 return this->subDataItem(c, sourceLocationToQCborValue(obj));
1975 } else if constexpr (std::is_same_v<BaseT, Reference>) {
1976 Q_ASSERT_X(false, "DomItem::wrap",
1977 "wrapping a reference object, probably an error (wrap the target path instead)");
1978 return this->copy(obj);
1979 } else if constexpr (std::is_same_v<BaseT, ConstantData>) {
1980 return this->subDataItem(c, obj);
1981 } else if constexpr (std::is_same_v<BaseT, Map>) {
1982 return this->subMapItem(obj);
1983 } else if constexpr (std::is_same_v<BaseT, List>) {
1984 return this->subListItem(obj);
1985 } else if constexpr (std::is_base_of_v<ListPBase, BaseT>) {
1986 return this->subListItem(obj);
1987 } else if constexpr (std::is_same_v<BaseT, SimpleObjectWrap>) {
1988 return DomItem(m_top, m_owner, m_ownerPath, obj);
1989 } else if constexpr (IsDomObject<BaseT>::value) {
1990 if constexpr (domTypeIsObjWrap(BaseT::kindValue) || domTypeIsValueWrap(BaseT::kindValue)) {
1991 return DomItem(
1992 m_top, m_owner, m_ownerPath,
1993 SimpleObjectWrap::fromObjectRef(this->pathFromOwner().withComponent(c), obj));
1994 } else if constexpr (domTypeIsDomElement(BaseT::kindValue)) {
1995 return this->copy(&obj);
1996 } else {
1997 qCWarning(domLog) << "Unhandled object of type " << domTypeToString(BaseT::kindValue)
1998 << " in DomItem::wrap, not using a shared_ptr for an "
1999 << "OwningItem, or unexpected wrapped object?";
2000 return DomItem();
2001 }
2002 } else if constexpr (IsSharedPointerToDomObject<BaseT>::value) {
2003 if constexpr (domTypeIsOwningItem(BaseT::element_type::kindValue)) {
2004 return this->subOwnerItem(c, obj);
2005 } else {
2006 Q_ASSERT_X(false, "DomItem::wrap", "shared_ptr with non owning item");
2007 return DomItem();
2008 }
2009 } else if constexpr (IsMultiMap<BaseT>::value) {
2010 if constexpr (std::is_same_v<typename BaseT::key_type, QString>) {
2011 return subMapItem(Map::fromMultiMapRef<typename BaseT::mapped_type>(
2012 pathFromOwner().withComponent(c), obj));
2013 } else {
2014 Q_ASSERT_X(false, "DomItem::wrap", "non string keys not supported (try .toString()?)");
2015 }
2016 } else if constexpr (IsMap<BaseT>::value) {
2017 if constexpr (std::is_same_v<typename BaseT::key_type, QString>) {
2018 return subMapItem(Map::fromMapRef<typename BaseT::mapped_type>(
2019 pathFromOwner().withComponent(c), obj,
2020 [](const DomItem &map, const PathEls::PathComponent &p,
2021 const typename BaseT::mapped_type &el) { return map.wrap(p, el); }));
2022 } else {
2023 Q_ASSERT_X(false, "DomItem::wrap", "non string keys not supported (try .toString()?)");
2024 }
2025 } else if constexpr (IsList<BaseT>::value) {
2026 if constexpr (IsDomObject<typename BaseT::value_type>::value) {
2027 return subListItem(List::fromQListRef<typename BaseT::value_type>(
2028 pathFromOwner().withComponent(c), obj,
2029 [](const DomItem &list, const PathEls::PathComponent &p,
2030 const typename BaseT::value_type &el) { return list.wrap(p, el); }));
2031 } else {
2032 Q_ASSERT_X(false, "DomItem::wrap", "Unsupported list type T");
2033 return DomItem();
2034 }
2035 } else {
2036 qCWarning(domLog) << "Cannot wrap " << typeid(BaseT).name();
2037 Q_ASSERT_X(false, "DomItem::wrap", "Do not know how to wrap type T");
2038 return DomItem();
2039 }
2040}
2041
2042template<typename T>
2043bool ListPT<T>::iterateDirectSubpaths(const DomItem &self, DirectVisitor v) const
2044{
2045 index_type len = index_type(m_pList.size());
2046 for (index_type i = 0; i < len; ++i) {
2047 if (!v(PathEls::Index(i), [this, &self, i] { return this->index(self, i); }))
2048 return false;
2049 }
2050 return true;
2051}
2052
2053template<typename T>
2054DomItem ListPT<T>::index(const DomItem &self, index_type index) const
2055{
2056 if (index >= 0 && index < m_pList.size())
2057 return self.wrap(PathEls::Index(index), *static_cast<const T *>(m_pList.value(index)));
2058 return DomItem();
2059}
2060
2061// allow inlining of DomBase
2062inline DomKind DomBase::domKind() const
2063{
2064 return kind2domKind(kind());
2065}
2066
2067inline DomItem DomBase::containingObject(const DomItem &self) const
2068{
2069 Path path = pathFromOwner();
2070 DomItem base = self.owner();
2071 if (!path) {
2072 path = canonicalPath(self);
2073 base = self;
2074 }
2075 Source source = path.split();
2076 return base.path(source.pathToSource);
2077}
2078
2079inline quintptr DomBase::id() const
2080{
2081 return quintptr(this);
2082}
2083
2084inline QString DomBase::typeName() const
2085{
2086 return domTypeToString(kind());
2087}
2088
2089inline QList<QString> DomBase::fields(const DomItem &self) const
2090{
2091 QList<QString> res;
2092 self.iterateDirectSubpaths([&res](const PathEls::PathComponent &c, function_ref<DomItem()>) {
2093 if (c.kind() == Path::Kind::Field)
2094 res.append(c.name());
2095 return true;
2096 });
2097 return res;
2098}
2099
2100inline DomItem DomBase::field(const DomItem &self, QStringView name) const
2101{
2102 DomItem res;
2103 self.iterateDirectSubpaths(
2104 [&res, name](const PathEls::PathComponent &c, function_ref<DomItem()> obj) {
2105 if (c.kind() == Path::Kind::Field && c.checkName(name)) {
2106 res = obj();
2107 return false;
2108 }
2109 return true;
2110 });
2111 return res;
2112}
2113
2114inline index_type DomBase::indexes(const DomItem &self) const
2115{
2116 index_type res = 0;
2117 self.iterateDirectSubpaths([&res](const PathEls::PathComponent &c, function_ref<DomItem()>) {
2118 if (c.kind() == Path::Kind::Index) {
2119 index_type i = c.index() + 1;
2120 if (res < i)
2121 res = i;
2122 }
2123 return true;
2124 });
2125 return res;
2126}
2127
2128inline DomItem DomBase::index(const DomItem &self, qint64 index) const
2129{
2130 DomItem res;
2131 self.iterateDirectSubpaths(
2132 [&res, index](const PathEls::PathComponent &c, function_ref<DomItem()> obj) {
2133 if (c.kind() == Path::Kind::Index && c.index() == index) {
2134 res = obj();
2135 return false;
2136 }
2137 return true;
2138 });
2139 return res;
2140}
2141
2142inline QSet<QString> const DomBase::keys(const DomItem &self) const
2143{
2144 QSet<QString> res;
2145 self.iterateDirectSubpaths([&res](const PathEls::PathComponent &c, function_ref<DomItem()>) {
2146 if (c.kind() == Path::Kind::Key)
2147 res.insert(c.name());
2148 return true;
2149 });
2150 return res;
2151}
2152
2153inline DomItem DomBase::key(const DomItem &self, const QString &name) const
2154{
2155 DomItem res;
2156 self.iterateDirectSubpaths(
2157 [&res, name](const PathEls::PathComponent &c, function_ref<DomItem()> obj) {
2158 if (c.kind() == Path::Kind::Key && c.checkName(name)) {
2159 res = obj();
2160 return false;
2161 }
2162 return true;
2163 });
2164 return res;
2165}
2166
2167inline DomItem DomItem::subListItem(const List &list) const
2168{
2169 return DomItem(m_top, m_owner, m_ownerPath, list);
2170}
2171
2172inline DomItem DomItem::subMapItem(const Map &map) const
2173{
2174 return DomItem(m_top, m_owner, m_ownerPath, map);
2175}
2176
2177// TODO
2178// refactor this workaround. ExternalOWningItem is not recognized as an owning type
2179// in ownerAs.
2180std::shared_ptr<ExternalOwningItem> getFileItemOwner(const DomItem &fileItem);
2181
2182} // end namespace Dom
2183} // end namespace QQmlJS
2184
2185QT_END_NAMESPACE
2186#endif // QMLDOMITEM_H
std::pair< AST::Node *, CommentAnchor > CommentKey
void setSemanticScope(const QQmlJSScope::ConstPtr &scope)
QQmlJSScope::ConstPtr m_semanticScope
void updatePathFromOwner(const Path &newPath)
QQmlJSScope::ConstPtr semanticScope() const
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
Path addAnnotation(const Path &selfPathFromOwner, const QmlObject &annotation, QmlObject **aPtr=nullptr)
BindingValue(const QList< QmlObject > &l)
void updatePathFromOwner(const Path &newPath)
BindingValue(const std::shared_ptr< ScriptExpression > &o)
BindingValue(const BindingValue &o)
DomItem value(const DomItem &binding) const
BindingValue & operator=(const BindingValue &o)
std::shared_ptr< ScriptExpression > scriptExpression
BindingValue(const QmlObject &o)
void setValue(std::unique_ptr< BindingValue > &&value)
BindingType bindingType() const
std::shared_ptr< ScriptExpression > scriptExpressionValue() const
RegionComments & comments()
Binding & operator=(const Binding &)
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const
void setBindingIdentifiers(const ScriptElementVariant &bindingIdentifiers)
Path addAnnotation(const Path &selfPathFromOwner, const QmlObject &a, QmlObject **aPtr=nullptr)
QList< QmlObject > annotations() const
void updatePathFromOwner(const Path &newPath)
static QString preCodeForName(QStringView n)
QmlObject const * objectValue() const
DomItem valueItem(const DomItem &self) const
QList< QmlObject > * arrayValue()
Binding(const Binding &o)
QList< QmlObject > const * arrayValue() const
static QString postCodeForName(QStringView)
void setAnnotations(const QList< QmlObject > &annotations)
Binding & operator=(Binding &&)=default
void writeOut(const DomItem &self, OutWriter &lw) const
Binding(const QString &m_name, const QString &scriptCode, BindingType bindingType=BindingType::Normal)
const RegionComments & comments() const
Binding(const QString &m_name, std::unique_ptr< BindingValue > &&value, BindingType bindingType=BindingType::Normal)
void writeOutValue(const DomItem &self, OutWriter &lw) const
Binding(const QString &m_name=QString())
static constexpr DomType kindValue
Binding(const QString &m_name, const QmlObject &value, BindingType bindingType=BindingType::Normal)
Binding(Binding &&o)=default
std::shared_ptr< ScriptExpression > scriptExpressionValue()
ScriptElementVariant bindingIdentifiers() const
BindingValueKind valueKind() const
Binding(const QString &m_name, const std::shared_ptr< ScriptExpression > &value, BindingType bindingType=BindingType::Normal)
const RegionComments & comments() const
CommentableDomElement & operator=(const CommentableDomElement &o)=default
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override
CommentableDomElement(const CommentableDomElement &o)
CommentableDomElement(const Path &pathFromOwner=Path())
void setIsSingleton(bool isSingleton)
void updatePathFromOwner(const Path &newPath) override
Component(const Path &pathFromOwner=Path())
void setIsComposite(bool isComposite)
Component & operator=(const Component &)=default
void setIsCreatable(bool isCreatable)
void setObjects(const QList< QmlObject > &objects)
const QMultiMap< QString, EnumDecl > & enumerations() const &
Component(const Component &o)=default
Path addObject(const QmlObject &object, QmlObject **oPtr=nullptr)
void setName(const QString &name)
Path attachedTypePath(const DomItem &) const
void setEnumerations(const QMultiMap< QString, EnumDecl > &enumerations)
DomItem field(const DomItem &self, QStringView name) const override
Path addEnumeration(const EnumDecl &enumeration, AddOption option=AddOption::Overwrite, EnumDecl **ePtr=nullptr)
void setAttachedTypeName(const QString &name)
bool iterateDirectSubpaths(const DomItem &, DirectVisitor) const override
QString attachedTypeName() const
Component(const QString &name)
void setAttachedTypePath(const Path &p)
const QList< QmlObject > & objects() const &
DomKind domKind() const override
ConstantData(const Path &pathFromOwner, const QCborValue &value, Options options=Options::MapIsMap)
QCborValue value() const override
quintptr id() const override
static constexpr DomType kindValue
DomType kind() const override
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override
ConstantData & operator*()
const ConstantData & operator*() const
const ConstantData * operator->() const
ConstantData * operator->()
QString typeName() const
virtual DomType kind() const =0
virtual DomKind domKind() const
virtual Path canonicalPath(const DomItem &self) const =0
virtual Path pathFromOwner() const =0
virtual QList< QString > fields(const DomItem &self) const
virtual bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const =0
virtual index_type indexes(const DomItem &self) const
const DomBase * domBase() const
virtual DomItem containingObject(const DomItem &self) const
virtual void writeOut(const DomItem &self, OutWriter &lw) const
virtual QSet< QString > const keys(const DomItem &self) const
virtual DomItem field(const DomItem &self, QStringView name) const
virtual quintptr id() const
virtual QCborValue value() const
virtual QString canonicalFilePath(const DomItem &self) const
virtual ~DomBase()=default
virtual void dump(const DomItem &, const Sink &sink, int indent, FilterT filter) const
virtual DomItem key(const DomItem &self, const QString &name) const
virtual DomItem index(const DomItem &self, index_type index) const
DomElement & operator=(const DomElement &)=default
virtual void updatePathFromOwner(const Path &newPath)
Path canonicalPath(const DomItem &self) const override
Path pathFromOwner() const override
DomElement(const DomElement &o)=default
DomElement(const Path &pathFromOwner=Path())
DomItem containingObject(const DomItem &self) const override
A value type that references any element of the Dom.
DomItem bindings() const
DomItem top() const
DomItem goUp(int) const
QDateTime createdAt() const
T const * as() const
bool resolve(const Path &path, Visitor visitor, const ErrorHandler &errorHandler, ResolveOptions options=ResolveOption::None, const Path &fullPath=Path(), QList< Path > *visitedRefs=nullptr) const
std::shared_ptr< OwningItem > owningItemPtr() const
DomItem operator[](const QString &component) const
std::function< void(const Path &, const DomItem &, const DomItem &)> Callback
QString toString() const
void writeOutPost(OutWriter &lw) const
bool visitTree(const Path &basePath, ChildrenVisitor visitor, VisitOptions options=VisitOption::Default, ChildrenVisitor openingVisitor=emptyChildrenVisitor, ChildrenVisitor closingVisitor=emptyChildrenVisitor, const FieldFilter &filter=FieldFilter::noFilter()) const
Visits recursively all the children of this item using the given visitors.
DomItem path(const Path &p, const ErrorHandler &h=&defaultErrorHandler) const
DomItem containingFile() const
DomItem filterUp(function_ref< bool(DomType k, const DomItem &)> filter, FilterUpOptions options) const
DomItem methods() const
QString internalKindStr() const
DomItem scope(FilterUpOptions options=FilterUpOptions::ReturnOuter) const
DomItem enumerations() const
DomItem subOwnerItem(const PathEls::PathComponent &c, Owner o) const
bool visitLookup1(const QString &symbolName, function_ref< bool(const DomItem &)> visitor, LookupOptions=LookupOption::Normal, const ErrorHandler &h=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
DomItem child(index_type i) const
DomItem key(QStringView name) const
std::shared_ptr< T > ownerAs() const
DomItem get(const ErrorHandler &h=nullptr, QList< Path > *visitedRefs=nullptr) const
static ErrorGroups myErrors()
DomItem operator[](const char16_t *component) const
bool visitUp(function_ref< bool(const DomItem &)> visitor) const
Let the visitor visit the Dom Tree hierarchy of this DomItem.
index_type indexes() const
bool hasAnnotations() const
bool iterateSubOwners(function_ref< bool(const DomItem &owner)> visitor) const
MutableDomItem makeCopy(CopyOption option=CopyOption::EnvConnected) const
DomItem refreshed() const
bool iterateErrors(function_ref< bool(const DomItem &, const ErrorMessage &)> visitor, bool iterate, Path inPath=Path()) const
DomItem pragmas() const
DomItem proceedToScope(const ErrorHandler &h=nullptr, QList< Path > *visitedRefs=nullptr) const
Dereference DomItems pointing to other DomItems.
QList< DomItem > values() const
DomItem universe() const
bool iterateDirectSubpaths(DirectVisitor v) const
DomItem container() const
void clearErrors(const ErrorGroups &groups=ErrorGroups({}), bool iterate=true) const
quintptr id() const
QList< QString > fields() const
bool writeOut(const QString &path, const LineWriterOptions &opt=LineWriterOptions(), FileWriter *fw=nullptr, WriteOutChecks extraChecks=WriteOutCheck::Default) const
static DomItem fromCode(const QString &code, DomType fileType=DomType::QmlFile)
Creates a new document with the given code.
QString idStr() const
DomItem(const std::shared_ptr< DomEnvironment > &)
FileWriter::Status dump(const QString &path, function_ref< bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)> filter=noFilter, int indent=0, FileWriter *fw=nullptr) const
DomItem copy(const T &base) const
bool visitScopeChain(function_ref< bool(const DomItem &)> visitor, LookupOptions=LookupOption::Normal, const ErrorHandler &h=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
Let the visitor visit the QML scope hierarchy of this DomItem.
std::shared_ptr< DomTop > topPtr() const
QCborValue value() const
index_type size() const
QDateTime frozenAt() const
DomItem subListItem(const List &list) const
DomItem component(GoTo option=GoTo::Strict) const
bool visitLookup(const QString &symbolName, function_ref< bool(const DomItem &)> visitor, LookupType type=LookupType::Symbol, LookupOptions=LookupOption::Normal, const ErrorHandler &errorHandler=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
bool invokeVisitorOnField(DirectVisitor visitor, QStringView f, T &obj) const
void writeOutPre(OutWriter &lw) const
DomItem lookupFirst(const QString &symbolName, LookupType type=LookupType::Symbol, LookupOptions=LookupOption::Normal, const ErrorHandler &errorHandler=nullptr) const
bool visitIndexes(function_ref< bool(const DomItem &)> visitor) const
DomItem fileObject(GoTo option=GoTo::Strict) const
bool visitKeys(function_ref< bool(const QString &, const DomItem &)> visitor) const
bool visitStaticTypePrototypeChains(function_ref< bool(const DomItem &)> visitor, VisitPrototypesOptions options=VisitPrototypesOption::Normal, const ErrorHandler &h=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
DomItem::visitStaticTypePrototypeChains.
QQmlJSScope::ConstPtr semanticScope() const
bool invokeVisitorOnValue(DirectVisitor visitor, const PathEls::PathComponent &c, const T &value, ConstantData::Options options=ConstantData::Options::MapIsMap) const
bool writeOutForFile(OutWriter &ow, WriteOutChecks extraChecks) const
bool commitToBase(const std::shared_ptr< DomEnvironment > &validPtr=nullptr) const
DomItem ids() const
DomItem copy(const Owner &owner, const Path &ownerPath) const
bool visitSubSymbolsNamed(const QString &name, function_ref< bool(const DomItem &)> visitor) const
DomItem wrap(const PathEls::PathComponent &c, const T &obj) const
QList< DomItem > lookup(const QString &symbolName, LookupType type=LookupType::Symbol, LookupOptions=LookupOption::Normal, const ErrorHandler &errorHandler=nullptr) const
void dump(const Sink &, int indent=0, function_ref< bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)> filter=noFilter) const
friend QMLDOM_EXPORT bool operator==(const DomItem &, const DomItem &)
QSet< QString > propertyInfoNames() const
static ErrorGroups myResolveErrors()
bool visitDirectAccessibleScopes(function_ref< bool(const DomItem &)> visitor, VisitPrototypesOptions options=VisitPrototypesOption::Normal, const ErrorHandler &h=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
DomItem environment() const
bool isCanonicalChild(const DomItem &child) const
index_type length() const
DomItem operator[](QStringView component) const
DomItem rootQmlObject(GoTo option=GoTo::Strict) const
DomItem subValueItem(const PathEls::PathComponent &c, const T &value, ConstantData::Options options=ConstantData::Options::MapIsMap) const
bool invokeVisitorOnLazyField(DirectVisitor visitor, QStringView f, F valueF, ConstantData::Options options=ConstantData::Options::MapIsMap) const
DomItem directParent() const
DomItem annotations() const
Path canonicalPath() const
QStringList sortedKeys() const
void addError(ErrorMessage &&msg) const
DomItem containingObject() const
DomItem containingScriptExpression() const
QList< DomItem > getAll(const ErrorHandler &h=nullptr, QList< Path > *visitedRefs=nullptr) const
bool visitPrototypeChain(function_ref< bool(const DomItem &)> visitor, VisitPrototypesOptions options=VisitPrototypesOption::Normal, const ErrorHandler &h=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
DomKind domKind() const
bool isContainer() const
DomItem index(index_type) const
DomItem subReferencesItem(const PathEls::PathComponent &c, const QList< Path > &paths) const
DomItem subMapItem(const Map &map) const
bool invokeVisitorOnReference(DirectVisitor visitor, QStringView f, const Path &referencedObject) const
bool visitLocalSymbolsNamed(const QString &name, function_ref< bool(const DomItem &)> visitor) const
bool isExternalItem() const
DomItem subReferenceItem(const PathEls::PathComponent &c, const Path &referencedObject) const
void dumpPtr(const Sink &sink) const
auto visitEl(F f) const
InternalKind internalKind() const
DomItem path(const QString &p, const ErrorHandler &h=&defaultErrorHandler) const
bool isOwningItem() const
DomItem owner() const
The owner of an element, for an qmlObject this is the containing qml file.
ErrorHandler errorHandler() const
DomItem operator[](const Path &path) const
static DomItem empty
DomItem subDataItem(const PathEls::PathComponent &c, const T &value, ConstantData::Options options=ConstantData::Options::MapIsMap) const
QQmlJSScope::ConstPtr nearestSemanticScope() const
QString canonicalFilePath() const
void writeOut(OutWriter &lw) const
Path pathFromOwner() const
DomItem qmlObject(GoTo option=GoTo::Strict, FilterUpOptions options=FilterUpOptions::ReturnOuter) const
Returns the QmlObject that this belongs to.
DomItem subScriptElementWrapperItem(const ScriptElementVariant &obj) const
DomItem path(QStringView p, const ErrorHandler &h=&defaultErrorHandler) const
DomItem copy(const Owner &owner, const Path &ownerPath, const T &base) const
DomItem key(const QString &name) const
PropertyInfo propertyInfoWithName(const QString &name) const
QSet< QString > keys() const
QString name() const
DomItem children() const
DomItem field(QStringView name) const
DomItem propertyDefs() const
bool invokeVisitorOnReferences(DirectVisitor visitor, QStringView f, const QList< Path > &paths) const
DomItem goToFile(const QString &filePath) const
QDateTime lastDataUpdateAt() const
DomItem(const std::shared_ptr< DomUniverse > &)
static ErrorGroup domErrorGroup
DomItem propertyInfos() const
void dump(const DomItem &, const Sink &s, int indent, function_ref< bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)> filter) const override
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override
static constexpr DomType kindValue
Path pathFromOwner() const override
Path canonicalPath(const DomItem &self) const override
const Empty & operator*() const
const Empty * operator->() const
DomType kind() const override
DomItem containingObject(const DomItem &self) const override
quintptr id() const override
const QList< QmlObject > & annotations() const &
const QList< EnumItem > & values() const &
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const override
void setAlias(const QString &aliasName)
void setAnnotations(const QList< QmlObject > &annotations)
EnumDecl(const QString &name=QString(), const QList< EnumItem > &values=QList< EnumItem >(), const Path &pathFromOwner=Path())
void writeOut(const DomItem &self, OutWriter &lw) const override
void updatePathFromOwner(const Path &newP) override
void setName(const QString &name)
Path addAnnotation(const QmlObject &child, QmlObject **cPtr=nullptr)
Path addValue(const EnumItem &value)
static constexpr DomType kindValue
void setValues(const QList< EnumItem > &values)
DomType kind() const override
EnumItem(const QString &name=QString(), int value=0, ValueKind valueKind=ValueKind::ImplicitValue)
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
const RegionComments & comments() const
RegionComments & comments()
void writeOut(const DomItem &self, OutWriter &lw) const
static constexpr DomType kindValue
convenience macro creating a new ErrorGroup and registering its groupId as translatable string
Represents a set of tags grouping a set of related error messages.
Represents an error message connected to the dom.
static Export fromString(const Path &source, QStringView exp, const Path &typePath, const ErrorHandler &h)
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
static FieldFilter noFilter()
Represents a Node of FileLocations tree.
QString logicalPath() const
QString canonicalPath() const
std::shared_ptr< DomEnvironment > environment() const
void setCanonicalPath(const QString &canonicalPath)
void setLogicalPath(const QString &logicalPath)
std::optional< InMemoryContents > content() const
static FileToLoad fromFileSystem(const std::weak_ptr< DomEnvironment > &environment, const QString &canonicalPath)
static FileToLoad fromMemory(const std::weak_ptr< DomEnvironment > &environment, const QString &path, const QString &data)
FileToLoad(const std::weak_ptr< DomEnvironment > &environment, const QString &canonicalPath, const QString &logicalPath, const std::optional< InMemoryContents > &content)
GlobalComponent(const Path &pathFromOwner=Path())
DomType kind() const override
static constexpr DomType kindValue
Path addAnnotation(const Path &selfPathFromOwner, const QmlObject &ann, QmlObject **aPtr=nullptr)
RegionComments comments
std::shared_ptr< ScriptExpression > value
static constexpr DomType kindValue
Id(const QString &idName=QString(), const Path &referredObject=Path())
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const
void updatePathFromOwner(const Path &pathFromOwner)
QList< QmlObject > annotations
Import(const QmlUri &uri=QmlUri(), Version version=Version(), const QString &importId=QString())
Import baseImport() const
friend bool operator==(const Import &i1, const Import &i2)
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const
static QRegularExpression importRe()
void writeOut(const DomItem &self, OutWriter &ow) const
static Import fromFileString(const QString &importStr, const QString &importId=QString(), const ErrorHandler &handler=nullptr)
friend bool operator!=(const Import &i1, const Import &i2)
static Import fromUriString(const QString &importStr, Version v=Version(), const QString &importId=QString(), const ErrorHandler &handler=nullptr)
JsResource(const Path &pathFromOwner=Path())
DomType kind() const override
bool iterateDirectSubpaths(const DomItem &, DirectVisitor) const override
static constexpr DomType kindValue
quintptr id() const override
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor v) const override
void writeOut(const DomItem &self, OutWriter &ow, bool compact) const
static constexpr DomType kindValue
index_type indexes(const DomItem &) const override
virtual void copyTo(ListPBase *) const
virtual void moveTo(ListPBase *) const
void writeOut(const DomItem &self, OutWriter &ow) const override
DomType kind() const override
QList< const void * > m_pList
ListPBase(const Path &pathFromOwner, const QList< const void * > &pList, const QString &elType)
void moveTo(ListPBase *t) const override
ListPT(const Path &pathFromOwner, const QList< T * > &pList, const QString &elType=QString(), ListOptions options=ListOptions::Normal)
DomItem index(const DomItem &self, index_type index) const override
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor v) const override
void copyTo(ListPBase *t) const override
static constexpr DomType kindValue
static constexpr DomType kindValue
ListPBase & operator*()
ListPBase * operator->()
const ListPBase * operator->() const
ListP(const Path &pathFromOwner, const QList< T * > &pList, const QString &elType=QString(), ListOptions options=ListOptions::Normal)
const ListPBase & operator*() const
void writeOut(const DomItem &self, OutWriter &ow, bool compact) const
std::function< bool(const DomItem &, function_ref< bool(index_type, function_ref< DomItem()>)>)> IteratorFunction
List(const Path &pathFromOwner, const LookupFunction &lookup, const Length &length, const IteratorFunction &iterator, const QString &elType)
DomType kind() const override
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override
const List & operator*() const
static List fromQList(const Path &pathFromOwner, const QList< T > &list, const std::function< DomItem(const DomItem &, const PathEls::PathComponent &, const T &)> &elWrapper, ListOptions options=ListOptions::Normal)
static List fromQListRef(const Path &pathFromOwner, const QList< T > &list, const std::function< DomItem(const DomItem &, const PathEls::PathComponent &, const T &)> &elWrapper, ListOptions options=ListOptions::Normal)
void dump(const DomItem &, const Sink &s, int indent, function_ref< bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)>) const override
std::function< DomItem(const DomItem &, index_type)> LookupFunction
void writeOut(const DomItem &self, OutWriter &ow) const override
quintptr id() const override
static constexpr DomType kindValue
const List * operator->() const
index_type indexes(const DomItem &self) const override
DomItem index(const DomItem &self, index_type index) const override
std::function< index_type(const DomItem &)> Length
std::function< DomItem(const DomItem &, QString)> LookupFunction
static Map fromMultiMapRef(const Path &pathFromOwner, const QMultiMap< QString, T > &mmap)
const Map * operator->() const
static Map fromFileRegionMap(const Path &pathFromOwner, const QMap< FileLocationRegion, T > &map)
Map(const Path &pathFromOwner, const LookupFunction &lookup, const Keys &keys, const QString &targetType)
const Map & operator*() const
static Map fromMapRef(const Path &pathFromOwner, const QMap< QString, T > &mmap, const std::function< DomItem(const DomItem &, const PathEls::PathComponent &, const T &)> &elWrapper)
static Map fromMultiMap(const Path &pathFromOwner, const QMultiMap< QString, T > &mmap)
std::function< QSet< QString >(const DomItem &)> Keys
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override
QSet< QString > const keys(const DomItem &self) const override
quintptr id() const override
DomItem key(const DomItem &self, const QString &name) const override
static constexpr DomType kindValue
DomType kind() const override
std::shared_ptr< ScriptExpression > body
QList< MethodParameter > parameters
std::shared_ptr< ScriptExpression > returnType
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
void writeOut(const DomItem &self, OutWriter &ow) const
void writePre(const DomItem &self, OutWriter &ow) const
QString signature(const DomItem &self) const
std::shared_ptr< ScriptExpression > defaultValue
void writeOut(const DomItem &self, OutWriter &ow) const
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
void writeOutSignal(const DomItem &self, OutWriter &ow) const
TypeAnnotationStyle typeAnnotationStyle
static constexpr DomType kindValue
std::shared_ptr< ScriptExpression > value
QMap< QString, QMap< QString, MockObject > > subMaps
friend bool operator==(const ModuleAutoExport &i1, const ModuleAutoExport &i2)
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
friend bool operator!=(const ModuleAutoExport &i1, const ModuleAutoExport &i2)
static constexpr DomType kindValue
std::shared_ptr< T > ownerAs() const
MutableDomItem addChild(QmlObject child)
friend bool operator==(const MutableDomItem &o1, const MutableDomItem &o2)
MutableDomItem addPropertyDef(const PropertyDefinition &propertyDef, AddOption option=AddOption::Overwrite)
bool commitToBase(const std::shared_ptr< DomEnvironment > &validEnvPtr=nullptr)
QString canonicalFilePath() const
MutableDomItem fileObject(GoTo option=GoTo::Strict)
MutableDomItem operator[](const char16_t *component)
FileWriter::Status dump(const QString &path, function_ref< bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)> filter=noFilter, int indent=0, FileWriter *fw=nullptr)
MutableDomItem key(QStringView name)
MutableDomItem operator[](const QString &component)
MutableDomItem addMethod(const MethodInfo &functionDef, AddOption option=AddOption::Overwrite)
MutableDomItem field(QStringView name)
void dump(const Sink &s, int indent=0, function_ref< bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)> filter=noFilter)
void writeOut(OutWriter &lw)
MutableDomItem(const DomItem &owner, const Path &pathFromOwner)
MutableDomItem containingObject()
void addError(ErrorMessage &&msg)
MutableDomItem path(const QString &p)
std::shared_ptr< DomTop > topPtr()
MutableDomItem key(const QString &name)
QSet< QString > const keys()
MutableDomItem qmlObject(GoTo option=GoTo::Strict, FilterUpOptions fOptions=FilterUpOptions::ReturnOuter)
QList< QString > const fields()
MutableDomItem component(GoTo option=GoTo::Strict)
MutableDomItem path(const Path &p)
MutableDomItem makeCopy(CopyOption option=CopyOption::EnvConnected)
MutableDomItem operator[](const Path &path)
MutableDomItem index(index_type i)
MutableDomItem child(index_type i)
MutableDomItem(const DomItem &item)
std::shared_ptr< OwningItem > owningItemPtr()
bool writeOut(const QString &path, const LineWriterOptions &opt=LineWriterOptions(), FileWriter *fw=nullptr)
friend bool operator!=(const MutableDomItem &o1, const MutableDomItem &o2)
MutableDomItem rootQmlObject(GoTo option=GoTo::Strict)
DomItem::CopyOption CopyOption
MutableDomItem operator[](QStringView component)
MutableDomItem path(QStringView p)
MutableDomItem addBinding(Binding binding, AddOption option=AddOption::Overwrite)
A DomItem that owns other DomItems and is managed through a shared pointer.
QDateTime createdAt() const
virtual bool iterateSubOwners(const DomItem &self, function_ref< bool(const DomItem &owner)> visitor)
virtual int revision() const
QBasicMutex * mutex() const
DomItem containingObject(const DomItem &self) const override
virtual std::shared_ptr< OwningItem > doCopy(const DomItem &self) const =0
std::shared_ptr< OwningItem > makeCopy(const DomItem &self) const
Path pathFromOwner() const override final
OwningItem(const OwningItem &&)=delete
bool iterateErrors(const DomItem &self, function_ref< bool(const DomItem &source, const ErrorMessage &msg)> visitor, const Path &inPath=Path())
virtual void addError(const DomItem &self, ErrorMessage &&msg)
QDateTime frozenAt() const
void addErrorLocal(ErrorMessage &&msg)
virtual QDateTime lastDataUpdateAt() const
void clearErrors(const ErrorGroups &groups=ErrorGroups({}))
Path canonicalPath(const DomItem &self) const override=0
QMultiMap< Path, ErrorMessage > localErrors() const
OwningItem & operator=(const OwningItem &&)=delete
OwningItem(int derivedFrom, const QDateTime &lastDataUpdateAt)
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override
virtual bool frozen() const
virtual void refreshedDataAt(QDateTime tNew)
OwningItem(int derivedFrom=0)
OwningItem(const OwningItem &o)
Source split() const
Splits the path at the last field, root or current Component.
PathEls::Kind Kind
static Path fromRoot(PathRoot r)
Path withComponent(const PathEls::PathComponent &c)
Path operator[](int i) const
Path mid(int offset, int length) const
Path last() const
Kind headKind() const
static Path fromCurrent(PathCurrent c)
Pragma(const QString &pragmaName=QString(), const QStringList &pragmaValues={})
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
void writeOut(const DomItem &self, OutWriter &ow) const
static constexpr DomType kindValue
static constexpr DomType kindValue
ScriptElementVariant m_nameIdentifiers
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
void writeOut(const DomItem &self, OutWriter &lw) const
ScriptElementVariant nameIdentifiers() const
void setNameIdentifiers(const ScriptElementVariant &name)
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const
static constexpr DomType kindValue
QQmlDomAstCreatorBase(const MutableDomItem &qmlFile)
void endVisit(AST::UiProgram *) override
std::shared_ptr< DomEnvironment > currentEnvironment()
void throwRecursionDepthError() override
void endVisitHelper(AST::PatternElement *pe, const std::shared_ptr< ScriptElements::GenericScriptElement > &element)
void loadAnnotations(AST::UiObjectMember *el)
bool visit(AST::UiProgram *program) override
void enableLoadFileLazily(bool enable=true)
void enableScriptExpressions(bool enable=true)
virtual QQmlJSASTClassListToVisit void throwRecursionDepthError() override
QQmlDomAstCreatorWithQQmlJSScope(MutableDomItem &qmlFile, QQmlJSLogger *logger, QQmlJSImporter *importer)
QQmlJSScope::ConstPtr semanticScope() const
void setIds(const QMultiMap< QString, Id > &ids)
void setNextComponentPath(const Path &p)
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override
QList< DomItem > subComponents(const DomItem &self) const
const QMultiMap< QString, Id > & ids() const &
void updatePathFromOwner(const Path &newPath) override
void setNameIdentifiers(const ScriptElementVariant &name)
static constexpr DomType kindValue
void writeOut(const DomItem &self, OutWriter &) const override
void setSemanticScope(const QQmlJSScope::ConstPtr &scope)
QmlComponent(const QString &name=QString())
QList< QString > subComponentsNames(const DomItem &self) const
Path addId(const Id &id, AddOption option=AddOption::Overwrite, Id **idPtr=nullptr)
ScriptElementVariant nameIdentifiers() const
DomType kind() const override
QList< QString > fields(const DomItem &) const override
void setNameIdentifiers(const ScriptElementVariant &name)
Path addChild(const QmlObject &child, QmlObject **cPtr=nullptr)
MutableDomItem addBinding(MutableDomItem &self, const Binding &binding, AddOption option)
void setMethods(const QMultiMap< QString, MethodInfo > &functionDefs)
void writeOutSortedEnumerations(const QList< DomItem > &descs, OutWriter &ow) const
void writeOut(const DomItem &self, OutWriter &ow, const QString &onTarget) const
ScriptElementVariant nameIdentifiers() const
void setName(const QString &name)
QList< std::pair< SourceLocation, DomItem > > orderOfAttributes(const DomItem &self, const DomItem &component) const
bool iterateSubOwners(const DomItem &self, function_ref< bool(const DomItem &owner)> visitor) const
MutableDomItem addChild(MutableDomItem &self, const QmlObject &child)
void setAnnotations(const QList< QmlObject > &annotations)
const QMultiMap< QString, Binding > & bindings() const &
DomType kind() const override
void setNextScopePath(const Path &nextScopePath)
void updatePathFromOwner(const Path &newPath) override
void setChildren(const QList< QmlObject > &children)
Path addBinding(const Binding &binding, AddOption option, Binding **bPtr=nullptr)
Path addAnnotation(const QmlObject &annotation, QmlObject **aPtr=nullptr)
LocallyResolvedAlias resolveAlias(const DomItem &self, std::shared_ptr< ScriptExpression > accessSequence) const
void writeOutId(const DomItem &self, OutWriter &ow) const
QList< QmlObject > children() const
LocallyResolvedAlias resolveAlias(const DomItem &self, const QStringList &accessSequence) const
const QList< Path > & prototypePaths() const &
void writeOutSortedPropertyDefinition(const DomItem &self, OutWriter &ow, QSet< QString > &mergedDefBinding, const QStringList &keys) const
Path addPropertyDef(const PropertyDefinition &propertyDef, AddOption option, PropertyDefinition **pDef=nullptr)
void writeOutSortedAttributes(const DomItem &self, OutWriter &ow, const DomItem &component, const Attributes &attribs) const
const QMultiMap< QString, MethodInfo > & methods() const &
MutableDomItem addPropertyDef(MutableDomItem &self, const PropertyDefinition &propertyDef, AddOption option)
DomItem field(const DomItem &self, QStringView name) const override
void setBindings(const QMultiMap< QString, Binding > &bindings)
QString localDefaultPropertyName() const
QString defaultPropertyName(const DomItem &self) const
void setPropertyDefs(const QMultiMap< QString, PropertyDefinition > &propertyDefs)
QmlObject(const Path &pathFromOwner=Path())
void writeOutAttributes(OutWriter &ow, const Attributes &attribs, const QString &code) const
MutableDomItem addMethod(MutableDomItem &self, const MethodInfo &functionDef, AddOption option)
void setIdStr(const QString &id)
QQmlJSScope::ConstPtr semanticScope() const
const QMultiMap< QString, PropertyDefinition > & propertyDefs() const &
void writeOut(const DomItem &self, OutWriter &lw) const override
Path addPrototypePath(const Path &prototypePath)
void setSemanticScope(const QQmlJSScope::ConstPtr &scope)
void setDefaultPropertyName(const QString &name)
void setPrototypePaths(const QList< Path > &prototypePaths)
QList< QmlObject > annotations() const
QList< QString > fields() const
QList< std::pair< SourceLocation, DomItem > > Attributes
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override
Path addMethod(const MethodInfo &functionDef, AddOption option, MethodInfo **mPtr=nullptr)
bool iterateBaseDirectSubpaths(const DomItem &self, DirectVisitor) const
static QmlUri fromString(const QString &importStr)
QString absoluteLocalPath(const QString &basePath=QString()) const
QString directoryString() const
static QmlUri fromUriString(const QString &importStr)
QString localPath() const
QString moduleUri() const
friend bool operator==(const QmlUri &i1, const QmlUri &i2)
static QmlUri fromDirectoryString(const QString &importStr)
friend bool operator!=(const QmlUri &i1, const QmlUri &i2)
QList< QString > fields(const DomItem &self) const override
quintptr id() const override
static constexpr DomType kindValue
const Reference & operator*() const
DomItem index(const DomItem &, index_type) const override
DomItem field(const DomItem &self, QStringView name) const override
DomItem get(const DomItem &self, const ErrorHandler &h=nullptr, QList< Path > *visitedRefs=nullptr) const
QList< DomItem > getAll(const DomItem &self, const ErrorHandler &h=nullptr, QList< Path > *visitedRefs=nullptr) const
index_type indexes(const DomItem &) const override
DomType kind() const override
QSet< QString > const keys(const DomItem &) const override
const Reference * operator->() const
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const override
Reference(const Path &referredObject=Path(), const Path &pathFromOwner=Path(), const SourceLocation &loc=SourceLocation())
DomItem key(const DomItem &, const QString &) const override
Keeps the comments associated with a DomItem.
const DomBase & operator*() const
const DomBase * operator->() const
static constexpr DomType kindValue
ScriptElementVariant element() const
ScriptElementDomWrapper(const ScriptElementVariant &element)
Use this to contain any script element.
void visitConst(F &&visitor) const
std::optional< ScriptElementT > data()
ScriptElement::PointerType< ScriptElement > base() const
Returns a pointer to the virtual base for virtual method calls.
static ScriptElementVariant fromElement(const T &element)
void setData(const ScriptElementT &data)
void replaceKindForGenericChildren(DomType oldType, DomType newType)
QStringView loc2Str(const SourceLocation &) const
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const override
DomType kind() const override
std::shared_ptr< AstComments > astComments() const
std::shared_ptr< QQmlJS::Engine > engine() const
ScriptExpression(const QString &code, ExpressionType expressionType)
static constexpr DomType kindValue
SourceLocation locationToLocal(const SourceLocation &x) const
std::shared_ptr< ScriptExpression > makeCopy(const DomItem &self) const
ScriptExpression(const ScriptExpression &e)
ExpressionType expressionType() const
void writeOut(const DomItem &self, OutWriter &lw) const override
SourceLocation globalLocation(const DomItem &self) const
ScriptExpression(QStringView code, const std::shared_ptr< QQmlJS::Engine > &engine, AST::Node *ast, const std::shared_ptr< AstComments > &comments, ExpressionType expressionType, const SourceLocation &localOffset=SourceLocation())
void setScriptElement(const ScriptElementVariant &p)
std::shared_ptr< OwningItem > doCopy(const DomItem &) const override
ScriptElementVariant scriptElement()
void astDumper(const Sink &s, AstDumperOptions options) const
SourceLocation localOffset() const
Path canonicalPath(const DomItem &self) const override
static constexpr DomType kindValue
bool iterateDirectSubpaths(const DomItem &, DirectVisitor) const override
SimpleObjectWrapBase(const Path &pathFromOwner, const QVariant &value, quintptr idValue, DomType kind=kindValue, SimpleWrapOptions options=SimpleWrapOption::None)
virtual void moveTo(SimpleObjectWrapBase *) const
DomKind domKind() const final override
virtual void copyTo(SimpleObjectWrapBase *) const
DomType kind() const final override
quintptr id() const final override
SimpleObjectWrapT(const Path &pathFromOwner, const QVariant &v, quintptr idValue, SimpleWrapOptions o)
void moveTo(SimpleObjectWrapBase *target) const override
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const override
static constexpr DomType kindValue
void writeOut(const DomItem &self, OutWriter &lw) const override
void copyTo(SimpleObjectWrapBase *target) const override
const SimpleObjectWrapBase & operator*() const
SimpleObjectWrapBase & operator*()
static SimpleObjectWrap fromObjectRef(const Path &pathFromOwner, T &value)
const SimpleObjectWrapBase * operator->() const
static constexpr DomType kindValue
SimpleObjectWrapBase * operator->()
bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const
QString majorString() const
static constexpr DomType kindValue
Version(qint32 majorVersion=Undefined, qint32 minorVersion=Undefined)
QString minorString() const
int compare(Version o) const
static Version fromString(QStringView v)
QString stringValue() const
static constexpr qint32 Undefined
static constexpr qint32 Latest
QString majorSymbolicString() const
Provides entities to maintain mappings between elements and their location in a file.
void addRegion(const Tree &fLoc, FileLocationRegion region, SourceLocation loc)
Tree ensure(const Tree &base, const Path &basePath)
Path lookupTypePath(const QString &name)
Path loadInfoPath(const Path &el)
Path moduleScopePath(const QString &uri, const ErrorHandler &errorHandler=nullptr)
Path jsFilePath(const QString &path)
Path lookupCppTypePath(const QString &name)
Path qmlFileInfoPath(const QString &canonicalFilePath)
Path moduleIndexPath(const QString &uri, int majorVersion, const ErrorHandler &errorHandler=nullptr)
Path qmlFilePath(const QString &canonicalFilePath)
Path moduleScopePath(const QString &uri, const QString &version, const ErrorHandler &errorHandler=nullptr)
Path lookupSymbolPath(const QString &name)
Path jsFileInfoPath(const QString &path)
Path lookupPropertyPath(const QString &name)
Path moduleScopePath(const QString &uri, Version version, const ErrorHandler &errorHandler=nullptr)
Path qmlFileObjectPath(const QString &canonicalFilePath)
bool operator>(Version v1, Version v2)
QMLDOM_EXPORT bool domTypeIsContainer(DomType k)
bool operator==(Version v1, Version v2)
constexpr bool domTypeIsOwningItem(DomType)
Path appendUpdatableElementInQList(const Path &listPathFromOwner, QList< T > &list, const T &value, T **vPtr=nullptr)
constexpr bool domTypeIsValueWrap(DomType k)
Path insertUpdatableElementInMultiMap(const Path &mapPathFromOwner, QMultiMap< K, T > &mmap, K key, const T &value, AddOption option=AddOption::KeepExisting, T **valuePtr=nullptr)
bool noFilter(const DomItem &, const PathEls::PathComponent &, const DomItem &)
QMLDOM_EXPORT QMap< DomKind, QString > domKindToStringMap()
QMLDOM_EXPORT QDebug operator<<(QDebug debug, const DomItem &c)
std::shared_ptr< ExternalOwningItem > getFileItemOwner(const DomItem &fileItem)
DomKind kind2domKind(DomType k)
static DomItem keyMultiMapHelper(const DomItem &self, const QString &key, const QMultiMap< QString, T > &mmap)
bool operator!=(const DomItem &o1, const DomItem &o2)
QMLDOM_EXPORT bool domTypeIsExternalItem(DomType k)
constexpr bool domTypeIsUnattachedOwningItem(DomType)
QMLDOM_EXPORT QMap< DomType, QString > domTypeToStringMap()
QMLDOM_EXPORT bool domTypeIsScope(DomType k)
std::variant< ConstantData, Empty, List, ListP, Map, Reference, ScriptElementDomWrapper, SimpleObjectWrap, const AstComments *, const FileLocations::Node *, const DomEnvironment *, const DomUniverse *, const EnumDecl *, const ExternalItemInfoBase *, const ExternalItemPairBase *, const GlobalComponent *, const JsFile *, const JsResource *, const LoadInfo *, const MockObject *, const MockOwner *, const QmlComponent *, const QmlFile *, const QmlObject *, const ScriptExpression * > ElementT
QMLDOM_EXPORT QDebug operator<<(QDebug debug, const MutableDomItem &c)
std::disjunction< std::is_same< U, V >... > IsInList
QMLDOM_EXPORT QString domTypeToString(DomType k)
auto writeOutWrap(const T &, const DomItem &, OutWriter &, rank< 0 >) -> void
constexpr bool domTypeIsScriptElement(DomType)
QMLDOM_EXPORT QString domKindToString(DomKind k)
constexpr bool domTypeIsDomElement(DomType)
std::variant< std::monostate, std::shared_ptr< MockOwner >, std::shared_ptr< ExternalItemInfoBase >, std::shared_ptr< ExternalItemPairBase >, std::shared_ptr< JsFile >, std::shared_ptr< QmlFile >, std::shared_ptr< ScriptExpression >, std::shared_ptr< AstComments >, std::shared_ptr< LoadInfo >, std::shared_ptr< FileLocations::Node >, std::shared_ptr< DomEnvironment >, std::shared_ptr< DomUniverse > > OwnerT
void updatePathFromOwnerQList(QList< T > &list, const Path &newPath)
constexpr bool domTypeCanBeInline(DomType k)
bool operator<(Version v1, Version v2)
bool operator<=(Version v1, Version v2)
auto writeOutWrap(const T &t, const DomItem &self, OutWriter &lw) -> void
auto writeOutWrap(const T &t, const DomItem &self, OutWriter &lw, rank< 1 >) -> decltype(t.writeOut(self, lw))
bool operator!=(Version v1, Version v2)
bool operator>=(Version v1, Version v2)
bool visitWithCustomListIteration(T *t, AST::Visitor *visitor)
std::function< void(const ErrorMessage &)> ErrorHandler
QMLDOM_EXPORT bool domTypeIsTopItem(DomType k)
QMLDOM_EXPORT void defaultErrorHandler(const ErrorMessage &)
Calls the default error handler (by default errorToQDebug).
void updatePathFromOwnerMultiMap(QMultiMap< K, T > &mmap, const Path &newPath)
constexpr bool domTypeIsObjWrap(DomType k)
bool emptyChildrenVisitor(Path, const DomItem &, bool)
static ErrorGroups importErrors
std::variant< std::monostate, std::shared_ptr< DomEnvironment >, std::shared_ptr< DomUniverse > > TopT
Combined button and popup list for selecting options.
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)
#define QMLDOM_EXPORT
#define Q_SCRIPTELEMENT_EXIT_IF(check)
#define Q_SCRIPTELEMENT_DISABLE()
#define NewErrorGroup(name)
A common base class for all the script elements.
void setSemanticScope(const QQmlJSScope::ConstPtr &scope)
virtual void createFileLocations(const std::shared_ptr< FileLocations::Node > &fileLocationOfOwner)=0
std::shared_ptr< T > PointerType
QQmlJSScope::ConstPtr semanticScope()
SubclassStorage & operator=(const SubclassStorage &o)
SubclassStorage(const SubclassStorage &&o)
SubclassStorage(const SubclassStorage &o)