Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmldomfieldfilter.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
7#include "QtCore/qglobal.h"
8
10
11namespace QQmlJS {
12namespace Dom {
13
14/*!
15\internal
16\class QQmljs::Dom::FieldFilter
17
18\brief Class that represent a filter on DomItem, when dumping or comparing
19
20DomItem can be duped or compared, but often one is interested only in a subset
21of them, FieldFilter is a simple way to select a subset of them.
22It uses two basic elements: the type of the object (internalKind) and the
23name of fields.
24
25A basic filter can be represented by <op><typeName>:<fieldName> or <op><fieldName>
26where op is either + or - (if the matching elements should be added or removed)
27Both typeName and fieldName can be the empty string (meaning any value matches).
28
29Basic filters are ordered from the most specific to the least specific as follow:
30type+field > type > field > empty.
31When combining several filters the most specific always wins, so
32-code,+ScriptExpression:code is the same as +ScriptExpression:code,-code and means
33that normally the field code is not outputted but for a ScriptExpression DomItem
34it is.
35
36It is possible to get the string representation of the current filter with
37FieldFilter::describeFieldsFilter(), and change the current filter with
38FieldFilter::addFilter(), but after it one should call FieldFilter::setFiltred()
39to ensure that the internal cache used to speed up comparisons is correct.
40*/
41
42QString FieldFilter::describeFieldsFilter() const
43{
44 QString fieldFilterStr;
45 {
46 auto it = m_fieldFilterRemove.begin();
47 while (it != m_fieldFilterRemove.end()) {
48 if (!fieldFilterStr.isEmpty())
49 fieldFilterStr.append(u",");
50 fieldFilterStr.append(QLatin1String("-%1:%2").arg(it.key(), it.value()));
51 ++it;
52 }
53 }
54 {
55 auto it = m_fieldFilterAdd.begin();
56 while (it != m_fieldFilterAdd.end()) {
57 if (!fieldFilterStr.isEmpty())
58 fieldFilterStr.append(u",");
59 fieldFilterStr.append(QLatin1String("+%1:%2").arg(it.key(), it.value()));
60 ++it;
61 }
62 }
63 return fieldFilterStr;
64}
65
66bool FieldFilter::operator()(const DomItem &obj, const Path &p, const DomItem &i) const
67{
68 if (p)
69 return this->operator()(obj, p.component(0), i);
70 else
71 return this->operator()(obj, PathEls::Empty(), i);
72}
73
74bool FieldFilter::operator()(const DomItem &base, const PathEls::PathComponent &c, const DomItem &obj) const
75{
76 DomType baseK = base.internalKind();
77 if (c.kind() == Path::Kind::Field) {
78 DomType objK = obj.internalKind();
79 if (!m_filtredTypes.contains(baseK) && !m_filtredTypes.contains(objK)
80 && !m_filtredFields.contains(qHash(c.stringView())))
81 return m_filtredDefault;
82 QString typeStr = domTypeToString(baseK);
83 QList<QString> tVals = m_fieldFilterRemove.values(typeStr);
84 QString name = c.name();
85 if (tVals.contains(name))
86 return false;
87 if (tVals.contains(QString())
88 || m_fieldFilterRemove.values(domTypeToString(objK)).contains(QString())
89 || m_fieldFilterRemove.values(QString()).contains(name)) {
90 return m_fieldFilterAdd.values(typeStr).contains(name);
91 }
92 } else if (m_filtredTypes.contains(baseK)) {
93 QString typeStr = domTypeToString(baseK);
94 QList<QString> tVals = m_fieldFilterRemove.values(typeStr);
95 return !tVals.contains(QString());
96 }
97 return true;
98}
99
100bool FieldFilter::addFilter(const QString &fFields)
101{
102 // parses a base filter of the form <op><typeName>:<fieldName> or <op><fieldName>
103 // as described in this class documentation
104 QRegularExpression fieldRe(QRegularExpression::anchoredPattern(QStringLiteral(
105 uR"((?<op>[-+])?(?:(?<type>[a-zA-Z0-9_]*):)?(?<field>[a-zA-Z0-9_]*))")));
106 for (const QString &fField : fFields.split(QLatin1Char(','))) {
107 QRegularExpressionMatch m = fieldRe.matchView(fField);
108 if (m.hasMatch()) {
109 if (m.capturedView(u"op") == u"+") {
110 m_fieldFilterRemove.remove(m.captured(u"type"), m.captured(u"field"));
111 m_fieldFilterAdd.insert(m.captured(u"type"), m.captured(u"field"));
112 } else {
113 m_fieldFilterRemove.insert(m.captured(u"type"), m.captured(u"field"));
114 m_fieldFilterAdd.remove(m.captured(u"type"), m.captured(u"field"));
115 }
116 } else {
117 qCWarning(domLog) << "could not extract filter from" << fField;
118 return false;
119 }
120 }
121 return true;
122}
123
125{
126 return FieldFilter{ {}, {} };
127}
128
130{
131 QMultiMap<QString, QString> fieldFilterAdd { { QLatin1String("ScriptExpression"),
132 QLatin1String("code") } };
133 QMultiMap<QString, QString> fieldFilterRemove{
134 { QString(), Fields::code.toString() },
135 { QString(), Fields::postCode.toString() },
136 { QString(), Fields::preCode.toString() },
137 { QString(), Fields::importScope.toString() },
138 { QString(), Fields::fileLocationsTree.toString() },
139 { QString(), Fields::astComments.toString() },
140 { QString(), Fields::comments.toString() },
141 { QString(), Fields::exports.toString() },
142 { QString(), Fields::propertyInfos.toString() },
143 { QLatin1String("FileLocationsNode"), Fields::parent.toString() }
144 };
145 return FieldFilter { fieldFilterAdd, fieldFilterRemove };
146}
147
149{
150 QMultiMap<QString, QString> fieldFilterAdd {};
151 QMultiMap<QString, QString> fieldFilterRemove{
152 { QString(), QLatin1String("code") },
153 { QString(), QLatin1String("propertyInfos") },
154 { QString(), QLatin1String("fileLocationsTree") },
155 { QString(), QLatin1String("location") },
156 { QLatin1String("ScriptExpression"), QLatin1String("localOffset") },
157 { QLatin1String("ScriptExpression"), QLatin1String("preCode") },
158 { QLatin1String("ScriptExpression"), QLatin1String("postCode") },
159 { QLatin1String("FileLocationsNode"), QLatin1String("parent") },
160 { QLatin1String("Reference"), QLatin1String("get") },
161 { QLatin1String("QmlComponent"), QLatin1String("ids") },
162 { QLatin1String("QmlObject"), QLatin1String("prototypes") }
163 };
164 return FieldFilter { fieldFilterAdd, fieldFilterRemove };
165}
166
168{
169 QMultiMap<QString, QString> fieldFilterAdd {};
170 QMultiMap<QString, QString> fieldFilterRemove{
171 { QString(), QLatin1String("propertyInfos") },
172 { QLatin1String("ScriptExpression"), QLatin1String("localOffset") },
173 { QLatin1String("FileLocationsInfo"), QLatin1String("regions") },
174 { QLatin1String("FileLocationsNode"), QLatin1String("parent") },
175 { QLatin1String("QmlComponent"), QLatin1String("ids") },
176 { QLatin1String("QmlObject"), QLatin1String("prototypes") },
177 { QLatin1String("Reference"), QLatin1String("get") }
178 };
179 return FieldFilter { fieldFilterAdd, fieldFilterRemove };
180}
181
183{
184 QMultiMap<QString, QString> fieldFilterAdd {};
185 QMultiMap<QString, QString> fieldFilterRemove{
186 { QString(), QLatin1String("propertyInfos") },
187 { QLatin1String("FileLocationsInfo"), QLatin1String("regions") },
188 { QLatin1String("Reference"), QLatin1String("get") },
189 { QLatin1String("QmlComponent"), QLatin1String("ids") },
190 { QLatin1String("QmlObject"), QLatin1String("prototypes") },
191 { QLatin1String(), QLatin1String("code") },
192 { QLatin1String("ScriptExpression"), QLatin1String("localOffset") },
193 { QLatin1String("ScriptExpression"), QLatin1String("astRelocatableDump") },
194 { QLatin1String("FileLocationsNode"), QLatin1String("parent") },
195 { QString(), QLatin1String("fileLocationsTree") },
196 { QString(), QLatin1String("preCode") },
197 { QString(), QLatin1String("postCode") },
198 { QString(), QLatin1String("comments") },
199 { QString(), QLatin1String("astComments") },
200 { QString(), QLatin1String("location") }
201 };
202 return FieldFilter { fieldFilterAdd, fieldFilterRemove };
203}
204
206{
207 QSet<QString> filtredFieldStrs;
208 QSet<QString> filtredTypeStrs;
209 static QHash<QString, DomType> fieldToId = []() {
210 QHash<QString, DomType> res;
211 auto reverseMap = domTypeToStringMap();
212 auto it = reverseMap.cbegin();
213 auto end = reverseMap.cend();
214 while (it != end) {
215 res[it.value()] = it.key();
216 ++it;
217 }
218 return res;
219 }();
220 auto addFilteredOfMap = [&](const QMultiMap<QString, QString> &map) {
221 auto it = map.cbegin();
222 auto end = map.cend();
223 while (it != end) {
224 filtredTypeStrs.insert(it.key());
225 ++it;
226 }
227 const auto &fieldKeys = map.values(QString());
228 for (const auto &f : fieldKeys)
229 filtredFieldStrs.insert(f);
230 };
231 addFilteredOfMap(m_fieldFilterAdd);
232 addFilteredOfMap(m_fieldFilterRemove);
233 m_filtredDefault = true;
234 if (m_fieldFilterRemove.values(QString()).contains(QString()))
235 m_filtredDefault = false;
236 m_filtredFields.clear();
237 for (const auto &s : filtredFieldStrs)
238 if (!s.isEmpty())
239 m_filtredFields.insert(qHash(QStringView(s)));
240 m_filtredTypes.clear();
241 for (const auto &s : filtredTypeStrs) {
242 if (s.isEmpty())
243 continue;
244 if (fieldToId.contains(s)) {
245 m_filtredTypes.insert(fieldToId.value(s));
246 } else {
247 qCWarning(domLog) << "Filter on unknown type " << s << " will be ignored";
248 }
249 }
250}
251
252} // end namespace Dom
253} // end namespace QQmlJS
254
255QT_END_NAMESPACE
256
257#include "moc_qqmldomfieldfilter_p.cpp"
A value type that references any element of the Dom.
InternalKind internalKind() const
static FieldFilter noLocationFilter()
bool operator()(const DomItem &, const Path &, const DomItem &) const
bool addFilter(const QString &f)
bool operator()(const DomItem &, const PathEls::PathComponent &c, const DomItem &) const
static FieldFilter compareNoCommentsFilter()
static FieldFilter defaultFilter()
static FieldFilter compareFilter()
static FieldFilter noFilter()
PathEls::Kind Kind