diff options
Diffstat (limited to 'src/qmldom/qqmldompath_p.h')
-rw-r--r-- | src/qmldom/qqmldompath_p.h | 880 |
1 files changed, 464 insertions, 416 deletions
diff --git a/src/qmldom/qqmldompath_p.h b/src/qmldom/qqmldompath_p.h index 839a34a233..1a5af85e8e 100644 --- a/src/qmldom/qqmldompath_p.h +++ b/src/qmldom/qqmldompath_p.h @@ -1,40 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -**/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + #ifndef QMLDOM_PATH_H #define QMLDOM_PATH_H @@ -103,82 +69,72 @@ class Filter; class Base { public: - virtual ~Base() = default; - virtual Kind kind() const = 0; - virtual QString name() const = 0; - virtual bool checkName(QStringView s) const = 0; - virtual QStringView stringView() const { return QStringView(); } - virtual index_type index(index_type defaultValue=-1) const { return defaultValue; } - - virtual void dump(Sink sink) const; - virtual bool hasSquareBrackets() const { return false; } - - // casting, could use optional, but that is c++17... - virtual const Empty *asEmpty() const { return nullptr; } - virtual const Field *asField() const { return nullptr; } - virtual const Index *asIndex() const { return nullptr; } - virtual const Key *asKey() const { return nullptr; } - virtual const Root *asRoot() const { return nullptr; } - virtual const Current *asCurrent() const { return nullptr; } - virtual const Any *asAny() const { return nullptr; } - virtual const Filter *asFilter() const { return nullptr; } + QStringView stringView() const { return QStringView(); } + index_type index(index_type defaultValue = -1) const { return defaultValue; } + bool hasSquareBrackets() const { return false; } + +protected: + void dump(const Sink &sink, const QString &name, bool hasSquareBrackets) const; }; -class Empty: public Base { +class Empty final : public Base +{ public: - Kind kind() const override { return Kind::Empty; } - QString name() const override { return QString(); } - bool checkName(QStringView s) const override { return s.isEmpty(); } - const Empty * asEmpty() const override { return this; } + Empty() = default; + QString name() const { return QString(); } + bool checkName(QStringView s) const { return s.isEmpty(); } + void dump(const Sink &sink) const { Base::dump(sink, name(), hasSquareBrackets()); } }; -class Field: public Base { +class Field final : public Base +{ public: + Field() = default; Field(QStringView n): fieldName(n) {} - Kind kind() const override { return Kind::Field; } - QString name() const override { return fieldName.toString(); } - bool checkName(QStringView s) const override { return s == fieldName; } - QStringView stringView() const override { return fieldName; } - const Field * asField() const override { return this; } - void dump(Sink sink) const override { sink(fieldName); } + QString name() const { return fieldName.toString(); } + bool checkName(QStringView s) const { return s == fieldName; } + QStringView stringView() const { return fieldName; } + void dump(const Sink &sink) const { sink(fieldName); } QStringView fieldName; }; -class Index: public Base { +class Index final : public Base +{ public: + Index() = default; Index(index_type i): indexValue(i) {} - Kind kind() const override { return Kind::Index; } - QString name() const override { return QString::number(indexValue); } - bool checkName(QStringView s) const override { return s == name(); } - index_type index(index_type = -1) const override { return indexValue; } - bool hasSquareBrackets() const override { return true; } - const Index * asIndex() const override { return this; } - - index_type indexValue; + QString name() const { return QString::number(indexValue); } + bool checkName(QStringView s) const { return s == name(); } + index_type index(index_type = -1) const { return indexValue; } + void dump(const Sink &sink) const { Base::dump(sink, name(), hasSquareBrackets()); } + bool hasSquareBrackets() const { return true; } + + index_type indexValue = -1; }; -class Key: public Base { +class Key final : public Base +{ public: - Key(QStringView n): keyValue(n) {} - Kind kind() const override { return Kind::Key; } - QString name() const override { return keyValue.toString(); } - bool checkName(QStringView s) const override { return s == keyValue; } - QStringView stringView() const override { return keyValue; } - void dump(Sink sink) const override { + Key() = default; + Key(const QString &n) : keyValue(n) { } + QString name() const { return keyValue; } + bool checkName(QStringView s) const { return s == keyValue; } + QStringView stringView() const { return keyValue; } + void dump(const Sink &sink) const { sink(u"["); sinkEscaped(sink, keyValue); sink(u"]"); } - bool hasSquareBrackets() const override { return true; } - const Key * asKey() const override { return this; } + bool hasSquareBrackets() const { return true; } - QStringView keyValue; + QString keyValue; }; -class Root: public Base { +class Root final : public Base +{ public: - Root(): contextKind(PathRoot::Other), contextName() {} + Root() = default; Root(PathRoot r): contextKind(r), contextName() {} Root(QStringView n) { QMetaEnum metaEnum = QMetaEnum::fromType<PathRoot>(); @@ -189,8 +145,7 @@ public: if (contextKind == PathRoot::Other) contextName = n; } - Kind kind() const override { return Kind::Root; } - QString name() const override { + QString name() const { switch (contextKind) { case PathRoot::Modules: return QStringLiteral(u"$modules"); @@ -210,24 +165,22 @@ public: Q_ASSERT(false && "Unexpected contextKind in name"); return QString(); } - bool checkName(QStringView s) const override { + bool checkName(QStringView s) const { if (contextKind != PathRoot::Other) return s.compare(name(), Qt::CaseInsensitive) == 0; return s.startsWith(QChar::fromLatin1('$')) && s.mid(1) == contextName; } - QStringView stringView() const override { return contextName; } - void dump(Sink sink) const override { - sink(name()); - } - const Root *asRoot() const override { return this; } + QStringView stringView() const { return contextName; } + void dump(const Sink &sink) const { sink(name()); } - PathRoot contextKind; + PathRoot contextKind = PathRoot::Other; QStringView contextName; }; -class Current: public Base { +class Current final : public Base +{ public: - Current(): contextName() {} + Current() = default; Current(PathCurrent c): contextKind(c) {} Current(QStringView n) { QMetaEnum metaEnum = QMetaEnum::fromType<PathCurrent>(); @@ -238,8 +191,7 @@ public: if (contextKind == PathCurrent::Other) contextName = n; } - Kind kind() const override { return Kind::Current; } - QString name() const override { + QString name() const { switch (contextKind) { case PathCurrent::Other: return QString::fromUtf8("@").append(contextName.toString()); @@ -267,172 +219,126 @@ public: Q_ASSERT(false && "Unexpected contextKind in Current::name"); return QString(); } - bool checkName(QStringView s) const override { + bool checkName(QStringView s) const { if (contextKind != PathCurrent::Other) return s.compare(name(), Qt::CaseInsensitive) == 0; return s.startsWith(QChar::fromLatin1('@')) && s.mid(1) == contextName; } - QStringView stringView() const override { return contextName; } - const Current *asCurrent() const override { return this; } + QStringView stringView() const { return contextName; } + void dump(const Sink &sink) const { Base::dump(sink, name(), hasSquareBrackets()); } - PathCurrent contextKind; + PathCurrent contextKind = PathCurrent::Other; QStringView contextName; }; -class Any: public Base { +class Any final : public Base +{ public: - Kind kind() const override { return Kind::Any; } - QString name() const override { return QLatin1String("*"); } - bool checkName(QStringView s) const override { return s == u"*"; } - bool hasSquareBrackets() const override { return true; } - const Any *asAny() const override { return this; } + Any() = default; + QString name() const { return QLatin1String("*"); } + bool checkName(QStringView s) const { return s == u"*"; } + void dump(const Sink &sink) const { Base::dump(sink, name(), hasSquareBrackets()); } + bool hasSquareBrackets() const { return true; } }; -class QMLDOM_EXPORT Filter: public Base { +class QMLDOM_EXPORT Filter final : public Base +{ public: - Filter(std::function<bool(DomItem)> f, QStringView filterDescription = u"<native code filter>"); - Kind kind() const override { return Kind::Filter; } - QString name() const override; - bool checkName(QStringView s) const override; - QStringView stringView() const override { return filterDescription; } - bool hasSquareBrackets() const override { return true; } - const Filter *asFilter() const override { return this; } - - std::function<bool(DomItem)> filterFunction; + Filter() = default; + Filter(const std::function<bool(const DomItem &)> &f, + QStringView filterDescription = u"<native code filter>"); + QString name() const; + bool checkName(QStringView s) const; + QStringView stringView() const { return filterDescription; } + void dump(const Sink &sink) const { Base::dump(sink, name(), hasSquareBrackets()); } + bool hasSquareBrackets() const { return true; } + + std::function<bool(const DomItem &)> filterFunction; QStringView filterDescription; }; class QMLDOM_EXPORT PathComponent { public: - PathComponent(): data() {} - ~PathComponent(); - - Kind kind() const { return base()->kind(); } - QString name() const { return base()->name(); }; - bool checkName(QStringView s) const { return base()->checkName(s); } - QStringView stringView() const { return base()->stringView(); }; - index_type index(index_type defaultValue=-1) const { return base()->index(defaultValue); } - void dump(Sink sink) const { base()->dump(sink); } - bool hasSquareBrackets() const { return base()->hasSquareBrackets(); } - - const Empty *asEmpty() const { return base()->asEmpty(); } - const Field *asField() const { return base()->asField(); } - const Index *asIndex() const { return base()->asIndex(); } - const Key *asKey() const { return base()->asKey(); } - const Root *asRoot() const { return base()->asRoot(); } - const Current *asCurrent() const { return base()->asCurrent(); } - const Any *asAny() const { return base()->asAny(); } + PathComponent() = default; + PathComponent(const PathComponent &) = default; + PathComponent(PathComponent &&) = default; + PathComponent &operator=(const PathComponent &) = default; + PathComponent &operator=(PathComponent &&) = default; + ~PathComponent() = default; + + Kind kind() const { return Kind(m_data.index()); } + + QString name() const + { + return std::visit([](auto &&d) { return d.name(); }, m_data); + } + + bool checkName(QStringView s) const + { + return std::visit([s](auto &&d) { return d.checkName(s); }, m_data); + } + + QStringView stringView() const + { + return std::visit([](auto &&d) { return d.stringView(); }, m_data); + } + + index_type index(index_type defaultValue=-1) const + { + return std::visit([defaultValue](auto &&d) { return d.index(defaultValue); }, m_data); + } + + void dump(const Sink &sink) const + { + return std::visit([sink](auto &&d) { return d.dump(sink); }, m_data); + } + + bool hasSquareBrackets() const + { + return std::visit([](auto &&d) { return d.hasSquareBrackets(); }, m_data); + } + + const Empty *asEmpty() const { return std::get_if<Empty>(&m_data); } + const Field *asField() const { return std::get_if<Field>(&m_data); } + const Index *asIndex() const { return std::get_if<Index>(&m_data); } + const Key *asKey() const { return std::get_if<Key>(&m_data); } + const Root *asRoot() const { return std::get_if<Root>(&m_data); } + const Current *asCurrent() const { return std::get_if<Current>(&m_data); } + const Any *asAny() const { return std::get_if<Any>(&m_data); } + const Filter *asFilter() const { return std::get_if<Filter>(&m_data); } + static int cmp(const PathComponent &p1, const PathComponent &p2); + + PathComponent(Empty &&o): m_data(std::move(o)) {} + PathComponent(Field &&o): m_data(std::move(o)) {} + PathComponent(Index &&o): m_data(std::move(o)) {} + PathComponent(Key &&o): m_data(std::move(o)) {} + PathComponent(Root &&o): m_data(std::move(o)) {} + PathComponent(Current &&o): m_data(std::move(o)) {} + PathComponent(Any &&o): m_data(std::move(o)) {} + PathComponent(Filter &&o): m_data(std::move(o)) {} + private: friend class QQmlJS::Dom::Path; friend class QQmlJS::Dom::PathEls::TestPaths; - PathComponent(const Empty &o): data(o) {} - PathComponent(const Field &o): data(o) {} - PathComponent(const Index &o): data(o) {} - PathComponent(const Key &o): data(o) {} - PathComponent(const Root &o): data(o) {} - PathComponent(const Current &o): data(o) {} - PathComponent(const Any &o): data(o) {} - PathComponent(const Filter &o): data(o) {} - - Base *base() { - return reinterpret_cast<Base*>(&data); - } - const Base *base() const { - return reinterpret_cast<const Base*>(&data); - } - union Data { - Data(): empty() { } - Data(const Data &d) { - switch (d.kind()){ - case Kind::Empty: - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&empty) && "non C++11 compliant compiler"); - new (&empty) Empty(d.empty); - break; - case Kind::Field: - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&field) && "non C++11 compliant compiler"); - new (&field) Field(d.field); - break; - case Kind::Index: - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&index) && "non C++11 compliant compiler"); - new (&index) Index(d.index); - break; - case Kind::Key: - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&key) && "non C++11 compliant compiler"); - new (&key) Key(d.key); - break; - case Kind::Root: - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&root) && "non C++11 compliant compiler"); - new (&root) Root(d.root); - break; - case Kind::Current: - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(¤t) && "non C++11 compliant compiler"); - new (¤t) Current(d.current); - break; - case Kind::Any: - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&any) && "non C++11 compliant compiler"); - new (&any) Any(d.any); - break; - case Kind::Filter: - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&filter) && "non C++11 compliant compiler"); - new (&filter) Filter(d.filter); - break; - } - } - Data(const Empty &o) { - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&empty) && "non C++11 compliant compiler"); - new (&empty) Empty(o); - } - Data(const Field &o) { - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&field) && "non C++11 compliant compiler"); - new (&field) Field(o); - } - Data(const Index &o){ - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&index) && "non C++11 compliant compiler"); - new (&index) Index(o); - } - Data(const Key &o) { - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&key) && "non C++11 compliant compiler"); - new (&key) Key(o); - } - Data(const Root &o) { - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&root) && "non C++11 compliant compiler"); - new (&root) Root(o); - } - Data(const Current &o) { - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(¤t) && "non C++11 compliant compiler"); - new (¤t) Current(o); - } - Data(const Any &o) { - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&any) && "non C++11 compliant compiler"); - new (&any) Any(o); - } - Data(const Filter &o) { - Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&filter) && "non C++11 compliant compiler"); - new (&filter) Filter(o); - } - Data &operator=(const Data &d) { - Q_ASSERT(this != &d); - this->~Data(); // destruct & construct new... - new (this)Data(d); - return *this; - } - Kind kind() const { - return reinterpret_cast<const Base*>(this)->kind(); - } - ~Data() { - reinterpret_cast<const Base*>(this)->~Base(); - } - Empty empty; - Field field; - Index index; - Key key; - Root root; - Current current; - Any any; - Filter filter; - } data; + using Variant = std::variant<Empty, Field, Index, Key, Root, Current, Any, Filter>; + + template<typename T, Kind K> + static constexpr bool variantTypeMatches + = std::is_same_v<std::variant_alternative_t<size_t(K), Variant>, T>; + + static_assert(size_t(Kind::Empty) == 0); + static_assert(variantTypeMatches<Empty, Kind::Empty>); + static_assert(variantTypeMatches<Field, Kind::Field>); + static_assert(variantTypeMatches<Key, Kind::Key>); + static_assert(variantTypeMatches<Root, Kind::Root>); + static_assert(variantTypeMatches<Current, Kind::Current>); + static_assert(variantTypeMatches<Any, Kind::Any>); + static_assert(variantTypeMatches<Filter, Kind::Filter>); + static_assert(std::variant_size_v<Variant> == size_t(Kind::Filter) + 1); + + Variant m_data; }; inline bool operator==(const PathComponent& lhs, const PathComponent& rhs){ return PathComponent::cmp(lhs,rhs) == 0; } @@ -444,9 +350,13 @@ inline bool operator>=(const PathComponent& lhs, const PathComponent& rhs){ retu class PathData { public: - PathData(QStringList strData, QVector<PathComponent> components): strData(strData), components(components) {} - PathData(QStringList strData, QVector<PathComponent> components, std::shared_ptr<PathData> parent): - strData(strData), components(components), parent(parent) {} + PathData(const QStringList &strData, const QVector<PathComponent> &components) + : strData(strData), components(components) + {} + PathData(const QStringList &strData, const QVector<PathComponent> &components, + const std::shared_ptr<PathData> &parent) + : strData(strData), components(components), parent(parent) + {} QStringList strData; QVector<PathComponent> components; @@ -455,149 +365,251 @@ public: } // namespace PathEls -#define QMLDOM_USTRING(name) constexpr const auto name = u#name +#define QMLDOM_USTRING(s) u##s +#define QMLDOM_FIELD(name) inline constexpr const auto name = QMLDOM_USTRING(#name) +/*! + \internal + In an ideal world, the Fields namespace would be an enum, not strings. + Use FieldType whenever you expect a static String from the Fields namespace instead of an + arbitrary QStringView. + */ +using FieldType = QStringView; // namespace, so it cam be reopened to add more entries namespace Fields{ -constexpr const auto access = u"access"; -constexpr const auto annotations = u"annotations"; -constexpr const auto attachedType = u"attachedType"; -constexpr const auto attachedTypeName = u"attachedTypeName"; -constexpr const auto autoExport = u"autoExport"; -constexpr const auto base = u"base"; -constexpr const auto bindingType = u"bindingType"; -constexpr const auto bindings = u"bindings"; -constexpr const auto body = u"body"; -constexpr const auto canonicalFilePath = u"canonicalFilePath"; -constexpr const auto canonicalPath = u"canonicalPath"; -constexpr const auto children = u"children"; -constexpr const auto classNames = u"classNames"; -constexpr const auto code = u"code"; -constexpr const auto components = u"components"; -constexpr const auto contents = u"contents"; -constexpr const auto contentsDate = u"contentsDate"; -constexpr const auto currentExposedAt = u"currentExposedAt"; -constexpr const auto currentIsValid = u"currentIsValid"; -constexpr const auto currentItem = u"currentItem"; -constexpr const auto currentRevision = u"currentRevision"; -constexpr const auto defaultPropertyName = u"defaultPropertyName"; -constexpr const auto designerSupported = u"designerSupported"; -constexpr const auto elementCanonicalPath = u"elementCanonicalPath"; -constexpr const auto enumerations = u"enumerations"; -constexpr const auto errors = u"errors"; -constexpr const auto exportSource = u"exportSource"; -constexpr const auto exports = u"exports"; -constexpr const auto extraRequired = u"extraRequired"; -constexpr const auto fileName = u"fileName"; -constexpr const auto get = u"get"; -constexpr const auto globalScopeName = u"globalScopeName"; -constexpr const auto globalScopeWithName = u"globalScopeWithName"; -constexpr const auto hasCallback = u"hasCallback"; -constexpr const auto idStr = u"idStr"; -constexpr const auto ids = u"ids"; -constexpr const auto import = u"import"; -constexpr const auto importId = u"importId"; -constexpr const auto imports = u"imports"; -constexpr const auto inheritVersion = u"inheritVersion"; -constexpr const auto inProgress = u"inProgress"; -constexpr const auto isAlias = u"isAlias"; -constexpr const auto isComposite = u"isComposite"; -constexpr const auto isCreatable = u"isCreatable"; -constexpr const auto isDefaultMember = u"isDefaultMember"; -constexpr const auto isInternal = u"isInternal"; -constexpr const auto isLatest = u"isLatest"; -constexpr const auto isList = u"isList"; -constexpr const auto isPointer = u"isPointer"; -constexpr const auto isRequired = u"isRequired"; -constexpr const auto isSingleton = u"isSingleton"; -constexpr const auto isValid = u"isValid"; -constexpr const auto isWritable = u"isWritable"; -constexpr const auto jsFileWithPath = u"jsFileWithPath"; -constexpr const auto kind = u"kind"; -constexpr const auto lastRevision = u"lastRevision"; -constexpr const auto lastValidRevision = u"lastValidRevision"; -constexpr const auto loadInfo = u"loadInfo"; -constexpr const auto loadOptions = u"loadOptions"; -constexpr const auto loadPaths = u"loadPaths"; -constexpr const auto loadsWithWork = u"loadsWithWork"; -constexpr const auto location = u"location"; -constexpr const auto logicalPath = u"logicalPath"; -constexpr const auto majorVersion = u"majorVersion"; -constexpr const auto metaRevisions = u"metaRevisions"; -constexpr const auto methodType = u"methodType"; -constexpr const auto methods = u"methods"; -constexpr const auto minorVersion = u"minorVersion"; -constexpr const auto moduleIndex = u"moduleIndex"; -constexpr const auto moduleIndexWithUri = u"moduleIndexWithUri"; -constexpr const auto moduleScope = u"moduleScope"; -constexpr const auto nAllLoadedCallbacks = u"nAllLoadedCallbacks"; -constexpr const auto nCallbacks = u"nCallbacks"; -constexpr const auto nLoaded = u"nLoaded"; -constexpr const auto nNotdone = u"nNotdone"; -constexpr const auto name = u"name"; -constexpr const auto nextScope = u"nextScope"; -constexpr const auto objects = u"objects"; -constexpr const auto onAttachedObject = u"onAttachedObject"; -constexpr const auto options = u"options"; -constexpr const auto parameters = u"parameters"; -constexpr const auto parentObject = u"parentObject"; -constexpr const auto path = u"path"; -constexpr const auto plugins = u"plugins"; -constexpr const auto pragma = u"pragma"; -constexpr const auto pragmas = u"pragmas"; -constexpr const auto propertyDef = u"propertyDef"; -constexpr const auto propertyDefRef = u"propertyDefRef"; -constexpr const auto propertyDefs = u"propertyDefs"; -constexpr const auto propertyName = u"propertyName"; -constexpr const auto prototype = u"prototype"; -constexpr const auto qmlDirectoryWithPath = u"qmlDirectoryWithPath"; -constexpr const auto qmlFileWithPath = u"qmlFileWithPath"; -constexpr const auto qmldirFileWithPath = u"qmldirFileWithPath"; -constexpr const auto qmltypesFileWithPath = u"qmltypesFileWithPath"; -constexpr const auto qmltypesFiles = u"qmltypesFiles"; -constexpr const auto queue = u"queue"; -constexpr const auto referredObject = u"referredObject"; -constexpr const auto referredObjectPath = u"referredObjectPath"; -constexpr const auto requestedAt = u"requestedAt"; -constexpr const auto requestingUniverse = u"requestingUniverse"; -constexpr const auto returnType = u"returnType"; -constexpr const auto returnTypeName = u"returnTypeName"; -constexpr const auto rootComponent = u"rootComponent"; -constexpr const auto sources = u"sources"; -constexpr const auto status = u"status"; -constexpr const auto stringValue = u"stringValue"; -constexpr const auto symbols = u"symbols"; -constexpr const auto target = u"target"; -constexpr const auto targetPropertyName = u"targetPropertyName"; -constexpr const auto type = u"type"; -constexpr const auto typeName = u"typeName"; -constexpr const auto types = u"types"; -constexpr const auto universe = u"universe"; -constexpr const auto uri = u"uri"; -constexpr const auto uris = u"uris"; -constexpr const auto validExposedAt = u"validExposedAt"; -constexpr const auto validItem = u"validItem"; -constexpr const auto value = u"value"; -constexpr const auto values = u"values"; -constexpr const auto version = u"version"; -constexpr const auto when = u"when"; -} +QMLDOM_FIELD(access); +QMLDOM_FIELD(accessSemantics); +QMLDOM_FIELD(allSources); +QMLDOM_FIELD(alternative); +QMLDOM_FIELD(annotations); +QMLDOM_FIELD(arguments); +QMLDOM_FIELD(astComments); +QMLDOM_FIELD(astRelocatableDump); +QMLDOM_FIELD(attachedType); +QMLDOM_FIELD(attachedTypeName); +QMLDOM_FIELD(autoExports); +QMLDOM_FIELD(base); +QMLDOM_FIELD(binaryExpression); +QMLDOM_FIELD(bindable); +QMLDOM_FIELD(bindingElement); +QMLDOM_FIELD(bindingIdentifiers); +QMLDOM_FIELD(bindingType); +QMLDOM_FIELD(bindings); +QMLDOM_FIELD(block); +QMLDOM_FIELD(body); +QMLDOM_FIELD(callee); +QMLDOM_FIELD(canonicalFilePath); +QMLDOM_FIELD(canonicalPath); +QMLDOM_FIELD(caseBlock); +QMLDOM_FIELD(caseClause); +QMLDOM_FIELD(caseClauses); +QMLDOM_FIELD(catchBlock); +QMLDOM_FIELD(catchParameter); +QMLDOM_FIELD(children); +QMLDOM_FIELD(classNames); +QMLDOM_FIELD(code); +QMLDOM_FIELD(commentedElements); +QMLDOM_FIELD(comments); +QMLDOM_FIELD(components); +QMLDOM_FIELD(condition); +QMLDOM_FIELD(consequence); +QMLDOM_FIELD(contents); +QMLDOM_FIELD(contentsDate); +QMLDOM_FIELD(cppType); +QMLDOM_FIELD(currentExposedAt); +QMLDOM_FIELD(currentIsValid); +QMLDOM_FIELD(currentItem); +QMLDOM_FIELD(currentRevision); +QMLDOM_FIELD(declarations); +QMLDOM_FIELD(defaultClause); +QMLDOM_FIELD(defaultPropertyName); +QMLDOM_FIELD(defaultValue); +QMLDOM_FIELD(designerSupported); +QMLDOM_FIELD(elLocation); +QMLDOM_FIELD(elements); +QMLDOM_FIELD(elementCanonicalPath); +QMLDOM_FIELD(enumerations); +QMLDOM_FIELD(errors); +QMLDOM_FIELD(exportSource); +QMLDOM_FIELD(exports); +QMLDOM_FIELD(expr); +QMLDOM_FIELD(expression); +QMLDOM_FIELD(expressionType); +QMLDOM_FIELD(extensionTypeName); +QMLDOM_FIELD(fileLocationsTree); +QMLDOM_FIELD(fileName); +QMLDOM_FIELD(finallyBlock); +QMLDOM_FIELD(forStatement); +QMLDOM_FIELD(fullRegion); +QMLDOM_FIELD(get); +QMLDOM_FIELD(globalScopeName); +QMLDOM_FIELD(globalScopeWithName); +QMLDOM_FIELD(hasCallback); +QMLDOM_FIELD(hasCustomParser); +QMLDOM_FIELD(idStr); +QMLDOM_FIELD(identifier); +QMLDOM_FIELD(ids); +QMLDOM_FIELD(implicit); +QMLDOM_FIELD(import); +QMLDOM_FIELD(importId); +QMLDOM_FIELD(importScope); +QMLDOM_FIELD(importSources); +QMLDOM_FIELD(imported); +QMLDOM_FIELD(imports); +QMLDOM_FIELD(inProgress); +QMLDOM_FIELD(infoItem); +QMLDOM_FIELD(inheritVersion); +QMLDOM_FIELD(initializer); +QMLDOM_FIELD(interfaceNames); +QMLDOM_FIELD(isAlias); +QMLDOM_FIELD(isComposite); +QMLDOM_FIELD(isConstructor); +QMLDOM_FIELD(isCreatable); +QMLDOM_FIELD(isDefaultMember); +QMLDOM_FIELD(isFinal); +QMLDOM_FIELD(isInternal); +QMLDOM_FIELD(isLatest); +QMLDOM_FIELD(isList); +QMLDOM_FIELD(isPointer); +QMLDOM_FIELD(isReadonly); +QMLDOM_FIELD(isRequired); +QMLDOM_FIELD(isSignalHandler); +QMLDOM_FIELD(isSingleton); +QMLDOM_FIELD(isValid); +QMLDOM_FIELD(jsFileWithPath); +QMLDOM_FIELD(kind); +QMLDOM_FIELD(lastRevision); +QMLDOM_FIELD(label); +QMLDOM_FIELD(lastValidRevision); +QMLDOM_FIELD(left); +QMLDOM_FIELD(loadInfo); +QMLDOM_FIELD(loadOptions); +QMLDOM_FIELD(loadPaths); +QMLDOM_FIELD(loadsWithWork); +QMLDOM_FIELD(localOffset); +QMLDOM_FIELD(location); +QMLDOM_FIELD(logicalPath); +QMLDOM_FIELD(majorVersion); +QMLDOM_FIELD(metaRevisions); +QMLDOM_FIELD(methodType); +QMLDOM_FIELD(methods); +QMLDOM_FIELD(minorVersion); +QMLDOM_FIELD(moduleIndex); +QMLDOM_FIELD(moduleIndexWithUri); +QMLDOM_FIELD(moduleScope); +QMLDOM_FIELD(moreCaseClauses); +QMLDOM_FIELD(nAllLoadedCallbacks); +QMLDOM_FIELD(nCallbacks); +QMLDOM_FIELD(nLoaded); +QMLDOM_FIELD(nNotdone); +QMLDOM_FIELD(name); +QMLDOM_FIELD(nameIdentifiers); +QMLDOM_FIELD(newlinesBefore); +QMLDOM_FIELD(nextComponent); +QMLDOM_FIELD(nextScope); +QMLDOM_FIELD(notify); +QMLDOM_FIELD(objects); +QMLDOM_FIELD(onAttachedObject); +QMLDOM_FIELD(operation); +QMLDOM_FIELD(options); +QMLDOM_FIELD(parameters); +QMLDOM_FIELD(parent); +QMLDOM_FIELD(parentObject); +QMLDOM_FIELD(path); +QMLDOM_FIELD(plugins); +QMLDOM_FIELD(postCode); +QMLDOM_FIELD(postCommentLocations); +QMLDOM_FIELD(postComments); +QMLDOM_FIELD(pragma); +QMLDOM_FIELD(pragmas); +QMLDOM_FIELD(preCode); +QMLDOM_FIELD(preCommentLocations); +QMLDOM_FIELD(preComments); +QMLDOM_FIELD(properties); +QMLDOM_FIELD(propertyDef); +QMLDOM_FIELD(propertyDefRef); +QMLDOM_FIELD(propertyDefs); +QMLDOM_FIELD(propertyInfos); +QMLDOM_FIELD(propertyName); +QMLDOM_FIELD(prototypes); +QMLDOM_FIELD(qmlDirectoryWithPath); +QMLDOM_FIELD(qmlFileWithPath); +QMLDOM_FIELD(qmlFiles); +QMLDOM_FIELD(qmldirFileWithPath); +QMLDOM_FIELD(qmldirWithPath); +QMLDOM_FIELD(qmltypesFileWithPath); +QMLDOM_FIELD(qmltypesFiles); +QMLDOM_FIELD(qualifiedImports); +QMLDOM_FIELD(rawComment); +QMLDOM_FIELD(read); +QMLDOM_FIELD(referredObject); +QMLDOM_FIELD(referredObjectPath); +QMLDOM_FIELD(regionComments); +QMLDOM_FIELD(regions); +QMLDOM_FIELD(requestedAt); +QMLDOM_FIELD(requestingUniverse); +QMLDOM_FIELD(returnType); +QMLDOM_FIELD(returnTypeName); +QMLDOM_FIELD(right); +QMLDOM_FIELD(rootComponent); +QMLDOM_FIELD(scopeType); +QMLDOM_FIELD(scriptElement); +QMLDOM_FIELD(sources); +QMLDOM_FIELD(statement); +QMLDOM_FIELD(statements); +QMLDOM_FIELD(status); +QMLDOM_FIELD(stringValue); +QMLDOM_FIELD(subComponents); +QMLDOM_FIELD(subImports); +QMLDOM_FIELD(subItems); +QMLDOM_FIELD(symbol); +QMLDOM_FIELD(symbols); +QMLDOM_FIELD(target); +QMLDOM_FIELD(targetPropertyName); +QMLDOM_FIELD(text); +QMLDOM_FIELD(type); +QMLDOM_FIELD(typeArgument); +QMLDOM_FIELD(typeArgumentName); +QMLDOM_FIELD(typeName); +QMLDOM_FIELD(types); +QMLDOM_FIELD(universe); +QMLDOM_FIELD(updatedScriptExpressions); +QMLDOM_FIELD(uri); +QMLDOM_FIELD(uris); +QMLDOM_FIELD(validExposedAt); +QMLDOM_FIELD(validItem); +QMLDOM_FIELD(value); +QMLDOM_FIELD(valueTypeName); +QMLDOM_FIELD(values); +QMLDOM_FIELD(version); +QMLDOM_FIELD(when); +QMLDOM_FIELD(write); +} // namespace Fields class Source; size_t qHash(const Path &, size_t); - +class PathIterator; // Define a iterator for it? // begin() can basically be itself, end() the empty path (zero length), iteration though dropFront() class QMLDOM_EXPORT Path{ + Q_GADGET Q_DECLARE_TR_FUNCTIONS(ErrorGroup); public: using Kind = PathEls::Kind; using Component = PathEls::PathComponent; static ErrorGroups myErrors(); // use static consts and central registration instead? - Path(){} + Path() = default; + explicit Path(const PathEls::PathComponent &c) : m_endOffset(0), m_length(0) + { + *this = appendComponent(c); + } + int length() const { return m_length; } Path operator[](int i) const; - operator bool() const; + explicit operator bool() const; + + PathIterator begin() const; + PathIterator end() const; PathRoot headRoot() const; PathCurrent headCurrent() const; @@ -605,47 +617,49 @@ public: QString headName() const; bool checkHeadName(QStringView name) const; index_type headIndex(index_type defaultValue=-1) const; - std::function<bool(DomItem)> headFilter() const; + std::function<bool(const DomItem &)> headFilter() const; Path head() const; Path last() const; Source split() const; - void dump(Sink sink) const; + void dump(const Sink &sink) const; QString toString() const; - Path dropFront() const; - Path dropTail() const; + Path dropFront(int n = 1) const; + Path dropTail(int n = 1) const; Path mid(int offset, int length) const; Path mid(int offset) const; + Path appendComponent(const PathEls::PathComponent &c); // # Path construction - static Path fromString(QString s, ErrorHandler errorHandler=nullptr); - static Path fromString(QStringView s, ErrorHandler errorHandler=nullptr); - static Path root(PathRoot r); - static Path root(QStringView s=u""); - static Path root(QString s); - static Path index(index_type i); - static Path field(QStringView s=u""); - static Path field(QString s); - static Path key(QStringView s=u""); - static Path key(QString s); - static Path current(PathCurrent c); - static Path current(QStringView s=u""); - static Path current(QString s); - static Path empty(); + static Path fromString(const QString &s, const ErrorHandler &errorHandler = nullptr); + static Path fromString(QStringView s, const ErrorHandler &errorHandler = nullptr); + static Path Root(PathRoot r); + static Path Root(QStringView s=u""); + static Path Root(const QString &s); + static Path Index(index_type i); + static Path Field(QStringView s=u""); + static Path Field(const QString &s); + static Path Key(QStringView s=u""); + static Path Key(const QString &s); + static Path Current(PathCurrent c); + static Path Current(QStringView s=u""); + static Path Current(const QString &s); + static Path Empty(); // add - Path subEmpty() const; - Path subField(QString name) const; - Path subField(QStringView name) const; - Path subKey(QString name) const; - Path subKey(QStringView name) const; - Path subIndex(index_type i) const; - Path subAny() const; - Path subFilter(std::function<bool(DomItem)>, QString) const; - Path subFilter(std::function<bool(DomItem)>, QStringView desc=u"<native code filter>") const; - Path subCurrent(PathCurrent s) const; - Path subCurrent(QString s) const; - Path subCurrent(QStringView s=u"") const; - Path subPath(Path toAdd, bool avoidToAddAsBase = false) const; + Path empty() const; + Path field(const QString &name) const; + Path field(QStringView name) const; + Path key(const QString &name) const; + Path key(QStringView name) const; + Path index(index_type i) const; + Path any() const; + Path filter(const std::function<bool(const DomItem &)> &, const QString &) const; + Path filter(const std::function<bool(const DomItem &)> &, + QStringView desc=u"<native code filter>") const; + Path current(PathCurrent s) const; + Path current(const QString &s) const; + Path current(QStringView s=u"") const; + Path path(const Path &toAdd, bool avoidToAddAsBase = false) const; Path expandFront() const; Path expandBack() const; @@ -661,25 +675,56 @@ public: using iterator_category = std::forward_iterator_tag; static int cmp(const Path &p1, const Path &p2); + private: - explicit Path(quint16 endOffset, quint16 length, std::shared_ptr<PathEls::PathData> data); + const Component &component(int i) const; + explicit Path(quint16 endOffset, quint16 length, + const std::shared_ptr<PathEls::PathData> &data); friend class QQmlJS::Dom::PathEls::TestPaths; + friend class FieldFilter; friend size_t qHash(const Path &, size_t); - Component component(int i) const; Path noEndOffset() const; quint16 m_endOffset = 0; quint16 m_length = 0; - std::shared_ptr<PathEls::PathData> m_data; + std::shared_ptr<PathEls::PathData> m_data = {}; }; -inline bool operator==(const Path& lhs, const Path& rhs){ return lhs.length() == rhs.length() && Path::cmp(lhs,rhs) == 0; } -inline bool operator!=(const Path& lhs, const Path& rhs){ return lhs.length() != rhs.length() || Path::cmp(lhs,rhs) != 0; } -inline bool operator< (const Path& lhs, const Path& rhs){ return Path::cmp(lhs,rhs) < 0; } -inline bool operator> (const Path& lhs, const Path& rhs){ return Path::cmp(lhs,rhs) > 0; } -inline bool operator<=(const Path& lhs, const Path& rhs){ return Path::cmp(lhs,rhs) <= 0; } -inline bool operator>=(const Path& lhs, const Path& rhs){ return Path::cmp(lhs,rhs) >= 0; } +inline bool operator==(const Path &lhs, const Path &rhs) +{ + return lhs.length() == rhs.length() && Path::cmp(lhs, rhs) == 0; +} +inline bool operator!=(const Path &lhs, const Path &rhs) +{ + return lhs.length() != rhs.length() || Path::cmp(lhs, rhs) != 0; +} +inline bool operator<(const Path &lhs, const Path &rhs) +{ + return Path::cmp(lhs, rhs) < 0; +} +inline bool operator>(const Path &lhs, const Path &rhs) +{ + return Path::cmp(lhs, rhs) > 0; +} +inline bool operator<=(const Path &lhs, const Path &rhs) +{ + return Path::cmp(lhs, rhs) <= 0; +} +inline bool operator>=(const Path &lhs, const Path &rhs) +{ + return Path::cmp(lhs, rhs) >= 0; +} + +class PathIterator { +public: + Path currentEl; + Path operator *() const { return currentEl.head(); } + PathIterator operator ++() { currentEl = currentEl.dropFront(); return *this; } + PathIterator operator ++(int) { PathIterator res{currentEl}; currentEl = currentEl.dropFront(); return res; } + bool operator ==(const PathIterator &o) const { return currentEl == o.currentEl; } + bool operator !=(const PathIterator &o) const { return currentEl != o.currentEl; } +}; class Source { public: @@ -704,6 +749,9 @@ inline size_t qHash(const Path &path, size_t seed) *it++ = qHash(p.component(0).stringView(), seed)^size_t(p.headRoot())^size_t(p.headCurrent()); } } + + // TODO: Get rid of the reinterpret_cast. + // Rather hash the path components in a more structured way. return qHash(QByteArray::fromRawData(reinterpret_cast<char *>(&buf[0]), (it - &buf[0])*sizeof(size_t)), seed); } |