16#include <QtQml/private/qqmljsast_p.h>
19#include <QtCore/QFileInfo>
20#include <QtCore/QScopeGuard>
21#include <QtCore/QLoggingCategory>
35#define Q_SCRIPTELEMENT_DISABLE() \
37 qDebug() << "Could not construct the JS DOM at" << __FILE__ << ":" << __LINE__ \
38 << ", skipping JS elements..."; \
39 disableScriptElements(); \
42#define Q_SCRIPTELEMENT_EXIT_IF(check) \
44 if (m_enableScriptExpressions && check) { \
45 Q_SCRIPTELEMENT_DISABLE(); \
56template<
typename K,
typename V>
67 while (it2 !=
end && it2.key() ==
key) {
90 if (
iter != qualifiedId)
112 return combine(
s1,
s2);
120QQmlDomAstCreator::QmlStackElement &QQmlDomAstCreator::currentQmlObjectOrComponentEl(
int idx)
122 Q_ASSERT_X(idx < nodeStack.size() && idx >= 0,
"currentQmlObjectOrComponentEl",
123 "Stack does not contain enough elements!");
124 int i = nodeStack.size() - idx;
126 DomType k = nodeStack.at(
i).item.kind;
130 Q_ASSERT_X(
false,
"currentQmlObjectEl",
"No QmlObject or component in stack");
131 return nodeStack.last();
134QQmlDomAstCreator::QmlStackElement &QQmlDomAstCreator::currentNodeEl(
int i)
136 Q_ASSERT_X(
i < nodeStack.size() &&
i >= 0,
"currentNode",
"Stack does not contain element!");
137 return nodeStack[nodeStack.size() -
i - 1];
140QQmlDomAstCreator::ScriptStackElement &QQmlDomAstCreator::currentScriptNodeEl(
int i)
143 "Stack does not contain element!");
144 return scriptNodeStack[scriptNodeStack.
size() -
i - 1];
147QQmlDomAstCreator::DomValue &QQmlDomAstCreator::currentNode(
int i)
149 Q_ASSERT_X(
i < nodeStack.size() &&
i >= 0,
"currentNode",
150 "Stack does not contain element!");
151 return nodeStack[nodeStack.size() -
i - 1].item;
154void QQmlDomAstCreator::removeCurrentNode(std::optional<DomType> expectedType)
156 Q_ASSERT_X(!nodeStack.isEmpty(), className,
"popCurrentNode() without any node");
158 Q_ASSERT(nodeStack.last().item.kind == *expectedType);
159 nodeStack.removeLast();
162void QQmlDomAstCreator::removeCurrentScriptNode(std::optional<DomType> expectedType)
166 "popCurrentScriptNode() without any node");
180const ScriptElementVariant &
181QQmlDomAstCreator::finalizeScriptExpression(
const ScriptElementVariant &element, Path pathFromOwner,
184 auto e = element.base();
187 e->updatePathFromOwner(pathFromOwner);
188 e->createFileLocations(
base);
205 switch (currentNode().kind) {
217 base = currentNodeEl().fileLocations;
218 if (
p.length() > 2) {
219 Path
p2 =
p[
p.length() - 2];
220 if (
p2.headKind() == Path::Kind::Field
221 && (
p2.checkHeadName(Fields::children) ||
p2.checkHeadName(Fields::objects)
222 ||
p2.checkHeadName(Fields::value) ||
p2.checkHeadName(Fields::annotations)
223 ||
p2.checkHeadName(Fields::children)))
224 p =
p.mid(
p.length() - 2, 2);
225 else if (
p.last().checkHeadName(Fields::value)
226 &&
p.last().headKind() == Path::Kind::Field)
229 qCWarning(domLog) <<
"unexpected path to QmlObject in createMap" <<
p;
233 qCWarning(domLog) <<
"unexpected path to QmlObject in createMap" <<
p;
238 base = currentNodeEl().fileLocations;
250 base = currentEl<QmlObject>().fileLocations;
252 p =
p.
mid(
p.length() - 3, 3);
260 return createMap(
base,
p,
n);
265 qmlFilePtr(qmlFile.ownerAs<
QmlFile>()),
266 rootMap(qmlFilePtr->fileLocationsTree())
278 Q_ASSERT_X(newC.
item(), className,
"could not recover component added with addComponent");
288 qmlFilePtr->addImport(selfDirImport);
292 qmlFilePtr->addImport(
i);
301 for (
const Pragma &
p : qmlFilePtr->pragmas()) {
309 Q_ASSERT_X(nodeStack.isEmpty(), className,
"ui program did not finish node stack");
315 for (
auto t =
el->values;
t;
t =
t->next)
316 valueList <<
t->value.toString();
325 if (
el->version &&
el->version->version.hasMajorVersion())
326 v.majorVersion =
el->version->version.majorVersion();
327 if (
el->version &&
el->version->version.hasMinorVersion())
328 v.minorVersion =
el->version->version.minorVersion();
329 if (
el->importUri !=
nullptr)
336 qmlFilePtr->addImport(
349 m.isReadonly =
el->isReadonly();
355 pushEl(
p, *mPtr,
el);
377 p.isReadonly =
el->isReadonly();
378 p.isDefaultMember =
el->isDefaultMember();
379 p.isRequired =
el->isRequired();
384 Path pPathFromOwner =
386 pushEl(pPathFromOwner, *pPtr,
el);
388 el->propertyToken());
391 .warning(
tr(
"id is a special attribute, that should not be "
392 "used as property name"))
393 .withPath(currentNodeEl().
path));
394 if (
p.isDefaultMember)
399 el->requiredToken());
405 auto script = std::make_shared<ScriptExpression>(
410 Path bPathFromOwner = current<QmlObject>().addBinding(
Binding(
p.name, script, bType),
419 nodeStack.append({ bPathFromOwner, *bPtr, bLoc });
430 Binding &
b = std::get<Binding>(lastEl.value);
431 if (m_enableScriptExpressions && scriptNodeStack.
size() != 1)
433 if (m_enableScriptExpressions) {
434 b.scriptExpressionValue()->setScriptElement(finalizeScriptExpression(
435 currentScriptNodeEl().takeVariant(),
Path().field(Fields::scriptElement),
437 Path().field(Fields::value))));
438 removeCurrentScriptNode({});
441 QmlObject &containingObject = current<QmlObject>();
445 removeCurrentNode({});
449 if ((
el->binding ||
el->statement)
459 ann.addAnnotation(duplicate);
460 it->addAnnotation(currentEl<QmlObject>()
461 .path.field(Fields::bindings)
463 .index(
obj.m_bindings.values(pDef.
name).size() - 1),
470 QmlStackElement &sEl = nodeStack.last();
471 switch (sEl.item.kind) {
480 MethodInfo m = std::get<MethodInfo>(sEl.item.value);
488 removeCurrentNode({});
496 m.name = fDef->name.toString();
510 m.body = std::make_shared<ScriptExpression>(
511 code.
mid(bodyLoc.
offset, bodyLoc.
length), qmlFilePtr->engine(), fDef->body,
513 0, preCode, postCode);
515 if (fDef->typeAnnotation) {
517 m.returnType = std::make_shared<ScriptExpression>(
519 fDef->typeAnnotation, qmlFilePtr->astComments(),
525 pushEl(mPathFromOwner, *mPtr,
528 if (fDef->identifierToken.isValid())
533 if (fDef->lparenToken.length != 0)
535 if (fDef->rparenToken.length != 0)
537 if (fDef->lbraceToken.length != 0)
539 if (fDef->rbraceToken.length != 0)
546 param.name =
args->element->bindingIdentifier.toString();
551 if (
args->element->initializer) {
553 auto script = std::make_shared<ScriptExpression>(
555 args->element->initializer, qmlFilePtr->astComments(),
557 param.defaultValue = script;
560 param.value = std::make_shared<ScriptExpression>(
561 code.
mid(parameterLoc.
offset, parameterLoc.
length), qmlFilePtr->engine(),
562 args->element, qmlFilePtr->astComments(),
584 if (
auto genericElement =
585 std::get_if<std::shared_ptr<ScriptElements::GenericScriptElement>>(&*
data)) {
601 if (m_enableScriptExpressions && scriptNodeStack.
isEmpty())
603 if (m_enableScriptExpressions) {
604 if (currentScriptNodeEl().isList()) {
607 auto body = makeScriptElement<ScriptElements::BlockStatement>(fDef->body);
608 body->setStatements(currentScriptNodeEl().takeList());
609 if (
auto semanticScope = body->statements().semanticScope())
610 body->setSemanticScope(*semanticScope);
611 m.body->setScriptElement(finalizeScriptExpression(
614 m.body->setScriptElement(finalizeScriptExpression(
615 currentScriptNodeEl().takeVariant(), bodyPath, bodyTree));
617 removeCurrentScriptNode({});
620 if (m_enableScriptExpressions) {
621 if (fDef->typeAnnotation) {
623 Path().field(Fields::returnType),
625 const Path pathToReturnType =
Path().
field(Fields::scriptElement);
628 finalizeScriptExpression(
variant, pathToReturnType, argLoc);
629 m.returnType->setScriptElement(
variant);
630 removeCurrentScriptNode({});
632 std::vector<FormalParameterList *> reversedInitializerExpressions;
633 for (
auto it = fDef->formals;
it;
it =
it->next) {
634 reversedInitializerExpressions.push_back(
it);
636 const size_t size = reversedInitializerExpressions.size();
637 for (
size_t idx =
size - 1; idx <
size; --idx) {
638 if (m_enableScriptExpressions && scriptNodeStack.
empty()) {
643 nodeStack.last().fileLocations,
644 Path().field(Fields::parameters).
index(idx).field(Fields::value),
646 const Path pathToArgument =
Path().
field(Fields::scriptElement);
650 finalizeScriptExpression(
variant, pathToArgument, argLoc);
651 m.parameters[idx].value->setScriptElement(
variant);
652 removeCurrentScriptNode({});
656 if (m_enableScriptExpressions && !scriptNodeStack.
empty()) {
676 if (!arrayBindingLevels.isEmpty() && nodeStack.size() == arrayBindingLevels.last()) {
680 int idx = vals->
size();
682 sPathFromOwner = currentNodeEl().path.field(Fields::value).index(idx);
683 sPtr = &((*vals)[idx]);
687 "expected an array binding with a valid QList<QmlScope> as value");
690 Q_ASSERT_X(
false, className,
"expected an array binding as last node on the stack");
693 DomValue &containingObject = currentQmlObjectOrComponentEl().item;
694 switch (containingObject.kind) {
696 sPathFromOwner = std::get<QmlComponent>(containingObject.value).addObject(scope, &sPtr);
699 sPathFromOwner = std::get<QmlObject>(containingObject.value).addChild(scope, &sPtr);
705 Q_ASSERT_X(sPtr, className,
"could not recover new scope");
706 pushEl(sPathFromOwner, *sPtr,
el);
714 int idx = currentIndex();
715 if (!arrayBindingLevels.isEmpty() && nodeStack.size() == arrayBindingLevels.last() + 1) {
720 "expected an array binding with a valid QList<QmlScope> as value");
723 Q_ASSERT_X(
false, className,
"expected an array binding as last node on the stack");
726 DomValue &containingObject = currentNodeEl(1).item;
727 Path p = currentNodeEl().path;
728 switch (containingObject.kind) {
731 std::get<QmlComponent>(containingObject.value).m_objects[idx] =
obj;
737 std::get<QmlObject>(containingObject.value).m_children[idx] =
obj;
754 Path bPathFromOwner = current<QmlObject>().addBinding(
756 if (bPtr->
name() == u
"id")
758 .warning(
tr(
"id attributes should only be a lower case letter "
759 "followed by letters, numbers or underscore, "
760 "assuming they refer to an id property"))
761 .withPath(bPathFromOwner));
762 pushEl(bPathFromOwner, *bPtr,
el);
766 Q_ASSERT_X(objValue, className,
"could not recover objectValue");
769 pushEl(bPathFromOwner.
field(Fields::value), *objValue,
el->initializer);
775 QmlObject &objValue = current<QmlObject>();
776 QmlObject &containingObj = current<QmlObject>(1);
781 index_type idx = currentNodeEl(1).path.last().headIndex();
793 auto script = std::make_shared<ScriptExpression>(
800 if (bindingV.
name() == u
"id") {
801 Node *exp = script->ast();
803 exp = eStat->expression;
805 QmlStackElement &containingObjectEl = currentEl<QmlObject>();
806 QmlObject &containingObject = std::get<QmlObject>(containingObjectEl.item.value);
807 QString idName = iExp->name.toString();
809 idVal.
value = script;
824 .warning(
tr(
"id attributes should only be a lower case letter "
825 "followed by letters, numbers or underscore, not %1")
827 .withPath(pathFromOwner));
832 Q_ASSERT_X(bindingPtr, className,
"binding could not be retrieved");
835 .warning(
tr(
"id attributes should only be a lower case letter "
836 "followed by letters, numbers or underscore, not %1 "
837 "%2, assuming they refer to a property")
838 .
arg(script->code(), script->astRelocatableDump()))
839 .withPath(pathFromOwner));
844 Q_ASSERT_X(bindingPtr, className,
"binding could not be retrieved");
847 pushEl(pathFromOwner, *bindingPtr,
el);
849 pushEl(pathFromOwner, *idPtr,
el);
858void QQmlDomAstCreator::setScriptExpression (
const std::shared_ptr<ScriptExpression>&
value)
860 if (m_enableScriptExpressions
861 && (scriptNodeStack.
size() != 1 || currentScriptNodeEl().isList()))
863 if (m_enableScriptExpressions) {
865 Path().field(Fields::value));
866 value->setScriptElement(finalizeScriptExpression(currentScriptNodeEl().takeVariant(),
867 Path().field(Fields::scriptElement),
869 removeCurrentScriptNode({});
875 DomValue &lastEl = currentNode();
878 Binding &
b = std::get<Binding>(lastEl.value);
880 setScriptExpression(
b.scriptExpressionValue());
882 QmlObject &containingObject = current<QmlObject>();
887 Id &
id = std::get<Id>(lastEl.value);
889 setScriptExpression(
id.
value);
899 if (m_enableScriptExpressions && !scriptNodeStack.
empty()) {
902 removeCurrentNode({});
910 Path bindingPathFromOwner =
912 if (bindingV.
name() == u
"id")
915 .
error(
tr(
"id attributes should have only simple strings as values"))
916 .withPath(bindingPathFromOwner));
917 pushEl(bindingPathFromOwner, *bindingPtr,
el);
921 createMap(currentNodeEl().fileLocations,
Path::Field(Fields::value),
nullptr);
924 arrayBindingLevels.append(nodeStack.size());
934 arrayBindingLevels.removeLast();
940 if (!m_enableScriptExpressions)
943 auto currentList = makeScriptList(
list);
947 if (!m_enableScriptExpressions)
950 if (scriptNodeStack.
empty()) {
954 currentList.append(scriptNodeStack.
last().takeVariant());
958 pushScriptElement(currentList);
971 if (!m_enableScriptExpressions)
974 auto currentList = makeScriptList(
list);
979 if (scriptNodeStack.
empty()) {
983 currentList.append(scriptNodeStack.
last().takeList());
988 if (scriptNodeStack.
empty()) {
992 currentList.append(scriptNodeStack.
last().takeVariant());
997 pushScriptElement(currentList);
1005 if (!m_enableScriptExpressions)
1008 auto currentList = makeScriptList(
list);
1013 if (!m_enableScriptExpressions)
1015 if (scriptNodeStack.
empty()) {
1019 currentList.append(scriptNodeStack.
last().takeVariant());
1024 pushScriptElement(currentList);
1038 auto id = std::make_shared<ScriptElements::IdentifierExpression>(
1040 id->setName(expression->
toString());
1047 if (!m_enableScriptExpressions)
1058 Path enumPathFromOwner =
1060 pushEl(enumPathFromOwner, *ePtr,
el);
1081 combine(
el->memberToken,
el->valueToken));
1097 pushEl(
p, *compPtr,
el);
1120 Path pathFromOwner =
1131 DomValue &containingElement = currentNode();
1134 switch (containingElement.kind) {
1136 pathFromOwner = std::get<QmlObject>(containingElement.value).addAnnotation(
a, &aPtr);
1139 pathFromOwner = std::get<Binding>(containingElement.value)
1140 .addAnnotation(currentNodeEl().
path,
a, &aPtr);
1144 std::get<Id>(containingElement.value).addAnnotation(currentNodeEl().
path,
a, &aPtr);
1147 pathFromOwner = std::get<PropertyDefinition>(containingElement.value)
1148 .addAnnotation(currentNodeEl().
path,
a, &aPtr);
1151 pathFromOwner = std::get<MethodInfo>(containingElement.value)
1152 .addAnnotation(currentNodeEl().
path,
a, &aPtr);
1155 qCWarning(domLog) <<
"Unexpected container object for annotation:"
1159 pushEl(pathFromOwner, *aPtr,
el);
1165 DomValue &containingElement = currentNode(1);
1168 switch (containingElement.kind) {
1170 std::get<QmlObject>(containingElement.value).m_annotations[currentIndex()] =
a;
1173 std::get<Binding>(containingElement.value).m_annotations[currentIndex()] =
a;
1176 std::get<Id>(containingElement.value).annotations[currentIndex()] =
a;
1179 std::get<PropertyDefinition>(containingElement.value).annotations[currentIndex()] =
a;
1182 std::get<MethodInfo>(containingElement.value).annotations[currentIndex()] =
a;
1193 tr(
"Maximum statement or expression depth exceeded in QmlDomAstCreator")));
1198 if (!m_enableScriptExpressions)
1206 if (!m_enableScriptExpressions)
1209 auto current = makeScriptList(
list);
1213 current.append(scriptNodeStack.
takeLast().takeVariant());
1217 pushScriptElement(current);
1222 if (!m_enableScriptExpressions)
1232 if (!m_enableScriptExpressions)
1235 auto current = makeScriptElement<ScriptElements::BinaryExpression>(exp);
1236 current->setRight(currentScriptNodeEl().takeVariant());
1237 removeCurrentScriptNode({});
1238 current->setLeft(currentScriptNodeEl().takeVariant());
1239 removeCurrentScriptNode({});
1241 pushScriptElement(current);
1246 if (!m_enableScriptExpressions)
1254 if (!m_enableScriptExpressions)
1257 auto current = makeScriptElement<ScriptElements::BlockStatement>(block);
1261 current->setStatements(currentScriptNodeEl().takeList());
1265 pushScriptElement(current);
1270 if (!m_enableScriptExpressions)
1278 if (!m_enableScriptExpressions)
1281 auto current = makeScriptElement<ScriptElements::ForStatement>(forStatement);
1285 current->setBody(currentScriptNodeEl().takeVariant());
1286 removeCurrentScriptNode(std::nullopt);
1291 current->setExpression(currentScriptNodeEl().takeVariant());
1292 removeCurrentScriptNode(std::nullopt);
1297 current->setCondition(currentScriptNodeEl().takeVariant());
1298 removeCurrentScriptNode(std::nullopt);
1303 auto variableDeclaration = makeGenericScriptElement(forStatement->
declarations,
1309 variableDeclaration->insertChild(Fields::declarations, std::move(
list));
1310 removeCurrentScriptNode({});
1317 current->setInitializer(currentScriptNodeEl().takeVariant());
1318 removeCurrentScriptNode(std::nullopt);
1320 pushScriptElement(current);
1325 if (!m_enableScriptExpressions)
1328 auto current = makeScriptElement<ScriptElements::IdentifierExpression>(expression);
1329 current->setName(expression->
name);
1330 pushScriptElement(current);
1336 if (!m_enableScriptExpressions)
1339 auto current = makeScriptElement<ScriptElements::Literal>(expression);
1340 current->setLiteralValue(expression->
value);
1341 pushScriptElement(current);
1347 if (!m_enableScriptExpressions)
1350 pushScriptElement(makeStringLiteral(expression->
value, expression));
1356 if (!m_enableScriptExpressions)
1359 auto current = makeScriptElement<ScriptElements::Literal>(expression);
1360 current->setLiteralValue(
nullptr);
1361 pushScriptElement(current);
1367 if (!m_enableScriptExpressions)
1370 auto current = makeScriptElement<ScriptElements::Literal>(expression);
1371 current->setLiteralValue(
true);
1372 pushScriptElement(current);
1378 if (!m_enableScriptExpressions)
1381 auto current = makeScriptElement<ScriptElements::Literal>(expression);
1382 current->setLiteralValue(
false);
1383 pushScriptElement(current);
1389 if (!m_enableScriptExpressions)
1392 auto current = makeScriptElement<ScriptElements::IdentifierExpression>(expression);
1393 current->setName(expression->
id);
1394 pushScriptElement(current);
1400 if (!m_enableScriptExpressions)
1403 pushScriptElement(makeStringLiteral(expression->
id, expression));
1409 if (!m_enableScriptExpressions)
1418 if (!m_enableScriptExpressions)
1421 auto current = makeScriptElement<ScriptElements::Literal>(expression);
1422 current->setLiteralValue(expression->
id);
1423 pushScriptElement(current);
1429 if (!m_enableScriptExpressions)
1438 if (!m_enableScriptExpressions)
1441 auto currentList = makeScriptList(
list);
1444 if (
it->declaration) {
1446 if (!m_enableScriptExpressions)
1448 if (scriptNodeStack.
empty()) {
1452 currentList.append(scriptNodeStack.
last().takeVariant());
1456 pushScriptElement(currentList);
1464 if (!m_enableScriptExpressions)
1467 auto currentList = makeScriptList(
list);
1473 pushScriptElement(currentList);
1481 if (!m_enableScriptExpressions)
1494 const std::shared_ptr<ScriptElements::GenericScriptElement> ¤t)
1498 std::make_shared<ScriptElements::IdentifierExpression>(pe->
identifierToken);
1504 current->insertChild(Fields::initializer, scriptNodeStack.
last().takeVariant());
1509 current->insertChild(Fields::type, scriptNodeStack.
last().takeVariant());
1514 current->insertChild(Fields::bindingElement, scriptNodeStack.
last().takeVariant());
1521 if (!m_enableScriptExpressions)
1527 if (!m_enableScriptExpressions)
1530 pushScriptElement(element);
1535 if (!m_enableScriptExpressions)
1543 if (!m_enableScriptExpressions)
1546 auto current = makeScriptElement<ScriptElements::IfStatement>(ifStatement);
1548 if (ifStatement->
ko) {
1550 current->setAlternative(scriptNodeStack.
last().takeVariant());
1554 if (ifStatement->
ok) {
1556 current->setConsequence(scriptNodeStack.
last().takeVariant());
1561 current->setCondition(scriptNodeStack.
last().takeVariant());
1565 pushScriptElement(current);
1570 if (!m_enableScriptExpressions)
1578 if (!m_enableScriptExpressions)
1581 auto current = makeScriptElement<ScriptElements::ReturnStatement>(returnStatement);
1585 current->setExpression(currentScriptNodeEl().takeVariant());
1586 removeCurrentScriptNode({});
1589 pushScriptElement(current);
1594 if (!m_enableScriptExpressions)
1602 if (!m_enableScriptExpressions)
1605 auto current = makeScriptElement<ScriptElements::BinaryExpression>(expression);
1608 if (expression->
base) {
1610 current->setLeft(currentScriptNodeEl().takeVariant());
1611 removeCurrentScriptNode({});
1615 auto scriptIdentifier =
1616 std::make_shared<ScriptElements::IdentifierExpression>(expression->
identifierToken);
1617 scriptIdentifier->setName(expression->
name);
1621 pushScriptElement(current);
1626 if (!m_enableScriptExpressions)
1634 if (!m_enableScriptExpressions)
1637 auto current = makeScriptElement<ScriptElements::BinaryExpression>(expression);
1644 current->setRight(currentScriptNodeEl().takeVariant());
1645 removeCurrentScriptNode({});
1648 if (expression->
base) {
1650 current->setLeft(currentScriptNodeEl().takeVariant());
1651 removeCurrentScriptNode({});
1654 pushScriptElement(current);
1659 if (!m_enableScriptExpressions)
1667 if (!m_enableScriptExpressions)
1674 current->insertChild(Fields::arguments, currentScriptNodeEl().takeList());
1675 removeCurrentScriptNode({});
1678 current->insertChild(Fields::arguments,
1684 current->insertChild(Fields::callee, currentScriptNodeEl().takeVariant());
1685 removeCurrentScriptNode({});
1688 pushScriptElement(current);
1693 if (!m_enableScriptExpressions)
1701 if (!m_enableScriptExpressions)
1710 current->insertChild(Fields::elements, std::move(
list));
1712 removeCurrentScriptNode({});
1715 current->insertChild(Fields::elements,
1719 pushScriptElement(current);
1724 if (!m_enableScriptExpressions)
1732 if (!m_enableScriptExpressions)
1739 current->insertChild(Fields::properties, currentScriptNodeEl().takeList());
1740 removeCurrentScriptNode({});
1743 current->insertChild(Fields::properties,
1747 pushScriptElement(current);
1752 if (!m_enableScriptExpressions)
1760 if (!m_enableScriptExpressions)
1769 if (!m_enableScriptExpressions)
1774 current->insertChild(Fields::name, currentScriptNodeEl().takeVariant());
1775 removeCurrentScriptNode({});
1778 pushScriptElement(current);
1783 if (!m_enableScriptExpressions)
1791 if (!m_enableScriptExpressions)
1802 current->insertChild(Fields::declarations, std::move(
list));
1804 removeCurrentScriptNode({});
1807 pushScriptElement(current);
1812 if (!m_enableScriptExpressions)
1820 if (!m_enableScriptExpressions)
1826 auto currentChild = scriptElementForQualifiedId(exp->
typeArgument);
1827 current->insertChild(Fields::typeArgument, currentChild);
1831 auto currentChild = scriptElementForQualifiedId(exp->
typeId);
1832 current->insertChild(Fields::typeName, currentChild);
1835 pushScriptElement(current);
1840 if (!m_enableScriptExpressions)
1848 if (!m_enableScriptExpressions)
1855 current->insertChild(Fields::statements, currentScriptNodeEl().takeList());
1856 removeCurrentScriptNode({});
1859 pushScriptElement(current);
1864 if (!m_enableScriptExpressions)
1872 if (!m_enableScriptExpressions)
1879 current->insertChild(Fields::statements, currentScriptNodeEl().takeList());
1880 removeCurrentScriptNode({});
1885 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
1886 removeCurrentScriptNode({});
1889 pushScriptElement(current);
1894 if (!m_enableScriptExpressions)
1902 if (!m_enableScriptExpressions)
1905 auto current = makeScriptList(
list);
1909 current.append(scriptNodeStack.
takeLast().takeVariant());
1913 pushScriptElement(current);
1918 if (!m_enableScriptExpressions)
1926 if (!m_enableScriptExpressions)
1933 current->insertChild(Fields::caseClauses, currentScriptNodeEl().takeList());
1934 removeCurrentScriptNode({});
1939 current->insertChild(Fields::defaultClause, currentScriptNodeEl().takeVariant());
1940 removeCurrentScriptNode({});
1945 current->insertChild(Fields::caseClauses, currentScriptNodeEl().takeList());
1946 removeCurrentScriptNode({});
1948 pushScriptElement(current);
1953 if (!m_enableScriptExpressions)
1961 if (!m_enableScriptExpressions)
1968 current->insertChild(Fields::caseBlock, currentScriptNodeEl().takeVariant());
1969 removeCurrentScriptNode({});
1973 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
1974 removeCurrentScriptNode({});
1977 pushScriptElement(current);
1982 if (!m_enableScriptExpressions)
1990 if (!m_enableScriptExpressions)
1997 current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
1998 removeCurrentScriptNode({});
2003 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2004 removeCurrentScriptNode({});
2007 pushScriptElement(current);
2012 if (!m_enableScriptExpressions)
2020 if (!m_enableScriptExpressions)
2027 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2028 removeCurrentScriptNode({});
2033 current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
2034 removeCurrentScriptNode({});
2037 pushScriptElement(current);
2042 if (!m_enableScriptExpressions)
2050 if (!m_enableScriptExpressions)
2057 current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
2058 removeCurrentScriptNode({});
2062 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2063 removeCurrentScriptNode({});
2068 current->insertChild(Fields::bindingElement, currentScriptNodeEl().takeVariant());
2069 removeCurrentScriptNode({});
2072 pushScriptElement(current);
2077 auto top = qmlFile.
top();
2082 if (!domEnvironment) {
2085 return domEnvironment;
2091 return env->loadPaths();
2099 return env->qmldirFiles();
2110 m_logger->
fileName(), m_importer.resourceFileMapper())),
2111 m_scopeCreator(m_root, &m_importer, m_logger, m_implicitImportDirectory,
2113 m_domCreator(qmlFile)
2118 bool QQmlDomAstCreatorWithQQmlJSScope::visit(name *node) \
2120 return visitT(node); \
2122 void QQmlDomAstCreatorWithQQmlJSScope::endVisit(name *node) \
2130 QQmlDomAstCreatorWithQQmlJSScope::setScopeInDomAfterEndvisit()
2133 if (!m_domCreator.scriptNodeStack.
isEmpty()) {
2134 auto topOfStack = m_domCreator.currentScriptNodeEl();
2135 switch (topOfStack.kind) {
2142 m_domCreator.currentScriptNodeEl().setSemanticScope(scope);
2148 }
else if (!m_domCreator.nodeStack.isEmpty()) {
2150 [&scope](
auto &&
e) {
2151 using U = std::remove_cv_t<std::remove_reference_t<
decltype(
e)>>;
2153 if constexpr (std::is_same_v<U, QmlObject>) {
2154 e.setSemanticScope(scope);
2155 }
else if constexpr (std::is_same_v<U, QmlComponent>) {
2156 e.setSemanticScope(scope);
2157 }
else if constexpr (std::is_same_v<U, MethodInfo>) {
2159 if (
auto scriptElement =
e.body->scriptElement())
2160 scriptElement.base()->setSemanticScope(scope);
2162 e.setSemanticScope(scope);
2165 m_domCreator.currentNodeEl().item.value);
2169void QQmlDomAstCreatorWithQQmlJSScope::setScopeInDomBeforeEndvisit()
2173 auto visitPropertyDefinition = [&scope](
auto &&
e) {
2174 using U = std::remove_cv_t<std::remove_reference_t<
decltype(
e)>>;
2175 if constexpr (std::is_same_v<U, PropertyDefinition>) {
2183 if (m_domCreator.nodeStack.size() > 1
2185 std::visit([&visitPropertyDefinition](
auto &&
e) { visitPropertyDefinition(
e); },
2186 m_domCreator.currentNodeEl(1).item.value);
2188 if (m_domCreator.nodeStack.size() > 0) {
2190 [&visitPropertyDefinition](
auto &&
e) {
2191 visitPropertyDefinition(
e);
2194 m_domCreator.currentNodeEl().item.value);
2204 if (std::shared_ptr<QmlFile> qmlFilePtr = qmlFile.
ownerAs<
QmlFile>()) {
2209 auto v = std::make_unique<QQmlDomAstCreatorWithQQmlJSScope>(qmlFile, &logger);
2215 auto typeResolver = std::make_shared<QQmlJSTypeResolver>(&
v->importer());
2216 typeResolver->init(&
v->scopeCreator(),
nullptr);
2217 qmlFilePtr->setTypeResolver(typeResolver);
2219 auto v = std::make_unique<QQmlDomAstCreator>(qmlFile);
2226 qCWarning(creatorLog) <<
"createDom called on non qmlFile";
2233#undef Q_SCRIPTELEMENT_DISABLE
2234#undef Q_SCRIPTELEMENT_EXIT_IF
static constexpr QChar fromLatin1(char c) noexcept
Converts the Latin-1 character c to its equivalent QChar.
\inmodule QtCore \reentrant
QString baseName() const
Returns the base name of the file without the path.
QString canonicalPath() const
Returns the file's path canonical path (excluding the file name), i.e.
qsizetype size() const noexcept
bool isEmpty() const noexcept
bool empty() const noexcept
void removeLast() noexcept
void append(parameter_type t)
iterator find(const Key &key)
QQmlJSScope::Ptr m_currentScope
void setFileName(const QString &fileName)
Tracks the types for the QmlCompiler.
ExpressionNode * expression
SourceLocation rbracketToken
PatternElementList * elements
SourceLocation lbracketToken
StatementList * statements
SourceLocation rparenToken
SourceLocation lparenToken
CaseClauses * moreClauses
DefaultClause * defaultClause
ExpressionNode * expression
StatementList * statements
StatementList * statements
ExpressionNode * expression
SourceLocation identifierToken
ExpressionNode * expression
ExpressionNode * expression
VariableDeclarationList * declarations
ExpressionNode * initialiser
ExpressionNode * condition
ExpressionNode * expression
void accept(BaseVisitor *visitor)
SourceLocation lbraceToken
SourceLocation rbraceToken
PatternPropertyList * properties
SourceLocation identifierToken
QStringView bindingIdentifier
ExpressionNode * initializer
TypeAnnotation * typeAnnotation
ExpressionNode * bindingTarget
ExpressionNode * expression
ExpressionNode * expression
UiQualifiedId * typeArgument
SourceLocation firstSourceLocation() const override
SourceLocation lastSourceLocation() const override
VariableDeclarationList * declarations
ExpressionNode * expression
QList< QmlObject > annotations
QmlObject const * objectValue() const
void setIsSingleton(bool isSingleton)
void setIsCreatable(bool isCreatable)
Path pathFromOwner(DomItem &self) const override
Represents a consistent set of types organized in modules, it is the top level of the DOM.
Path addValue(EnumItem value)
void setName(QString name)
Represents a set of tags grouping a set of related error messages.
static void addRegion(Tree fLoc, QString locName, SourceLocation loc)
static Tree ensure(Tree base, Path basePath, AttachedInfo::PathType pType=AttachedInfo::PathType::Relative)
std::shared_ptr< AttachedInfoT< FileLocations > > Tree
std::shared_ptr< ScriptExpression > value
static Import fromUriString(QString importStr, Version v=Version(), QString importId=QString(), ErrorHandler handler=nullptr)
static Import fromFileString(QString importStr, QString importId=QString(), ErrorHandler handler=nullptr)
QList< MethodParameter > parameters
MutableDomItem environment()
std::shared_ptr< T > ownerAs()
QString canonicalFilePath()
MutableDomItem path(const Path &p)
void addError(ErrorMessage msg)
Path path(Path toAdd, bool avoidToAddAsBase=false) const
Path field(QString name) const
static Path Field(QStringView s=u"")
Path index(index_type i) const
virtual QQmlJSASTClassListToVisit void throwRecursionDepthError() override
QQmlDomAstCreatorWithQQmlJSScope(MutableDomItem &qmlFile, QQmlJSLogger *logger)
void endVisit(AST::UiProgram *) override
void endVisitHelper(AST::PatternElement *pe, const std::shared_ptr< ScriptElements::GenericScriptElement > &element)
QQmlDomAstCreator(MutableDomItem qmlFile)
bool visit(AST::UiProgram *program) override
void throwRecursionDepthError() override
void loadAnnotations(AST::UiObjectMember *el)
Path addId(const Id &id, AddOption option=AddOption::Overwrite, Id **idPtr=nullptr)
void setName(QString name)
void setIdStr(QString id)
Path addPrototypePath(Path prototypePath)
void updatePathFromOwner(Path newPath) override
static QmlUri fromDirectoryString(const QString &importStr)
Use this to contain any script element.
static ScriptElementVariant fromElement(T element)
static constexpr qint32 Latest
\inmodule QtCore \reentrant
QRegularExpressionMatch matchView(QStringView subjectView, qsizetype offset=0, MatchType matchType=NormalMatch, MatchOptions matchOptions=NoMatchOption) const
static QString anchoredPattern(const QString &expression)
iterator find(const T &value)
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
QString toString() const
Returns a deep copy of this string view's data as a QString.
constexpr bool empty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString last(qsizetype n) const
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
void * data()
Returns a pointer to the contained object as a generic void* that can be written to.
QSet< QString >::iterator it
Path lookupTypePath(QString name)
void createDom(MutableDomItem qmlFile, DomCreationOptions options=None)
static const DomEnvironment * environmentFrom(MutableDomItem &qmlFile)
static ErrorGroups astParseErrors()
V * valueFromMultimap(QMultiMap< K, V > &mmap, const K &key, index_type idx)
QMLDOM_EXPORT QString domTypeToString(DomType k)
static QString toString(const UiQualifiedId *qualifiedId, QChar delimiter=QLatin1Char('.'))
static QStringList importPathsFrom(MutableDomItem &qmlFile)
@ ScriptVariableDeclarationEntry
@ ScriptVariableDeclaration
static QStringList qmldirFilesFrom(MutableDomItem &qmlFile)
static void setFormalParameterKind(ScriptElementVariant &variant)
static QString typeToString(AST::Type *t)
SourceLocation combineLocations(SourceLocation s1, SourceLocation s2)
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
GLdouble GLdouble GLdouble GLdouble top
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum const GLint * param
GLsizei const GLchar *const * path
static qreal component(const QPointF &point, unsigned int i)
#define Q_SCRIPTELEMENT_EXIT_IF(check)
#define Q_SCRIPTELEMENT_DISABLE()
#define NewErrorGroup(name)
#define QQmlJSASTClassListToVisit
#define Q_ASSERT_X(cond, x, msg)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
\inmodule QtCore \reentrant