aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFawzi Mohamed <fawzi.mohamed@qt.io>2021-06-08 10:33:32 +0200
committerFawzi Mohamed <fawzi@gmx.ch>2021-09-07 11:28:08 +0200
commitf2e61c50beb92723b789d563a1c50630cdb094d0 (patch)
tree974653f3de77fc3dff075d7598871670d24b1a62
parent6a7952022737a6680569f2d6be4efa43825135f5 (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.h63
-rw-r--r--src/qmldom/qqmldomitem.cpp10
-rw-r--r--src/qmldom/qqmldomitem_p.h1
-rw-r--r--src/qmldom/qqmldompath.cpp15
-rw-r--r--src/qmldom/qqmldompath_p.h28
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;