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 | |
24 | QT_BEGIN_NAMESPACE |
25 | |
26 | namespace QQmlJS { |
27 | namespace Dom { |
28 | struct AttachedInfoLookupResultBase |
29 | { |
30 | Path lookupPath; |
31 | Path rootTreePath; |
32 | Path foundTreePath; |
33 | }; |
34 | template<typename TreePtr> |
35 | class AttachedInfoLookupResult: public AttachedInfoLookupResultBase |
36 | { |
37 | public: |
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 | |
51 | class QMLDOM_EXPORT AttachedInfo : public OwningItem { |
52 | Q_GADGET |
53 | public: |
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 | } |
138 | protected: |
139 | Path m_path; |
140 | std::weak_ptr<AttachedInfo> m_parent; |
141 | QMap<Path, Ptr> m_subItems; |
142 | }; |
143 | |
144 | template<typename Info> |
145 | class QMLDOM_EXPORT AttachedInfoT final : public AttachedInfo |
146 | { |
147 | public: |
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 | |
235 | protected: |
236 | std::shared_ptr<OwningItem> doCopy(const DomItem &) const override |
237 | { |
238 | return Ptr(new AttachedInfoT(*this)); |
239 | } |
240 | |
241 | private: |
242 | Info m_info; |
243 | }; |
244 | |
245 | class QMLDOM_EXPORT FileLocations { |
246 | public: |
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 | |
270 | private: |
271 | static QMetaEnum regionEnum; |
272 | |
273 | public: |
274 | SourceLocation fullRegion; |
275 | QMap<FileLocationRegion, SourceLocation> regions; |
276 | QMap<FileLocationRegion, QList<SourceLocation>> preCommentLocations; |
277 | QMap<FileLocationRegion, QList<SourceLocation>> postCommentLocations; |
278 | }; |
279 | |
280 | class QMLDOM_EXPORT UpdatedScriptExpression |
281 | { |
282 | Q_GADGET |
283 | public: |
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 | |
310 | QT_END_NAMESPACE |
311 | #endif // QMLDOMATTACHEDINFO_P_H |
312 |
Definitions
- AttachedInfoLookupResultBase
- AttachedInfoLookupResult
- operator bool
- as
- AttachedInfo
- PathType
- kindValue
- kind
- canonicalPath
- makeCopy
- parent
- path
- setPath
- AttachedInfo
- treePtr
- itemAtPath
- infoAtPath
- ensureItemAtPath
- ensureInfoAtPath
- subItems
- setSubItems
- AttachedInfoT
- kindValue
- AttachedInfoT
- AttachedInfoT
- createTree
- ensure
- find
- findAttachedInfo
- treePtr
- visitTree
- instantiate
- infoItem
- makeCopy
- parent
- info
- info
- canonicalPathForTesting
- doCopy
- FileLocations
- kindValue
- kind
- find
- UpdatedScriptExpression
- kindValue
Learn to use CMake with our Intro Training
Find out more