diff options
author | Fawzi Mohamed <fawzi.mohamed@qt.io> | 2021-06-08 10:33:32 +0200 |
---|---|---|
committer | Fawzi Mohamed <fawzi@gmx.ch> | 2021-09-07 11:28:08 +0200 |
commit | f2e61c50beb92723b789d563a1c50630cdb094d0 (patch) | |
tree | 974653f3de77fc3dff075d7598871670d24b1a62 | |
parent | 6a7952022737a6680569f2d6be4efa43825135f5 (diff) |
qmldom: improve path and addError performance
* avoid copy in Path::component(i)
* find duplicate errors via map insert (log() comparisons vs n)
Change-Id: Ib664615187fada810427665d161a0c3cabace1cf
Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
(cherry picked from commit 3b19b9a9e67cae723496fadf97f91661596d6d33)
-rw-r--r-- | src/qmldom/qqmldomerrormessage_p.h | 63 | ||||
-rw-r--r-- | src/qmldom/qqmldomitem.cpp | 10 | ||||
-rw-r--r-- | src/qmldom/qqmldomitem_p.h | 1 | ||||
-rw-r--r-- | src/qmldom/qqmldompath.cpp | 15 | ||||
-rw-r--r-- | src/qmldom/qqmldompath_p.h | 28 |
5 files changed, 90 insertions, 27 deletions
diff --git a/src/qmldom/qqmldomerrormessage_p.h b/src/qmldom/qqmldomerrormessage_p.h index fc3e0a2e11..3e7233125e 100644 --- a/src/qmldom/qqmldomerrormessage_p.h +++ b/src/qmldom/qqmldomerrormessage_p.h @@ -160,6 +160,46 @@ public: void dump(Sink s) const; QString toString() const; QCborMap toCbor() const; + friend int compare(const ErrorMessage &msg1, const ErrorMessage &msg2) + { + int c; + c = msg1.location.offset - msg2.location.offset; + if (c != 0) + return c; + c = msg1.location.startLine - msg2.location.startLine; + if (c != 0) + return c; + c = msg1.errorId.compare(msg2.errorId); + if (c != 0) + return c; + if (!msg1.errorId.isEmpty()) + return 0; + c = msg1.message.compare(msg2.message); + if (c != 0) + return c; + c = msg1.file.compare(msg2.file); + if (c != 0) + return c; + c = Path::cmp(msg1.path, msg2.path); + if (c != 0) + return c; + c = int(msg1.level) - int(msg2.level); + if (c != 0) + return c; + c = int(msg1.errorGroups.groups.size() - msg2.errorGroups.groups.size()); + if (c != 0) + return c; + for (qsizetype i = 0; i < msg1.errorGroups.groups.size(); ++i) { + c = msg1.errorGroups.groups[i].groupId().compare(msg2.errorGroups.groups[i].groupId()); + if (c != 0) + return c; + } + c = msg1.location.length - msg2.location.length; + if (c != 0) + return c; + c = msg1.location.startColumn - msg2.location.startColumn; + return c; + } QLatin1String errorId; QString message; @@ -171,13 +211,26 @@ public: }; inline bool operator !=(const ErrorMessage &e1, const ErrorMessage &e2) { - return e1.errorId != e2.errorId || e1.message != e2.message || e1.errorGroups != e2.errorGroups - || e1.level != e2.level || e1.path != e2.path || e1.file != e2.file - || e1.location.startLine != e2.location.startLine || e1.location.offset != e2.location.offset - || e1.location.startColumn != e2.location.startColumn || e1.location.length != e2.location.length; + return compare(e1, e2) != 0; } inline bool operator ==(const ErrorMessage &e1, const ErrorMessage &e2) { - return !(e1 != e2); + return compare(e1, e2) == 0; +} +inline bool operator<(const ErrorMessage &e1, const ErrorMessage &e2) +{ + return compare(e1, e2) < 0; +} +inline bool operator<=(const ErrorMessage &e1, const ErrorMessage &e2) +{ + return compare(e1, e2) <= 0; +} +inline bool operator>(const ErrorMessage &e1, const ErrorMessage &e2) +{ + return compare(e1, e2) > 0; +} +inline bool operator>=(const ErrorMessage &e1, const ErrorMessage &e2) +{ + return compare(e1, e2) >= 0; } QMLDOM_EXPORT void silentError(const ErrorMessage &); diff --git a/src/qmldom/qqmldomitem.cpp b/src/qmldom/qqmldomitem.cpp index 30ac7091bf..0a52a11121 100644 --- a/src/qmldom/qqmldomitem.cpp +++ b/src/qmldom/qqmldomitem.cpp @@ -2974,12 +2974,10 @@ void OwningItem::addError(DomItem &, ErrorMessage msg) void OwningItem::addErrorLocal(ErrorMessage msg) { QMutexLocker l(mutex()); - auto it = m_errors.constFind(msg.path); - while (it != m_errors.constEnd() && it->path == msg.path) { - if (*it++ == msg) - return; - } - m_errors.insert(msg.path, msg); + quint32 &c = m_errorsCounts[msg]; + c += 1; + if (c == 1) + m_errors.insert(msg.path, msg); } void OwningItem::clearErrors(ErrorGroups groups) diff --git a/src/qmldom/qqmldomitem_p.h b/src/qmldom/qqmldomitem_p.h index bf2e42be52..c3720d74ea 100644 --- a/src/qmldom/qqmldomitem_p.h +++ b/src/qmldom/qqmldomitem_p.h @@ -1342,6 +1342,7 @@ private: QDateTime m_lastDataUpdateAt; QDateTime m_frozenAt; QMultiMap<Path, ErrorMessage> m_errors; + QMap<ErrorMessage, quint32> m_errorsCounts; }; template<typename T> diff --git a/src/qmldom/qqmldompath.cpp b/src/qmldom/qqmldompath.cpp index c2ceeaf3cc..8aea7de148 100644 --- a/src/qmldom/qqmldompath.cpp +++ b/src/qmldom/qqmldompath.cpp @@ -205,24 +205,25 @@ int PathComponent::cmp(const PathComponent &p1, const PathComponent &p2) } // namespace PathEls -PathEls::PathComponent Path::component(int i) const +const PathEls::PathComponent &Path::component(int i) const { + static Component emptyComponent; if (i < 0) i += m_length; if (i >= m_length || i < 0) { Q_ASSERT(false && "index out of bounds"); - return Component(); + return emptyComponent; } i = i - m_length - m_endOffset; auto data = m_data.get(); while (data) { i += data->components.length(); if (i >= 0) - return data->components.at(i); + return qAsConst(data)->components[i]; data = data->parent.get(); } Q_ASSERT(false && "Invalid data reached while resolving a seemengly valid index in Path (inconsisten Path object)"); - return Component(); + return emptyComponent; } Path Path::operator[](int i) const @@ -247,7 +248,7 @@ PathIterator Path::end() const PathRoot Path::headRoot() const { - auto comp = component(0); + auto &comp = component(0); if (PathEls::Root const * r = comp.base()->asRoot()) return r->contextKind; return PathRoot::Other; @@ -285,7 +286,7 @@ index_type Path::headIndex(index_type defaultValue) const function<bool (DomItem)> Path::headFilter() const { - auto comp = component(0); + auto &comp = component(0); if (PathEls::Filter const * f = comp.base()->asFilter()) { return f->filterFunction; } @@ -939,7 +940,7 @@ void Path::dump(Sink sink) const { bool first = true; for (int i = 0; i < m_length; ++i) { - auto c = component(i); + auto &c = component(i); if (!c.hasSquareBrackets()) { if (!first || (c.kind() != Kind::Root && c.kind() != Kind::Current)) sink(u"."); diff --git a/src/qmldom/qqmldompath_p.h b/src/qmldom/qqmldompath_p.h index 7fe68428d7..50508a469d 100644 --- a/src/qmldom/qqmldompath_p.h +++ b/src/qmldom/qqmldompath_p.h @@ -124,7 +124,8 @@ public: virtual const Filter *asFilter() const { return nullptr; } }; -class Empty: public Base { +class Empty final : public Base +{ public: Empty() = default; Kind kind() const override { return Kind::Empty; } @@ -133,7 +134,8 @@ public: const Empty * asEmpty() const override { return this; } }; -class Field: public Base { +class Field final : public Base +{ public: Field() = default; Field(QStringView n): fieldName(n) {} @@ -147,7 +149,8 @@ public: QStringView fieldName; }; -class Index: public Base { +class Index final : public Base +{ public: Index() = default; Index(index_type i): indexValue(i) {} @@ -161,7 +164,8 @@ public: index_type indexValue = -1; }; -class Key: public Base { +class Key final : public Base +{ public: Key() = default; Key(QString n) : keyValue(n) { } @@ -180,7 +184,8 @@ public: QString keyValue; }; -class Root: public Base { +class Root final : public Base +{ public: Root() = default; Root(PathRoot r): contextKind(r), contextName() {} @@ -229,7 +234,8 @@ public: QStringView contextName; }; -class Current: public Base { +class Current final : public Base +{ public: Current() = default; Current(PathCurrent c): contextKind(c) {} @@ -283,7 +289,8 @@ public: QStringView contextName; }; -class Any: public Base { +class Any final : public Base +{ public: Any() = default; Kind kind() const override { return Kind::Any; } @@ -293,7 +300,8 @@ public: const Any *asAny() const override { return this; } }; -class QMLDOM_EXPORT Filter: public Base { +class QMLDOM_EXPORT Filter final : public Base +{ public: Filter() = default; Filter(std::function<bool(DomItem)> f, QStringView filterDescription = u"<native code filter>"); @@ -718,10 +726,12 @@ public: using iterator_category = std::forward_iterator_tag; static int cmp(const Path &p1, const Path &p2); - Component component(int i) const; + private: + const Component &component(int i) const; explicit Path(quint16 endOffset, quint16 length, std::shared_ptr<PathEls::PathData> data); friend class QQmlJS::Dom::PathEls::TestPaths; + friend class FieldFilter; friend size_t qHash(const Path &, size_t); Path noEndOffset() const; |