aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmldom/qqmldomastcreator_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmldom/qqmldomastcreator_p.h')
-rw-r--r--src/qmldom/qqmldomastcreator_p.h710
1 files changed, 710 insertions, 0 deletions
diff --git a/src/qmldom/qqmldomastcreator_p.h b/src/qmldom/qqmldomastcreator_p.h
new file mode 100644
index 0000000000..8176721d7e
--- /dev/null
+++ b/src/qmldom/qqmldomastcreator_p.h
@@ -0,0 +1,710 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QQMLDOMASTCREATOR_P_H
+#define QQMLDOMASTCREATOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qqmldomelements_p.h"
+#include "qqmldomitem_p.h"
+#include "qqmldompath_p.h"
+#include "qqmldomscriptelements_p.h"
+
+#include <QtQmlCompiler/private/qqmljsimportvisitor_p.h>
+
+#include <QtQml/private/qqmljsastvisitor_p.h>
+#include <memory>
+#include <type_traits>
+#include <variant>
+
+QT_BEGIN_NAMESPACE
+
+namespace QQmlJS {
+namespace Dom {
+
+class QQmlDomAstCreator final : public AST::Visitor
+{
+ Q_DECLARE_TR_FUNCTIONS(QQmlDomAstCreator)
+ using AST::Visitor::endVisit;
+ using AST::Visitor::visit;
+
+ static constexpr const auto className = "QmlDomAstCreator";
+
+ class DomValue
+ {
+ public:
+ template<typename T>
+ DomValue(const T &obj) : kind(T::kindValue), value(obj)
+ {
+ }
+ DomType kind;
+ std::variant<QmlObject, MethodInfo, QmlComponent, PropertyDefinition, Binding, EnumDecl,
+ EnumItem, ConstantData, Id>
+ value;
+ };
+
+ class QmlStackElement
+ {
+ public:
+ Path path;
+ DomValue item;
+ FileLocations::Tree fileLocations;
+ };
+
+ /*!
+ \internal
+ Contains a ScriptElementVariant, that can be used everywhere in the DOM representation, or a
+ List that should always be inside of something else, e.g., that cannot be the root of the
+ script element DOM representation.
+
+ Also, it makes sure you do not mistreat a list as a regular script element and vice versa.
+
+ The reason for this is that Lists can get pretty unintuitive, as a List could be a Block of
+ statements or a list of variable declarations (let i = 3, j = 4, ...) or something completely
+ different. Instead, always put lists inside named construct (BlockStatement,
+ VariableDeclaration, ...).
+ */
+ class ScriptStackElement
+ {
+ public:
+ template<typename T>
+ static ScriptStackElement from(const T &obj)
+ {
+ if constexpr (std::is_same_v<T, ScriptElements::ScriptList>) {
+ ScriptStackElement s{ ScriptElements::ScriptList::kindValue, obj };
+ return s;
+ } else {
+ ScriptStackElement s{ obj->kind(), ScriptElementVariant::fromElement(obj) };
+ return s;
+ }
+ Q_UNREACHABLE();
+ }
+
+ DomType kind;
+ using Variant = std::variant<ScriptElementVariant, ScriptElements::ScriptList>;
+ Variant value;
+
+ ScriptElementVariant takeVariant()
+ {
+ Q_ASSERT_X(std::holds_alternative<ScriptElementVariant>(value), "takeVariant",
+ "Should be a variant, did the parser change?");
+ return std::get<ScriptElementVariant>(std::move(value));
+ }
+
+ bool isList() const { return std::holds_alternative<ScriptElements::ScriptList>(value); };
+
+ ScriptElements::ScriptList takeList()
+ {
+ Q_ASSERT_X(std::holds_alternative<ScriptElements::ScriptList>(value), "takeList",
+ "Should be a List, did the parser change?");
+ return std::get<ScriptElements::ScriptList>(std::move(value));
+ }
+
+ void setSemanticScope(const QQmlJSScope::ConstPtr &scope)
+ {
+ if (auto x = std::get_if<ScriptElementVariant>(&value)) {
+ x->base()->setSemanticScope(scope);
+ return;
+ } else if (auto x = std::get_if<ScriptElements::ScriptList>(&value)) {
+ x->setSemanticScope(scope);
+ return;
+ }
+ Q_UNREACHABLE();
+ }
+ };
+
+public:
+ void enableScriptExpressions(bool enable = true) { m_enableScriptExpressions = enable; }
+ void enableLoadFileLazily(bool enable = true) { m_loadFileLazily = enable; }
+
+private:
+
+ MutableDomItem qmlFile;
+ std::shared_ptr<QmlFile> qmlFilePtr;
+ QVector<QmlStackElement> nodeStack;
+ QList<ScriptStackElement> scriptNodeStack;
+ QVector<int> arrayBindingLevels;
+ FileLocations::Tree rootMap;
+ bool m_enableScriptExpressions = false;
+ bool m_loadFileLazily = false;
+
+ // A Binding inside a UiPublicMember (= a Property definition) will shadow the
+ // propertydefinition's binding identifiers with its own binding identifiers. Therefore, disable
+ // bindingIdentifiers for the Binding inside a Property definition by using this flag.
+ bool m_skipBindingIdentifiers = false;
+
+ void setBindingIdentifiers(const Path &pathFromOwner, const AST::UiQualifiedId *identifiers,
+ Binding *bindingPtr);
+ template<typename T>
+ QmlStackElement &currentEl(int idx = 0)
+ {
+ Q_ASSERT_X(idx < nodeStack.size() && idx >= 0, "currentQmlObjectOrComponentEl",
+ "Stack does not contain enough elements!");
+ int i = nodeStack.size() - idx;
+ while (i-- > 0) {
+ DomType k = nodeStack.at(i).item.kind;
+ if (k == T::kindValue)
+ return nodeStack[i];
+ }
+ Q_ASSERT_X(false, "currentEl", "Stack does not contan object of type ");
+ return nodeStack.last();
+ }
+
+ template<typename T>
+ ScriptStackElement &currentScriptEl(int idx = 0)
+ {
+ Q_ASSERT_X(m_enableScriptExpressions, "currentScriptEl",
+ "Cannot access script elements when they are disabled!");
+
+ Q_ASSERT_X(idx < scriptNodeStack.size() && idx >= 0, "currentQmlObjectOrComponentEl",
+ "Stack does not contain enough elements!");
+ int i = scriptNodeStack.size() - idx;
+ while (i-- > 0) {
+ DomType k = scriptNodeStack.at(i).kind;
+ if (k == T::element_type::kindValue)
+ return scriptNodeStack[i];
+ }
+ Q_ASSERT_X(false, "currentEl", "Stack does not contain object of type ");
+ return scriptNodeStack.last();
+ }
+
+ template<typename T>
+ T &current(int idx = 0)
+ {
+ return std::get<T>(currentEl<T>(idx).item.value);
+ }
+
+ index_type currentIndex() { return currentNodeEl().path.last().headIndex(); }
+
+ QmlStackElement &currentQmlObjectOrComponentEl(int idx = 0);
+
+ QmlStackElement &currentNodeEl(int i = 0);
+ ScriptStackElement &currentScriptNodeEl(int i = 0);
+
+ DomValue &currentNode(int i = 0);
+
+ void removeCurrentNode(std::optional<DomType> expectedType);
+ void removeCurrentScriptNode(std::optional<DomType> expectedType);
+
+ void pushEl(const Path &p, const DomValue &it, AST::Node *n)
+ {
+ nodeStack.append({ p, it, createMap(it.kind, p, n) });
+ }
+
+ FileLocations::Tree createMap(const FileLocations::Tree &base, const Path &p, AST::Node *n);
+
+ FileLocations::Tree createMap(DomType k, const Path &p, AST::Node *n);
+
+ const ScriptElementVariant &
+ finalizeScriptExpression(const ScriptElementVariant &element, const Path &pathFromOwner,
+ const FileLocations::Tree &ownerFileLocations);
+
+ void setScriptExpression (const std::shared_ptr<ScriptExpression>& value);
+
+ Path pathOfLastScriptNode() const;
+
+ /*!
+ \internal
+ Helper to create string literals from AST nodes.
+ */
+ template<typename AstNodeT>
+ static std::shared_ptr<ScriptElements::Literal> makeStringLiteral(QStringView value,
+ AstNodeT *ast)
+ {
+ auto myExp = std::make_shared<ScriptElements::Literal>(ast->firstSourceLocation(),
+ ast->lastSourceLocation());
+ myExp->setLiteralValue(value.toString());
+ return myExp;
+ }
+
+ static std::shared_ptr<ScriptElements::Literal> makeStringLiteral(QStringView value,
+ QQmlJS::SourceLocation loc)
+ {
+ auto myExp = std::make_shared<ScriptElements::Literal>(loc);
+ myExp->setLiteralValue(value.toString());
+ return myExp;
+ }
+
+ /*!
+ \internal
+ Helper to create script elements from AST nodes, as the DOM classes should be completely
+ dependency-free from AST and parser classes. Using the AST classes in qqmldomastcreator is
+ fine because it needs them for the construction/visit. \sa makeScriptList
+ */
+ template<typename ScriptElementT, typename AstNodeT,
+ typename Enable =
+ std::enable_if_t<!std::is_same_v<ScriptElementT, ScriptElements::ScriptList>>>
+ static decltype(auto) makeScriptElement(AstNodeT *ast)
+ {
+ auto myExp = std::make_shared<ScriptElementT>(ast->firstSourceLocation(),
+ ast->lastSourceLocation());
+ return myExp;
+ }
+
+ /*!
+ \internal
+ Helper to create generic script elements from AST nodes.
+ \sa makeScriptElement
+ */
+ template<typename AstNodeT>
+ static std::shared_ptr<ScriptElements::GenericScriptElement>
+ makeGenericScriptElement(AstNodeT *ast, DomType kind)
+ {
+ auto myExp = std::make_shared<ScriptElements::GenericScriptElement>(
+ ast->firstSourceLocation(), ast->lastSourceLocation());
+ myExp->setKind(kind);
+ return myExp;
+ }
+
+ enum UnaryExpressionKind { Prefix, Postfix };
+ std::shared_ptr<ScriptElements::GenericScriptElement>
+ makeUnaryExpression(AST::Node *expression, QQmlJS::SourceLocation operatorToken,
+ bool hasExpression, UnaryExpressionKind type);
+
+ static std::shared_ptr<ScriptElements::GenericScriptElement>
+ makeGenericScriptElement(SourceLocation location, DomType kind)
+ {
+ auto myExp = std::make_shared<ScriptElements::GenericScriptElement>(location);
+ myExp->setKind(kind);
+ return myExp;
+ }
+
+ /*!
+ \internal
+ Helper to create script lists from AST nodes.
+ \sa makeScriptElement
+ */
+ template<typename AstNodeT>
+ static decltype(auto) makeScriptList(AstNodeT *ast)
+ {
+ auto myExp =
+ ScriptElements::ScriptList(ast->firstSourceLocation(), ast->lastSourceLocation());
+ return myExp;
+ }
+
+ template<typename ScriptElementT>
+ void pushScriptElement(const ScriptElementT &element)
+ {
+ Q_ASSERT_X(m_enableScriptExpressions, "pushScriptElement",
+ "Cannot create script elements when they are disabled!");
+ scriptNodeStack.append(ScriptStackElement::from(element));
+ }
+
+ void disableScriptElements()
+ {
+ m_enableScriptExpressions = false;
+ scriptNodeStack.clear();
+ }
+
+ ScriptElementVariant scriptElementForQualifiedId(AST::UiQualifiedId *expression);
+
+public:
+ explicit QQmlDomAstCreator(const MutableDomItem &qmlFile);
+
+ bool visit(AST::UiProgram *program) override;
+ void endVisit(AST::UiProgram *) override;
+
+ bool visit(AST::UiPragma *el) override;
+
+ bool visit(AST::UiImport *el) override;
+
+ bool visit(AST::UiPublicMember *el) override;
+ void endVisit(AST::UiPublicMember *el) override;
+
+ bool visit(AST::FunctionDeclaration *el) override;
+ void endVisit(AST::FunctionDeclaration *) override;
+
+ bool visit(AST::UiSourceElement *el) override;
+ void endVisit(AST::UiSourceElement *) override;
+
+ void loadAnnotations(AST::UiObjectMember *el) { AST::Node::accept(el->annotations, this); }
+
+ bool visit(AST::UiObjectDefinition *el) override;
+ void endVisit(AST::UiObjectDefinition *) override;
+
+ bool visit(AST::UiObjectBinding *el) override;
+ void endVisit(AST::UiObjectBinding *) override;
+
+ bool visit(AST::UiScriptBinding *el) override;
+ void endVisit(AST::UiScriptBinding *) override;
+
+ bool visit(AST::UiArrayBinding *el) override;
+ void endVisit(AST::UiArrayBinding *) override;
+
+ bool visit(AST::UiQualifiedId *) override;
+
+ bool visit(AST::UiEnumDeclaration *el) override;
+ void endVisit(AST::UiEnumDeclaration *) override;
+
+ bool visit(AST::UiEnumMemberList *el) override;
+ void endVisit(AST::UiEnumMemberList *el) override;
+
+ bool visit(AST::UiInlineComponent *el) override;
+ void endVisit(AST::UiInlineComponent *) override;
+
+ bool visit(AST::UiRequired *el) override;
+
+ bool visit(AST::UiAnnotation *el) override;
+ void endVisit(AST::UiAnnotation *) override;
+
+ // for Script elements:
+ bool visit(AST::BinaryExpression *exp) override;
+ void endVisit(AST::BinaryExpression *exp) override;
+
+ bool visit(AST::Block *block) override;
+ void endVisit(AST::Block *) override;
+
+ bool visit(AST::ReturnStatement *block) override;
+ void endVisit(AST::ReturnStatement *) override;
+
+ bool visit(AST::ForStatement *forStatement) override;
+ void endVisit(AST::ForStatement *forStatement) override;
+
+ bool visit(AST::PatternElement *pe) override;
+ void endVisit(AST::PatternElement *pe) override;
+ void endVisitHelper(AST::PatternElement *pe,
+ const std::shared_ptr<ScriptElements::GenericScriptElement> &element);
+
+ bool visit(AST::IfStatement *) override;
+ void endVisit(AST::IfStatement *) override;
+
+ bool visit(AST::FieldMemberExpression *) override;
+ void endVisit(AST::FieldMemberExpression *) override;
+
+ bool visit(AST::ArrayMemberExpression *) override;
+ void endVisit(AST::ArrayMemberExpression *) override;
+
+ bool visit(AST::CallExpression *) override;
+ void endVisit(AST::CallExpression *) override;
+
+ bool visit(AST::ArrayPattern *) override;
+ void endVisit(AST::ArrayPattern *) override;
+
+ bool visit(AST::ObjectPattern *) override;
+ void endVisit(AST::ObjectPattern *) override;
+
+ bool visit(AST::PatternProperty *) override;
+ void endVisit(AST::PatternProperty *) override;
+
+ bool visit(AST::VariableStatement *) override;
+ void endVisit(AST::VariableStatement *) override;
+
+ bool visit(AST::Type *expression) override;
+ void endVisit(AST::Type *expression) override;
+
+ bool visit(AST::DefaultClause *) override;
+ void endVisit(AST::DefaultClause *) override;
+
+ bool visit(AST::CaseClause *) override;
+ void endVisit(AST::CaseClause *) override;
+
+ bool visit(AST::CaseClauses *) override;
+ void endVisit(AST::CaseClauses *) override;
+
+ bool visit(AST::CaseBlock *) override;
+ void endVisit(AST::CaseBlock *) override;
+
+ bool visit(AST::SwitchStatement *) override;
+ void endVisit(AST::SwitchStatement *) override;
+
+ bool visit(AST::WhileStatement *) override;
+ void endVisit(AST::WhileStatement *) override;
+
+ bool visit(AST::DoWhileStatement *) override;
+ void endVisit(AST::DoWhileStatement *) override;
+
+ bool visit(AST::ForEachStatement *) override;
+ void endVisit(AST::ForEachStatement *) override;
+
+ bool visit(AST::ClassExpression *) override;
+ void endVisit(AST::ClassExpression *) override;
+
+ bool visit(AST::TemplateLiteral *) override;
+
+ bool visit(AST::TryStatement *) override;
+ void endVisit(AST::TryStatement *) override;
+
+ bool visit(AST::Catch *) override;
+ void endVisit(AST::Catch *) override;
+
+ bool visit(AST::Finally *) override;
+ void endVisit(AST::Finally *) override;
+
+ bool visit(AST::ThrowStatement *) override;
+ void endVisit(AST::ThrowStatement *) override;
+
+ bool visit(AST::LabelledStatement *) override;
+ void endVisit(AST::LabelledStatement *) override;
+
+ bool visit(AST::ContinueStatement *) override;
+ void endVisit(AST::ContinueStatement *) override;
+
+ bool visit(AST::BreakStatement *) override;
+ void endVisit(AST::BreakStatement *) override;
+
+ bool visit(AST::Expression *) override;
+ void endVisit(AST::Expression *) override;
+
+ bool visit(AST::ConditionalExpression *) override;
+ void endVisit(AST::ConditionalExpression *) override;
+
+ bool visit(AST::UnaryMinusExpression *) override;
+ void endVisit(AST::UnaryMinusExpression *) override;
+
+ bool visit(AST::UnaryPlusExpression *) override;
+ void endVisit(AST::UnaryPlusExpression *) override;
+
+ bool visit(AST::TildeExpression *) override;
+ void endVisit(AST::TildeExpression *) override;
+
+ bool visit(AST::NotExpression *) override;
+ void endVisit(AST::NotExpression *) override;
+
+ bool visit(AST::TypeOfExpression *) override;
+ void endVisit(AST::TypeOfExpression *) override;
+
+ bool visit(AST::DeleteExpression *) override;
+ void endVisit(AST::DeleteExpression *) override;
+
+ bool visit(AST::VoidExpression *) override;
+ void endVisit(AST::VoidExpression *) override;
+
+ bool visit(AST::PostDecrementExpression *) override;
+ void endVisit(AST::PostDecrementExpression *) override;
+
+ bool visit(AST::PostIncrementExpression *) override;
+ void endVisit(AST::PostIncrementExpression *) override;
+
+ bool visit(AST::PreDecrementExpression *) override;
+ void endVisit(AST::PreDecrementExpression *) override;
+
+ bool visit(AST::PreIncrementExpression *) override;
+ void endVisit(AST::PreIncrementExpression *) override;
+
+ bool visit(AST::EmptyStatement *) override;
+ void endVisit(AST::EmptyStatement *) override;
+
+ bool visit(AST::NestedExpression *) override;
+ void endVisit(AST::NestedExpression *) override;
+
+ // lists of stuff whose children do not need a qqmljsscope: visitation order can be custom
+ bool visit(AST::ArgumentList *) override;
+ bool visit(AST::UiParameterList *) override;
+ bool visit(AST::PatternElementList *) override;
+ bool visit(AST::PatternPropertyList *) override;
+ bool visit(AST::VariableDeclarationList *vdl) override;
+ bool visit(AST::Elision *elision) override;
+
+ // lists of stuff whose children need a qqmljsscope: visitation order cannot be custom
+ bool visit(AST::StatementList *list) override;
+ void endVisit(AST::StatementList *list) override;
+
+ // literals and ids
+ bool visit(AST::IdentifierExpression *expression) override;
+ bool visit(AST::NumericLiteral *expression) override;
+ bool visit(AST::StringLiteral *expression) override;
+ bool visit(AST::NullExpression *expression) override;
+ bool visit(AST::TrueLiteral *expression) override;
+ bool visit(AST::FalseLiteral *expression) override;
+ bool visit(AST::ComputedPropertyName *expression) override;
+ bool visit(AST::IdentifierPropertyName *expression) override;
+ bool visit(AST::NumericLiteralPropertyName *expression) override;
+ bool visit(AST::StringLiteralPropertyName *expression) override;
+ bool visit(AST::TypeAnnotation *expression) override;
+
+ void throwRecursionDepthError() override;
+
+public:
+ friend class QQmlDomAstCreatorWithQQmlJSScope;
+};
+
+class QQmlDomAstCreatorWithQQmlJSScope : public AST::Visitor
+{
+public:
+ QQmlDomAstCreatorWithQQmlJSScope(const QQmlJSScope::Ptr &current, MutableDomItem &qmlFile,
+ QQmlJSLogger *logger, QQmlJSImporter *importer);
+
+#define X(name) \
+ bool visit(AST::name *) override; \
+ void endVisit(AST::name *) override;
+ QQmlJSASTClassListToVisit
+#undef X
+
+ virtual void throwRecursionDepthError() override;
+ /*!
+ \internal
+ Disable the DOM for scriptexpressions, as not yet unimplemented script elements might crash
+ the construction.
+ */
+ void enableScriptExpressions(bool enable = true)
+ {
+ m_enableScriptExpressions = enable;
+ m_domCreator.enableScriptExpressions(enable);
+ }
+
+ void enableLoadFileLazily(bool enable = true)
+ {
+ m_loadFileLazily = enable;
+ m_domCreator.enableLoadFileLazily(enable);
+ }
+
+ QQmlJSImportVisitor &scopeCreator() { return m_scopeCreator; }
+
+private:
+ void setScopeInDomAfterEndvisit();
+ void setScopeInDomBeforeEndvisit();
+
+ template<typename U, typename... V>
+ using IsInList = std::disjunction<std::is_same<U, V>...>;
+ template<typename U>
+ using RequiresCustomIteration = IsInList<U, AST::PatternElementList, AST::PatternPropertyList,
+ AST::FormalParameterList>;
+
+ enum VisitorKind : bool { DomCreator, ScopeCreator };
+ /*! \internal
+ \brief Holds the information to reactivate a visitor
+ This struct tracks a visitor during its inactive phases
+ and holds the information needed to reactivate the visitor.
+ */
+ struct InactiveVisitorMarker
+ {
+ qsizetype count;
+ AST::Node::Kind nodeKind;
+ VisitorKind inactiveVisitorKind;
+
+ VisitorKind stillActiveVisitorKind() const
+ {
+ return inactiveVisitorKind == DomCreator ? ScopeCreator : DomCreator;
+ }
+ };
+
+ template<typename T>
+ void customListIteration(T *t)
+ {
+ static_assert(RequiresCustomIteration<T>::value);
+ for (auto it = t; it; it = it->next) {
+ if constexpr (std::is_same_v<T, AST::PatternElementList>) {
+ AST::Node::accept(it->elision, this);
+ AST::Node::accept(it->element, this);
+ } else if constexpr (std::is_same_v<T, AST::PatternPropertyList>) {
+ AST::Node::accept(it->property, this);
+ } else if constexpr (std::is_same_v<T, AST::FormalParameterList>) {
+ AST::Node::accept(it->element, this);
+ } else {
+ Q_UNREACHABLE();
+ }
+ }
+ }
+
+ static void initMarkerForActiveVisitor(std::optional<InactiveVisitorMarker> &inactiveVisitorMarker,
+ AST::Node::Kind nodeKind, bool continueForDom)
+ {
+ inactiveVisitorMarker.emplace();
+ inactiveVisitorMarker->inactiveVisitorKind = continueForDom ? ScopeCreator : DomCreator;
+ inactiveVisitorMarker->count = 1;
+ inactiveVisitorMarker->nodeKind = nodeKind;
+ };
+
+ template<typename T>
+ bool performListIterationIfRequired(T *t)
+ {
+ if constexpr (RequiresCustomIteration<T>::value) {
+ customListIteration(t);
+ return false;
+ }
+ Q_UNUSED(t);
+ return true;
+ }
+
+ template<typename T>
+ bool visitT(T *t)
+ {
+ const auto handleVisitResult = [this, t](const bool continueVisit) {
+ if (m_inactiveVisitorMarker && m_inactiveVisitorMarker->nodeKind == t->kind)
+ m_inactiveVisitorMarker->count += 1;
+
+ if (continueVisit)
+ return performListIterationIfRequired(t);
+ return continueVisit;
+ };
+
+ // first case: no marker, both can visit
+ if (!m_inactiveVisitorMarker) {
+ bool continueForDom = m_domCreator.visit(t);
+ bool continueForScope = m_scopeCreator.visit(t);
+ if (!continueForDom && !continueForScope)
+ return false;
+ else if (continueForDom ^ continueForScope) {
+ initMarkerForActiveVisitor(m_inactiveVisitorMarker, AST::Node::Kind(t->kind),
+ continueForDom);
+ return performListIterationIfRequired(t);
+ } else {
+ Q_ASSERT(continueForDom && continueForScope);
+ return performListIterationIfRequired(t);
+ }
+ Q_UNREACHABLE();
+ }
+
+ // second case: a marker, just one visit
+ switch (m_inactiveVisitorMarker->stillActiveVisitorKind()) {
+ case DomCreator:
+ return handleVisitResult(m_domCreator.visit(t));
+ case ScopeCreator:
+ return handleVisitResult(m_scopeCreator.visit(t));
+ };
+ Q_UNREACHABLE();
+ }
+
+ template<typename T>
+ void endVisitT(T *t)
+ {
+ if (m_inactiveVisitorMarker && m_inactiveVisitorMarker->nodeKind == t->kind) {
+ m_inactiveVisitorMarker->count -= 1;
+ if (m_inactiveVisitorMarker->count == 0)
+ m_inactiveVisitorMarker.reset();
+ }
+ if (m_inactiveVisitorMarker) {
+ switch (m_inactiveVisitorMarker->stillActiveVisitorKind()) {
+ case DomCreator:
+ m_domCreator.endVisit(t);
+ return;
+ case ScopeCreator:
+ m_scopeCreator.endVisit(t);
+ return;
+ };
+ Q_UNREACHABLE();
+ }
+
+ setScopeInDomBeforeEndvisit();
+ m_domCreator.endVisit(t);
+ setScopeInDomAfterEndvisit();
+ m_scopeCreator.endVisit(t);
+ }
+
+ QQmlJSScope::Ptr m_root;
+ QQmlJSLogger *m_logger = nullptr;
+ QQmlJSImporter *m_importer = nullptr;
+ QString m_implicitImportDirectory;
+ QQmlJSImportVisitor m_scopeCreator;
+ QQmlDomAstCreator m_domCreator;
+
+ std::optional<InactiveVisitorMarker> m_inactiveVisitorMarker;
+ bool m_enableScriptExpressions = false;
+ bool m_loadFileLazily = false;
+};
+
+} // end namespace Dom
+} // end namespace QQmlJS
+
+QT_END_NAMESPACE
+#endif // QQMLDOMASTCREATOR_P_H