aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmldom/qqmldomitem_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmldom/qqmldomitem_p.h')
-rw-r--r--src/qmldom/qqmldomitem_p.h2280
1 files changed, 1584 insertions, 696 deletions
diff --git a/src/qmldom/qqmldomitem_p.h b/src/qmldom/qqmldomitem_p.h
index 9fc73e4486..f94344e266 100644
--- a/src/qmldom/qqmldomitem_p.h
+++ b/src/qmldom/qqmldomitem_p.h
@@ -52,13 +52,14 @@
#include "qqmldom_global.h"
#include "qqmldom_fwd_p.h"
#include "qqmldomconstants_p.h"
-#include "qqmldomfunctionref_p.h"
#include "qqmldomstringdumper_p.h"
#include "qqmldompath_p.h"
#include "qqmldomerrormessage_p.h"
+#include "qqmldomfunctionref_p.h"
#include <QtCore/QMap>
#include <QtCore/QMultiMap>
+#include <QtCore/QSet>
#include <QtCore/QString>
#include <QtCore/QStringView>
#include <QtCore/QDebug>
@@ -70,6 +71,10 @@
#include <memory>
#include <typeinfo>
#include <utility>
+#include <type_traits>
+#include <variant>
+#include <optional>
+#include <cstddef>
QT_BEGIN_NAMESPACE
@@ -79,19 +84,143 @@ namespace Dom {
class Path;
-bool domTypeIsObjWrap(DomType k);
-bool domTypeIsDomElement(DomType);
-bool domTypeIsOwningItem(DomType);
-bool domTypeIsExternalItem(DomType k);
-bool domTypeIsTopItem(DomType k);
-bool domTypeIsContainer(DomType k);
-bool domTypeCanBeInline(DomType k);
+constexpr bool domTypeIsObjWrap(DomType k);
+constexpr bool domTypeIsValueWrap(DomType k);
+constexpr bool domTypeIsDomElement(DomType);
+constexpr bool domTypeIsOwningItem(DomType);
+constexpr bool domTypeIsUnattachedOwningItem(DomType);
+QMLDOM_EXPORT bool domTypeIsExternalItem(DomType k);
+QMLDOM_EXPORT bool domTypeIsTopItem(DomType k);
+QMLDOM_EXPORT bool domTypeIsContainer(DomType k);
+constexpr bool domTypeCanBeInline(DomType k)
+{
+ switch (k) {
+ case DomType::Empty:
+ case DomType::Map:
+ case DomType::List:
+ case DomType::ListP:
+ case DomType::ConstantData:
+ case DomType::SimpleObjectWrap:
+ case DomType::Reference:
+ return true;
+ default:
+ return false;
+ }
+}
+QMLDOM_EXPORT bool domTypeIsScope(DomType k);
QMLDOM_EXPORT QMap<DomType,QString> domTypeToStringMap();
QMLDOM_EXPORT QString domTypeToString(DomType k);
+QMLDOM_EXPORT QMap<DomKind, QString> domKindToStringMap();
+QMLDOM_EXPORT QString domKindToString(DomKind k);
QMLDOM_EXPORT QCborValue locationToData(SourceLocation loc, QStringView strValue=u"");
+inline bool noFilter(DomItem &, const PathEls::PathComponent &, DomItem &)
+{
+ return true;
+}
+
+using DirectVisitor = function_ref<bool(const PathEls::PathComponent &, function_ref<DomItem()>)>;
+// using DirectVisitor = function_ref<bool(Path, DomItem &)>;
+
+namespace {
+template<typename T>
+struct IsMultiMap : std::false_type
+{
+};
+
+template<typename Key, typename T>
+struct IsMultiMap<QMultiMap<Key, T>> : std::true_type
+{
+};
+
+template<typename T>
+struct IsMap : std::false_type
+{
+};
+
+template<typename Key, typename T>
+struct IsMap<QMap<Key, T>> : std::true_type
+{
+};
+
+template<typename... Ts>
+using void_t = void;
+
+template<typename T, typename = void>
+struct IsDomObject : std::false_type
+{
+};
+
+template<typename T>
+struct IsDomObject<T, void_t<decltype(T::kindValue)>> : std::true_type
+{
+};
+
+template<typename T, typename = void>
+struct IsInlineDom : std::false_type
+{
+};
+
+template<typename T>
+struct IsInlineDom<T, void_t<decltype(T::kindValue)>>
+ : std::integral_constant<bool, domTypeCanBeInline(T::kindValue)>
+{
+};
+
+template<typename T>
+struct IsInlineDom<T *, void_t<decltype(T::kindValue)>> : std::true_type
+{
+};
+
+template<typename T>
+struct IsInlineDom<std::shared_ptr<T>, void_t<decltype(T::kindValue)>> : std::true_type
+{
+};
+
+template<typename T>
+struct IsSharedPointerToDomObject : std::false_type
+{
+};
+
+template<typename T>
+struct IsSharedPointerToDomObject<std::shared_ptr<T>> : IsDomObject<T>
+{
+};
+
+template<typename T, typename = void>
+struct IsList : std::false_type
+{
+};
+
+template<typename T>
+struct IsList<T, void_t<typename T::value_type>> : std::true_type
+{
+};
+
+}
+
+template<typename T>
+union SubclassStorage {
+ int i;
+ T lp;
+ T *data() { return reinterpret_cast<T *>(this); }
+ const T *data() const { return reinterpret_cast<const T *>(this); }
+ SubclassStorage() { }
+ SubclassStorage(T &&el) { el.moveTo(data()); }
+ SubclassStorage(const T *el) { el->copyTo(data()); }
+ SubclassStorage(const SubclassStorage &o) : SubclassStorage(o.data()) { }
+ SubclassStorage(const SubclassStorage &&o) : SubclassStorage(o.data()) { }
+ SubclassStorage &operator=(const SubclassStorage &o)
+ {
+ data()->~T();
+ o.data()->copyTo(data());
+ return *this;
+ }
+ ~SubclassStorage() { data()->~T(); }
+};
+
class QMLDOM_EXPORT DomBase{
public:
virtual ~DomBase() = default;
@@ -99,32 +228,37 @@ public:
// minimal overload set:
virtual DomType kind() const = 0;
virtual DomKind domKind() const;
- virtual Path pathFromOwner(const DomItem &self) const = 0;
- virtual Path canonicalPath(const DomItem &self) const = 0;
- virtual bool iterateDirectSubpaths(DomItem &self, function_ref<bool(Path, DomItem &)>) = 0; // iterates the *direct* subpaths, returns false if a quick end was requested
- bool iterateDirectSubpathsConst(const DomItem &self, function_ref<bool(Path, const DomItem &)>) const; // iterates the *direct* subpaths, returns false if a quick end was requested
-
- virtual DomItem containingObject(const DomItem &self) const; // the DomItem corresponding to the canonicalSource source
- virtual void dump(const DomItem &, Sink sink, int indent) const;
+ virtual Path pathFromOwner(DomItem &self) const = 0;
+ virtual Path canonicalPath(DomItem &self) const = 0;
+ virtual bool
+ iterateDirectSubpaths(DomItem &self,
+ DirectVisitor visitor) = 0; // iterates the *direct* subpaths, returns
+ // false if a quick end was requested
+ bool iterateDirectSubpathsConst(DomItem &self, DirectVisitor)
+ const; // iterates the *direct* subpaths, returns false if a quick end was requested
+
+ virtual DomItem containingObject(
+ DomItem &self) const; // the DomItem corresponding to the canonicalSource source
+ virtual void
+ dump(DomItem &, Sink sink, int indent,
+ function_ref<bool(DomItem &, const PathEls::PathComponent &, DomItem &)> filter) const;
virtual quintptr id() const;
- virtual QString typeName() const;
+ QString typeName() const;
- virtual QList<QString> const fields(const DomItem &self) const;
- virtual DomItem field(const DomItem &self, QStringView name) const;
+ virtual QList<QString> fields(DomItem &self) const;
+ virtual DomItem field(DomItem &self, QStringView name) const;
- virtual index_type indexes(const DomItem &self) const;
- virtual DomItem index(const DomItem &self, index_type index) const;
+ virtual index_type indexes(DomItem &self) const;
+ virtual DomItem index(DomItem &self, index_type index) const;
- virtual QSet<QString> const keys(const DomItem &self) const;
- virtual DomItem key(const DomItem &self, QString name) const;
+ virtual QSet<QString> const keys(DomItem &self) const;
+ virtual DomItem key(DomItem &self, QString name) const;
- virtual QString canonicalFilePath(const DomItem &self) const;
- virtual SourceLocation location(const DomItem &self) const;
+ virtual QString canonicalFilePath(DomItem &self) const;
virtual QCborValue value() const {
return QCborValue();
}
-
};
inline DomKind kind2domKind(DomType k)
@@ -133,6 +267,7 @@ inline DomKind kind2domKind(DomType k)
case DomType::Empty:
return DomKind::Empty;
case DomType::List:
+ case DomType::ListP:
return DomKind::List;
case DomType::Map:
return DomKind::Map;
@@ -143,80 +278,113 @@ inline DomKind kind2domKind(DomType k)
}
}
-class QMLDOM_EXPORT Empty: public DomBase {
+class QMLDOM_EXPORT Empty final : public DomBase
+{
public:
constexpr static DomType kindValue = DomType::Empty;
DomType kind() const override { return kindValue; }
+ Empty *operator->() { return this; }
+ const Empty *operator->() const { return this; }
+ Empty &operator*() { return *this; }
+ const Empty &operator*() const { return *this; }
+
Empty();
- Path pathFromOwner(const DomItem &self) const override;
- Path canonicalPath(const DomItem &self) const override;
- DomItem containingObject(const DomItem &self) const override;
- bool iterateDirectSubpaths(DomItem &self, function_ref<bool (Path, DomItem &)>) override;
- void dump(const DomItem &, Sink s, int indent) const override;
+ quintptr id() const override { return ~quintptr(0); }
+ Path pathFromOwner(DomItem &self) const override;
+ Path canonicalPath(DomItem &self) const override;
+ DomItem containingObject(DomItem &self) const override;
+ bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override;
+ void dump(DomItem &, Sink s, int indent,
+ function_ref<bool(DomItem &, const PathEls::PathComponent &, DomItem &)> filter)
+ const override;
};
class QMLDOM_EXPORT DomElement: public DomBase {
protected:
DomElement& operator=(const DomElement&) = default;
public:
- DomElement(Path pathFromOwner = Path(), const SourceLocation & loc = SourceLocation());
+ DomElement(Path pathFromOwner = Path());
DomElement(const DomElement &o) = default;
- Path pathFromOwner(const DomItem &self) const override;
+ Path pathFromOwner(DomItem &self) const override;
Path pathFromOwner() const { return m_pathFromOwner; }
- Path canonicalPath(const DomItem &self) const override;
- DomItem containingObject(const DomItem &self) const override;
+ Path canonicalPath(DomItem &self) const override;
+ DomItem containingObject(DomItem &self) const override;
virtual void updatePathFromOwner(Path newPath);
- SourceLocation location(const DomItem &self) const override;
-
- SourceLocation loc;
private:
Path m_pathFromOwner;
};
-class QMLDOM_EXPORT Map: public DomElement {
+class QMLDOM_EXPORT Map final : public DomElement
+{
public:
constexpr static DomType kindValue = DomType::Map;
DomType kind() const override { return kindValue; }
- using LookupFunction = std::function<DomItem (const DomItem&, QString)>;
- using Keys = std::function<QSet<QString> (const DomItem &)>;
+ Map *operator->() { return this; }
+ const Map *operator->() const { return this; }
+ Map &operator*() { return *this; }
+ const Map &operator*() const { return *this; }
+
+ using LookupFunction = std::function<DomItem(DomItem &, QString)>;
+ using Keys = std::function<QSet<QString>(DomItem &)>;
Map(Path pathFromOwner, LookupFunction lookup, Keys keys, QString targetType);
quintptr id() const override;
- bool iterateDirectSubpaths(DomItem &self, function_ref<bool(Path, DomItem &)>) override;
- QSet<QString> const keys(const DomItem &self) const override;
- DomItem key(const DomItem &self, QString name) const override;
+ bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override;
+ QSet<QString> const keys(DomItem &self) const override;
+ DomItem key(DomItem &self, QString name) const override;
+
+ template<typename T>
+ static Map fromMultiMapRef(
+ Path pathFromOwner, QMultiMap<QString, T> &mmap,
+ std::function<DomItem(DomItem &, const PathEls::PathComponent &c, T &)> elWrapper);
+ template<typename T>
+ static Map
+ fromMapRef(Path pathFromOwner, QMap<QString, T> &mmap,
+ std::function<DomItem(DomItem &, const PathEls::PathComponent &, T &)> elWrapper);
- template <typename T>
- static Map fromMultiMapRef(Path pathFromOwner, QMultiMap<QString,T> &mmap, std::function<DomItem(const DomItem &, Path, T&)> elWrapper);
- template <typename T>
- static Map fromMapRef(Path pathFromOwner, QMap<QString,T> &mmap, std::function<DomItem(const DomItem &, Path, T&)> elWrapper);
private:
LookupFunction m_lookup;
Keys m_keys;
QString m_targetType;
};
-class QMLDOM_EXPORT List: public DomElement {
+class QMLDOM_EXPORT List final : public DomElement
+{
public:
constexpr static DomType kindValue = DomType::List;
DomType kind() const override { return kindValue; }
- using LookupFunction = std::function<DomItem (const DomItem &, index_type)>;
- using Length = std::function<index_type (const DomItem &)>;
- using IteratorFunction = std::function<bool (const DomItem &, function_ref<bool(index_type,DomItem &)>)>;
+ List *operator->() { return this; }
+ const List *operator->() const { return this; }
+ List &operator*() { return *this; }
+ const List &operator*() const { return *this; }
+
+ using LookupFunction = std::function<DomItem(DomItem &, index_type)>;
+ using Length = std::function<index_type(DomItem &)>;
+ using IteratorFunction =
+ std::function<bool(DomItem &, function_ref<bool(index_type, function_ref<DomItem()>)>)>;
List(Path pathFromOwner, LookupFunction lookup, Length length, IteratorFunction iterator, QString elType);
quintptr id() const override;
- bool iterateDirectSubpaths(DomItem &self, function_ref<bool(Path, DomItem &)>) override;
- void dump(const DomItem &, Sink s, int indent) const override;
- index_type indexes(const DomItem &self) const override;
- DomItem index(const DomItem &self, index_type index) const override;
+ bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override;
+ void
+ dump(DomItem &, Sink s, int indent,
+ function_ref<bool(DomItem &, const PathEls::PathComponent &, DomItem &)>) const override;
+ index_type indexes(DomItem &self) const override;
+ DomItem index(DomItem &self, index_type index) const override;
template<typename T>
- static List fromQList(Path pathFromOwner, QList<T> list, std::function<DomItem(const DomItem &, Path, T&)> elWrapper, ListOptions options = ListOptions::Normal);
+ static List
+ fromQList(Path pathFromOwner, QList<T> list,
+ std::function<DomItem(DomItem &, const PathEls::PathComponent &, T &)> elWrapper,
+ ListOptions options = ListOptions::Normal);
template<typename T>
- static List fromQListRef(Path pathFromOwner, QList<T> &list, std::function<DomItem(const DomItem &, Path, T&)> elWrapper, ListOptions options = ListOptions::Normal);
+ static List
+ fromQListRef(Path pathFromOwner, QList<T> &list,
+ std::function<DomItem(DomItem &, const PathEls::PathComponent &, T &)> elWrapper,
+ ListOptions options = ListOptions::Normal);
+
private:
LookupFunction m_lookup;
Length m_length;
@@ -224,18 +392,100 @@ private:
QString m_elType;
};
-class QMLDOM_EXPORT ConstantData: public DomElement {
+class QMLDOM_EXPORT ListPBase : public DomElement
+{
+public:
+ constexpr static DomType kindValue = DomType::ListP;
+ DomType kind() const override { return kindValue; }
+
+ ListPBase(Path pathFromOwner, const QList<void *> &pList, QString elType)
+ : DomElement(pathFromOwner), m_pList(pList), m_elType(elType)
+ {
+ }
+ bool iterateDirectSubpaths(DomItem &self, DirectVisitor v) override;
+ virtual void copyTo(ListPBase *) const { Q_ASSERT(false); };
+ virtual void moveTo(ListPBase *) const { Q_ASSERT(false); };
+ quintptr id() const override { return quintptr(0); }
+ index_type indexes(DomItem &) const override { return index_type(m_pList.size()); }
+
+protected:
+ QList<void *> m_pList;
+ QString m_elType;
+};
+
+template<typename T>
+class QMLDOM_EXPORT ListPT final : public ListPBase
+{
+public:
+ constexpr static DomType kindValue = DomType::ListP;
+
+ ListPT(Path pathFromOwner, QList<T *> pList, QString elType = QString(),
+ ListOptions options = ListOptions::Normal)
+ : ListPBase(pathFromOwner, {},
+ (elType.isEmpty() ? QLatin1String(typeid(T).name()) : elType))
+ {
+ static_assert(sizeof(ListPBase) == sizeof(ListPT),
+ "ListPT does not have the same size as ListPBase");
+ static_assert(alignof(ListPBase) == alignof(ListPT),
+ "ListPT does not have the same size as ListPBase");
+ m_pList.reserve(pList.size());
+ if (options == ListOptions::Normal) {
+ for (void *p : pList)
+ m_pList.append(p);
+ } else if (options == ListOptions::Reverse) {
+ for (qsizetype i = pList.length(); i-- != 0;)
+ // probably writing in reverse and reading sequentially would be better
+ m_pList.append(pList.at(i));
+ } else {
+ Q_ASSERT(false);
+ }
+ }
+ void copyTo(ListPBase *t) const override { new (t) ListPT(*this); }
+ void moveTo(ListPBase *t) const override { new (t) ListPT(std::move(*this)); }
+ bool iterateDirectSubpaths(DomItem &self, DirectVisitor v) override;
+
+ DomItem index(DomItem &self, index_type index) const override;
+};
+
+class QMLDOM_EXPORT ListP
+{
+public:
+ constexpr static DomType kindValue = DomType::ListP;
+ template<typename T>
+ ListP(Path pathFromOwner, QList<T *> pList, QString elType = QString(),
+ ListOptions options = ListOptions::Normal)
+ : list(ListPT<T>(pathFromOwner, pList, elType, options))
+ {
+ }
+ ListP() = delete;
+
+ ListPBase *operator->() { return list.data(); }
+ const ListPBase *operator->() const { return list.data(); }
+ ListPBase &operator*() { return *list.data(); }
+ const ListPBase &operator*() const { return *list.data(); }
+
+private:
+ SubclassStorage<ListPBase> list;
+};
+
+class QMLDOM_EXPORT ConstantData final : public DomElement
+{
public:
constexpr static DomType kindValue = DomType::ConstantData;
- DomType kind() const override { return kindValue; }
+ DomType kind() const override { return kindValue; }
enum class Options {
MapIsMap,
FirstMapIsFields
};
- ConstantData(Path pathFromOwner, QCborValue value, Options options = Options::MapIsMap, const SourceLocation & loc = SourceLocation());
- bool iterateDirectSubpaths(DomItem &self, function_ref<bool(Path, DomItem &)>) override;
+ ConstantData *operator->() { return this; }
+ const ConstantData *operator->() const { return this; }
+ ConstantData &operator*() { return *this; }
+ const ConstantData &operator*() const { return *this; }
+
+ ConstantData(Path pathFromOwner, QCborValue value, Options options = Options::MapIsMap);
+ bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override;
quintptr id() const override;
DomKind domKind() const override;
QCborValue value() const override { return m_value; }
@@ -245,283 +495,650 @@ private:
Options m_options;
};
-class QMLDOM_EXPORT SimpleObjectWrap: public DomElement {
+class QMLDOM_EXPORT SimpleObjectWrapBase : public DomElement
+{
public:
constexpr static DomType kindValue = DomType::SimpleObjectWrap;
- DomType kind() const override { return kindValue; }
+ DomType kind() const final override { return m_kind; }
- template <typename T>
- static SimpleObjectWrap fromDataObject(
- Path pathFromOwner, T const & val,
- std::function<QCborValue(T const &)> toData,
- const SourceLocation & loc = SourceLocation(),
- DomType kind = kindValue,
- DomKind domKind = DomKind::Object,
- QString typeName = QString());
+ quintptr id() const final override { return m_id; }
+ DomKind domKind() const final override { return m_domKind; }
template <typename T>
- static SimpleObjectWrap fromObjectRef(
- Path pathFromOwner, T &value,
- std::function<bool(DomItem &, T &val, function_ref<bool(Path, DomItem &)>)> directSubpathsIterate,
- const SourceLocation & loc = SourceLocation(),
- DomType kind = kindValue,
- QString typeName = QString(),
- DomKind domKind = DomKind::Object);
-
- bool iterateDirectSubpaths(DomItem &self, function_ref<bool(Path, DomItem &)>) override;
- quintptr id() const override;
- QString typeName() const override { return m_typeName; }
- DomType internalKind() const { return m_kind; }
- DomKind domKind() const override { return m_domKind; }
- template <typename T>
T const *as() const
{
- return m_value.value<T*>();
+ if (m_options & SimpleWrapOption::ValueType) {
+ if (m_value.metaType().id() == QMetaType::fromType<T>().id())
+ return reinterpret_cast<const T *>(m_value.constData());
+ return nullptr;
+ } else {
+ return m_value.value<T *>();
+ }
}
template <typename T>
T *mutableAs()
{
- return m_value.value<T*>();
+ if (m_options & SimpleWrapOption::ValueType) {
+ if (m_value.metaType().id() == QMetaType::fromType<T>().id())
+ return reinterpret_cast<T *>(m_value.data());
+ return nullptr;
+ } else {
+ return m_value.value<T *>();
+ }
+ }
+
+ SimpleObjectWrapBase() = delete;
+ virtual void copyTo(SimpleObjectWrapBase *) const { Q_ASSERT(false); }
+ virtual void moveTo(SimpleObjectWrapBase *) const { Q_ASSERT(false); }
+ bool iterateDirectSubpaths(DomItem &, DirectVisitor) override
+ {
+ Q_ASSERT(false);
+ return true;
+ }
+
+protected:
+ friend class TestDomItem;
+ SimpleObjectWrapBase(Path pathFromOwner, QVariant value, quintptr idValue,
+ DomType kind = kindValue,
+ SimpleWrapOptions options = SimpleWrapOption::None)
+ : DomElement(pathFromOwner),
+ m_kind(kind),
+ m_domKind(kind2domKind(kind)),
+ m_value(value),
+ m_id(idValue),
+ m_options(options)
+ {
}
-private:
- SimpleObjectWrap(
- Path pathFromOwner, QVariant value,
- std::function<bool(DomItem &, QVariant, function_ref<bool(Path, DomItem &)>)> directSubpathsIterate,
- DomType kind = kindValue,
- DomKind domKind = DomKind::Object,
- QString typeName = QString(),
- const SourceLocation & loc = SourceLocation());
DomType m_kind;
DomKind m_domKind;
- QString m_typeName;
QVariant m_value;
- std::function<bool(DomItem &, QVariant, function_ref<bool(Path, DomItem &)>)> m_directSubpathsIterate;
+ quintptr m_id;
+ SimpleWrapOptions m_options;
};
-class QMLDOM_EXPORT Reference: public DomElement {
+template<typename T>
+class QMLDOM_EXPORT SimpleObjectWrapT final : public SimpleObjectWrapBase
+{
+public:
+ constexpr static DomType kindValue = DomType::SimpleObjectWrap;
+
+ bool iterateDirectSubpaths(DomItem &self, DirectVisitor visitor) override
+ {
+ return mutableAsT()->iterateDirectSubpaths(self, visitor);
+ }
+
+ T const *asT() const
+ {
+ if constexpr (domTypeIsValueWrap(T::kindValue)) {
+ if (m_value.metaType().id() == QMetaType::fromType<T>().id())
+ return reinterpret_cast<const T *>(m_value.constData());
+ return nullptr;
+ } else if constexpr (domTypeIsObjWrap(T::kindValue)) {
+ return m_value.value<T *>();
+ } else {
+ Q_ASSERT_X(false, "SimpleObjectWrapT", "wrapping of unexpected type");
+ }
+ }
+
+ T *mutableAsT()
+ {
+ if (domTypeIsValueWrap(T::kindValue)) {
+ if (m_value.metaType().id() == QMetaType::fromType<T>().id())
+ return reinterpret_cast<T *>(m_value.data());
+ return nullptr;
+ } else if constexpr (domTypeIsObjWrap(T::kindValue)) {
+ return m_value.value<T *>();
+ } else {
+ Q_ASSERT_X(false, "SimpleObjectWrap", "wrapping of unexpected type");
+ return nullptr;
+ }
+ }
+
+ void copyTo(SimpleObjectWrapBase *target) const override
+ {
+ static_assert(sizeof(SimpleObjectWrapBase) == sizeof(SimpleObjectWrapT),
+ "Size mismatch in SimpleObjectWrapT");
+ static_assert(alignof(SimpleObjectWrapBase) == alignof(SimpleObjectWrapT),
+ "Size mismatch in SimpleObjectWrapT");
+ new (target) SimpleObjectWrapT(*this);
+ }
+
+ void moveTo(SimpleObjectWrapBase *target) const override
+ {
+ static_assert(sizeof(SimpleObjectWrapBase) == sizeof(SimpleObjectWrapT),
+ "Size mismatch in SimpleObjectWrapT");
+ static_assert(alignof(SimpleObjectWrapBase) == alignof(SimpleObjectWrapT),
+ "Size mismatch in SimpleObjectWrapT");
+ new (target) SimpleObjectWrapT(std::move(*this));
+ }
+
+ SimpleObjectWrapT(Path pathFromOwner, QVariant v, quintptr idValue, SimpleWrapOptions o)
+ : SimpleObjectWrapBase(pathFromOwner, v, idValue, T::kindValue, o)
+ {
+ Q_ASSERT(domTypeIsValueWrap(T::kindValue) == bool(o & SimpleWrapOption::ValueType));
+ }
+};
+
+class QMLDOM_EXPORT SimpleObjectWrap
+{
+public:
+ constexpr static DomType kindValue = DomType::SimpleObjectWrap;
+
+ SimpleObjectWrapBase *operator->() { return wrap.data(); }
+ const SimpleObjectWrapBase *operator->() const { return wrap.data(); }
+ SimpleObjectWrapBase &operator*() { return *wrap.data(); }
+ const SimpleObjectWrapBase &operator*() const { return *wrap.data(); }
+
+ template<typename T>
+ static SimpleObjectWrap fromObjectRef(Path pathFromOwner, T &value)
+ {
+ return SimpleObjectWrap(pathFromOwner, value);
+ }
+ SimpleObjectWrap() = delete;
+
+private:
+ template<typename T>
+ SimpleObjectWrap(Path pathFromOwner, T &value)
+ {
+ using BaseT = std::decay_t<T>;
+ if constexpr (domTypeIsObjWrap(BaseT::kindValue)) {
+ new (wrap.data()) SimpleObjectWrapT<BaseT>(pathFromOwner, QVariant::fromValue(&value),
+ quintptr(&value), SimpleWrapOption::None);
+ } else if constexpr (domTypeIsValueWrap(BaseT::kindValue)) {
+ new (wrap.data()) SimpleObjectWrapT<BaseT>(pathFromOwner, QVariant::fromValue(value),
+ quintptr(0), SimpleWrapOption::ValueType);
+ } else {
+ qCWarning(domLog) << "Unexpected object to wrap in SimpleObjectWrap: "
+ << domTypeToString(BaseT::kindValue);
+ Q_ASSERT_X(false, "SimpleObjectWrap",
+ "simple wrap of unexpected object"); // allow? (mocks for testing,...)
+ new (wrap.data())
+ SimpleObjectWrapT<BaseT>(pathFromOwner, nullptr, 0, SimpleWrapOption::None);
+ }
+ }
+ SubclassStorage<SimpleObjectWrapBase> wrap;
+};
+
+class QMLDOM_EXPORT Reference final : public DomElement
+{
+ Q_GADGET
public:
constexpr static DomType kindValue = DomType::Reference;
DomType kind() const override { return kindValue; }
+ Reference *operator->() { return this; }
+ const Reference *operator->() const { return this; }
+ Reference &operator*() { return *this; }
+ const Reference &operator*() const { return *this; }
+
+ bool shouldCache() const;
Reference(Path referredObject = Path(), Path pathFromOwner = Path(), const SourceLocation & loc = SourceLocation());
quintptr id() const override;
- bool iterateDirectSubpaths(DomItem &self, function_ref<bool(Path, DomItem &)>) override;
- DomItem field(const DomItem &self, QStringView name) const override;
- QList<QString> const fields(const DomItem &self) const override;
- index_type indexes(const DomItem &) const override {
- return 0;
- }
- DomItem index(const DomItem &, index_type) const override;
- QSet<QString> const keys(const DomItem &) const override {
- return {};
- }
- DomItem key(const DomItem &, QString) const override;
-
- DomItem get(const DomItem &self) const;
+ bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override;
+ DomItem field(DomItem &self, QStringView name) const override;
+ QList<QString> fields(DomItem &self) const override;
+ index_type indexes(DomItem &) const override { return 0; }
+ DomItem index(DomItem &, index_type) const override;
+ QSet<QString> const keys(DomItem &) const override { return {}; }
+ DomItem key(DomItem &, QString) const override;
+
+ DomItem get(DomItem &self, ErrorHandler h = nullptr, QList<Path> *visitedRefs = nullptr) const;
+ QList<DomItem> getAll(DomItem &self, ErrorHandler h = nullptr,
+ QList<Path> *visitedRefs = nullptr) const;
Path referredObjectPath;
};
-inline bool emptyChildrenVisitor(Path, const DomItem &, bool) { return true; }
+using ElementT = std::variant<
+ Empty, Map, List, ListP, ConstantData, SimpleObjectWrap, Reference, GlobalComponent *,
+ JsResource *, QmlComponent *, QmltypesComponent *, EnumDecl *, MockObject *, ModuleScope *,
+ AstComments *, AttachedInfo *, DomEnvironment *, DomUniverse *, ExternalItemInfoBase *,
+ ExternalItemPairBase *, GlobalScope *, JsFile *, QmlDirectory *, QmlFile *, QmldirFile *,
+ QmlObject *, QmltypesFile *, LoadInfo *, MockOwner *, ModuleIndex *, ScriptExpression *>;
+
+using TopT = std::variant<std::shared_ptr<DomEnvironment>, std::shared_ptr<DomUniverse>>;
+
+using OwnerT =
+ std::variant<std::shared_ptr<ModuleIndex>, std::shared_ptr<MockOwner>,
+ std::shared_ptr<ExternalItemInfoBase>, std::shared_ptr<ExternalItemPairBase>,
+ std::shared_ptr<QmlDirectory>, std::shared_ptr<QmldirFile>,
+ std::shared_ptr<JsFile>, std::shared_ptr<QmlFile>,
+ std::shared_ptr<QmltypesFile>, std::shared_ptr<GlobalScope>,
+ std::shared_ptr<ScriptExpression>, std::shared_ptr<AstComments>,
+ std::shared_ptr<LoadInfo>, std::shared_ptr<AttachedInfo>,
+ std::shared_ptr<DomEnvironment>, std::shared_ptr<DomUniverse>>;
+
+inline bool emptyChildrenVisitor(Path, DomItem &, bool)
+{
+ return true;
+}
class MutableDomItem;
class QMLDOM_EXPORT DomItem {
Q_DECLARE_TR_FUNCTIONS(DomItem);
public:
- using Callback = function<void(Path, const DomItem &, const DomItem &)>;
+ using Callback = function<void(Path, DomItem &, DomItem &)>;
using InternalKind = DomType;
- using Visitor = function_ref<bool(Path, const DomItem &)>;
- using ChildrenVisitor = function_ref<bool(Path, const DomItem &, bool)>;
+ using Visitor = function_ref<bool(Path, DomItem &)>;
+ using ChildrenVisitor = function_ref<bool(Path, DomItem &, bool)>;
static ErrorGroup domErrorGroup;
static ErrorGroups myErrors();
static ErrorGroups myResolveErrors();
+ static DomItem empty;
- operator bool() const { return base()->kind() != DomType::Empty; }
- InternalKind internalKind() const {
- InternalKind res = base()->kind();
- if (res == InternalKind::SimpleObjectWrap)
- return static_cast<SimpleObjectWrap const *>(base())->internalKind();
- return res;
+ enum class CopyOption { EnvConnected, EnvDisconnected };
+
+ template<typename F>
+ auto visitMutableEl(F f)
+ {
+ return std::visit(f, this->m_element);
}
- DomKind domKind() const {
- return base()->domKind();
+ template<typename F>
+ auto visitEl(F f)
+ {
+ return std::visit(f, this->m_element);
}
- Path canonicalPath() const;
- DomItem containingObject() const;
- DomItem container() const;
- DomItem component() const;
- DomItem owner() const;
- DomItem top() const;
- DomItem environment() const;
- DomItem universe() const;
-
- DomItem fileObject(GoTo option = GoTo::Strict) const;
-
- // convenience getters
- QString name() const;
- DomItem qmlChildren() const;
- DomItem annotations() const;
-
- bool resolve(Path path, Visitor visitor, ErrorHandler errorHandler, ResolveOptions options = ResolveOption::None, Path fullPath = Path(), QList<Path> *visitedRefs = nullptr) const;
-
- DomItem operator[](Path path) const;
- DomItem operator[](QStringView component) const;
- DomItem operator[](const QString &component) const;
- DomItem operator[](const char16_t *component) const { return (*this)[QStringView(component)]; } // to avoid clash with stupid builtin ptrdiff_t[DomItem&], coming from C
- DomItem operator[](index_type i) const { return index(i); }
- DomItem operator[](int i) const { return index(i); }
-
- DomItem path(Path p, ErrorHandler h = &defaultErrorHandler) const;
- DomItem path(QString p, ErrorHandler h = &defaultErrorHandler) const;
- DomItem path(QStringView p, ErrorHandler h = &defaultErrorHandler) const;
-
- QList<QString> const fields() const;
- DomItem field(QStringView name) const;
+ explicit operator bool() const { return m_kind != DomType::Empty; }
+ InternalKind internalKind() const {
+ return m_kind;
+ }
+ QString internalKindStr() const { return domTypeToString(internalKind()); }
+ DomKind domKind() const
+ {
+ if (m_kind == DomType::ConstantData)
+ return std::get<ConstantData>(m_element).domKind();
+ else
+ return kind2domKind(m_kind);
+ }
- index_type indexes() const;
- DomItem index(index_type) const;
+ Path canonicalPath();
- QSet<QString> const keys() const;
- DomItem key(QString name) const;
+ DomItem filterUp(function_ref<bool(DomType k, DomItem &)> filter, FilterUpOptions options);
+ DomItem containingObject();
+ DomItem container();
+ DomItem owner();
+ DomItem top();
+ DomItem environment();
+ DomItem universe();
- bool visitChildren(Path basePath, ChildrenVisitor visitor, VisitOptions options = VisitOption::VisitAdopted, ChildrenVisitor openingVisitor = emptyChildrenVisitor, ChildrenVisitor closingVisitor = emptyChildrenVisitor) const;
+ DomItem qmlObject(GoTo option = GoTo::Strict,
+ FilterUpOptions options = FilterUpOptions::ReturnOuter);
+ DomItem fileObject(GoTo option = GoTo::Strict);
+ DomItem rootQmlObject(GoTo option = GoTo::Strict);
+ DomItem globalScope();
+ DomItem component(GoTo option = GoTo::Strict);
+ DomItem scope(FilterUpOptions options = FilterUpOptions::ReturnOuter);
- quintptr id() const { return base()->id(); }
- Path pathFromOwner() const { return base()->pathFromOwner(*this); }
- QString canonicalFilePath() const { return base()->canonicalFilePath(*this); }
- SourceLocation location() const { return base()->location(*this); }
+ // convenience getters
+ DomItem get(ErrorHandler h = nullptr, QList<Path> *visitedRefs = nullptr);
+ QList<DomItem> getAll(ErrorHandler h = nullptr, QList<Path> *visitedRefs = nullptr);
+ bool isOwningItem() { return domTypeIsOwningItem(internalKind()); }
+ bool isExternalItem() { return domTypeIsExternalItem(internalKind()); }
+ bool isTopItem() { return domTypeIsTopItem(internalKind()); }
+ bool isContainer() { return domTypeIsContainer(internalKind()); }
+ bool isScope() { return domTypeIsScope(internalKind()); }
+ bool isCanonicalChild(DomItem &child);
+ bool hasAnnotations();
+ QString name() { return field(Fields::name).value().toString(); }
+ DomItem pragmas() { return field(Fields::pragmas); }
+ DomItem ids() { return field(Fields::ids); }
+ QString idStr() { return field(Fields::idStr).value().toString(); }
+ DomItem propertyInfos() { return field(Fields::propertyInfos); }
+ PropertyInfo propertyInfoWithName(QString name);
+ QSet<QString> propertyInfoNames();
+ DomItem propertyDefs() { return field(Fields::propertyDefs); }
+ DomItem bindings() { return field(Fields::bindings); }
+ DomItem methods() { return field(Fields::methods); }
+ DomItem enumerations() { return field(Fields::enumerations); }
+ DomItem children() { return field(Fields::children); }
+ DomItem child(index_type i) { return field(Fields::children).index(i); }
+ DomItem annotations()
+ {
+ if (hasAnnotations())
+ return field(Fields::annotations);
+ else
+ return DomItem();
+ }
- QCborValue value() const;
+ bool resolve(Path path, Visitor visitor, ErrorHandler errorHandler,
+ ResolveOptions options = ResolveOption::None, Path fullPath = Path(),
+ QList<Path> *visitedRefs = nullptr);
- void dumpPtr(Sink) const;
- void dump(Sink, int indent = 0) const;
- QString toString() const;
+ DomItem operator[](Path path);
+ DomItem operator[](QStringView component);
+ DomItem operator[](const QString &component);
+ DomItem operator[](const char16_t *component)
+ {
+ return (*this)[QStringView(component)];
+ } // to avoid clash with stupid builtin ptrdiff_t[DomItem&], coming from C
+ DomItem operator[](index_type i) { return index(i); }
+ DomItem operator[](int i) { return index(i); }
+ index_type size() { return indexes() + keys().size(); }
+ index_type length() { return size(); }
+
+ DomItem path(Path p, ErrorHandler h = &defaultErrorHandler);
+ DomItem path(QString p, ErrorHandler h = &defaultErrorHandler);
+ DomItem path(QStringView p, ErrorHandler h = &defaultErrorHandler);
+
+ QList<QString> fields();
+ DomItem field(QStringView name);
+
+ index_type indexes();
+ DomItem index(index_type);
+ bool visitIndexes(function_ref<bool(DomItem &)> visitor);
+
+ QSet<QString> keys();
+ QStringList sortedKeys();
+ DomItem key(QString name);
+ DomItem key(QStringView name) { return key(name.toString()); }
+ bool visitKeys(function_ref<bool(QString, DomItem &)> visitor);
+
+ QList<DomItem> values();
+
+ bool visitTree(Path basePath, ChildrenVisitor visitor,
+ VisitOptions options = VisitOption::Default,
+ ChildrenVisitor openingVisitor = emptyChildrenVisitor,
+ ChildrenVisitor closingVisitor = emptyChildrenVisitor);
+ bool visitPrototypeChain(function_ref<bool(DomItem &)> visitor,
+ VisitPrototypesOptions options = VisitPrototypesOption::Normal,
+ ErrorHandler h = nullptr, QSet<quintptr> *visited = nullptr,
+ QList<Path> *visitedRefs = nullptr);
+ bool visitDirectAccessibleScopes(function_ref<bool(DomItem &)> visitor,
+ VisitPrototypesOptions options = VisitPrototypesOption::Normal,
+ ErrorHandler h = nullptr, QSet<quintptr> *visited = nullptr,
+ QList<Path> *visitedRefs = nullptr);
+ bool
+ visitStaticTypePrototypeChains(function_ref<bool(DomItem &)> visitor,
+ VisitPrototypesOptions options = VisitPrototypesOption::Normal,
+ ErrorHandler h = nullptr, QSet<quintptr> *visited = nullptr,
+ QList<Path> *visitedRefs = nullptr);
+ bool visitScopeChain(function_ref<bool(DomItem &)> visitor,
+ LookupOptions = LookupOption::Normal, ErrorHandler h = nullptr,
+ QSet<quintptr> *visited = nullptr, QList<Path> *visitedRefs = nullptr);
+ bool visitLocalSymbolsNamed(QString name, function_ref<bool(DomItem &)> visitor);
+ QSet<QString> localSymbolNames();
+ bool visitLookup1(QString symbolName, function_ref<bool(DomItem &)> visitor,
+ LookupOptions = LookupOption::Normal, ErrorHandler h = nullptr,
+ QSet<quintptr> *visited = nullptr, QList<Path> *visitedRefs = nullptr);
+ bool visitLookup(QString symbolName, function_ref<bool(DomItem &)> visitor,
+ LookupType type = LookupType::Symbol, LookupOptions = LookupOption::Normal,
+ ErrorHandler errorHandler = nullptr, QSet<quintptr> *visited = nullptr,
+ QList<Path> *visitedRefs = nullptr);
+ bool visitSubSymbolsNamed(QString name, function_ref<bool(DomItem &)> visitor);
+ DomItem proceedToScope(ErrorHandler h = nullptr, QList<Path> *visitedRefs = nullptr);
+ QList<DomItem> lookup(QString symbolName, LookupType type = LookupType::Symbol,
+ LookupOptions = LookupOption::Normal,
+ ErrorHandler errorHandler = nullptr);
+ DomItem lookupFirst(QString symbolName, LookupType type = LookupType::Symbol,
+ LookupOptions = LookupOption::Normal, ErrorHandler errorHandler = nullptr);
+
+ quintptr id();
+ Path pathFromOwner();
+ QString canonicalFilePath();
+ DomItem fileLocationsTree();
+ DomItem fileLocations();
+ MutableDomItem makeCopy(CopyOption option = CopyOption::EnvConnected);
+ bool commitToBase();
+ DomItem refreshed() { return top().path(canonicalPath()); }
+ QCborValue value();
+
+ void dumpPtr(Sink sink);
+ void dump(Sink, int indent = 0,
+ function_ref<bool(DomItem &, const PathEls::PathComponent &, DomItem &)> filter =
+ noFilter);
+ QString toString();
+ QString toString() const
+ {
+ DomItem self = *this;
+ return self.toString();
+ }
// OwnigItem elements
- int derivedFrom() const;
- int revision() const;
- QDateTime createdAt() const;
- QDateTime frozenAt() const;
- QDateTime lastDataUpdateAt() const;
-
- void addError(ErrorMessage msg) const;
- ErrorHandler errorHandler() const;
- void clearErrors(ErrorGroups groups = ErrorGroups({}), bool iterate = true) const;
+ int derivedFrom();
+ int revision();
+ QDateTime createdAt();
+ QDateTime frozenAt();
+ QDateTime lastDataUpdateAt();
+
+ void addError(ErrorMessage msg);
+ ErrorHandler errorHandler();
+ void clearErrors(ErrorGroups groups = ErrorGroups({}), bool iterate = true);
// return false if a quick exit was requested
bool iterateErrors(function_ref<bool(DomItem source, ErrorMessage msg)> visitor, bool iterate,
- Path inPath = Path())const;
-
- bool iterateSubOwners(function_ref<bool(DomItem owner)> visitor) const;
-
- Subpath subDataField(QStringView fieldName, QCborValue value, ConstantData::Options options = ConstantData::Options::MapIsMap, const SourceLocation &loc = SourceLocation()) const;
- Subpath subDataField(QString fieldName, QCborValue value, ConstantData::Options options = ConstantData::Options::MapIsMap, const SourceLocation &loc = SourceLocation()) const;
- Subpath subDataIndex(index_type i, QCborValue value, ConstantData::Options options = ConstantData::Options::MapIsMap, const SourceLocation &loc = SourceLocation()) const;
- Subpath subDataKey(QStringView keyName, QCborValue value, ConstantData::Options options = ConstantData::Options::MapIsMap, const SourceLocation &loc = SourceLocation()) const;
- Subpath subDataKey(QString keyName, QCborValue value, ConstantData::Options options = ConstantData::Options::MapIsMap, const SourceLocation &loc = SourceLocation()) const;
- Subpath subDataPath(Path path, QCborValue value, ConstantData::Options options = ConstantData::Options::MapIsMap, const SourceLocation &loc = SourceLocation()) const;
- Subpath subReferenceField(QStringView fieldName, Path referencedObject,
- const SourceLocation & loc = SourceLocation()) const;
- Subpath subReferenceField(QString fieldName, Path referencedObject, const SourceLocation & loc = SourceLocation()) const;
- Subpath subReferenceKey(QStringView keyName, Path referencedObject, const SourceLocation & loc = SourceLocation()) const;
- Subpath subReferenceKey(QString keyName, Path referencedObject, const SourceLocation & loc = SourceLocation()) const;
- Subpath subReferenceIndex(index_type i, Path referencedObject, const SourceLocation & loc = SourceLocation()) const;
- Subpath subReferencePath(Path subPath, Path referencedObject, const SourceLocation & loc = SourceLocation()) const;
-
- Subpath toSubField(QStringView fieldName) const;
- Subpath toSubField(QString fieldName) const;
- Subpath toSubKey(QStringView keyName) const;
- Subpath toSubKey(QString keyName) const;
- Subpath toSubIndex(index_type i) const;
- Subpath toSubPath(Path subPath) const;
- Subpath subList(const List &list) const;
- Subpath subMap(const Map &map) const;
- Subpath subObjectWrap(const SimpleObjectWrap &o) const;
- template <typename T>
- Subpath subWrapPath(Path p, T &obj, SourceLocation loc = SourceLocation()) const;
- template <typename T>
- Subpath subWrapField(QString p, T &obj, SourceLocation loc = SourceLocation()) const;
- template <typename T>
- Subpath subWrapField(QStringView p, T &obj, SourceLocation loc = SourceLocation()) const;
- template <typename T>
- Subpath subWrapKey(QString p, T &obj, SourceLocation loc = SourceLocation()) const;
- template <typename T>
- Subpath subWrapKey(QStringView p, T &obj, SourceLocation loc = SourceLocation()) const;
- template <typename T>
- Subpath subWrapIndex(index_type i, T &obj, SourceLocation loc = SourceLocation()) const;
+ Path inPath = Path());
+
+ bool iterateSubOwners(function_ref<bool(DomItem &owner)> visitor);
+ bool iterateDirectSubpaths(DirectVisitor v);
+
+ template<typename T>
+ DomItem subDataItem(const PathEls::PathComponent &c, T value,
+ ConstantData::Options options = ConstantData::Options::MapIsMap);
+ template<typename T>
+ DomItem subDataItemField(QStringView f, T value,
+ ConstantData::Options options = ConstantData::Options::MapIsMap)
+ {
+ return subDataItem(PathEls::Field(f), value, options);
+ }
+ template<typename T>
+ DomItem subValueItem(const PathEls::PathComponent &c, T value,
+ ConstantData::Options options = ConstantData::Options::MapIsMap);
+ template<typename T>
+ bool dvValue(DirectVisitor visitor, const PathEls::PathComponent &c, T value,
+ ConstantData::Options options = ConstantData::Options::MapIsMap);
+ template<typename T>
+ bool dvValueField(DirectVisitor visitor, QStringView f, T value,
+ ConstantData::Options options = ConstantData::Options::MapIsMap)
+ {
+ return this->dvValue<T>(visitor, PathEls::Field(f), value, options);
+ }
+ template<typename F>
+ bool dvValueLazy(DirectVisitor visitor, const PathEls::PathComponent &c, F valueF,
+ ConstantData::Options options = ConstantData::Options::MapIsMap);
+ template<typename F>
+ bool dvValueLazyField(DirectVisitor visitor, QStringView f, F valueF,
+ ConstantData::Options options = ConstantData::Options::MapIsMap)
+ {
+ return this->dvValueLazy(visitor, PathEls::Field(f), valueF, options);
+ }
+ DomItem subLocationItem(const PathEls::PathComponent &c, SourceLocation loc,
+ QStringView code = QStringView())
+ {
+ return this->subDataItem(c, locationToData(loc, code));
+ }
+ // bool dvSubReference(DirectVisitor visitor, const PathEls::PathComponent &c, Path
+ // referencedObject);
+ DomItem subReferencesItem(const PathEls::PathComponent &c, QList<Path> paths);
+ DomItem subReferenceItem(const PathEls::PathComponent &c, Path referencedObject);
+ bool dvReference(DirectVisitor visitor, const PathEls::PathComponent &c, Path referencedObject)
+ {
+ return dvItem(visitor, c, [c, this, referencedObject]() {
+ return this->subReferenceItem(c, referencedObject);
+ });
+ }
+ bool dvReferences(DirectVisitor visitor, const PathEls::PathComponent &c, QList<Path> paths)
+ {
+ return dvItem(visitor, c, [c, this, paths]() { return this->subReferencesItem(c, paths); });
+ }
+ bool dvReferenceField(DirectVisitor visitor, QStringView f, Path referencedObject)
+ {
+ return dvReference(visitor, PathEls::Field(f), referencedObject);
+ }
+ bool dvReferencesField(DirectVisitor visitor, QStringView f, QList<Path> paths)
+ {
+ return dvReferences(visitor, PathEls::Field(f), paths);
+ }
+ bool dvItem(DirectVisitor visitor, const PathEls::PathComponent &c, function_ref<DomItem()> it)
+ {
+ return visitor(c, it);
+ }
+ bool dvItemField(DirectVisitor visitor, QStringView f, function_ref<DomItem()> it)
+ {
+ return dvItem(visitor, PathEls::Field(f), it);
+ }
+ DomItem subListItem(const List &list);
+ DomItem subMapItem(const Map &map);
+ DomItem subObjectWrapItem(SimpleObjectWrap obj)
+ {
+ return DomItem(m_top, m_owner, m_ownerPath, obj);
+ }
+ template<typename Owner>
+ DomItem subOwnerItem(const PathEls::PathComponent &c, Owner o)
+ {
+ if constexpr (domTypeIsUnattachedOwningItem(Owner::element_type::kindValue))
+ return DomItem(m_top, o, canonicalPath().appendComponent(c), o.get());
+ else
+ return DomItem(m_top, o, Path(), o.get());
+ }
+ template<typename T>
+ DomItem wrap(const PathEls::PathComponent &c, T &obj);
+ template<typename T>
+ DomItem wrapField(QStringView f, T &obj)
+ {
+ return wrap<T>(PathEls::Field(f), obj);
+ }
+ template<typename T>
+ bool dvWrap(DirectVisitor visitor, const PathEls::PathComponent &c, T &obj);
+ template<typename T>
+ bool dvWrapField(DirectVisitor visitor, QStringView f, T &obj)
+ {
+ return dvWrap<T>(visitor, PathEls::Field(f), obj);
+ }
- DomItem();
+ DomItem() = default;
DomItem(std::shared_ptr<DomEnvironment>);
DomItem(std::shared_ptr<DomUniverse>);
+ void loadFile(QString filePath, QString logicalPath,
+ std::function<void(Path, DomItem &, DomItem &)> callback,
+ LoadOptions loadOptions);
+ void loadFile(QString canonicalFilePath, QString logicalPath, QString code, QDateTime codeDate,
+ std::function<void(Path, DomItem &, DomItem &)> callback,
+ LoadOptions loadOptions);
+ void loadModuleDependency(QString uri, Version v,
+ std::function<void(Path, DomItem &, DomItem &)> callback = nullptr,
+ ErrorHandler = nullptr);
+ void loadBuiltins(std::function<void(Path, DomItem &, DomItem &)> callback = nullptr,
+ ErrorHandler = nullptr);
+ void loadPendingDependencies();
+
// --- start of potentially dangerous stuff, make private? ---
- std::shared_ptr<DomTop> topPtr() const;
- std::shared_ptr<OwningItem> owningItemPtr() const;
+ std::shared_ptr<DomTop> topPtr();
+ std::shared_ptr<OwningItem> owningItemPtr();
// keep the DomItem around to ensure that it doesn't get deleted
- template <typename T, typename std::enable_if<std::is_base_of<DomBase, T>::value, bool>::type = true>
- T const*as() const {
- InternalKind k = base()->kind();
- if (k == T::kindValue)
- return static_cast<T const*>(base());
- if (k == InternalKind::SimpleObjectWrap)
- return static_cast<SimpleObjectWrap const *>(base())->as<T>();
+ template<typename T, typename std::enable_if<std::is_base_of_v<DomBase, T>, bool>::type = true>
+ T const *as()
+ {
+ if (m_kind == T::kindValue) {
+ if constexpr (domTypeIsObjWrap(T::kindValue) || domTypeIsValueWrap(T::kindValue))
+ return std::get<SimpleObjectWrap>(m_element)->as<T>();
+ else
+ return static_cast<T const *>(base());
+ }
return nullptr;
}
- template <typename T, typename std::enable_if<!std::is_base_of<DomBase, T>::value, bool>::type = true>
- T const*as() const {
- InternalKind k = base()->kind();
- if (k == InternalKind::SimpleObjectWrap)
- return static_cast<SimpleObjectWrap const *>(base())->as<T>();
+ template<typename T, typename std::enable_if<!std::is_base_of_v<DomBase, T>, bool>::type = true>
+ T const *as()
+ {
+ if (m_kind == T::kindValue) {
+ Q_ASSERT(domTypeIsObjWrap(m_kind) || domTypeIsValueWrap(m_kind));
+ return std::get<SimpleObjectWrap>(m_element)->as<T>();
+ }
return nullptr;
}
- template <typename T>
- std::shared_ptr<T> ownerAs() const;
+ template<typename T>
+ std::shared_ptr<T> ownerAs();
- DomItem copy(std::shared_ptr<OwningItem> owner, Path ownerPath, DomBase *base) const;
- DomItem copy(std::shared_ptr<OwningItem> owner, Path ownerPath = Path()) const;
- DomItem copy(DomBase *base) const;
-private:
- DomBase const* base() const {
- if (m_base == nullptr)
- return reinterpret_cast<DomBase const*>(&inlineEl);
- return m_base;
+ template<typename Owner, typename T>
+ DomItem copy(Owner owner, Path ownerPath, T base)
+ {
+ Q_ASSERT(m_top);
+ static_assert(IsInlineDom<std::decay_t<T>>::value, "Expected an inline item or pointer");
+ return DomItem(m_top, owner, ownerPath, base);
+ }
+
+ template<typename Owner>
+ DomItem copy(Owner owner, Path ownerPath)
+ {
+ Q_ASSERT(m_top);
+ return DomItem(m_top, owner, ownerPath, owner.get());
+ }
+
+ template<typename T>
+ DomItem copy(T base)
+ {
+ Q_ASSERT(m_top);
+ using BaseT = std::decay_t<T>;
+ static_assert(!std::is_same_v<BaseT, ElementT>,
+ "variant not supported, pass in the stored types");
+ static_assert(IsInlineDom<BaseT>::value, "expected either a pointer or an inline item");
+ if constexpr (IsSharedPointerToDomObject<BaseT>::value) {
+ return DomItem(m_top, base, Path(), base.get());
+ } else {
+ return DomItem(m_top, m_owner, m_ownerPath, base);
+ }
}
+
+private:
+ DomBase const *base();
template <typename T, typename std::enable_if<std::is_base_of<DomBase, T>::value, bool>::type = true>
T *mutableAs() {
- InternalKind k = base()->kind();
- if (k == T::kindValue)
- return static_cast<T*>(mutableBase());
- if (k == InternalKind::SimpleObjectWrap)
- return static_cast<SimpleObjectWrap *>(mutableBase())->mutableAs<T>();
+ if (m_kind == T::kindValue) {
+ if constexpr (domTypeIsObjWrap(T::kindValue) || domTypeIsValueWrap(T::kindValue))
+ return static_cast<SimpleObjectWrapBase *>(mutableBase())->mutableAs<T>();
+ else
+ return static_cast<T *>(mutableBase());
+ }
return nullptr;
}
template <typename T, typename std::enable_if<!std::is_base_of<DomBase, T>::value, bool>::type = true>
T *mutableAs() {
- InternalKind k = base()->kind();
- if (k == InternalKind::SimpleObjectWrap)
- return static_cast<SimpleObjectWrap *>(mutableBase())->mutableAs<T>();
+ if (m_kind == T::kindValue) {
+ Q_ASSERT(domTypeIsObjWrap(m_kind) || domTypeIsValueWrap(m_kind));
+ return static_cast<SimpleObjectWrapBase *>(mutableBase())->mutableAs<T>();
+ }
return nullptr;
}
- DomBase * mutableBase() {
- if (m_base == nullptr)
- return reinterpret_cast<DomBase*>(&inlineEl);
- return m_base;
- }
- DomItem(std::shared_ptr<DomTop> env, std::shared_ptr<OwningItem> owner, Path ownerPath, DomBase *base);
- DomItem(std::shared_ptr<DomTop> env, std::shared_ptr<OwningItem> owner, Map map);
- DomItem(std::shared_ptr<DomTop> env, std::shared_ptr<OwningItem> owner, List list);
- DomItem(std::shared_ptr<DomTop> env, std::shared_ptr<OwningItem> owner, ConstantData data);
- DomItem(std::shared_ptr<DomTop> env, std::shared_ptr<OwningItem> owner, Reference reference);
- DomItem(std::shared_ptr<DomTop> env, std::shared_ptr<OwningItem> owner, SimpleObjectWrap wrapper);
+ DomBase *mutableBase();
+ template<typename Env, typename Owner>
+ DomItem(Env, Owner, Path, std::nullptr_t) : DomItem()
+ {
+ }
+ template<typename Env, typename Owner, typename T,
+ typename = std::enable_if_t<IsInlineDom<std::decay_t<T>>::value>>
+ DomItem(Env env, Owner owner, Path ownerPath, T el)
+ : m_top(env), m_owner(owner), m_ownerPath(ownerPath), m_element(el)
+ {
+ using BaseT = std::decay_t<T>;
+ if constexpr (std::is_pointer_v<BaseT>) {
+ if (!el || el->kind() == DomType::Empty) { // avoid null ptr, and allow only a
+ // single kind of Empty
+ m_kind = DomType::Empty;
+ m_top.reset();
+ m_owner.reset();
+ m_ownerPath = Path();
+ m_element = Empty();
+ } else {
+ using DomT = std::remove_pointer_t<BaseT>;
+ m_element = el;
+ m_kind = DomT::kindValue;
+ }
+ } else {
+ static_assert(!std::is_same_v<BaseT, ElementT>,
+ "variant not supported, pass in the internal type");
+ m_kind = el->kind();
+ }
+ }
+ friend class DomBase;
friend class DomElement;
friend class Map;
friend class List;
@@ -531,212 +1148,144 @@ private:
friend class ExternalItemInfoBase;
friend class ConstantData;
friend class MutableDomItem;
+ friend class ScriptExpression;
+ friend class AstComments;
friend class AttachedInfo;
- friend bool operator ==(const DomItem &, const DomItem &);
- std::shared_ptr<DomTop> m_top;
- std::shared_ptr<OwningItem> m_owner;
+ friend class TestDomItem;
+ friend bool operator==(const DomItem &, const DomItem &);
+ DomType m_kind = DomType::Empty;
+ std::optional<TopT> m_top;
+ std::optional<OwnerT> m_owner;
Path m_ownerPath;
- DomBase *m_base;
- union InlineEl {
- // Should add optimized move ops (should be able to do a bit copy of union)
- InlineEl(): empty() { }
- InlineEl(const InlineEl &d) {
- switch (d.kind()){
- case DomType::Empty:
- Q_ASSERT((quintptr)this == (quintptr)&empty && "non C++11 compliant compiler");
- new (&empty) Empty(d.empty);
- break;
- case DomType::Map:
- Q_ASSERT((quintptr)this == (quintptr)&map && "non C++11 compliant compiler");
- new (&map) Map(d.map);
- break;
- case DomType::List:
- Q_ASSERT((quintptr)this == (quintptr)&list && "non C++11 compliant compiler");
- new (&list) List(d.list);
- break;
- case DomType::ConstantData:
- Q_ASSERT((quintptr)this == (quintptr)&data && "non C++11 compliant compiler");
- new (&data) ConstantData(d.data);
- break;
- case DomType::SimpleObjectWrap:
- Q_ASSERT((quintptr)this == (quintptr)&simpleObjectWrap && "non C++11 compliant compiler");
- new (&simpleObjectWrap) SimpleObjectWrap(d.simpleObjectWrap);
- break;
- case DomType::Reference:
- Q_ASSERT((quintptr)this == (quintptr)&reference && "non C++11 compliant compiler");
- new (&reference) Reference(d.reference);
- break;
- default:
- Q_ASSERT(false && "unexpected kind in inline element");
- break;
- }
- }
- InlineEl(const Empty &o) {
- Q_ASSERT((quintptr)this == (quintptr)&empty && "non C++11 compliant compiler");
- new (&empty) Empty(o);
- }
- InlineEl(const Map &o) {
- Q_ASSERT((quintptr)this == (quintptr)&map && "non C++11 compliant compiler");
- new (&map) Map(o);
- }
- InlineEl(const List &o){
- Q_ASSERT((quintptr)this == (quintptr)&list && "non C++11 compliant compiler");
- new (&list) List(o);
- }
- InlineEl(const ConstantData &o) {
- Q_ASSERT((quintptr)this == (quintptr)&data && "non C++11 compliant compiler");
- new (&data) ConstantData(o);
- }
- InlineEl(const SimpleObjectWrap &o) {
- Q_ASSERT((quintptr)this == (quintptr)&simpleObjectWrap && "non C++11 compliant compiler");
- new (&simpleObjectWrap) SimpleObjectWrap(o);
- }
- InlineEl(const Reference &o) {
- Q_ASSERT((quintptr)this == (quintptr)&reference && "non C++11 compliant compiler");
- new (&reference) Reference(o);
- }
- InlineEl &operator=(const InlineEl &d) {
- Q_ASSERT(this != &d);
- this->~InlineEl(); // destruct & construct new...
- new (this)InlineEl(d);
- return *this;
- }
- DomType kind() const {
- return reinterpret_cast<const DomBase*>(this)->kind();
- }
- ~InlineEl() {
- reinterpret_cast<const DomBase*>(this)->~DomBase();
- }
- Empty empty;
- Map map;
- List list;
- ConstantData data;
- SimpleObjectWrap simpleObjectWrap;
- Reference reference;
- } inlineEl;
+ ElementT m_element = Empty();
};
-bool operator ==(const DomItem &o1, const DomItem &o2);
-inline bool operator !=(const DomItem &o1, const DomItem &o2) {
+bool operator==(const DomItem &o1, const DomItem &o2);
+inline bool operator!=(const DomItem &o1, const DomItem &o2)
+{
return !(o1 == o2);
}
-Q_DECLARE_OPERATORS_FOR_FLAGS(LoadOptions)
-
-class Subpath {
-public:
- Path path;
- DomItem item;
-
- bool visit(function_ref<bool(Path, DomItem &)> visitor){
- return visitor(path, item);
- }
-};
-
template<typename T>
-Map Map::fromMultiMapRef(Path pathFromOwner, QMultiMap<QString,T> &mmap, std::function<DomItem(const DomItem &, Path, T&)> elWrapper)
+Map Map::fromMultiMapRef(
+ Path pathFromOwner, QMultiMap<QString, T> &mmap,
+ std::function<DomItem(DomItem &, const PathEls::PathComponent &, T &)> elWrapper)
{
- return Map(pathFromOwner, [&mmap, elWrapper](const DomItem &self, QString key) {
- auto it = mmap.find(key);
- auto end = mmap.cend();
- if (it == end)
- return DomItem();
- else {
- QList<T *> values;
- while (it != end && it.key() == key)
- values.append(&(*it++));
- return self.subList(List::fromQList<T*>(self.pathFromOwner().key(key), values, [elWrapper](const DomItem &l, Path p,T * &el) {
- return elWrapper(l,p,*el);
- }, ListOptions::Reverse)).item;
- }
- }, [&mmap](const DomItem&){
- return QSet<QString>(mmap.keyBegin(), mmap.keyEnd());
- }, QLatin1String(typeid(T).name()));
+ return Map(
+ pathFromOwner,
+ [&mmap, elWrapper](DomItem &self, QString key) {
+ auto it = mmap.find(key);
+ auto end = mmap.cend();
+ if (it == end)
+ return DomItem();
+ else {
+ // special case single element (++it == end || it.key() != key)?
+ QList<T *> values;
+ while (it != end && it.key() == key)
+ values.append(&(*it++));
+ ListP ll(self.pathFromOwner().appendComponent(PathEls::Key(key)), values,
+ QString(), ListOptions::Reverse);
+ return self.copy(ll);
+ }
+ },
+ [&mmap](DomItem &) { return QSet<QString>(mmap.keyBegin(), mmap.keyEnd()); },
+ QLatin1String(typeid(T).name()));
}
template<typename T>
-Map Map::fromMapRef(Path pathFromOwner, QMap<QString,T> &map,
- std::function<DomItem(const DomItem &, Path, T&)> elWrapper)
+Map Map::fromMapRef(
+ Path pathFromOwner, QMap<QString, T> &map,
+ std::function<DomItem(DomItem &, const PathEls::PathComponent &, T &)> elWrapper)
{
- return Map(pathFromOwner, [&map, elWrapper](const DomItem &self, QString key) {
- if (!map.contains(key))
- return DomItem();
- else {
- return elWrapper(self, Path::Key(key), map[key]);
- }
- }, [&map](const DomItem&){
- return QSet<QString>(map.keyBegin(), map.keyEnd());
- }, QLatin1String(typeid(T).name()));
+ return Map(
+ pathFromOwner,
+ [&map, elWrapper](DomItem &self, QString key) {
+ if (!map.contains(key))
+ return DomItem();
+ else {
+ return elWrapper(self, PathEls::Key(key), map[key]);
+ }
+ },
+ [&map](DomItem &) { return QSet<QString>(map.keyBegin(), map.keyEnd()); },
+ QLatin1String(typeid(T).name()));
}
template<typename T>
-List List::fromQList(Path pathFromOwner, QList<T> list, std::function<DomItem(const DomItem &, Path, T&)> elWrapper, ListOptions options)
+List List::fromQList(
+ Path pathFromOwner, QList<T> list,
+ std::function<DomItem(DomItem &, const PathEls::PathComponent &, T &)> elWrapper,
+ ListOptions options)
{
index_type len = list.length();
if (options == ListOptions::Reverse) {
return List(
- pathFromOwner,
- [list, elWrapper](const DomItem &self, index_type i) mutable {
- if (i < 0 || i >= list.length())
- return DomItem();
- return elWrapper(self, Path::Index(i), list[list.length() -i - 1]);
- }, [len](const DomItem &) {
- return len;
- }, nullptr, QLatin1String(typeid(T).name()));
+ pathFromOwner,
+ [list, elWrapper](DomItem &self, index_type i) mutable {
+ if (i < 0 || i >= list.length())
+ return DomItem();
+ return elWrapper(self, PathEls::Index(i), list[list.length() - i - 1]);
+ },
+ [len](DomItem &) { return len; }, nullptr, QLatin1String(typeid(T).name()));
} else {
- return List(pathFromOwner,
- [list, elWrapper](const DomItem &self, index_type i) mutable {
- if (i < 0 || i >= list.length())
- return DomItem();
- return elWrapper(self, Path::Index(i), list[i]);
- }, [len](const DomItem &) {
- return len;
- }, nullptr, QLatin1String(typeid(T).name()));
+ return List(
+ pathFromOwner,
+ [list, elWrapper](DomItem &self, index_type i) mutable {
+ if (i < 0 || i >= list.length())
+ return DomItem();
+ return elWrapper(self, PathEls::Index(i), list[i]);
+ },
+ [len](DomItem &) { return len; }, nullptr, QLatin1String(typeid(T).name()));
}
}
template<typename T>
-List List::fromQListRef(Path pathFromOwner, QList<T> &list, std::function<DomItem(const DomItem &, Path, T&)> elWrapper, ListOptions options)
+List List::fromQListRef(
+ Path pathFromOwner, QList<T> &list,
+ std::function<DomItem(DomItem &, const PathEls::PathComponent &, T &)> elWrapper,
+ ListOptions options)
{
if (options == ListOptions::Reverse) {
return List(
- pathFromOwner,
- [&list, elWrapper](const DomItem &self, index_type i) {
- if (i < 0 || i >= list.length())
- return DomItem();
- return elWrapper(self, Path::Index(i), list[list.length() -i - 1]);
- }, [&list](const DomItem &) {
- return list.length();
- }, nullptr, QLatin1String(typeid(T).name()));
+ pathFromOwner,
+ [&list, elWrapper](DomItem &self, index_type i) {
+ if (i < 0 || i >= list.length())
+ return DomItem();
+ return elWrapper(self, PathEls::Index(i), list[list.length() - i - 1]);
+ },
+ [&list](DomItem &) { return list.length(); }, nullptr,
+ QLatin1String(typeid(T).name()));
} else {
- return List(pathFromOwner,
- [&list, elWrapper](const DomItem &self, index_type i) {
- if (i < 0 || i >= list.length())
- return DomItem();
- return elWrapper(self, Path::Index(i), list[i]);
- }, [&list](const DomItem &) {
- return list.length();
- }, nullptr, QLatin1String(typeid(T).name()));
+ return List(
+ pathFromOwner,
+ [&list, elWrapper](DomItem &self, index_type i) {
+ if (i < 0 || i >= list.length())
+ return DomItem();
+ return elWrapper(self, PathEls::Index(i), list[i]);
+ },
+ [&list](DomItem &) { return list.length(); }, nullptr,
+ QLatin1String(typeid(T).name()));
}
}
class QMLDOM_EXPORT OwningItem: public DomBase {
protected:
- virtual std::shared_ptr<OwningItem> doCopy(const DomItem &self) const = 0;
+ virtual std::shared_ptr<OwningItem> doCopy(DomItem &self) const = 0;
+
public:
OwningItem(const OwningItem &o);
OwningItem(int derivedFrom=0);
OwningItem(int derivedFrom, QDateTime lastDataUpdateAt);
+ OwningItem(const OwningItem &&) = delete;
+ OwningItem &operator=(const OwningItem &&) = delete;
static int nextRevision();
- Path canonicalPath(const DomItem &self) const override = 0;
+ Path canonicalPath(DomItem &self) const override = 0;
- bool iterateDirectSubpaths(DomItem &self, function_ref<bool (Path, DomItem &)>) override;
- std::shared_ptr<OwningItem> makeCopy(const DomItem &self) {
- return doCopy(self);
- }
- Path pathFromOwner(const DomItem &self) const override;
- DomItem containingObject(const DomItem &self) const override;
+ bool iterateDirectSubpaths(DomItem &self, DirectVisitor) override;
+ std::shared_ptr<OwningItem> makeCopy(DomItem &self) const { return doCopy(self); }
+ Path pathFromOwner() const { return Path(); }
+ Path pathFromOwner(DomItem &) const override final { return Path(); }
+ DomItem containingObject(DomItem &self) const override;
int derivedFrom() const;
virtual int revision() const;
@@ -749,18 +1298,18 @@ public:
virtual bool freeze();
QDateTime frozenAt() const;
- virtual void addError(const DomItem &self, ErrorMessage msg);
+ virtual void addError(DomItem &self, ErrorMessage msg);
void addErrorLocal(ErrorMessage msg);
void clearErrors(ErrorGroups groups = ErrorGroups({}));
// return false if a quick exit was requested
- bool iterateErrors(const DomItem &self, function_ref<bool(DomItem source, ErrorMessage msg)> visitor, Path inPath = Path());
+ bool iterateErrors(DomItem &self, function_ref<bool(DomItem source, ErrorMessage msg)> visitor,
+ Path inPath = Path());
QMultiMap<Path, ErrorMessage> localErrors() const {
QMutexLocker l(mutex());
return m_errors;
}
-
- virtual bool iterateSubOwners(const DomItem &self, function_ref<bool(const DomItem &owner)> visitor);
+ virtual bool iterateSubOwners(DomItem &self, function_ref<bool(DomItem &owner)> visitor);
QBasicMutex *mutex() const { return &m_mutex; }
private:
@@ -773,162 +1322,52 @@ private:
QMultiMap<Path, ErrorMessage> m_errors;
};
-template <typename T>
-std::shared_ptr<T> DomItem::ownerAs() const {
- if (m_owner && m_owner->kind() == T::kindValue)
- return std::static_pointer_cast<T>(m_owner);
- return nullptr;
-}
-
-template <typename T>
-SimpleObjectWrap SimpleObjectWrap::fromDataObject(
- Path pathFromOwner, T const & val,
- std::function<QCborValue(T const &)> toData,
- const SourceLocation &loc,
- DomType kind,
- DomKind domKind,
- QString typeName)
-{
- QString objectName;
- if (!typeName.isEmpty())
- objectName = typeName;
- else if (kind != kindValue)
- objectName = domTypeToStringMap()[kind];
- else
- objectName = QLatin1String("SimpleObjectWrap<%1>").arg(QLatin1String(typeid(T).name()));
- return SimpleObjectWrap(
- pathFromOwner, QVariant::fromValue(&val),
- [toData, pathFromOwner](DomItem &self, QVariant v, function_ref<bool(Path, DomItem &)> visitor){
- ConstantData data = ConstantData(pathFromOwner, toData(*v.value<T const*>()), ConstantData::Options::FirstMapIsFields);
- return data.iterateDirectSubpaths(self, visitor);
- }, kind, domKind, objectName, loc);
-}
-
-template <typename T>
-SimpleObjectWrap SimpleObjectWrap::fromObjectRef(
- Path pathFromOwner, T &value,
- std::function<bool(DomItem &, T &val, function_ref<bool(Path, DomItem &)>)> directSubpathsIterate,
- const SourceLocation &loc,
- DomType kind,
- QString typeName,
- DomKind domKind)
-{
- return SimpleObjectWrap(
- pathFromOwner, QVariant::fromValue(&value),
- [directSubpathsIterate](DomItem &self, QVariant v, function_ref<bool(Path, DomItem &)> visitor){
- return directSubpathsIterate(self, *v.value<T *>(), visitor);
- },
- kind, domKind,
- ((!typeName.isEmpty()) ? typeName :
- (kind != kindValue) ? domTypeToStringMap()[kind] :
- QStringLiteral(u"SimpleObjectWrap<%1>").arg(QLatin1String(typeid(T).name()))),
- loc);
-}
-
-template <typename T>
-Subpath DomItem::subWrapPath(Path p, T &obj, SourceLocation loc) const {
- return this->subObjectWrap(SimpleObjectWrap::fromObjectRef<T>(
- this->pathFromOwner().path(p),
- obj,
- [](DomItem &self, T &fDef, function_ref<bool(Path, DomItem &)> visitor) {
- return fDef.iterateDirectSubpaths(self, visitor);
- },loc,
- T::kindValue));
-}
-
-template <typename T>
-Subpath DomItem::subWrapField(QString p, T &obj, SourceLocation loc) const {
- return this->subWrapPath<T>(Path::Field(p), obj, loc);
-}
-template <typename T>
-Subpath DomItem::subWrapField(QStringView p, T &obj, SourceLocation loc) const {
- return this->subWrapPath<T>(Path::Field(p), obj, loc);
-}
-template <typename T>
-Subpath DomItem::subWrapKey(QString p, T &obj, SourceLocation loc) const {
- return this->subWrapPath<T>(Path::Key(p), obj, loc);
-}
-template <typename T>
-Subpath DomItem::subWrapKey(QStringView p, T &obj, SourceLocation loc) const {
- return this->subWrapPath<T>(Path::Key(p), obj, loc);
-}
-template <typename T>
-Subpath DomItem::subWrapIndex(index_type i, T &obj, SourceLocation loc) const {
- return this->subWrapPath<T>(Path::Index(i), obj, loc);
+template<typename T>
+std::shared_ptr<T> DomItem::ownerAs()
+{
+ if constexpr (domTypeIsOwningItem(T::kindValue)) {
+ if (m_owner) {
+ if constexpr (T::kindValue == DomType::AttachedInfo) {
+ if (std::holds_alternative<std::shared_ptr<AttachedInfo>>(*m_owner))
+ return std::static_pointer_cast<T>(
+ std::get<std::shared_ptr<AttachedInfo>>(*m_owner));
+ } else if constexpr (T::kindValue == DomType::ExternalItemInfo) {
+ if (std::holds_alternative<std::shared_ptr<ExternalItemInfoBase>>(*m_owner))
+ return std::static_pointer_cast<T>(
+ std::get<std::shared_ptr<ExternalItemInfoBase>>(*m_owner));
+ } else if constexpr (T::kindValue == DomType::ExternalItemPair) {
+ if (std::holds_alternative<std::shared_ptr<ExternalItemPairBase>>(*m_owner))
+ return std::static_pointer_cast<T>(
+ std::get<std::shared_ptr<ExternalItemPairBase>>(*m_owner));
+ } else {
+ if (std::holds_alternative<std::shared_ptr<T>>(*m_owner)) {
+ return std::get<std::shared_ptr<T>>(*m_owner);
+ }
+ }
+ }
+ } else {
+ Q_ASSERT_X(false, "DomItem::ownerAs", "unexpected non owning value in ownerAs");
+ }
+ return std::shared_ptr<T> {};
}
-// mainly for debugging purposes
-class GenericObject: public DomElement {
-public:
- constexpr static DomType kindValue = DomType::GenericObject;
- DomType kind() const override { return kindValue; }
-
- GenericObject(Path pathFromOwner = Path(), const SourceLocation & loc = SourceLocation(),
- QMap<QString, GenericObject> subObjects = {},
- QMap<QString, QCborValue> subValues = {}):
- DomElement(pathFromOwner, loc), subObjects(subObjects), subValues(subValues) {}
-
- GenericObject copy() const;
- std::pair<QString, GenericObject> asStringPair() const;
-
- bool iterateDirectSubpaths(DomItem &self, function_ref<bool (Path, DomItem &)>) override;
-
- QMap<QString, GenericObject> subObjects;
- QMap<QString, QCborValue> subValues;
-};
-
-// mainly for debugging purposes
-class GenericOwner: public OwningItem {
-protected:
- std::shared_ptr<OwningItem> doCopy(const DomItem &self) const override;
-public:
- constexpr static DomType kindValue = DomType::GenericOwner;
- DomType kind() const override { return kindValue; }
-
- GenericOwner(Path pathFromTop = Path(), int derivedFrom = 0,
- QMap<QString, GenericObject> subObjects = {},
- QMap<QString, QCborValue> subValues = {}):
- OwningItem(derivedFrom), pathFromTop(pathFromTop), subObjects(subObjects),
- subValues(subValues)
- {}
-
- GenericOwner(Path pathFromTop, int derivedFrom, QDateTime dataRefreshedAt,
- QMap<QString, GenericObject> subObjects = {},
- QMap<QString, QCborValue> subValues = {}):
- OwningItem(derivedFrom, dataRefreshedAt), pathFromTop(pathFromTop), subObjects(subObjects),
- subValues(subValues)
- {}
-
- GenericOwner(const GenericOwner &o);
-
- std::shared_ptr<GenericOwner> makeCopy(const DomItem &self);
- Path canonicalPath(const DomItem &self) const override;
-
- bool iterateDirectSubpaths(DomItem &self, function_ref<bool (Path, DomItem &)>) override;
-
- Path pathFromTop;
- QMap<QString, GenericObject> subObjects;
- QMap<QString, QCborValue> subValues;
-};
-
QDebug operator<<(QDebug debug, const DomItem &c);
-
class MutableDomItem {
public:
- operator bool() const {
- return m_owner && base();
- }
- DomType internalKind() const {
- return base().internalKind();
- }
- DomKind domKind() const { return kind2domKind(internalKind()); }
+ using CopyOption = DomItem::CopyOption;
- Path canonicalPath() const
+ explicit operator bool() const
+ {
+ return bool(m_owner);
+ } // this is weaker than item(), but normally correct
+ DomType internalKind() { return item().internalKind(); }
+ QString internalKindStr() { return domTypeToString(internalKind()); }
+ DomKind domKind() { return kind2domKind(internalKind()); }
+
+ Path canonicalPath() { return m_owner.canonicalPath().path(m_pathFromOwner); }
+ MutableDomItem containingObject()
{
- return m_owner.canonicalPath().path(m_pathFromOwner);
- }
- MutableDomItem containingObject() const {
if (m_pathFromOwner)
return MutableDomItem(m_owner, m_pathFromOwner.split().pathToSource);
else {
@@ -937,126 +1376,135 @@ public:
}
}
- MutableDomItem container() const {
+ MutableDomItem container()
+ {
if (m_pathFromOwner)
return MutableDomItem(m_owner, m_pathFromOwner.dropTail());
else {
- return MutableDomItem(base().container());
+ return MutableDomItem(item().container());
}
}
- MutableDomItem component() const {
- return MutableDomItem{base().component()};
- }
- MutableDomItem owner() const {
- return MutableDomItem(m_owner);
- }
- MutableDomItem top() const {
- return MutableDomItem(base().top());
- }
- MutableDomItem environment() const {
- return MutableDomItem(base().environment());
- }
- MutableDomItem universe() const {
- return MutableDomItem(base().universe());
- }
- Path pathFromOwner() const {
- return m_pathFromOwner;
- }
- MutableDomItem operator[](const Path &path) const {
- return MutableDomItem(base()[path]);
- }
- MutableDomItem operator[](QStringView component) const {
- return MutableDomItem(base()[component]);
- }
- MutableDomItem operator[](const QString &component) const {
- return MutableDomItem(base()[component]);
+ MutableDomItem qmlObject(GoTo option = GoTo::Strict,
+ FilterUpOptions fOptions = FilterUpOptions::ReturnOuter)
+ {
+ return MutableDomItem(item().qmlObject(option, fOptions));
}
- MutableDomItem operator[](const char16_t *component) const {
- // to avoid clash with stupid builtin ptrdiff_t[MutableDomItem&], coming from C
- return MutableDomItem(base()[QStringView(component)]);
+ MutableDomItem fileObject(GoTo option = GoTo::Strict)
+ {
+ return MutableDomItem(item().fileObject(option));
}
- MutableDomItem operator[](index_type i) const {
- return MutableDomItem(base().index(i));
+ MutableDomItem rootQmlObject(GoTo option = GoTo::Strict)
+ {
+ return MutableDomItem(item().rootQmlObject(option));
}
+ MutableDomItem globalScope() { return MutableDomItem(item().globalScope()); }
+ MutableDomItem scope() { return MutableDomItem(item().scope()); }
- MutableDomItem path(const Path &p) const {
- return MutableDomItem(base().path(p));
+ MutableDomItem component(GoTo option = GoTo::Strict)
+ {
+ return MutableDomItem { item().component(option) };
}
- MutableDomItem path(const QString &p) const {
- return path(Path::fromString(p));
+ MutableDomItem owner() { return MutableDomItem(m_owner); }
+ MutableDomItem top() { return MutableDomItem(item().top()); }
+ MutableDomItem environment() { return MutableDomItem(item().environment()); }
+ MutableDomItem universe() { return MutableDomItem(item().universe()); }
+ Path pathFromOwner() { return m_pathFromOwner; }
+ MutableDomItem operator[](const Path &path) { return MutableDomItem(item()[path]); }
+ MutableDomItem operator[](QStringView component) { return MutableDomItem(item()[component]); }
+ MutableDomItem operator[](const QString &component)
+ {
+ return MutableDomItem(item()[component]);
}
- MutableDomItem path(QStringView p) const {
- return path(Path::fromString(p));
+ MutableDomItem operator[](const char16_t *component)
+ {
+ // to avoid clash with stupid builtin ptrdiff_t[MutableDomItem&], coming from C
+ return MutableDomItem(item()[QStringView(component)]);
}
+ MutableDomItem operator[](index_type i) { return MutableDomItem(item().index(i)); }
- QList<QString> const fields() const {
- return base().fields();
- }
- MutableDomItem field(QStringView name) const {
- return MutableDomItem(base().field(name));
- }
- index_type indexes() const {
- return base().indexes();
- }
- MutableDomItem index(index_type i) const {
- return MutableDomItem(base().index(i));
- }
+ MutableDomItem path(const Path &p) { return MutableDomItem(item().path(p)); }
+ MutableDomItem path(const QString &p) { return path(Path::fromString(p)); }
+ MutableDomItem path(QStringView p) { return path(Path::fromString(p)); }
- QSet<QString> const keys() const {
- return base().keys();
- }
- MutableDomItem key(QString name) const {
- return MutableDomItem(base().key(name));
- }
+ QList<QString> const fields() { return item().fields(); }
+ MutableDomItem field(QStringView name) { return MutableDomItem(item().field(name)); }
+ index_type indexes() { return item().indexes(); }
+ MutableDomItem index(index_type i) { return MutableDomItem(item().index(i)); }
- QString canonicalFilePath() const { return base().canonicalFilePath(); }
- SourceLocation location() const { return base().location(); }
+ QSet<QString> const keys() { return item().keys(); }
+ MutableDomItem key(QString name) { return MutableDomItem(item().key(name)); }
+ MutableDomItem key(QStringView name) { return key(name.toString()); }
- QCborValue value() const {
- return base().value();
+ void
+ dump(Sink s, int indent = 0,
+ function_ref<bool(DomItem &, const PathEls::PathComponent &, DomItem &)> filter = noFilter)
+ {
+ item().dump(s, indent, filter);
}
- void dump(Sink sink, int indent = 0) const {
- return base().dump(sink, indent);
- }
- QString toString() const {
- return base().toString();
+ MutableDomItem fileLocations() { return MutableDomItem(item().fileLocations()); }
+ MutableDomItem makeCopy(CopyOption option = CopyOption::EnvConnected)
+ {
+ return item().makeCopy(option);
}
+ bool commitToBase() { return item().commitToBase(); }
+ QString canonicalFilePath() { return item().canonicalFilePath(); }
- // convenience getters
- QString name() const;
- MutableDomItem qmlChildren() const {
- return MutableDomItem(base().qmlChildren());
- }
- MutableDomItem annotations() const {
- return MutableDomItem(base().annotations());
- }
+ MutableDomItem refreshed() { return MutableDomItem(item().refreshed()); }
- QMultiMap<QString, RequiredProperty> extraRequired() const;
+ QCborValue value() { return item().value(); }
+ QString toString() { return item().toString(); }
-// // OwnigItem elements
- int derivedFrom() const {
- return m_owner.derivedFrom();
- }
- int revision() const {
- return m_owner.revision();
- }
- QDateTime createdAt() const {
- return m_owner.createdAt();
- }
- QDateTime frozenAt() const {
- return m_owner.frozenAt();
- }
- QDateTime lastDataUpdateAt() const {
- return m_owner.lastDataUpdateAt();
+ // convenience getters
+ QString name() { return item().name(); }
+ MutableDomItem pragmas() { return item().pragmas(); }
+ MutableDomItem ids() { return MutableDomItem::item().ids(); }
+ QString idStr() { return item().idStr(); }
+ MutableDomItem propertyDefs() { return MutableDomItem(item().propertyDefs()); }
+ MutableDomItem bindings() { return MutableDomItem(item().bindings()); }
+ MutableDomItem methods() { return MutableDomItem(item().methods()); }
+ MutableDomItem children() { return MutableDomItem(item().children()); }
+ MutableDomItem child(index_type i) { return MutableDomItem(item().child(i)); }
+ MutableDomItem annotations() { return MutableDomItem(item().annotations()); }
+
+ // // OwnigItem elements
+ int derivedFrom() { return m_owner.derivedFrom(); }
+ int revision() { return m_owner.revision(); }
+ QDateTime createdAt() { return m_owner.createdAt(); }
+ QDateTime frozenAt() { return m_owner.frozenAt(); }
+ QDateTime lastDataUpdateAt() { return m_owner.lastDataUpdateAt(); }
+
+ void addError(ErrorMessage msg) { item().addError(msg); }
+ ErrorHandler errorHandler();
+
+ // convenience setters
+ MutableDomItem addPrototypePath(Path prototypePath);
+ MutableDomItem setNextScopePath(Path nextScopePath);
+ MutableDomItem setPropertyDefs(QMultiMap<QString, PropertyDefinition> propertyDefs);
+ MutableDomItem setBindings(QMultiMap<QString, Binding> bindings);
+ MutableDomItem setMethods(QMultiMap<QString, MethodInfo> functionDefs);
+ MutableDomItem setChildren(QList<QmlObject> children);
+ MutableDomItem setAnnotations(QList<QmlObject> annotations);
+ MutableDomItem setScript(std::shared_ptr<ScriptExpression> exp);
+ MutableDomItem setCode(QString code);
+ MutableDomItem addPropertyDef(PropertyDefinition propertyDef,
+ AddOption option = AddOption::Overwrite);
+ MutableDomItem addBinding(Binding binding, AddOption option = AddOption::Overwrite);
+ MutableDomItem addMethod(MethodInfo functionDef, AddOption option = AddOption::Overwrite);
+ MutableDomItem addChild(QmlObject child);
+ MutableDomItem addAnnotation(QmlObject child);
+ MutableDomItem addPreComment(const Comment &comment, QString regionName = QString());
+ MutableDomItem addPreComment(const Comment &comment, QStringView regionName)
+ {
+ return addPreComment(comment, regionName.toString());
}
-
- void addError(ErrorMessage msg) const {
- base().addError(msg);
+ MutableDomItem addPostComment(const Comment &comment, QString regionName = QString());
+ MutableDomItem addPostComment(const Comment &comment, QStringView regionName)
+ {
+ return addPostComment(comment, regionName.toString());
}
- ErrorHandler errorHandler() const;
MutableDomItem() = default;
MutableDomItem(DomItem owner, Path pathFromOwner):
@@ -1066,32 +1514,38 @@ public:
m_owner(item.owner()), m_pathFromOwner(item.pathFromOwner())
{}
- std::shared_ptr<DomTop> topPtr() const {
- return m_owner.topPtr();
- }
- std::shared_ptr<OwningItem> owningItemPtr() const {
- return m_owner.owningItemPtr();
- }
+ std::shared_ptr<DomTop> topPtr() { return m_owner.topPtr(); }
+ std::shared_ptr<OwningItem> owningItemPtr() { return m_owner.owningItemPtr(); }
- template <typename T>
- T const*as() const {
- return base().as<T>();
+ template<typename T>
+ T const *as()
+ {
+ return item().as<T>();
}
template <typename T>
T *mutableAs() {
- Q_ASSERT(!m_owner.owningItemPtr()->frozen());
- return base().mutableAs<T>();
+ Q_ASSERT(!m_owner || !m_owner.owningItemPtr()->frozen());
+ return item().mutableAs<T>();
}
- template <typename T>
- std::shared_ptr<T> ownerAs() const {
+ template<typename T>
+ std::shared_ptr<T> ownerAs()
+ {
return m_owner.ownerAs<T>();
}
// it is dangerous to assume it stays valid when updates are preformed...
- DomItem base() const {
- return m_owner.path(m_pathFromOwner);
+ DomItem item() { return m_owner.path(m_pathFromOwner); }
+
+ friend bool operator==(const MutableDomItem o1, const MutableDomItem &o2)
+ {
+ return o1.m_owner == o2.m_owner && o1.m_pathFromOwner == o2.m_pathFromOwner;
+ }
+ friend bool operator!=(const MutableDomItem &o1, const MutableDomItem &o2)
+ {
+ return !(o1 == o2);
}
+
private:
DomItem m_owner;
Path m_pathFromOwner;
@@ -1099,8 +1553,27 @@ private:
QDebug operator<<(QDebug debug, const MutableDomItem &c);
-template <typename K, typename T>
-Path insertUpdatableElementInMultiMap(Path mapPathFromOwner, QMultiMap<K, T> &mmap, K key, const T&value) {
+template<typename K, typename T>
+Path insertUpdatableElementInMultiMap(Path mapPathFromOwner, QMultiMap<K, T> &mmap, K key,
+ const T &value, AddOption option = AddOption::KeepExisting,
+ T **valuePtr = nullptr)
+{
+ if (option == AddOption::Overwrite) {
+ auto it = mmap.find(key);
+ if (it != mmap.end()) {
+ T &v = *it;
+ v = value;
+ if (++it != mmap.end() && it.key() == key) {
+ qWarning() << " requested overwrite of " << key
+ << " that contains aleready multiple entries in" << mapPathFromOwner;
+ }
+ Path newPath = mapPathFromOwner.key(key).index(0);
+ v.updatePathFromOwner(newPath);
+ if (valuePtr)
+ *valuePtr = &v;
+ return newPath;
+ }
+ }
mmap.insert(key, value);
auto it = mmap.find(key);
auto it2 = it;
@@ -1110,21 +1583,27 @@ Path insertUpdatableElementInMultiMap(Path mapPathFromOwner, QMultiMap<K, T> &mm
++it2;
}
Path newPath = mapPathFromOwner.key(key).index(nVal-1);
- T &newComp = *it;
- newComp.updatePathFromOwner(newPath);
+ T &v = *it;
+ v.updatePathFromOwner(newPath);
+ if (valuePtr)
+ *valuePtr = &v;
return newPath;
}
-template <typename T>
-Path appendUpdatableElementInQList(Path listPathFromOwner, QList<T> &list, const T&value) {
+template<typename T>
+Path appendUpdatableElementInQList(Path listPathFromOwner, QList<T> &list, const T &value,
+ T **vPtr = nullptr)
+{
int idx = list.length();
list.append(value);
Path newPath = listPathFromOwner.index(idx);
- list[idx].updatePathFromOwner(newPath);
+ T &targetV = list[idx];
+ targetV.updatePathFromOwner(newPath);
+ if (vPtr)
+ *vPtr = &targetV;
return newPath;
}
-
template <typename T, typename K = QString>
void updatePathFromOwnerMultiMap(QMultiMap<K, T> &mmap, Path newPath)
{
@@ -1136,7 +1615,7 @@ void updatePathFromOwnerMultiMap(QMultiMap<K, T> &mmap, Path newPath)
while (it != end) {
if (i > 0 && name != it.key()) {
Path pName = newPath.key(QString(name));
- foreach (T *el, els)
+ for (T *el : els)
el->updatePathFromOwner(pName.index(--i));
els.clear();
els.append(&(*it));
@@ -1150,7 +1629,7 @@ void updatePathFromOwnerMultiMap(QMultiMap<K, T> &mmap, Path newPath)
++it;
}
Path pName = newPath.key(name);
- foreach (T *el, els)
+ for (T *el : els)
el->updatePathFromOwner(pName.index(--i));
}
@@ -1164,6 +1643,415 @@ void updatePathFromOwnerQList(QList<T> &list, Path newPath)
(it++)->updatePathFromOwner(newPath.index(i++));
}
+constexpr bool domTypeIsObjWrap(DomType k)
+{
+ switch (k) {
+ case DomType::Binding:
+ case DomType::EnumItem:
+ case DomType::ErrorMessage:
+ case DomType::Export:
+ case DomType::Id:
+ case DomType::Import:
+ case DomType::ImportScope:
+ case DomType::MethodInfo:
+ case DomType::MethodParameter:
+ case DomType::ModuleAutoExport:
+ case DomType::Pragma:
+ case DomType::PropertyDefinition:
+ case DomType::Version:
+ case DomType::Comment:
+ case DomType::CommentedElement:
+ case DomType::RegionComments:
+ case DomType::FileLocations:
+ case DomType::UpdatedScriptExpression:
+ return true;
+ default:
+ return false;
+ }
+}
+
+constexpr bool domTypeIsValueWrap(DomType k)
+{
+ switch (k) {
+ case DomType::PropertyInfo:
+ return true;
+ default:
+ return false;
+ }
+}
+
+constexpr bool domTypeIsDomElement(DomType k)
+{
+ switch (k) {
+ case DomType::ModuleScope:
+ case DomType::QmlObject:
+ case DomType::ConstantData:
+ case DomType::SimpleObjectWrap:
+ case DomType::Reference:
+ case DomType::Map:
+ case DomType::List:
+ case DomType::ListP:
+ case DomType::EnumDecl:
+ case DomType::JsResource:
+ case DomType::QmltypesComponent:
+ case DomType::QmlComponent:
+ case DomType::GlobalComponent:
+ case DomType::MockObject:
+ return true;
+ default:
+ return false;
+ }
+}
+
+constexpr bool domTypeIsOwningItem(DomType k)
+{
+ switch (k) {
+ case DomType::ModuleIndex:
+
+ case DomType::MockOwner:
+
+ case DomType::ExternalItemInfo:
+ case DomType::ExternalItemPair:
+
+ case DomType::QmlDirectory:
+ case DomType::QmldirFile:
+ case DomType::JsFile:
+ case DomType::QmlFile:
+ case DomType::QmltypesFile:
+ case DomType::GlobalScope:
+
+ case DomType::ScriptExpression:
+ case DomType::AstComments:
+
+ case DomType::LoadInfo:
+ case DomType::AttachedInfo:
+
+ case DomType::DomEnvironment:
+ case DomType::DomUniverse:
+ return true;
+ default:
+ return false;
+ }
+}
+
+constexpr bool domTypeIsUnattachedOwningItem(DomType k)
+{
+ switch (k) {
+ case DomType::ScriptExpression:
+ case DomType::AstComments:
+ case DomType::AttachedInfo:
+ return true;
+ default:
+ return false;
+ }
+}
+
+template<typename T>
+DomItem DomItem::subValueItem(const PathEls::PathComponent &c, T value,
+ ConstantData::Options options)
+{
+ using BaseT = std::remove_cv_t<std::remove_reference_t<T>>;
+ if constexpr (
+ std::is_base_of_v<
+ QCborValue,
+ BaseT> || std::is_base_of_v<QCborArray, BaseT> || std::is_base_of_v<QCborMap, BaseT>) {
+ return DomItem(m_top, m_owner, m_ownerPath,
+ ConstantData(pathFromOwner().appendComponent(c), value, options));
+ } else if constexpr (std::is_same_v<DomItem, BaseT>) {
+ Q_UNUSED(options);
+ return value;
+ } else if constexpr (IsList<T>::value && !std::is_convertible_v<BaseT, QStringView>) {
+ return subListItem(List::fromQList<typename BaseT::value_type>(
+ pathFromOwner().appendComponent(c), value,
+ [options](DomItem &list, const PathEls::PathComponent &p,
+ typename T::value_type &v) { return list.subValueItem(p, v, options); }));
+ } else if constexpr (IsSharedPointerToDomObject<BaseT>::value) {
+ Q_UNUSED(options);
+ return subOwnerItem(c, value);
+ } else {
+ return subDataItem(c, value, options);
+ }
+}
+
+template<typename T>
+DomItem DomItem::subDataItem(const PathEls::PathComponent &c, T value,
+ ConstantData::Options options)
+{
+ using BaseT = std::remove_cv_t<std::remove_reference_t<T>>;
+ if constexpr (std::is_same_v<BaseT, ConstantData>) {
+ return this->copy(value);
+ } else if constexpr (std::is_base_of_v<QCborValue, BaseT>) {
+ return DomItem(m_top, m_owner, m_ownerPath,
+ ConstantData(pathFromOwner().appendComponent(c), value, options));
+ } else {
+ return DomItem(
+ m_top, m_owner, m_ownerPath,
+ ConstantData(pathFromOwner().appendComponent(c), QCborValue(value), options));
+ }
+}
+
+template<typename T>
+bool DomItem::dvValue(DirectVisitor visitor, const PathEls::PathComponent &c, T value,
+ ConstantData::Options options)
+{
+ auto lazyWrap = [this, &c, &value, options]() {
+ return this->subValueItem<T>(c, value, options);
+ };
+ return visitor(c, lazyWrap);
+}
+
+template<typename F>
+bool DomItem::dvValueLazy(DirectVisitor visitor, const PathEls::PathComponent &c, F valueF,
+ ConstantData::Options options)
+{
+ auto lazyWrap = [this, &c, &valueF, options]() {
+ return this->subValueItem<decltype(valueF())>(c, valueF(), options);
+ };
+ return visitor(c, lazyWrap);
+}
+
+template<typename T>
+DomItem DomItem::wrap(const PathEls::PathComponent &c, T &obj)
+{
+ using BaseT = std::decay_t<T>;
+ if constexpr (std::is_same_v<QString, BaseT> || std::is_arithmetic_v<BaseT>) {
+ return this->subDataItem(c, QCborValue(obj));
+ } else if constexpr (std::is_same_v<SourceLocation, BaseT>) {
+ return this->subLocationItem(c, obj);
+ } else if constexpr (std::is_same_v<BaseT, Reference>) {
+ Q_ASSERT_X(false, "DomItem::wrap",
+ "wrapping a reference object, probably an error (wrap the target path instead)");
+ return this->copy(obj);
+ } else if constexpr (std::is_same_v<BaseT, ConstantData>) {
+ return this->subDataItem(c, obj);
+ } else if constexpr (std::is_same_v<BaseT, Map>) {
+ return this->subMapItem(obj);
+ } else if constexpr (std::is_same_v<BaseT, List>) {
+ return this->subListItem(obj);
+ } else if constexpr (std::is_base_of_v<ListPBase, BaseT>) {
+ return this->subListItem(obj);
+ } else if constexpr (std::is_same_v<BaseT, SimpleObjectWrap>) {
+ return this->subObjectWrapItem(obj);
+ } else if constexpr (IsDomObject<BaseT>::value) {
+ if constexpr (domTypeIsObjWrap(BaseT::kindValue) || domTypeIsValueWrap(BaseT::kindValue)) {
+ return this->subObjectWrapItem(
+ SimpleObjectWrap::fromObjectRef(this->pathFromOwner().appendComponent(c), obj));
+ } else if constexpr (domTypeIsDomElement(BaseT::kindValue)) {
+ return this->copy(&obj);
+ } else {
+ qCWarning(domLog) << "Unhandled object of type " << domTypeToString(BaseT::kindValue)
+ << " in DomItem::wrap, not using a shared_ptr for an "
+ << "OwningItem, or unexpected wrapped object?";
+ return DomItem();
+ }
+ } else if constexpr (IsSharedPointerToDomObject<BaseT>::value) {
+ if constexpr (domTypeIsOwningItem(BaseT::element_type::kindValue)) {
+ return this->subOwnerItem(c, obj);
+ } else {
+ Q_ASSERT_X(false, "DomItem::wrap", "shared_ptr with non owning item");
+ return DomItem();
+ }
+ } else if constexpr (IsMultiMap<BaseT>::value) {
+ if constexpr (std::is_same_v<typename BaseT::key_type, QString>) {
+ return subMapItem(Map::fromMultiMapRef<typename BaseT::mapped_type>(
+ pathFromOwner().appendComponent(c), obj,
+ [](DomItem &map, const PathEls::PathComponent &p,
+ typename BaseT::mapped_type &el) { return map.wrap(p, el); }));
+ } else {
+ Q_ASSERT_X(false, "DomItem::wrap", "non string keys not supported (try .toString()?)");
+ }
+ } else if constexpr (IsMap<BaseT>::value) {
+ if constexpr (std::is_same_v<typename BaseT::key_type, QString>) {
+ return subMapItem(Map::fromMapRef<typename BaseT::mapped_type>(
+ pathFromOwner().appendComponent(c), obj,
+ [](DomItem &map, const PathEls::PathComponent &p,
+ typename BaseT::mapped_type &el) { return map.wrap(p, el); }));
+ } else {
+ Q_ASSERT_X(false, "DomItem::wrap", "non string keys not supported (try .toString()?)");
+ }
+ } else if constexpr (IsList<BaseT>::value) {
+ if constexpr (IsDomObject<typename BaseT::value_type>::value) {
+ return subListItem(List::fromQListRef<typename BaseT::value_type>(
+ pathFromOwner().appendComponent(c), obj,
+ [](DomItem &list, const PathEls::PathComponent &p,
+ typename BaseT::value_type &el) { return list.wrap(p, el); }));
+ } else {
+ Q_ASSERT_X(false, "DomItem::wrap", "Unsupported list type T");
+ return DomItem();
+ }
+ } else {
+ qCWarning(domLog) << "Cannot wrap " << typeid(BaseT).name();
+ Q_ASSERT_X(false, "DomItem::wrap", "Do not know how to wrap type T");
+ return DomItem();
+ }
+}
+
+template<typename T>
+bool DomItem::dvWrap(DirectVisitor visitor, const PathEls::PathComponent &c, T &obj)
+{
+ auto lazyWrap = [this, &c, &obj]() { return this->wrap<T>(c, obj); };
+ return visitor(c, lazyWrap);
+}
+
+template<typename T>
+bool ListPT<T>::iterateDirectSubpaths(DomItem &self, DirectVisitor v)
+{
+ index_type len = index_type(m_pList.size());
+ for (index_type i = 0; i < len; ++i) {
+ if (!v(PathEls::Index(i), [this, &self, i] { return this->index(self, i); }))
+ return false;
+ }
+ return true;
+}
+
+template<typename T>
+DomItem ListPT<T>::index(DomItem &self, index_type index) const
+{
+ if (index >= 0 && index < m_pList.length())
+ return self.wrap(PathEls::Index(index), *reinterpret_cast<T *>(m_pList.value(index)));
+ return DomItem();
+}
+
+// allow inlining of DomBase
+inline DomKind DomBase::domKind() const
+{
+ return kind2domKind(kind());
+}
+
+inline bool DomBase::iterateDirectSubpathsConst(DomItem &self, DirectVisitor visitor) const
+{
+ Q_ASSERT(self.base() == this);
+ return self.iterateDirectSubpaths(visitor);
+}
+
+inline DomItem DomBase::containingObject(DomItem &self) const
+{
+ Path path = pathFromOwner(self);
+ DomItem base = self.owner();
+ if (!path) {
+ path = canonicalPath(self);
+ base = self;
+ }
+ Source source = path.split();
+ return base.path(source.pathToSource);
+}
+
+inline quintptr DomBase::id() const
+{
+ return quintptr(this);
+}
+
+inline QString DomBase::typeName() const
+{
+ return domTypeToString(kind());
+}
+
+inline QList<QString> DomBase::fields(DomItem &self) const
+{
+ QList<QString> res;
+ self.iterateDirectSubpaths([&res](const PathEls::PathComponent &c, function_ref<DomItem()>) {
+ if (c.kind() == Path::Kind::Field)
+ res.append(c.name());
+ return true;
+ });
+ return res;
+}
+
+inline DomItem DomBase::field(DomItem &self, QStringView name) const
+{
+ DomItem res;
+ self.iterateDirectSubpaths(
+ [&res, name](const PathEls::PathComponent &c, function_ref<DomItem()> obj) {
+ if (c.kind() == Path::Kind::Field && c.checkName(name)) {
+ res = obj();
+ return false;
+ }
+ return true;
+ });
+ return res;
+}
+
+inline index_type DomBase::indexes(DomItem &self) const
+{
+ index_type res = 0;
+ self.iterateDirectSubpaths([&res](const PathEls::PathComponent &c, function_ref<DomItem()>) {
+ if (c.kind() == Path::Kind::Index) {
+ index_type i = c.index() + 1;
+ if (res < i)
+ res = i;
+ }
+ return true;
+ });
+ return res;
+}
+
+inline DomItem DomBase::index(DomItem &self, qint64 index) const
+{
+ DomItem res;
+ self.iterateDirectSubpaths(
+ [&res, index](const PathEls::PathComponent &c, function_ref<DomItem()> obj) {
+ if (c.kind() == Path::Kind::Index && c.index() == index) {
+ res = obj();
+ return false;
+ }
+ return true;
+ });
+ return res;
+}
+
+inline QSet<QString> const DomBase::keys(DomItem &self) const
+{
+ QSet<QString> res;
+ self.iterateDirectSubpaths([&res](const PathEls::PathComponent &c, function_ref<DomItem()>) {
+ if (c.kind() == Path::Kind::Key)
+ res.insert(c.name());
+ return true;
+ });
+ return res;
+}
+
+inline DomItem DomBase::key(DomItem &self, QString name) const
+{
+ DomItem res;
+ self.iterateDirectSubpaths(
+ [&res, name](const PathEls::PathComponent &c, function_ref<DomItem()> obj) {
+ if (c.kind() == Path::Kind::Key && c.checkName(name)) {
+ res = obj();
+ return false;
+ }
+ return true;
+ });
+ return res;
+}
+
+inline DomItem DomItem::subReferencesItem(const PathEls::PathComponent &c, QList<Path> paths)
+{
+ return subListItem(
+ List::fromQList<Path>(pathFromOwner().appendComponent(c), paths,
+ [](DomItem &list, const PathEls::PathComponent &p, Path &el) {
+ return list.subReferenceItem(p, el);
+ }));
+}
+
+inline DomItem DomItem::subReferenceItem(const PathEls::PathComponent &c, Path referencedObject)
+{
+ if (domTypeIsOwningItem(internalKind()))
+ return DomItem(m_top, m_owner, m_ownerPath, Reference(referencedObject, Path(c)));
+ else
+ return DomItem(m_top, m_owner, m_ownerPath,
+ Reference(referencedObject, pathFromOwner().appendComponent(c)));
+}
+
+inline DomItem DomItem::subListItem(const List &list)
+{
+ return DomItem(m_top, m_owner, m_ownerPath, list);
+}
+
+inline DomItem DomItem::subMapItem(const Map &map)
+{
+ return DomItem(m_top, m_owner, m_ownerPath, map);
+}
+
} // end namespace Dom
} // end namespace QQmlJS