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