39 Q_DECLARE_TR_FUNCTIONS(QQmlDomAstCreator)
45 static constexpr const auto className =
"QmlDomAstCreator";
51 DomValue(
const T &obj) : kind(T::kindValue), value(obj)
69
70
71
72
73
74
75
76
77
78
79
80
81 class ScriptStackElement
85 static ScriptStackElement from(
const T &obj)
88 ScriptStackElement s{ ScriptElements::ScriptList::kindValue, obj };
104 "Should be a variant, did the parser change?");
113 "Should be a List, did the parser change?");
117 void setSemanticScope(
const QQmlJSScope::ConstPtr &scope)
119 if (
auto x = std::get_if<ScriptElementVariant>(&value)) {
120 x->base()->setSemanticScope(scope);
122 }
else if (
auto x = std::get_if<ScriptElements::ScriptList>(&value)) {
123 x->setSemanticScope(scope);
135 return qmlFile.environment().ownerAs<DomEnvironment>();
141 std::shared_ptr<QmlFile> qmlFilePtr;
142 QList<QmlStackElement> nodeStack;
143 QList<ScriptStackElement> scriptNodeStack;
144 QList<
int> arrayBindingLevels;
146 int m_nestedFunctionDepth = 0;
147 bool m_enableScriptExpressions =
false;
148 bool m_loadFileLazily =
false;
153 bool m_skipBindingIdentifiers =
false;
155 void setBindingIdentifiers(
const Path &pathFromOwner,
const AST::UiQualifiedId *identifiers,
158 QmlStackElement ¤tEl(
int idx = 0)
160 Q_ASSERT_X(idx < nodeStack.size() && idx >= 0,
"currentQmlObjectOrComponentEl",
161 "Stack does not contain enough elements!");
162 int i = nodeStack.size() - idx;
164 DomType k = nodeStack.at(i).item.kind;
165 if (k == T::kindValue)
168 Q_ASSERT_X(
false,
"currentEl",
"Stack does not contan object of type ");
169 return nodeStack.last();
173 ScriptStackElement ¤tScriptEl(
int idx = 0)
175 Q_ASSERT_X(m_enableScriptExpressions,
"currentScriptEl",
176 "Cannot access script elements when they are disabled!");
178 Q_ASSERT_X(idx < scriptNodeStack.size() && idx >= 0,
"currentQmlObjectOrComponentEl",
179 "Stack does not contain enough elements!");
180 int i = scriptNodeStack.size() - idx;
182 DomType k = scriptNodeStack.at(i).kind;
183 if (k == T::element_type::kindValue)
184 return scriptNodeStack[i];
186 Q_ASSERT_X(
false,
"currentEl",
"Stack does not contain object of type ");
187 return scriptNodeStack.last();
191 T ¤t(
int idx = 0)
193 return std::get<T>(currentEl<T>(idx).item.value);
196 index_type currentIndex() {
return currentNodeEl().path.last().headIndex(); }
198 QmlStackElement ¤tQmlObjectOrComponentEl(
int idx = 0);
200 QmlStackElement ¤tNodeEl(
int i = 0);
201 ScriptStackElement ¤tScriptNodeEl(
int i = 0);
203 DomValue ¤tNode(
int i = 0);
205 void removeCurrentNode(
std::optional<
DomType> expectedType);
206 void removeCurrentScriptNode(
std::optional<
DomType> expectedType);
208 void pushEl(
const Path &p,
const DomValue &it, AST::Node *n)
210 nodeStack.append({ p, it, createMap(it.kind, p, n) });
223 Path pathOfLastScriptNode()
const;
226
227
228
229 template<
typename AstNodeT>
234 ast->lastSourceLocation());
235 myExp->setLiteralValue(value.toString());
240 QQmlJS::SourceLocation loc)
243 myExp->setLiteralValue(value.toString());
248
249
250
251
252
253 template<
typename ScriptElementT,
typename AstNodeT,
255 std::enable_if_t<!std::is_same_v<ScriptElementT, ScriptElements::ScriptList>>>
256 static decltype(
auto) makeScriptElement(AstNodeT *ast)
258 auto myExp =
std::make_shared<ScriptElementT>(ast->firstSourceLocation(),
259 ast->lastSourceLocation());
264
265
266
267
268 template<
typename AstNodeT>
270 makeGenericScriptElement(AstNodeT *ast,
DomType kind)
273 ast->firstSourceLocation(), ast->lastSourceLocation());
274 myExp->setKind(kind);
278 enum UnaryExpressionKind { Prefix, Postfix };
280 makeUnaryExpression(AST::Node *expression, QQmlJS::SourceLocation operatorToken,
281 bool hasExpression, UnaryExpressionKind type);
284 makeGenericScriptElement(SourceLocation location,
DomType kind)
287 myExp->setKind(kind);
292
293
294
295
296 template<
typename AstNodeT>
297 static decltype(
auto) makeScriptList(AstNodeT *ast)
304 template<
typename ScriptElementT>
305 void pushScriptElement(
const ScriptElementT &element)
307 Q_ASSERT_X(m_enableScriptExpressions,
"pushScriptElement",
308 "Cannot create script elements when they are disabled!");
309 scriptNodeStack.append(ScriptStackElement::from(element));
312 void disableScriptElements()
314 m_enableScriptExpressions =
false;
315 scriptNodeStack.clear();
323 bool visit(AST::UiProgram *program)
override;
326 bool visit(AST::UiPragma *el)
override;
328 bool visit(AST::UiImport *el)
override;
330 bool visit(AST::UiPublicMember *el)
override;
337 bool visit(AST::FunctionExpression *el)
override;
340 bool visit(AST::FunctionDeclaration *el)
override;
341 void endVisit(AST::FunctionDeclaration *)
override;
343 bool visit(AST::UiSourceElement *el)
override;
346 void loadAnnotations(AST::UiObjectMember *el) { AST::Node::accept(el->annotations,
this); }
348 bool visit(AST::UiObjectDefinition *el)
override;
351 bool visit(AST::UiObjectBinding *el)
override;
354 bool visit(AST::UiScriptBinding *el)
override;
357 bool visit(AST::UiArrayBinding *el)
override;
360 bool visit(AST::UiQualifiedId *)
override;
362 bool visit(AST::UiEnumDeclaration *el)
override;
365 bool visit(AST::UiEnumMemberList *el)
override;
368 bool visit(AST::UiInlineComponent *el)
override;
371 bool visit(AST::UiRequired *el)
override;
373 bool visit(AST::UiAnnotation *el)
override;
377 bool visit(AST::BinaryExpression *exp)
override;
378 void endVisit(AST::BinaryExpression *exp)
override;
380 bool visit(AST::Block *block)
override;
383 bool visit(AST::YieldExpression *block)
override;
386 bool visit(AST::ReturnStatement *block)
override;
389 bool visit(AST::ForStatement *forStatement)
override;
390 void endVisit(AST::ForStatement *forStatement)
override;
392 bool visit(AST::PatternElement *pe)
override;
397 bool visit(AST::IfStatement *)
override;
400 bool visit(AST::FieldMemberExpression *)
override;
401 void endVisit(AST::FieldMemberExpression *)
override;
403 bool visit(AST::ArrayMemberExpression *)
override;
404 void endVisit(AST::ArrayMemberExpression *)
override;
406 bool visit(AST::CallExpression *)
override;
409 bool visit(AST::ArrayPattern *)
override;
412 bool visit(AST::ObjectPattern *)
override;
415 bool visit(AST::PatternProperty *)
override;
418 bool visit(AST::VariableStatement *)
override;
421 bool visit(AST::Type *expression)
override;
424 bool visit(AST::DefaultClause *)
override;
427 bool visit(AST::CaseClause *)
override;
430 bool visit(AST::CaseClauses *)
override;
433 bool visit(AST::CaseBlock *)
override;
436 bool visit(AST::SwitchStatement *)
override;
439 bool visit(AST::WhileStatement *)
override;
442 bool visit(AST::DoWhileStatement *)
override;
445 bool visit(AST::ForEachStatement *)
override;
448 bool visit(AST::ClassExpression *)
override;
451 bool visit(AST::TryStatement *)
override;
457 bool visit(AST::Finally *)
override;
460 bool visit(AST::ThrowStatement *)
override;
463 bool visit(AST::LabelledStatement *)
override;
466 bool visit(AST::ContinueStatement *)
override;
469 bool visit(AST::BreakStatement *)
override;
472 bool visit(AST::CommaExpression *)
override;
475 bool visit(AST::ConditionalExpression *)
override;
476 void endVisit(AST::ConditionalExpression *)
override;
478 bool visit(AST::UnaryMinusExpression *)
override;
479 void endVisit(AST::UnaryMinusExpression *)
override;
481 bool visit(AST::UnaryPlusExpression *)
override;
482 void endVisit(AST::UnaryPlusExpression *)
override;
484 bool visit(AST::TildeExpression *)
override;
487 bool visit(AST::NotExpression *)
override;
490 bool visit(AST::TypeOfExpression *)
override;
493 bool visit(AST::DeleteExpression *)
override;
496 bool visit(AST::VoidExpression *)
override;
499 bool visit(AST::PostDecrementExpression *)
override;
500 void endVisit(AST::PostDecrementExpression *)
override;
502 bool visit(AST::PostIncrementExpression *)
override;
503 void endVisit(AST::PostIncrementExpression *)
override;
505 bool visit(AST::PreDecrementExpression *)
override;
506 void endVisit(AST::PreDecrementExpression *)
override;
508 bool visit(AST::PreIncrementExpression *)
override;
509 void endVisit(AST::PreIncrementExpression *)
override;
511 bool visit(AST::EmptyStatement *)
override;
514 bool visit(AST::NestedExpression *)
override;
517 bool visit(AST::NewExpression *)
override;
520 bool visit(AST::NewMemberExpression *)
override;
521 void endVisit(AST::NewMemberExpression *)
override;
526 bool visit(AST::UiParameterList *)
override;
527 bool visit(AST::Elision *elision)
override;
532 void endVisit(AST::VariableDeclarationList *vdl)
override;
535 void endVisit(AST::PatternPropertyList *)
override;
536 void endVisit(AST::FormalParameterList *el)
override;
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;
561 return !scriptNodeStack.isEmpty() && !scriptNodeStack.last().isList();
565 return !scriptNodeStack.isEmpty() && scriptNodeStack.last().isList();
570 void endVisitForLists(T *list,
const std::function<
int(T *)> &scriptElementsPerEntry = {});
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);
631 QQmlJSImporter *importer);
634 bool visit(AST::name *) override;
635 void endVisit(AST::name *) override;
641
642
643
644
647 m_enableScriptExpressions = enable;
648 m_domCreator.enableScriptExpressions(enable);
653 m_loadFileLazily = enable;
654 m_domCreator.enableLoadFileLazily(enable);
660 void setScopeInDomAfterEndvisit();
661 void setScopeInDomBeforeEndvisit();
663 enum VisitorKind :
bool { DomCreator, ScopeCreator };
665
666
667
668
669 struct InactiveVisitorMarker
672 AST::Node::Kind nodeKind;
673 VisitorKind inactiveVisitorKind;
675 VisitorKind stillActiveVisitorKind()
const
677 return inactiveVisitorKind == DomCreator ? ScopeCreator : DomCreator;
681 static void initMarkerForActiveVisitor(
std::optional<InactiveVisitorMarker> &inactiveVisitorMarker,
682 AST::Node::Kind nodeKind,
bool continueForDom)
684 inactiveVisitorMarker.emplace();
685 inactiveVisitorMarker->inactiveVisitorKind = continueForDom ? ScopeCreator : DomCreator;
686 inactiveVisitorMarker->count = 1;
687 inactiveVisitorMarker->nodeKind = nodeKind;
693 const auto handleVisitResult = [
this, t](
const bool continueVisit) {
694 if (m_inactiveVisitorMarker && m_inactiveVisitorMarker->nodeKind == t->kind)
695 m_inactiveVisitorMarker->count += 1;
698 return visitWithCustomListIteration(t,
this);
699 return continueVisit;
703 if (!m_inactiveVisitorMarker) {
704 bool continueForDom = m_domCreator.visit(t);
705 bool continueForScope = m_scopeCreator.visit(t);
706 if (!continueForDom && !continueForScope)
708 else if (continueForDom ^ continueForScope) {
709 initMarkerForActiveVisitor(m_inactiveVisitorMarker, AST::Node::Kind(t->kind),
711 return visitWithCustomListIteration(t,
this);
713 Q_ASSERT(continueForDom && continueForScope);
714 return visitWithCustomListIteration(t,
this);
720 switch (m_inactiveVisitorMarker->stillActiveVisitorKind()) {
722 return handleVisitResult(m_domCreator.visit(t));
724 return handleVisitResult(m_scopeCreator.visit(t));
729 void loadQmlDependenciesInDom();
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();
739 if (m_inactiveVisitorMarker && m_inactiveVisitorMarker->nodeKind == t->kind) {
740 m_inactiveVisitorMarker->count -= 1;
741 if (m_inactiveVisitorMarker->count == 0)
742 m_inactiveVisitorMarker.reset();
744 if (m_inactiveVisitorMarker) {
745 switch (m_inactiveVisitorMarker->stillActiveVisitorKind()) {
747 m_domCreator.endVisit(t);
750 m_scopeCreator.endVisit(t);
756 setScopeInDomBeforeEndvisit();
757 m_domCreator.endVisit(t);
758 setScopeInDomAfterEndvisit();
759 m_scopeCreator.endVisit(t);
762 QQmlJSLogger *m_logger =
nullptr;
763 QQmlJSImporter *m_importer =
nullptr;
764 QString m_implicitImportDirectory;
765 QQmlJSImportVisitor m_scopeCreator;
768 std::optional<InactiveVisitorMarker> m_inactiveVisitorMarker;
769 bool m_enableScriptExpressions =
false;
770 bool m_loadFileLazily =
false;