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
4#ifndef QMLDOM_PATH_H
5#define QMLDOM_PATH_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qqmldomconstants_p.h"
19#include "qqmldomstringdumper_p.h"
20#include "qqmldom_global.h"
21
22#include <QtCore/QCoreApplication>
23#include <QtCore/QMetaEnum>
24#include <QtCore/QString>
25#include <QtCore/QStringView>
26#include <QtCore/QStringList>
27#include <QtCore/QVector>
28#include <QtCore/QDebug>
29
30#include <functional>
31#include <iterator>
32
33QT_BEGIN_NAMESPACE
34
35namespace QQmlJS {
36namespace Dom {
37
38class ErrorGroups;
39class ErrorMessage;
40class DomItem;
41class Path;
42
43using ErrorHandler = std::function<void(const ErrorMessage &)> ;
44
45using index_type = qint64;
46
47namespace PathEls {
48
49enum class Kind{
50 Empty,
51 Field,
52 Index,
53 Key,
54 Root,
55 Current,
56 Any,
57 Filter
58};
59
60class TestPaths;
61class Empty;
62class Field;
63class Index;
64class Key;
65class Root;
66class Current;
67class Any;
68class Filter;
69
70class Base {
71public:
72 virtual ~Base() = default;
73 virtual Kind kind() const = 0;
74 virtual QString name() const = 0;
75 virtual bool checkName(QStringView s) const = 0;
76 virtual QStringView stringView() const { return QStringView(); }
77 virtual index_type index(index_type defaultValue=-1) const { return defaultValue; }
78
79 virtual void dump(Sink sink) const;
80 virtual bool hasSquareBrackets() const { return false; }
81
82 // casting, could use optional, but that is c++17...
83 virtual const Empty *asEmpty() const { return nullptr; }
84 virtual const Field *asField() const { return nullptr; }
85 virtual const Index *asIndex() const { return nullptr; }
86 virtual const Key *asKey() const { return nullptr; }
87 virtual const Root *asRoot() const { return nullptr; }
88 virtual const Current *asCurrent() const { return nullptr; }
89 virtual const Any *asAny() const { return nullptr; }
90 virtual const Filter *asFilter() const { return nullptr; }
91};
92
93class Empty final : public Base
94{
95public:
96 Empty() = default;
97 Kind kind() const override { return Kind::Empty; }
98 QString name() const override { return QString(); }
99 bool checkName(QStringView s) const override { return s.isEmpty(); }
100 const Empty * asEmpty() const override { return this; }
101};
102
103class Field final : public Base
104{
105public:
106 Field() = default;
107 Field(QStringView n): fieldName(n) {}
108 Kind kind() const override { return Kind::Field; }
109 QString name() const override { return fieldName.toString(); }
110 bool checkName(QStringView s) const override { return s == fieldName; }
111 QStringView stringView() const override { return fieldName; }
112 const Field * asField() const override { return this; }
113 void dump(Sink sink) const override { sink(fieldName); }
114
115 QStringView fieldName;
116};
117
118class Index final : public Base
119{
120public:
121 Index() = default;
122 Index(index_type i): indexValue(i) {}
123 Kind kind() const override { return Kind::Index; }
124 QString name() const override { return QString::number(indexValue); }
125 bool checkName(QStringView s) const override { return s == name(); }
126 index_type index(index_type = -1) const override { return indexValue; }
127 bool hasSquareBrackets() const override { return true; }
128 const Index * asIndex() const override { return this; }
129
130 index_type indexValue = -1;
131};
132
133class Key final : public Base
134{
135public:
136 Key() = default;
137 Key(QString n) : keyValue(n) { }
138 Kind kind() const override { return Kind::Key; }
139 QString name() const override { return keyValue; }
140 bool checkName(QStringView s) const override { return s == keyValue; }
141 QStringView stringView() const override { return keyValue; }
142 void dump(Sink sink) const override {
143 sink(u"[");
144 sinkEscaped(sink, s: keyValue);
145 sink(u"]");
146 }
147 bool hasSquareBrackets() const override { return true; }
148 const Key * asKey() const override { return this; }
149
150 QString keyValue;
151};
152
153class Root final : public Base
154{
155public:
156 Root() = default;
157 Root(PathRoot r): contextKind(r), contextName() {}
158 Root(QStringView n) {
159 QMetaEnum metaEnum = QMetaEnum::fromType<PathRoot>();
160 contextKind = PathRoot::Other;
161 for (int i = 0; i < metaEnum.keyCount(); ++ i)
162 if (n.compare(other: QString::fromUtf8(utf8: metaEnum.key(index: i)), cs: Qt::CaseInsensitive) == 0)
163 contextKind = PathRoot(metaEnum.value(index: i));
164 if (contextKind == PathRoot::Other)
165 contextName = n;
166 }
167 Kind kind() const override { return Kind::Root; }
168 QString name() const override {
169 switch (contextKind) {
170 case PathRoot::Modules:
171 return QStringLiteral(u"$modules");
172 case PathRoot::Cpp:
173 return QStringLiteral(u"$cpp");
174 case PathRoot::Libs:
175 return QStringLiteral(u"$libs");
176 case PathRoot::Top:
177 return QStringLiteral(u"$top");
178 case PathRoot::Env:
179 return QStringLiteral(u"$env");
180 case PathRoot::Universe:
181 return QStringLiteral(u"$universe");
182 case PathRoot::Other:
183 return QString::fromUtf8(utf8: "$").append(s: contextName.toString());
184 }
185 Q_ASSERT(false && "Unexpected contextKind in name");
186 return QString();
187 }
188 bool checkName(QStringView s) const override {
189 if (contextKind != PathRoot::Other)
190 return s.compare(other: name(), cs: Qt::CaseInsensitive) == 0;
191 return s.startsWith(c: QChar::fromLatin1(c: '$')) && s.mid(pos: 1) == contextName;
192 }
193 QStringView stringView() const override { return contextName; }
194 void dump(Sink sink) const override {
195 sink(name());
196 }
197 const Root *asRoot() const override { return this; }
198
199 PathRoot contextKind = PathRoot::Other;
200 QStringView contextName;
201};
202
203class Current final : public Base
204{
205public:
206 Current() = default;
207 Current(PathCurrent c): contextKind(c) {}
208 Current(QStringView n) {
209 QMetaEnum metaEnum = QMetaEnum::fromType<PathCurrent>();
210 contextKind = PathCurrent::Other;
211 for (int i = 0; i < metaEnum.keyCount(); ++ i)
212 if (n.compare(other: QString::fromUtf8(utf8: metaEnum.key(index: i)), cs: Qt::CaseInsensitive) == 0)
213 contextKind = PathCurrent(metaEnum.value(index: i));
214 if (contextKind == PathCurrent::Other)
215 contextName = n;
216 }
217 Kind kind() const override { return Kind::Current; }
218 QString name() const override {
219 switch (contextKind) {
220 case PathCurrent::Other:
221 return QString::fromUtf8(utf8: "@").append(s: contextName.toString());
222 case PathCurrent::Obj:
223 return QStringLiteral(u"@obj");
224 case PathCurrent::ObjChain:
225 return QStringLiteral(u"@objChain");
226 case PathCurrent::ScopeChain:
227 return QStringLiteral(u"@scopeChain");
228 case PathCurrent::Component:
229 return QStringLiteral(u"@component");
230 case PathCurrent::Module:
231 return QStringLiteral(u"@module");
232 case PathCurrent::Ids:
233 return QStringLiteral(u"@ids");
234 case PathCurrent::Types:
235 return QStringLiteral(u"@types");
236 case PathCurrent::LookupStrict:
237 return QStringLiteral(u"@lookupStrict");
238 case PathCurrent::LookupDynamic:
239 return QStringLiteral(u"@lookupDynamic");
240 case PathCurrent::Lookup:
241 return QStringLiteral(u"@lookup");
242 }
243 Q_ASSERT(false && "Unexpected contextKind in Current::name");
244 return QString();
245 }
246 bool checkName(QStringView s) const override {
247 if (contextKind != PathCurrent::Other)
248 return s.compare(other: name(), cs: Qt::CaseInsensitive) == 0;
249 return s.startsWith(c: QChar::fromLatin1(c: '@')) && s.mid(pos: 1) == contextName;
250 }
251 QStringView stringView() const override { return contextName; }
252 const Current *asCurrent() const override { return this; }
253
254 PathCurrent contextKind = PathCurrent::Other;
255 QStringView contextName;
256};
257
258class Any final : public Base
259{
260public:
261 Any() = default;
262 Kind kind() const override { return Kind::Any; }
263 QString name() const override { return QLatin1String("*"); }
264 bool checkName(QStringView s) const override { return s == u"*"; }
265 bool hasSquareBrackets() const override { return true; }
266 const Any *asAny() const override { return this; }
267};
268
269class QMLDOM_EXPORT Filter final : public Base
270{
271public:
272 Filter() = default;
273 Filter(std::function<bool(DomItem)> f, QStringView filterDescription = u"<native code filter>");
274 Kind kind() const override { return Kind::Filter; }
275 QString name() const override;
276 bool checkName(QStringView s) const override;
277 QStringView stringView() const override { return filterDescription; }
278 bool hasSquareBrackets() const override { return true; }
279 const Filter *asFilter() const override { return this; }
280
281 std::function<bool(DomItem)> filterFunction;
282 QStringView filterDescription;
283};
284
285class QMLDOM_EXPORT PathComponent {
286public:
287 PathComponent(): data() {}
288 ~PathComponent();
289
290 Kind kind() const { return base()->kind(); }
291 QString name() const { return base()->name(); };
292 bool checkName(QStringView s) const { return base()->checkName(s); }
293 QStringView stringView() const { return base()->stringView(); };
294 index_type index(index_type defaultValue=-1) const { return base()->index(defaultValue); }
295 void dump(Sink sink) const { base()->dump(sink); }
296 bool hasSquareBrackets() const { return base()->hasSquareBrackets(); }
297
298 const Empty *asEmpty() const { return base()->asEmpty(); }
299 const Field *asField() const { return base()->asField(); }
300 const Index *asIndex() const { return base()->asIndex(); }
301 const Key *asKey() const { return base()->asKey(); }
302 const Root *asRoot() const { return base()->asRoot(); }
303 const Current *asCurrent() const { return base()->asCurrent(); }
304 const Any *asAny() const { return base()->asAny(); }
305 static int cmp(const PathComponent &p1, const PathComponent &p2);
306
307 PathComponent(const Empty &o): data(o) {}
308 PathComponent(const Field &o): data(o) {}
309 PathComponent(const Index &o): data(o) {}
310 PathComponent(const Key &o): data(o) {}
311 PathComponent(const Root &o): data(o) {}
312 PathComponent(const Current &o): data(o) {}
313 PathComponent(const Any &o): data(o) {}
314 PathComponent(const Filter &o): data(o) {}
315private:
316 friend class QQmlJS::Dom::Path;
317 friend class QQmlJS::Dom::PathEls::TestPaths;
318
319 Base *base() {
320 return reinterpret_cast<Base*>(&data);
321 }
322 const Base *base() const {
323 return reinterpret_cast<const Base*>(&data);
324 }
325 union Data {
326 Data(): empty() { }
327 Data(const Data &d) {
328 switch (d.kind()){
329 case Kind::Empty:
330 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&empty) && "non C++11 compliant compiler");
331 new (&empty) Empty(d.empty);
332 break;
333 case Kind::Field:
334 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&field) && "non C++11 compliant compiler");
335 new (&field) Field(d.field);
336 break;
337 case Kind::Index:
338 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&index) && "non C++11 compliant compiler");
339 new (&index) Index(d.index);
340 break;
341 case Kind::Key:
342 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&key) && "non C++11 compliant compiler");
343 new (&key) Key(d.key);
344 break;
345 case Kind::Root:
346 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&root) && "non C++11 compliant compiler");
347 new (&root) Root(d.root);
348 break;
349 case Kind::Current:
350 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&current) && "non C++11 compliant compiler");
351 new (&current) Current(d.current);
352 break;
353 case Kind::Any:
354 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&any) && "non C++11 compliant compiler");
355 new (&any) Any(d.any);
356 break;
357 case Kind::Filter:
358 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&filter) && "non C++11 compliant compiler");
359 new (&filter) Filter(d.filter);
360 break;
361 }
362 }
363 Data(const Empty &o) {
364 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&empty) && "non C++11 compliant compiler");
365 new (&empty) Empty(o);
366 }
367 Data(const Field &o) {
368 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&field) && "non C++11 compliant compiler");
369 new (&field) Field(o);
370 }
371 Data(const Index &o){
372 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&index) && "non C++11 compliant compiler");
373 new (&index) Index(o);
374 }
375 Data(const Key &o) {
376 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&key) && "non C++11 compliant compiler");
377 new (&key) Key(o);
378 }
379 Data(const Root &o) {
380 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&root) && "non C++11 compliant compiler");
381 new (&root) Root(o);
382 }
383 Data(const Current &o) {
384 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&current) && "non C++11 compliant compiler");
385 new (&current) Current(o);
386 }
387 Data(const Any &o) {
388 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&any) && "non C++11 compliant compiler");
389 new (&any) Any(o);
390 }
391 Data(const Filter &o) {
392 Q_ASSERT(static_cast<void*>(this)==static_cast<void*>(&filter) && "non C++11 compliant compiler");
393 new (&filter) Filter(o);
394 }
395 Data &operator=(const Data &d) {
396 Q_ASSERT(this != &d);
397 this->~Data(); // destruct & construct new...
398 new (this)Data(d);
399 return *this;
400 }
401 Kind kind() const {
402 return reinterpret_cast<const Base*>(this)->kind();
403 }
404 ~Data() {
405 reinterpret_cast<const Base*>(this)->~Base();
406 }
407 Empty empty;
408 Field field;
409 Index index;
410 Key key;
411 Root root;
412 Current current;
413 Any any;
414 Filter filter;
415 } data;
416};
417
418inline bool operator==(const PathComponent& lhs, const PathComponent& rhs){ return PathComponent::cmp(p1: lhs,p2: rhs) == 0; }
419inline bool operator!=(const PathComponent& lhs, const PathComponent& rhs){ return PathComponent::cmp(p1: lhs,p2: rhs) != 0; }
420inline bool operator< (const PathComponent& lhs, const PathComponent& rhs){ return PathComponent::cmp(p1: lhs,p2: rhs) < 0; }
421inline bool operator> (const PathComponent& lhs, const PathComponent& rhs){ return PathComponent::cmp(p1: lhs,p2: rhs) > 0; }
422inline bool operator<=(const PathComponent& lhs, const PathComponent& rhs){ return PathComponent::cmp(p1: lhs,p2: rhs) <= 0; }
423inline bool operator>=(const PathComponent& lhs, const PathComponent& rhs){ return PathComponent::cmp(p1: lhs,p2: rhs) >= 0; }
424
425class PathData {
426public:
427 PathData(QStringList strData, QVector<PathComponent> components): strData(strData), components(components) {}
428 PathData(QStringList strData, QVector<PathComponent> components, std::shared_ptr<PathData> parent):
429 strData(strData), components(components), parent(parent) {}
430
431 QStringList strData;
432 QVector<PathComponent> components;
433 std::shared_ptr<PathData> parent;
434};
435
436} // namespace PathEls
437
438#define QMLDOM_USTRING(s) u##s
439#define QMLDOM_FIELD(name) inline constexpr const auto name = QMLDOM_USTRING(#name)
440/*!
441 \internal
442 In an ideal world, the Fields namespace would be an enum, not strings.
443 Use FieldType whenever you expect a static String from the Fields namespace instead of an
444 arbitrary QStringView.
445 */
446using FieldType = QStringView;
447// namespace, so it cam be reopened to add more entries
448namespace Fields{
449QMLDOM_FIELD(access);
450QMLDOM_FIELD(accessSemantics);
451QMLDOM_FIELD(allSources);
452QMLDOM_FIELD(alternative);
453QMLDOM_FIELD(annotations);
454QMLDOM_FIELD(arguments);
455QMLDOM_FIELD(astComments);
456QMLDOM_FIELD(astRelocatableDump);
457QMLDOM_FIELD(attachedType);
458QMLDOM_FIELD(attachedTypeName);
459QMLDOM_FIELD(autoExports);
460QMLDOM_FIELD(base);
461QMLDOM_FIELD(binaryExpression);
462QMLDOM_FIELD(bindable);
463QMLDOM_FIELD(bindingElement);
464QMLDOM_FIELD(bindingType);
465QMLDOM_FIELD(bindings);
466QMLDOM_FIELD(block);
467QMLDOM_FIELD(body);
468QMLDOM_FIELD(callee);
469QMLDOM_FIELD(canonicalFilePath);
470QMLDOM_FIELD(canonicalPath);
471QMLDOM_FIELD(children);
472QMLDOM_FIELD(classNames);
473QMLDOM_FIELD(code);
474QMLDOM_FIELD(commentedElements);
475QMLDOM_FIELD(comments);
476QMLDOM_FIELD(components);
477QMLDOM_FIELD(condition);
478QMLDOM_FIELD(consequence);
479QMLDOM_FIELD(contents);
480QMLDOM_FIELD(contentsDate);
481QMLDOM_FIELD(cppType);
482QMLDOM_FIELD(currentExposedAt);
483QMLDOM_FIELD(currentIsValid);
484QMLDOM_FIELD(currentItem);
485QMLDOM_FIELD(currentRevision);
486QMLDOM_FIELD(declarations);
487QMLDOM_FIELD(defaultPropertyName);
488QMLDOM_FIELD(defaultValue);
489QMLDOM_FIELD(designerSupported);
490QMLDOM_FIELD(elLocation);
491QMLDOM_FIELD(elements);
492QMLDOM_FIELD(elementCanonicalPath);
493QMLDOM_FIELD(enumerations);
494QMLDOM_FIELD(errors);
495QMLDOM_FIELD(exportSource);
496QMLDOM_FIELD(exports);
497QMLDOM_FIELD(expr);
498QMLDOM_FIELD(expression);
499QMLDOM_FIELD(expressionType);
500QMLDOM_FIELD(extensionTypeName);
501QMLDOM_FIELD(fileLocationsTree);
502QMLDOM_FIELD(fileName);
503QMLDOM_FIELD(forStatement);
504QMLDOM_FIELD(fullRegion);
505QMLDOM_FIELD(get);
506QMLDOM_FIELD(globalScopeName);
507QMLDOM_FIELD(globalScopeWithName);
508QMLDOM_FIELD(hasCallback);
509QMLDOM_FIELD(hasCustomParser);
510QMLDOM_FIELD(idStr);
511QMLDOM_FIELD(identifier);
512QMLDOM_FIELD(ids);
513QMLDOM_FIELD(implicit);
514QMLDOM_FIELD(import);
515QMLDOM_FIELD(importId);
516QMLDOM_FIELD(importScope);
517QMLDOM_FIELD(importSources);
518QMLDOM_FIELD(imported);
519QMLDOM_FIELD(imports);
520QMLDOM_FIELD(inProgress);
521QMLDOM_FIELD(infoItem);
522QMLDOM_FIELD(inheritVersion);
523QMLDOM_FIELD(initializer);
524QMLDOM_FIELD(interfaceNames);
525QMLDOM_FIELD(isAlias);
526QMLDOM_FIELD(isComposite);
527QMLDOM_FIELD(isConstructor);
528QMLDOM_FIELD(isCreatable);
529QMLDOM_FIELD(isDefaultMember);
530QMLDOM_FIELD(isFinal);
531QMLDOM_FIELD(isInternal);
532QMLDOM_FIELD(isLatest);
533QMLDOM_FIELD(isList);
534QMLDOM_FIELD(isPointer);
535QMLDOM_FIELD(isReadonly);
536QMLDOM_FIELD(isRequired);
537QMLDOM_FIELD(isSignalHandler);
538QMLDOM_FIELD(isSingleton);
539QMLDOM_FIELD(isValid);
540QMLDOM_FIELD(jsFileWithPath);
541QMLDOM_FIELD(kind);
542QMLDOM_FIELD(lastRevision);
543QMLDOM_FIELD(lastValidRevision);
544QMLDOM_FIELD(left);
545QMLDOM_FIELD(loadInfo);
546QMLDOM_FIELD(loadOptions);
547QMLDOM_FIELD(loadPaths);
548QMLDOM_FIELD(loadsWithWork);
549QMLDOM_FIELD(localOffset);
550QMLDOM_FIELD(location);
551QMLDOM_FIELD(logicalPath);
552QMLDOM_FIELD(majorVersion);
553QMLDOM_FIELD(metaRevisions);
554QMLDOM_FIELD(methodType);
555QMLDOM_FIELD(methods);
556QMLDOM_FIELD(minorVersion);
557QMLDOM_FIELD(moduleIndex);
558QMLDOM_FIELD(moduleIndexWithUri);
559QMLDOM_FIELD(moduleScope);
560QMLDOM_FIELD(nAllLoadedCallbacks);
561QMLDOM_FIELD(nCallbacks);
562QMLDOM_FIELD(nLoaded);
563QMLDOM_FIELD(nNotdone);
564QMLDOM_FIELD(name);
565QMLDOM_FIELD(newlinesBefore);
566QMLDOM_FIELD(nextComponent);
567QMLDOM_FIELD(nextScope);
568QMLDOM_FIELD(notify);
569QMLDOM_FIELD(objects);
570QMLDOM_FIELD(onAttachedObject);
571QMLDOM_FIELD(operation);
572QMLDOM_FIELD(options);
573QMLDOM_FIELD(parameters);
574QMLDOM_FIELD(parent);
575QMLDOM_FIELD(parentObject);
576QMLDOM_FIELD(path);
577QMLDOM_FIELD(plugins);
578QMLDOM_FIELD(postCode);
579QMLDOM_FIELD(postCommentLocations);
580QMLDOM_FIELD(postComments);
581QMLDOM_FIELD(pragma);
582QMLDOM_FIELD(pragmas);
583QMLDOM_FIELD(preCode);
584QMLDOM_FIELD(preCommentLocations);
585QMLDOM_FIELD(preComments);
586QMLDOM_FIELD(properties);
587QMLDOM_FIELD(propertyDef);
588QMLDOM_FIELD(propertyDefRef);
589QMLDOM_FIELD(propertyDefs);
590QMLDOM_FIELD(propertyInfos);
591QMLDOM_FIELD(propertyName);
592QMLDOM_FIELD(prototypes);
593QMLDOM_FIELD(qmlDirectoryWithPath);
594QMLDOM_FIELD(qmlFileWithPath);
595QMLDOM_FIELD(qmlFiles);
596QMLDOM_FIELD(qmldirFileWithPath);
597QMLDOM_FIELD(qmldirWithPath);
598QMLDOM_FIELD(qmltypesFileWithPath);
599QMLDOM_FIELD(qmltypesFiles);
600QMLDOM_FIELD(qualifiedImports);
601QMLDOM_FIELD(queue);
602QMLDOM_FIELD(rawComment);
603QMLDOM_FIELD(read);
604QMLDOM_FIELD(referredObject);
605QMLDOM_FIELD(referredObjectPath);
606QMLDOM_FIELD(regionComments);
607QMLDOM_FIELD(regions);
608QMLDOM_FIELD(requestedAt);
609QMLDOM_FIELD(requestingUniverse);
610QMLDOM_FIELD(returnType);
611QMLDOM_FIELD(returnTypeName);
612QMLDOM_FIELD(right);
613QMLDOM_FIELD(rootComponent);
614QMLDOM_FIELD(scopeType);
615QMLDOM_FIELD(scriptElement);
616QMLDOM_FIELD(sources);
617QMLDOM_FIELD(statements);
618QMLDOM_FIELD(status);
619QMLDOM_FIELD(stringValue);
620QMLDOM_FIELD(subComponents);
621QMLDOM_FIELD(subImports);
622QMLDOM_FIELD(subItems);
623QMLDOM_FIELD(symbol);
624QMLDOM_FIELD(symbols);
625QMLDOM_FIELD(target);
626QMLDOM_FIELD(targetPropertyName);
627QMLDOM_FIELD(text);
628QMLDOM_FIELD(type);
629QMLDOM_FIELD(typeArgument);
630QMLDOM_FIELD(typeName);
631QMLDOM_FIELD(types);
632QMLDOM_FIELD(universe);
633QMLDOM_FIELD(updatedScriptExpressions);
634QMLDOM_FIELD(uri);
635QMLDOM_FIELD(uris);
636QMLDOM_FIELD(validExposedAt);
637QMLDOM_FIELD(validItem);
638QMLDOM_FIELD(value);
639QMLDOM_FIELD(valueTypeName);
640QMLDOM_FIELD(values);
641QMLDOM_FIELD(version);
642QMLDOM_FIELD(when);
643QMLDOM_FIELD(write);
644} // namespace Fields
645
646class Source;
647size_t qHash(const Path &, size_t);
648class PathIterator;
649// Define a iterator for it?
650// begin() can basically be itself, end() the empty path (zero length), iteration though dropFront()
651class QMLDOM_EXPORT Path{
652 Q_GADGET
653 Q_DECLARE_TR_FUNCTIONS(ErrorGroup);
654public:
655 using Kind = PathEls::Kind;
656 using Component = PathEls::PathComponent;
657 static ErrorGroups myErrors(); // use static consts and central registration instead?
658
659 Path() = default;
660 explicit Path(const PathEls::PathComponent &c) : m_endOffset(0), m_length(0)
661 {
662 *this = appendComponent(c);
663 }
664
665 int length() const { return m_length; }
666 Path operator[](int i) const;
667 explicit operator bool() const;
668
669 PathIterator begin() const;
670 PathIterator end() const;
671
672 PathRoot headRoot() const;
673 PathCurrent headCurrent() const;
674 Kind headKind() const;
675 QString headName() const;
676 bool checkHeadName(QStringView name) const;
677 index_type headIndex(index_type defaultValue=-1) const;
678 std::function<bool(DomItem)> headFilter() const;
679 Path head() const;
680 Path last() const;
681 Source split() const;
682
683 void dump(Sink sink) const;
684 QString toString() const;
685 Path dropFront(int n = 1) const;
686 Path dropTail(int n = 1) const;
687 Path mid(int offset, int length) const;
688 Path mid(int offset) const;
689 Path appendComponent(const PathEls::PathComponent &c);
690
691 // # Path construction
692 static Path fromString(QString s, ErrorHandler errorHandler=nullptr);
693 static Path fromString(QStringView s, ErrorHandler errorHandler=nullptr);
694 static Path Root(PathRoot r);
695 static Path Root(QStringView s=u"");
696 static Path Root(QString s);
697 static Path Index(index_type i);
698 static Path Field(QStringView s=u"");
699 static Path Field(QString s);
700 static Path Key(QStringView s=u"");
701 static Path Key(QString s);
702 static Path Current(PathCurrent c);
703 static Path Current(QStringView s=u"");
704 static Path Current(QString s);
705 static Path Empty();
706 // add
707 Path empty() const;
708 Path field(QString name) const;
709 Path field(QStringView name) const;
710 Path key(QString name) const;
711 Path key(QStringView name) const;
712 Path index(index_type i) const;
713 Path any() const;
714 Path filter(std::function<bool(DomItem)>, QString) const;
715 Path filter(std::function<bool(DomItem)>, QStringView desc=u"<native code filter>") const;
716 Path current(PathCurrent s) const;
717 Path current(QString s) const;
718 Path current(QStringView s=u"") const;
719 Path path(Path toAdd, bool avoidToAddAsBase = false) const;
720
721 Path expandFront() const;
722 Path expandBack() const;
723
724 Path &operator++();
725 Path operator ++(int);
726
727 // iterator traits
728 using difference_type = long;
729 using value_type = Path;
730 using pointer = const Component*;
731 using reference = const Path&;
732 using iterator_category = std::forward_iterator_tag;
733
734 static int cmp(const Path &p1, const Path &p2);
735
736private:
737 const Component &component(int i) const;
738 explicit Path(quint16 endOffset, quint16 length, std::shared_ptr<PathEls::PathData> data);
739 friend class QQmlJS::Dom::PathEls::TestPaths;
740 friend class FieldFilter;
741 friend size_t qHash(const Path &, size_t);
742
743 Path noEndOffset() const;
744
745 quint16 m_endOffset = 0;
746 quint16 m_length = 0;
747 std::shared_ptr<PathEls::PathData> m_data = {};
748};
749
750inline bool operator==(const Path &lhs, const Path &rhs)
751{
752 return lhs.length() == rhs.length() && Path::cmp(p1: lhs, p2: rhs) == 0;
753}
754inline bool operator!=(const Path &lhs, const Path &rhs)
755{
756 return lhs.length() != rhs.length() || Path::cmp(p1: lhs, p2: rhs) != 0;
757}
758inline bool operator<(const Path &lhs, const Path &rhs)
759{
760 return Path::cmp(p1: lhs, p2: rhs) < 0;
761}
762inline bool operator>(const Path &lhs, const Path &rhs)
763{
764 return Path::cmp(p1: lhs, p2: rhs) > 0;
765}
766inline bool operator<=(const Path &lhs, const Path &rhs)
767{
768 return Path::cmp(p1: lhs, p2: rhs) <= 0;
769}
770inline bool operator>=(const Path &lhs, const Path &rhs)
771{
772 return Path::cmp(p1: lhs, p2: rhs) >= 0;
773}
774
775class PathIterator {
776public:
777 Path currentEl;
778 Path operator *() const { return currentEl.head(); }
779 PathIterator operator ++() { currentEl = currentEl.dropFront(); return *this; }
780 PathIterator operator ++(int) { PathIterator res{.currentEl: currentEl}; currentEl = currentEl.dropFront(); return res; }
781 bool operator ==(const PathIterator &o) const { return currentEl == o.currentEl; }
782 bool operator !=(const PathIterator &o) const { return currentEl != o.currentEl; }
783};
784
785class Source {
786public:
787 Path pathToSource;
788 Path pathFromSource;
789};
790
791inline size_t qHash(const Path &path, size_t seed)
792{
793 const size_t bufSize = 256;
794 size_t buf[bufSize];
795 size_t *it = &buf[0];
796 *it++ = path.length();
797 if (path.length()>0) {
798 int iPath = path.length();
799 size_t maxPath = bufSize / 2 - 1;
800 size_t endPath = (size_t(iPath) > maxPath) ? maxPath - iPath : 0;
801 while (size_t(iPath) > endPath) {
802 Path p = path[--iPath];
803 Path::Kind k = p.headKind();
804 *it++ = size_t(k);
805 *it++ = qHash(key: p.component(i: 0).stringView(), seed)^size_t(p.headRoot())^size_t(p.headCurrent());
806 }
807 }
808 return qHash(key: QByteArray::fromRawData(data: reinterpret_cast<char *>(&buf[0]), size: (it - &buf[0])*sizeof(size_t)), seed);
809}
810
811inline QDebug operator<<(QDebug debug, const Path &p)
812{
813 debug << p.toString();
814 return debug;
815}
816
817} // end namespace Dom
818} // end namespace QQmlJS
819
820QT_END_NAMESPACE
821
822#endif // QMLDOM_PATH_H
823

source code of qtdeclarative/src/qmldom/qqmldompath_p.h