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
qqmldomastcreator_p.h
Go to the documentation of this file.
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// Qt-Security score:significant
4
5#ifndef QQMLDOMASTCREATOR_P_H
6#define QQMLDOMASTCREATOR_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
20#include "qqmldomitem_p.h"
21#include "qqmldompath_p.h"
23
24#include <QtQmlCompiler/private/qqmljsimportvisitor_p.h>
25
26#include <QtQml/private/qqmljsastvisitor_p.h>
27#include <memory>
28#include <type_traits>
29#include <variant>
30
32
33namespace QQmlJS {
34namespace Dom {
35
37{
38 Q_DECLARE_TR_FUNCTIONS(QQmlDomAstCreator)
39public:
40 using AST::Visitor::endVisit;
41 using AST::Visitor::visit;
42private:
43
44 static constexpr const auto className = "QmlDomAstCreator";
45
46 class DomValue
47 {
48 public:
49 template<typename T>
50 DomValue(const T &obj) : kind(T::kindValue), value(obj)
51 {
52 }
53 DomType kind;
54 std::variant<QmlObject, MethodInfo, QmlComponent, PropertyDefinition, Binding, EnumDecl,
55 EnumItem, ConstantData, Id>
56 value;
57 };
58
59 class QmlStackElement
60 {
61 public:
62 Path path;
63 DomValue item;
64 FileLocations::Tree fileLocations;
65 };
66
67 /*!
68 \internal
69 Contains a ScriptElementVariant, that can be used everywhere in the DOM representation, or a
70 List that should always be inside of something else, e.g., that cannot be the root of the
71 script element DOM representation.
72
73 Also, it makes sure you do not mistreat a list as a regular script element and vice versa.
74
75 The reason for this is that Lists can get pretty unintuitive, as a List could be a Block of
76 statements or a list of variable declarations (let i = 3, j = 4, ...) or something completely
77 different. Instead, always put lists inside named construct (BlockStatement,
78 VariableDeclaration, ...).
79 */
80 class ScriptStackElement
81 {
82 public:
83 template<typename T>
84 static ScriptStackElement from(const T &obj)
85 {
86 if constexpr (std::is_same_v<T, ScriptElements::ScriptList>) {
87 ScriptStackElement s{ ScriptElements::ScriptList::kindValue, obj };
88 return s;
89 } else {
90 ScriptStackElement s{ obj->kind(), ScriptElementVariant::fromElement(obj) };
91 return s;
92 }
93 Q_UNREACHABLE();
94 }
95
96 DomType kind;
97 using Variant = std::variant<ScriptElementVariant, ScriptElements::ScriptList>;
98 Variant value;
99
100 ScriptElementVariant takeVariant()
101 {
102 Q_ASSERT_X(std::holds_alternative<ScriptElementVariant>(value), "takeVariant",
103 "Should be a variant, did the parser change?");
104 return std::get<ScriptElementVariant>(std::move(value));
105 }
106
107 bool isList() const { return std::holds_alternative<ScriptElements::ScriptList>(value); };
108
109 ScriptElements::ScriptList takeList()
110 {
111 Q_ASSERT_X(std::holds_alternative<ScriptElements::ScriptList>(value), "takeList",
112 "Should be a List, did the parser change?");
113 return std::get<ScriptElements::ScriptList>(std::move(value));
114 }
115
116 void setSemanticScope(const QQmlJSScope::ConstPtr &scope)
117 {
118 if (auto x = std::get_if<ScriptElementVariant>(&value)) {
119 x->base()->setSemanticScope(scope);
120 return;
121 } else if (auto x = std::get_if<ScriptElements::ScriptList>(&value)) {
122 x->setSemanticScope(scope);
123 return;
124 }
125 Q_UNREACHABLE();
126 }
127 };
128
129public:
130 void enableScriptExpressions(bool enable = true) { m_enableScriptExpressions = enable; }
131 void enableLoadFileLazily(bool enable = true) { m_loadFileLazily = enable; }
132
133private:
134
135 MutableDomItem qmlFile;
136 std::shared_ptr<QmlFile> qmlFilePtr;
137 QVector<QmlStackElement> nodeStack;
138 QList<ScriptStackElement> scriptNodeStack;
139 QVector<int> arrayBindingLevels;
140 FileLocations::Tree rootMap;
141 int m_nestedFunctionDepth = 0;
142 bool m_enableScriptExpressions = false;
143 bool m_loadFileLazily = false;
144
145 // A Binding inside a UiPublicMember (= a Property definition) will shadow the
146 // propertydefinition's binding identifiers with its own binding identifiers. Therefore, disable
147 // bindingIdentifiers for the Binding inside a Property definition by using this flag.
148 bool m_skipBindingIdentifiers = false;
149
150 void setBindingIdentifiers(const Path &pathFromOwner, const AST::UiQualifiedId *identifiers,
151 Binding *bindingPtr);
152 template<typename T>
153 QmlStackElement &currentEl(int idx = 0)
154 {
155 Q_ASSERT_X(idx < nodeStack.size() && idx >= 0, "currentQmlObjectOrComponentEl",
156 "Stack does not contain enough elements!");
157 int i = nodeStack.size() - idx;
158 while (i-- > 0) {
159 DomType k = nodeStack.at(i).item.kind;
160 if (k == T::kindValue)
161 return nodeStack[i];
162 }
163 Q_ASSERT_X(false, "currentEl", "Stack does not contan object of type ");
164 return nodeStack.last();
165 }
166
167 template<typename T>
168 ScriptStackElement &currentScriptEl(int idx = 0)
169 {
170 Q_ASSERT_X(m_enableScriptExpressions, "currentScriptEl",
171 "Cannot access script elements when they are disabled!");
172
173 Q_ASSERT_X(idx < scriptNodeStack.size() && idx >= 0, "currentQmlObjectOrComponentEl",
174 "Stack does not contain enough elements!");
175 int i = scriptNodeStack.size() - idx;
176 while (i-- > 0) {
177 DomType k = scriptNodeStack.at(i).kind;
178 if (k == T::element_type::kindValue)
179 return scriptNodeStack[i];
180 }
181 Q_ASSERT_X(false, "currentEl", "Stack does not contain object of type ");
182 return scriptNodeStack.last();
183 }
184
185 template<typename T>
186 T &current(int idx = 0)
187 {
188 return std::get<T>(currentEl<T>(idx).item.value);
189 }
190
191 index_type currentIndex() { return currentNodeEl().path.last().headIndex(); }
192
193 QmlStackElement &currentQmlObjectOrComponentEl(int idx = 0);
194
195 QmlStackElement &currentNodeEl(int i = 0);
196 ScriptStackElement &currentScriptNodeEl(int i = 0);
197
198 DomValue &currentNode(int i = 0);
199
200 void removeCurrentNode(std::optional<DomType> expectedType);
201 void removeCurrentScriptNode(std::optional<DomType> expectedType);
202
203 void pushEl(const Path &p, const DomValue &it, AST::Node *n)
204 {
205 nodeStack.append({ p, it, createMap(it.kind, p, n) });
206 }
207
208 FileLocations::Tree createMap(const FileLocations::Tree &base, const Path &p, AST::Node *n);
209
210 FileLocations::Tree createMap(DomType k, const Path &p, AST::Node *n);
211
213 finalizeScriptExpression(const ScriptElementVariant &element, const Path &pathFromOwner,
214 const FileLocations::Tree &ownerFileLocations);
215
216 void setScriptExpression (const std::shared_ptr<ScriptExpression>& value);
217
218 Path pathOfLastScriptNode() const;
219
220 /*!
221 \internal
222 Helper to create string literals from AST nodes.
223 */
224 template<typename AstNodeT>
225 static std::shared_ptr<ScriptElements::Literal> makeStringLiteral(QStringView value,
226 AstNodeT *ast)
227 {
228 auto myExp = std::make_shared<ScriptElements::Literal>(ast->firstSourceLocation(),
229 ast->lastSourceLocation());
230 myExp->setLiteralValue(value.toString());
231 return myExp;
232 }
233
234 static std::shared_ptr<ScriptElements::Literal> makeStringLiteral(QStringView value,
235 QQmlJS::SourceLocation loc)
236 {
237 auto myExp = std::make_shared<ScriptElements::Literal>(loc);
238 myExp->setLiteralValue(value.toString());
239 return myExp;
240 }
241
242 /*!
243 \internal
244 Helper to create script elements from AST nodes, as the DOM classes should be completely
245 dependency-free from AST and parser classes. Using the AST classes in qqmldomastcreator is
246 fine because it needs them for the construction/visit. \sa makeScriptList
247 */
248 template<typename ScriptElementT, typename AstNodeT,
249 typename Enable =
250 std::enable_if_t<!std::is_same_v<ScriptElementT, ScriptElements::ScriptList>>>
251 static decltype(auto) makeScriptElement(AstNodeT *ast)
252 {
253 auto myExp = std::make_shared<ScriptElementT>(ast->firstSourceLocation(),
254 ast->lastSourceLocation());
255 return myExp;
256 }
257
258 /*!
259 \internal
260 Helper to create generic script elements from AST nodes.
261 \sa makeScriptElement
262 */
263 template<typename AstNodeT>
264 static std::shared_ptr<ScriptElements::GenericScriptElement>
265 makeGenericScriptElement(AstNodeT *ast, DomType kind)
266 {
267 auto myExp = std::make_shared<ScriptElements::GenericScriptElement>(
268 ast->firstSourceLocation(), ast->lastSourceLocation());
269 myExp->setKind(kind);
270 return myExp;
271 }
272
273 enum UnaryExpressionKind { Prefix, Postfix };
275 makeUnaryExpression(AST::Node *expression, QQmlJS::SourceLocation operatorToken,
276 bool hasExpression, UnaryExpressionKind type);
277
278 static std::shared_ptr<ScriptElements::GenericScriptElement>
279 makeGenericScriptElement(SourceLocation location, DomType kind)
280 {
281 auto myExp = std::make_shared<ScriptElements::GenericScriptElement>(location);
282 myExp->setKind(kind);
283 return myExp;
284 }
285
286 /*!
287 \internal
288 Helper to create script lists from AST nodes.
289 \sa makeScriptElement
290 */
291 template<typename AstNodeT>
292 static decltype(auto) makeScriptList(AstNodeT *ast)
293 {
294 auto myExp =
295 ScriptElements::ScriptList(ast->firstSourceLocation(), ast->lastSourceLocation());
296 return myExp;
297 }
298
299 template<typename ScriptElementT>
300 void pushScriptElement(const ScriptElementT &element)
301 {
302 Q_ASSERT_X(m_enableScriptExpressions, "pushScriptElement",
303 "Cannot create script elements when they are disabled!");
304 scriptNodeStack.append(ScriptStackElement::from(element));
305 }
306
307 void disableScriptElements()
308 {
309 m_enableScriptExpressions = false;
310 scriptNodeStack.clear();
311 }
312
313 ScriptElementVariant scriptElementForQualifiedId(AST::UiQualifiedId *expression);
314
315public:
316 explicit QQmlDomAstCreatorBase(const MutableDomItem &qmlFile);
317
318 bool visit(AST::UiProgram *program) override;
319 void endVisit(AST::UiProgram *) override;
320
321 bool visit(AST::UiPragma *el) override;
322
323 bool visit(AST::UiImport *el) override;
324
325 bool visit(AST::UiPublicMember *el) override;
326 void endVisit(AST::UiPublicMember *el) override;
327
328private:
329 ScriptElementVariant prepareBodyForFunction(AST::FunctionExpression *fExpression);
330
331public:
332 bool visit(AST::FunctionExpression *el) override;
333 void endVisit(AST::FunctionExpression *) override;
334
335 bool visit(AST::FunctionDeclaration *el) override;
336 void endVisit(AST::FunctionDeclaration *) override;
337
338 bool visit(AST::UiSourceElement *el) override;
339 void endVisit(AST::UiSourceElement *) override;
340
341 void loadAnnotations(AST::UiObjectMember *el) { AST::Node::accept(el->annotations, this); }
342
343 bool visit(AST::UiObjectDefinition *el) override;
344 void endVisit(AST::UiObjectDefinition *) override;
345
346 bool visit(AST::UiObjectBinding *el) override;
347 void endVisit(AST::UiObjectBinding *) override;
348
349 bool visit(AST::UiScriptBinding *el) override;
350 void endVisit(AST::UiScriptBinding *) override;
351
352 bool visit(AST::UiArrayBinding *el) override;
353 void endVisit(AST::UiArrayBinding *) override;
354
355 bool visit(AST::UiQualifiedId *) override;
356
357 bool visit(AST::UiEnumDeclaration *el) override;
358 void endVisit(AST::UiEnumDeclaration *) override;
359
360 bool visit(AST::UiEnumMemberList *el) override;
361 void endVisit(AST::UiEnumMemberList *el) override;
362
363 bool visit(AST::UiInlineComponent *el) override;
364 void endVisit(AST::UiInlineComponent *) override;
365
366 bool visit(AST::UiRequired *el) override;
367
368 bool visit(AST::UiAnnotation *el) override;
369 void endVisit(AST::UiAnnotation *) override;
370
371 // for Script elements:
372 bool visit(AST::BinaryExpression *exp) override;
373 void endVisit(AST::BinaryExpression *exp) override;
374
375 bool visit(AST::Block *block) override;
376 void endVisit(AST::Block *) override;
377
378 bool visit(AST::YieldExpression *block) override;
379 void endVisit(AST::YieldExpression *) override;
380
381 bool visit(AST::ReturnStatement *block) override;
382 void endVisit(AST::ReturnStatement *) override;
383
384 bool visit(AST::ForStatement *forStatement) override;
385 void endVisit(AST::ForStatement *forStatement) override;
386
387 bool visit(AST::PatternElement *pe) override;
388 void endVisit(AST::PatternElement *pe) override;
389 void endVisitHelper(AST::PatternElement *pe,
390 const std::shared_ptr<ScriptElements::GenericScriptElement> &element);
391
392 bool visit(AST::IfStatement *) override;
393 void endVisit(AST::IfStatement *) override;
394
395 bool visit(AST::FieldMemberExpression *) override;
396 void endVisit(AST::FieldMemberExpression *) override;
397
398 bool visit(AST::ArrayMemberExpression *) override;
399 void endVisit(AST::ArrayMemberExpression *) override;
400
401 bool visit(AST::CallExpression *) override;
402 void endVisit(AST::CallExpression *) override;
403
404 bool visit(AST::ArrayPattern *) override;
405 void endVisit(AST::ArrayPattern *) override;
406
407 bool visit(AST::ObjectPattern *) override;
408 void endVisit(AST::ObjectPattern *) override;
409
410 bool visit(AST::PatternProperty *) override;
411 void endVisit(AST::PatternProperty *) override;
412
413 bool visit(AST::VariableStatement *) override;
414 void endVisit(AST::VariableStatement *) override;
415
416 bool visit(AST::Type *expression) override;
417 void endVisit(AST::Type *expression) override;
418
419 bool visit(AST::DefaultClause *) override;
420 void endVisit(AST::DefaultClause *) override;
421
422 bool visit(AST::CaseClause *) override;
423 void endVisit(AST::CaseClause *) override;
424
425 bool visit(AST::CaseClauses *) override;
426 void endVisit(AST::CaseClauses *) override;
427
428 bool visit(AST::CaseBlock *) override;
429 void endVisit(AST::CaseBlock *) override;
430
431 bool visit(AST::SwitchStatement *) override;
432 void endVisit(AST::SwitchStatement *) override;
433
434 bool visit(AST::WhileStatement *) override;
435 void endVisit(AST::WhileStatement *) override;
436
437 bool visit(AST::DoWhileStatement *) override;
438 void endVisit(AST::DoWhileStatement *) override;
439
440 bool visit(AST::ForEachStatement *) override;
441 void endVisit(AST::ForEachStatement *) override;
442
443 bool visit(AST::ClassExpression *) override;
444 void endVisit(AST::ClassExpression *) override;
445
446 bool visit(AST::TryStatement *) override;
447 void endVisit(AST::TryStatement *) override;
448
449 bool visit(AST::Catch *) override;
450 void endVisit(AST::Catch *) override;
451
452 bool visit(AST::Finally *) override;
453 void endVisit(AST::Finally *) override;
454
455 bool visit(AST::ThrowStatement *) override;
456 void endVisit(AST::ThrowStatement *) override;
457
458 bool visit(AST::LabelledStatement *) override;
459 void endVisit(AST::LabelledStatement *) override;
460
461 bool visit(AST::ContinueStatement *) override;
462 void endVisit(AST::ContinueStatement *) override;
463
464 bool visit(AST::BreakStatement *) override;
465 void endVisit(AST::BreakStatement *) override;
466
467 bool visit(AST::CommaExpression *) override;
468 void endVisit(AST::CommaExpression *) override;
469
470 bool visit(AST::ConditionalExpression *) override;
471 void endVisit(AST::ConditionalExpression *) override;
472
473 bool visit(AST::UnaryMinusExpression *) override;
474 void endVisit(AST::UnaryMinusExpression *) override;
475
476 bool visit(AST::UnaryPlusExpression *) override;
477 void endVisit(AST::UnaryPlusExpression *) override;
478
479 bool visit(AST::TildeExpression *) override;
480 void endVisit(AST::TildeExpression *) override;
481
482 bool visit(AST::NotExpression *) override;
483 void endVisit(AST::NotExpression *) override;
484
485 bool visit(AST::TypeOfExpression *) override;
486 void endVisit(AST::TypeOfExpression *) override;
487
488 bool visit(AST::DeleteExpression *) override;
489 void endVisit(AST::DeleteExpression *) override;
490
491 bool visit(AST::VoidExpression *) override;
492 void endVisit(AST::VoidExpression *) override;
493
494 bool visit(AST::PostDecrementExpression *) override;
495 void endVisit(AST::PostDecrementExpression *) override;
496
497 bool visit(AST::PostIncrementExpression *) override;
498 void endVisit(AST::PostIncrementExpression *) override;
499
500 bool visit(AST::PreDecrementExpression *) override;
501 void endVisit(AST::PreDecrementExpression *) override;
502
503 bool visit(AST::PreIncrementExpression *) override;
504 void endVisit(AST::PreIncrementExpression *) override;
505
506 bool visit(AST::EmptyStatement *) override;
507 void endVisit(AST::EmptyStatement *) override;
508
509 bool visit(AST::NestedExpression *) override;
510 void endVisit(AST::NestedExpression *) override;
511
512 bool visit(AST::NewExpression *) override;
513 void endVisit(AST::NewExpression *) override;
514
515 bool visit(AST::NewMemberExpression *) override;
516 void endVisit(AST::NewMemberExpression *) override;
517
518 void endVisit(AST::WithStatement *) override;
519
520 // lists of stuff whose children don't need a qqmljsscope: visitation order can be custom
521 bool visit(AST::UiParameterList *) override;
522 bool visit(AST::Elision *elision) override;
523
524
525 // lists of stuff whose children need a qqmljsscope: visitation order cannot be custom
526 void endVisit(AST::StatementList *list) override;
527 void endVisit(AST::VariableDeclarationList *vdl) override;
528 void endVisit(AST::ArgumentList *) override;
529 void endVisit(AST::PatternElementList *) override;
530 void endVisit(AST::PatternPropertyList *) override;
531 void endVisit(AST::FormalParameterList *el) override;
532 void endVisit(AST::TemplateLiteral *) override;
533 void endVisit(AST::TaggedTemplate *) override;
534
535
536 // literals and ids
537 bool visit(AST::IdentifierExpression *expression) override;
538 bool visit(AST::NumericLiteral *expression) override;
539 bool visit(AST::StringLiteral *expression) override;
540 bool visit(AST::NullExpression *expression) override;
541 bool visit(AST::TrueLiteral *expression) override;
542 bool visit(AST::FalseLiteral *expression) override;
543 bool visit(AST::ComputedPropertyName *expression) override;
544 bool visit(AST::IdentifierPropertyName *expression) override;
545 bool visit(AST::NumericLiteralPropertyName *expression) override;
546 bool visit(AST::StringLiteralPropertyName *expression) override;
547 bool visit(AST::TypeAnnotation *expression) override;
548 bool visit(AST::RegExpLiteral *) override;
549 bool visit(AST::ThisExpression *) override;
550 bool visit(AST::SuperLiteral *) override;
551
553
555 {
556 return !scriptNodeStack.isEmpty() && !scriptNodeStack.last().isList();
557 }
559 {
560 return !scriptNodeStack.isEmpty() && scriptNodeStack.last().isList();
561 }
562
563private:
564 template<typename T>
565 void endVisitForLists(T *list, const std::function<int(T *)> &scriptElementsPerEntry = {});
566
567public:
569};
570
571template<typename U, typename... V>
572using IsInList = std::disjunction<std::is_same<U, V>...>;
573template<typename U>
577
578template <typename T, typename std::enable_if_t<RequiresCustomIteration<T>::value, bool> = true>
579bool visitWithCustomListIteration(T *t, AST::Visitor *visitor)
580{
581 for (T *it = t; it; it = it->next) {
582 if constexpr (std::is_same_v<T, AST::PatternElementList>) {
583 AST::Node::accept(it->elision, visitor);
584 AST::Node::accept(it->element, visitor);
585 } else if constexpr (std::is_same_v<T, AST::PatternPropertyList>) {
586 AST::Node::accept(it->property, visitor);
587 } else if constexpr (std::is_same_v<T, AST::FormalParameterList>) {
588 AST::Node::accept(it->element, visitor);
589 } else if constexpr (std::is_same_v<T, AST::VariableDeclarationList>) {
590 AST::Node::accept(it->declaration, visitor);
591 } else if constexpr (std::is_same_v<T, AST::ArgumentList>) {
592 AST::Node::accept(it->expression, visitor);
593 } else if constexpr (std::is_same_v<T, AST::PatternElementList>) {
594 AST::Node::accept(it->elision, visitor);
595 AST::Node::accept(it->element, visitor);
596 } else if constexpr (std::is_same_v<T, AST::TemplateLiteral>) {
597 AST::Node::accept(it->expression, visitor);
598 } else {
599 Q_UNREACHABLE();
600 }
601 }
602 return false;
603}
604
605template <typename T, typename std::enable_if_t<!RequiresCustomIteration<T>::value, bool> = true>
606bool visitWithCustomListIteration(T *, AST::Visitor *)
607{
608 return true;
609}
610
611class QQmlDomAstCreator final : public QQmlDomAstCreatorBase
612{
613 using QQmlDomAstCreatorBase::QQmlDomAstCreatorBase;
614 using QQmlDomAstCreatorBase::visit;
615 using QQmlDomAstCreatorBase::endVisit;
616
617#define X(name) bool visit(AST::name *) override;
618 QQmlJSASTClassListToVisit
619#undef X
620};
621
623{
624public:
625 QQmlDomAstCreatorWithQQmlJSScope(const QQmlJSScope::Ptr &current, MutableDomItem &qmlFile,
626 QQmlJSLogger *logger, QQmlJSImporter *importer);
627
628#define X(name)
629 bool visit(AST::name *) override;
630 void endVisit(AST::name *) override;
632#undef X
633
634 virtual void throwRecursionDepthError() override;
635 /*!
636 \internal
637 Disable the DOM for scriptexpressions, as not yet unimplemented script elements might crash
638 the construction.
639 */
640 void enableScriptExpressions(bool enable = true)
641 {
642 m_enableScriptExpressions = enable;
643 m_domCreator.enableScriptExpressions(enable);
644 }
645
646 void enableLoadFileLazily(bool enable = true)
647 {
648 m_loadFileLazily = enable;
649 m_domCreator.enableLoadFileLazily(enable);
650 }
651
652 QQmlJSImportVisitor &scopeCreator() { return m_scopeCreator; }
653
654private:
655 void setScopeInDomAfterEndvisit();
656 void setScopeInDomBeforeEndvisit();
657
658 enum VisitorKind : bool { DomCreator, ScopeCreator };
659 /*! \internal
660 \brief Holds the information to reactivate a visitor
661 This struct tracks a visitor during its inactive phases
662 and holds the information needed to reactivate the visitor.
663 */
664 struct InactiveVisitorMarker
665 {
666 qsizetype count;
667 AST::Node::Kind nodeKind;
668 VisitorKind inactiveVisitorKind;
669
670 VisitorKind stillActiveVisitorKind() const
671 {
672 return inactiveVisitorKind == DomCreator ? ScopeCreator : DomCreator;
673 }
674 };
675
676 static void initMarkerForActiveVisitor(std::optional<InactiveVisitorMarker> &inactiveVisitorMarker,
677 AST::Node::Kind nodeKind, bool continueForDom)
678 {
679 inactiveVisitorMarker.emplace();
680 inactiveVisitorMarker->inactiveVisitorKind = continueForDom ? ScopeCreator : DomCreator;
681 inactiveVisitorMarker->count = 1;
682 inactiveVisitorMarker->nodeKind = nodeKind;
683 };
684
685 template<typename T>
686 bool visitT(T *t)
687 {
688 const auto handleVisitResult = [this, t](const bool continueVisit) {
689 if (m_inactiveVisitorMarker && m_inactiveVisitorMarker->nodeKind == t->kind)
690 m_inactiveVisitorMarker->count += 1;
691
692 if (continueVisit)
693 return visitWithCustomListIteration(t, this);
694 return continueVisit;
695 };
696
697 // first case: no marker, both can visit
698 if (!m_inactiveVisitorMarker) {
699 bool continueForDom = m_domCreator.visit(t);
700 bool continueForScope = m_scopeCreator.visit(t);
701 if (!continueForDom && !continueForScope)
702 return false;
703 else if (continueForDom ^ continueForScope) {
704 initMarkerForActiveVisitor(m_inactiveVisitorMarker, AST::Node::Kind(t->kind),
705 continueForDom);
706 return visitWithCustomListIteration(t, this);
707 } else {
708 Q_ASSERT(continueForDom && continueForScope);
709 return visitWithCustomListIteration(t, this);
710 }
711 Q_UNREACHABLE();
712 }
713
714 // second case: a marker, just one visit
715 switch (m_inactiveVisitorMarker->stillActiveVisitorKind()) {
716 case DomCreator:
717 return handleVisitResult(m_domCreator.visit(t));
718 case ScopeCreator:
719 return handleVisitResult(m_scopeCreator.visit(t));
720 };
721 Q_UNREACHABLE();
722 }
723
724 template<typename T>
725 void endVisitT(T *t)
726 {
727 if (m_inactiveVisitorMarker && m_inactiveVisitorMarker->nodeKind == t->kind) {
728 m_inactiveVisitorMarker->count -= 1;
729 if (m_inactiveVisitorMarker->count == 0)
730 m_inactiveVisitorMarker.reset();
731 }
732 if (m_inactiveVisitorMarker) {
733 switch (m_inactiveVisitorMarker->stillActiveVisitorKind()) {
734 case DomCreator:
735 m_domCreator.endVisit(t);
736 return;
737 case ScopeCreator:
738 m_scopeCreator.endVisit(t);
739 return;
740 };
741 Q_UNREACHABLE();
742 }
743
744 setScopeInDomBeforeEndvisit();
745 m_domCreator.endVisit(t);
746 setScopeInDomAfterEndvisit();
747 m_scopeCreator.endVisit(t);
748 }
749
750 QQmlJSScope::Ptr m_root;
751 QQmlJSLogger *m_logger = nullptr;
752 QQmlJSImporter *m_importer = nullptr;
753 QString m_implicitImportDirectory;
754 QQmlJSImportVisitor m_scopeCreator;
755 QQmlDomAstCreatorBase m_domCreator;
756
757 std::optional<InactiveVisitorMarker> m_inactiveVisitorMarker;
758 bool m_enableScriptExpressions = false;
759 bool m_loadFileLazily = false;
760};
761
762} // end namespace Dom
763} // end namespace QQmlJS
764
765QT_END_NAMESPACE
766#endif // QQMLDOMASTCREATOR_P_H
Binding & operator=(const Binding &)
std::shared_ptr< ScriptExpression > scriptExpressionValue()
Path addValue(const EnumItem &value)
Represents a set of tags grouping a set of related error messages.
TypeAnnotationStyle typeAnnotationStyle
PathEls::Kind Kind
Path operator[](int i) const
Path mid(int offset, int length) const
Path last() const
Kind headKind() const
QQmlDomAstCreatorBase(const MutableDomItem &qmlFile)
void endVisit(AST::UiProgram *) override
void throwRecursionDepthError() override
void endVisitHelper(AST::PatternElement *pe, const std::shared_ptr< ScriptElements::GenericScriptElement > &element)
void loadAnnotations(AST::UiObjectMember *el)
bool visit(AST::UiProgram *program) override
void enableLoadFileLazily(bool enable=true)
void enableScriptExpressions(bool enable=true)
virtual QQmlJSASTClassListToVisit void throwRecursionDepthError() override
QQmlDomAstCreatorWithQQmlJSScope(const QQmlJSScope::Ptr &current, MutableDomItem &qmlFile, QQmlJSLogger *logger, QQmlJSImporter *importer)
Path addId(const Id &id, AddOption option=AddOption::Overwrite, Id **idPtr=nullptr)
void updatePathFromOwner(const Path &newPath) override
static constexpr DomType kindValue
Path addPrototypePath(const Path &prototypePath)
Use this to contain any script element.
void replaceKindForGenericChildren(DomType oldType, DomType newType)
Provides entities to maintain mappings between elements and their location in a file.
Tree ensure(const Tree &base, const Path &basePath)
std::disjunction< std::is_same< U, V >... > IsInList
bool visitWithCustomListIteration(T *t, AST::Visitor *visitor)
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
#define Q_SCRIPTELEMENT_EXIT_IF(check)
#define Q_SCRIPTELEMENT_DISABLE()
#define NewErrorGroup(name)