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

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