1// Copyright (C) 2021 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 QMLDOMATTACHEDINFO_P_H
5#define QMLDOMATTACHEDINFO_P_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 "qqmldom_global.h"
19#include "qqmldomitem_p.h"
20
21#include <memory>
22#include <optional>
23
24QT_BEGIN_NAMESPACE
25
26namespace QQmlJS {
27namespace Dom {
28struct AttachedInfoLookupResultBase
29{
30 Path lookupPath;
31 Path rootTreePath;
32 Path foundTreePath;
33};
34template<typename TreePtr>
35class AttachedInfoLookupResult: public AttachedInfoLookupResultBase
36{
37public:
38 TreePtr foundTree;
39
40 operator bool() { return bool(foundTree); }
41 template<typename T>
42 AttachedInfoLookupResult<std::shared_ptr<T>> as() const
43 {
44 AttachedInfoLookupResult<std::shared_ptr<T>> res;
45 res.AttachedInfoLookupResultBase::operator=(*this);
46 res.foundTree = std::static_pointer_cast<T>(foundTree);
47 return res;
48 }
49};
50
51class QMLDOM_EXPORT AttachedInfo : public OwningItem {
52 Q_GADGET
53public:
54 enum class PathType {
55 Relative,
56 Canonical
57 };
58 Q_ENUM(PathType)
59
60 constexpr static DomType kindValue = DomType::AttachedInfo;
61 using Ptr = std::shared_ptr<AttachedInfo>;
62
63 DomType kind() const override { return kindValue; }
64 Path canonicalPath(const DomItem &self) const override { return self.m_ownerPath; }
65 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor visitor) const override;
66
67 AttachedInfo::Ptr makeCopy(const DomItem &self) const
68 {
69 return std::static_pointer_cast<AttachedInfo>(r: doCopy(self));
70 }
71
72 Ptr parent() const { return m_parent.lock(); }
73 Path path() const { return m_path; }
74 void setPath(const Path &p) { m_path = p; }
75
76 AttachedInfo(const Ptr &parent = nullptr, const Path &p = Path())
77 : m_path(p), m_parent(parent)
78 {}
79
80 AttachedInfo(const AttachedInfo &o);
81
82 static Ptr ensure(const Ptr &self, const Path &path, PathType pType = PathType::Relative);
83 static Ptr find(const Ptr &self, const Path &p, PathType pType = PathType::Relative);
84 static AttachedInfoLookupResult<Ptr> findAttachedInfo(const DomItem &item,
85 QStringView treeFieldName);
86 static Ptr treePtr(const DomItem &item, QStringView fieldName)
87 {
88 return findAttachedInfo(item, treeFieldName: fieldName).foundTree;
89 }
90
91 DomItem itemAtPath(const DomItem &self, const Path &p, PathType pType = PathType::Relative) const
92 {
93 if (Ptr resPtr = find(self: self.ownerAs<AttachedInfo>(), p, pType)) {
94 const Path relative = (pType == PathType::Canonical) ? p.mid(offset: m_path.length()) : p;
95 Path resPath = self.canonicalPath();
96 for (const Path &pEl : relative) {
97 resPath = resPath.field(name: Fields::subItems).key(name: pEl.toString());
98 }
99 return self.copy(owner: resPtr, ownerPath: resPath);
100 }
101 return DomItem();
102 }
103
104 DomItem infoAtPath(const DomItem &self, const Path &p, PathType pType = PathType::Relative) const
105 {
106 return itemAtPath(self, p, pType).field(name: Fields::infoItem);
107 }
108
109 MutableDomItem ensureItemAtPath(MutableDomItem &self, const Path &p,
110 PathType pType = PathType::Relative)
111 {
112 if (Ptr resPtr = ensure(self: self.ownerAs<AttachedInfo>(), path: p, pType)) {
113 const Path relative = (pType == PathType::Canonical) ? p.mid(offset: m_path.length()) : p;
114 Path resPath = self.canonicalPath();
115 for (const Path &pEl : relative) {
116 resPath = resPath.field(name: Fields::subItems).key(name: pEl.toString());
117 }
118 return MutableDomItem(self.item().copy(owner: resPtr, ownerPath: resPath));
119 }
120 return MutableDomItem();
121 }
122
123 MutableDomItem ensureInfoAtPath(MutableDomItem &self, const Path &p,
124 PathType pType = PathType::Relative)
125 {
126 return ensureItemAtPath(self, p, pType).field(name: Fields::infoItem);
127 }
128
129 virtual AttachedInfo::Ptr instantiate(
130 const AttachedInfo::Ptr &parent, const Path &p = Path()) const = 0;
131 virtual DomItem infoItem(const DomItem &self) const = 0;
132 QMap<Path, Ptr> subItems() const {
133 return m_subItems;
134 }
135 void setSubItems(QMap<Path, Ptr> v) {
136 m_subItems = v;
137 }
138protected:
139 Path m_path;
140 std::weak_ptr<AttachedInfo> m_parent;
141 QMap<Path, Ptr> m_subItems;
142};
143
144template<typename Info>
145class QMLDOM_EXPORT AttachedInfoT final : public AttachedInfo
146{
147public:
148 constexpr static DomType kindValue = DomType::AttachedInfo;
149 using Ptr = std::shared_ptr<AttachedInfoT>;
150 using InfoType = Info;
151
152 AttachedInfoT(const Ptr &parent = nullptr, const Path &p = Path()) : AttachedInfo(parent, p) {}
153 AttachedInfoT(const AttachedInfoT &o):
154 AttachedInfo(o),
155 m_info(o.m_info)
156 {
157 auto end = o.m_subItems.end();
158 auto i = o.m_subItems.begin();
159 while (i != end) {
160 m_subItems.insert(i.key(), Ptr(
161 new AttachedInfoT(*std::static_pointer_cast<AttachedInfoT>(i.value()).get())));
162 }
163 }
164
165 static Ptr createTree(const Path &p = Path()) {
166 return Ptr(new AttachedInfoT(nullptr, p));
167 }
168
169 static Ptr ensure(const Ptr &self, const Path &path, PathType pType = PathType::Relative)
170 {
171 return std::static_pointer_cast<AttachedInfoT>(AttachedInfo::ensure(self, path, pType));
172 }
173
174 static Ptr find(const Ptr &self, const Path &p, PathType pType = PathType::Relative)
175 {
176 return std::static_pointer_cast<AttachedInfoT>(AttachedInfo::find(self, p, pType));
177 }
178
179 static AttachedInfoLookupResult<Ptr> findAttachedInfo(const DomItem &item,
180 QStringView fieldName)
181 {
182 return AttachedInfo::findAttachedInfo(item, treeFieldName: fieldName).template as<AttachedInfoT>();
183 }
184 static Ptr treePtr(const DomItem &item, QStringView fieldName)
185 {
186 return std::static_pointer_cast<AttachedInfoT>(AttachedInfo::treePtr(item, fieldName));
187 }
188 static bool visitTree(
189 const Ptr &base, function_ref<bool(const Path &, const Ptr &)> visitor,
190 const Path &basePath = Path()) {
191 if (base) {
192 Path pNow = basePath.path(toAdd: base->path());
193 if (visitor(pNow, base)) {
194 auto it = base->m_subItems.cbegin();
195 auto end = base->m_subItems.cend();
196 while (it != end) {
197 if (!visitTree(base: std::static_pointer_cast<AttachedInfoT>(it.value()), visitor, basePath: pNow))
198 return false;
199 ++it;
200 }
201 } else {
202 return false;
203 }
204 }
205 return true;
206 }
207
208 AttachedInfo::Ptr instantiate(
209 const AttachedInfo::Ptr &parent, const Path &p = Path()) const override
210 {
211 return Ptr(new AttachedInfoT(std::static_pointer_cast<AttachedInfoT>(parent), p));
212 }
213
214 DomItem infoItem(const DomItem &self) const override { return self.wrapField(Fields::infoItem, m_info); }
215
216 Ptr makeCopy(const DomItem &self) const
217 {
218 return std::static_pointer_cast<AttachedInfoT>(doCopy(self));
219 }
220
221 Ptr parent() const { return std::static_pointer_cast<AttachedInfoT>(AttachedInfo::parent()); }
222
223 const Info &info() const { return m_info; }
224 Info &info() { return m_info; }
225
226 QString canonicalPathForTesting() const
227 {
228 QString result;
229 for (auto *it = this; it; it = it->parent().get()) {
230 result.prepend(it->path().toString());
231 }
232 return result;
233 }
234
235protected:
236 std::shared_ptr<OwningItem> doCopy(const DomItem &) const override
237 {
238 return Ptr(new AttachedInfoT(*this));
239 }
240
241private:
242 Info m_info;
243};
244
245class QMLDOM_EXPORT FileLocations {
246public:
247 using Tree = std::shared_ptr<AttachedInfoT<FileLocations>>;
248 constexpr static DomType kindValue = DomType::FileLocations;
249 DomType kind() const { return kindValue; }
250 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const;
251
252 static Tree createTree(const Path &basePath);
253 static Tree ensure(const Tree &base, const Path &basePath,
254 AttachedInfo::PathType pType = AttachedInfo::PathType::Relative);
255 static Tree find(const Tree &self, const Path &p,
256 AttachedInfo::PathType pType = AttachedInfo::PathType::Relative)
257 {
258 return AttachedInfoT<FileLocations>::find(self, p, pType);
259 }
260
261 // returns the path looked up and the found tree when looking for the info attached to item
262 static AttachedInfoLookupResult<Tree> findAttachedInfo(const DomItem &item);
263 static FileLocations::Tree treeOf(const DomItem &);
264 static const FileLocations *fileLocationsOf(const DomItem &);
265
266 static void updateFullLocation(const Tree &fLoc, SourceLocation loc);
267 static void addRegion(const Tree &fLoc, FileLocationRegion region, SourceLocation loc);
268 static QQmlJS::SourceLocation region(const Tree &fLoc, FileLocationRegion region);
269
270private:
271 static QMetaEnum regionEnum;
272
273public:
274 SourceLocation fullRegion;
275 QMap<FileLocationRegion, SourceLocation> regions;
276 QMap<FileLocationRegion, QList<SourceLocation>> preCommentLocations;
277 QMap<FileLocationRegion, QList<SourceLocation>> postCommentLocations;
278};
279
280class QMLDOM_EXPORT UpdatedScriptExpression
281{
282 Q_GADGET
283public:
284 using Tree = std::shared_ptr<AttachedInfoT<UpdatedScriptExpression>>;
285 constexpr static DomType kindValue = DomType::UpdatedScriptExpression;
286 DomType kind() const { return kindValue; }
287 bool iterateDirectSubpaths(const DomItem &self, DirectVisitor) const;
288
289 static Tree createTree(const Path &basePath);
290 static Tree ensure(const Tree &base, const Path &basePath, AttachedInfo::PathType pType);
291
292 // returns the path looked up and the found tree when looking for the info attached to item
293 static AttachedInfoLookupResult<Tree>
294 findAttachedInfo(const DomItem &item);
295 // convenience: find FileLocations::Tree attached to the given item
296 static Tree treePtr(const DomItem &);
297 // convenience: find FileLocations* attached to the given item (if there is one)
298 static const UpdatedScriptExpression *exprPtr(const DomItem &);
299
300 static bool visitTree(
301 const Tree &base, function_ref<bool(const Path &, const Tree &)> visitor,
302 const Path &basePath = Path());
303
304 std::shared_ptr<ScriptExpression> expr;
305};
306
307} // end namespace Dom
308} // end namespace QQmlJS
309
310QT_END_NAMESPACE
311#endif // QMLDOMATTACHEDINFO_P_H
312

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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