38 using AST::Visitor::endVisit;
39 using AST::Visitor::visit;
41 static constexpr const auto className =
"QmlDomAstCreator";
47 DomValue(
const T &
obj) : kind(T::kindValue),
value(
obj)
77 class ScriptStackElement
81 static ScriptStackElement from(
const T &
obj)
83 if constexpr (std::is_same_v<T, ScriptElements::ScriptList>) {
94 using Variant = std::variant<ScriptElementVariant, ScriptElements::ScriptList>;
99 Q_ASSERT_X(std::holds_alternative<ScriptElementVariant>(
value),
"takeVariant",
100 "Should be a variant, did the parser change?");
101 return std::get<ScriptElementVariant>(std::move(
value));
104 bool isList()
const {
return std::holds_alternative<ScriptElements::ScriptList>(
value); };
108 Q_ASSERT_X(std::holds_alternative<ScriptElements::ScriptList>(
value),
"takeList",
109 "Should be a List, did the parser change?");
110 return std::get<ScriptElements::ScriptList>(std::move(
value));
115 if (
auto x = std::get_if<ScriptElementVariant>(&
value)) {
116 x->base()->setSemanticScope(scope);
118 }
else if (
auto x = std::get_if<ScriptElements::ScriptList>(&
value)) {
119 x->setSemanticScope(scope);
133 std::shared_ptr<QmlFile> qmlFilePtr;
134 QVector<QmlStackElement> nodeStack;
135 QList<ScriptStackElement> scriptNodeStack;
136 QVector<int> arrayBindingLevels;
138 bool m_enableScriptExpressions =
false;
139 bool m_loadFileLazily =
false;
144 bool m_skipBindingIdentifiers =
false;
149 QmlStackElement ¤tEl(
int idx = 0)
151 Q_ASSERT_X(idx < nodeStack.size() && idx >= 0,
"currentQmlObjectOrComponentEl",
152 "Stack does not contain enough elements!");
153 int i = nodeStack.size() - idx;
155 DomType k = nodeStack.at(
i).item.kind;
156 if (k == T::kindValue)
159 Q_ASSERT_X(
false,
"currentEl",
"Stack does not contan object of type ");
160 return nodeStack.last();
164 ScriptStackElement ¤tScriptEl(
int idx = 0)
166 Q_ASSERT_X(m_enableScriptExpressions,
"currentScriptEl",
167 "Cannot access script elements when they are disabled!");
169 Q_ASSERT_X(idx < scriptNodeStack.size() && idx >= 0,
"currentQmlObjectOrComponentEl",
170 "Stack does not contain enough elements!");
171 int i = scriptNodeStack.size() - idx;
173 DomType k = scriptNodeStack.at(
i).kind;
174 if (k == T::element_type::kindValue)
175 return scriptNodeStack[
i];
177 Q_ASSERT_X(
false,
"currentEl",
"Stack does not contain object of type ");
178 return scriptNodeStack.last();
182 T ¤t(
int idx = 0)
184 return std::get<T>(currentEl<T>(idx).
item.value);
189 QmlStackElement ¤tQmlObjectOrComponentEl(
int idx = 0);
191 QmlStackElement ¤tNodeEl(
int i = 0);
192 ScriptStackElement ¤tScriptNodeEl(
int i = 0);
194 DomValue ¤tNode(
int i = 0);
196 void removeCurrentNode(std::optional<DomType> expectedType);
197 void removeCurrentScriptNode(std::optional<DomType> expectedType);
199 void pushEl(
const Path &
p,
const DomValue &
it, AST::Node *
n)
201 nodeStack.append({
p,
it, createMap(
it.kind,
p,
n) });
208 const ScriptElementVariant &
209 finalizeScriptExpression(
const ScriptElementVariant &element,
const Path &pathFromOwner,
212 void setScriptExpression (
const std::shared_ptr<ScriptExpression>&
value);
214 Path pathOfLastScriptNode()
const;
220 template<
typename AstNodeT>
221 static std::shared_ptr<ScriptElements::Literal> makeStringLiteral(
QStringView value,
224 auto myExp = std::make_shared<ScriptElements::Literal>(ast->firstSourceLocation(),
225 ast->lastSourceLocation());
226 myExp->setLiteralValue(
value.toString());
230 static std::shared_ptr<ScriptElements::Literal> makeStringLiteral(
QStringView value,
233 auto myExp = std::make_shared<ScriptElements::Literal>(loc);
234 myExp->setLiteralValue(
value.toString());
244 template<
typename ScriptElementT,
typename AstNodeT,
246 std::enable_if_t<!std::is_same_v<ScriptElementT, ScriptElements::ScriptList>>>
247 static decltype(
auto) makeScriptElement(AstNodeT *ast)
249 auto myExp = std::make_shared<ScriptElementT>(ast->firstSourceLocation(),
250 ast->lastSourceLocation());
259 template<
typename AstNodeT>
260 static std::shared_ptr<ScriptElements::GenericScriptElement>
261 makeGenericScriptElement(AstNodeT *ast, DomType kind)
263 auto myExp = std::make_shared<ScriptElements::GenericScriptElement>(
264 ast->firstSourceLocation(), ast->lastSourceLocation());
265 myExp->setKind(kind);
269 enum UnaryExpressionKind { Prefix, Postfix };
270 std::shared_ptr<ScriptElements::GenericScriptElement>
272 bool hasExpression, UnaryExpressionKind
type);
274 static std::shared_ptr<ScriptElements::GenericScriptElement>
275 makeGenericScriptElement(SourceLocation
location, DomType kind)
277 auto myExp = std::make_shared<ScriptElements::GenericScriptElement>(
location);
278 myExp->setKind(kind);
287 template<
typename AstNodeT>
288 static decltype(
auto) makeScriptList(AstNodeT *ast)
291 ScriptElements::ScriptList(ast->firstSourceLocation(), ast->lastSourceLocation());
295 template<
typename ScriptElementT>
296 void pushScriptElement(
const ScriptElementT &element)
298 Q_ASSERT_X(m_enableScriptExpressions,
"pushScriptElement",
299 "Cannot create script elements when they are disabled!");
300 scriptNodeStack.append(ScriptStackElement::from(element));
303 void disableScriptElements()
305 m_enableScriptExpressions =
false;
306 scriptNodeStack.clear();
309 ScriptElementVariant scriptElementForQualifiedId(AST::UiQualifiedId *expression);
315 void endVisit(AST::UiProgram *)
override;
317 bool visit(AST::UiPragma *
el)
override;
319 bool visit(AST::UiImport *
el)
override;
321 bool visit(AST::UiPublicMember *
el)
override;
322 void endVisit(AST::UiPublicMember *
el)
override;
324 bool visit(AST::FunctionDeclaration *
el)
override;
325 void endVisit(AST::FunctionDeclaration *)
override;
327 bool visit(AST::UiSourceElement *
el)
override;
328 void endVisit(AST::UiSourceElement *)
override;
376 const std::shared_ptr<ScriptElements::GenericScriptElement> &element);
538 bool visit(AST::name *) override; \
539 void endVisit(AST::name *) override;
551 m_enableScriptExpressions =
enable;
557 m_loadFileLazily =
enable;
564 void setScopeInDomAfterEndvisit();
565 void setScopeInDomBeforeEndvisit();
567 template<
typename U,
typename... V>
568 using IsInList = std::disjunction<std::is_same<U, V>...>;
573 enum VisitorKind :
bool { DomCreator, ScopeCreator };
579 struct InactiveVisitorMarker
583 VisitorKind inactiveVisitorKind;
585 VisitorKind stillActiveVisitorKind()
const
587 return inactiveVisitorKind == DomCreator ? ScopeCreator : DomCreator;
592 void customListIteration(T *
t)
594 static_assert(RequiresCustomIteration<T>::value);
596 if constexpr (std::is_same_v<T, AST::PatternElementList>) {
599 }
else if constexpr (std::is_same_v<T, AST::PatternPropertyList>) {
601 }
else if constexpr (std::is_same_v<T, AST::FormalParameterList>) {
609 static void initMarkerForActiveVisitor(std::optional<InactiveVisitorMarker> &inactiveVisitorMarker,
612 inactiveVisitorMarker.emplace();
613 inactiveVisitorMarker->inactiveVisitorKind = continueForDom ? ScopeCreator : DomCreator;
614 inactiveVisitorMarker->count = 1;
615 inactiveVisitorMarker->nodeKind = nodeKind;
619 bool performListIterationIfRequired(T *
t)
621 if constexpr (RequiresCustomIteration<T>::value) {
622 customListIteration(
t);
632 const auto handleVisitResult = [
this,
t](
const bool continueVisit) {
633 if (m_inactiveVisitorMarker && m_inactiveVisitorMarker->nodeKind ==
t->kind)
634 m_inactiveVisitorMarker->count += 1;
637 return performListIterationIfRequired(
t);
638 return continueVisit;
642 if (!m_inactiveVisitorMarker) {
643 bool continueForDom = m_domCreator.
visit(
t);
644 bool continueForScope = m_scopeCreator.
visit(
t);
645 if (!continueForDom && !continueForScope)
647 else if (continueForDom ^ continueForScope) {
648 initMarkerForActiveVisitor(m_inactiveVisitorMarker,
AST::Node::Kind(
t->kind),
650 return performListIterationIfRequired(
t);
652 Q_ASSERT(continueForDom && continueForScope);
653 return performListIterationIfRequired(
t);
659 switch (m_inactiveVisitorMarker->stillActiveVisitorKind()) {
661 return handleVisitResult(m_domCreator.
visit(
t));
663 return handleVisitResult(m_scopeCreator.
visit(
t));
671 if (m_inactiveVisitorMarker && m_inactiveVisitorMarker->nodeKind ==
t->kind) {
672 m_inactiveVisitorMarker->count -= 1;
673 if (m_inactiveVisitorMarker->count == 0)
674 m_inactiveVisitorMarker.reset();
676 if (m_inactiveVisitorMarker) {
677 switch (m_inactiveVisitorMarker->stillActiveVisitorKind()) {
688 setScopeInDomBeforeEndvisit();
690 setScopeInDomAfterEndvisit();
697 QString m_implicitImportDirectory;
699 QQmlDomAstCreator m_domCreator;
701 std::optional<InactiveVisitorMarker> m_inactiveVisitorMarker;
702 bool m_enableScriptExpressions =
false;
703 bool m_loadFileLazily =
false;