15#include <QtQml/private/qqmljsast_p.h>
16#include <QtQmlCompiler/private/qqmljsutils_p.h>
19#include <QtCore/QFileInfo>
20#include <QtCore/QScopeGuard>
21#include <QtCore/QLoggingCategory>
32
33
34
35#define Q_SCRIPTELEMENT_DISABLE()
37 qCDebug(creatorLog) << "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>
57V *valueFromMultimap(QMultiMap<K, V> &mmap,
const K &key, index_type idx)
61 auto it = mmap.find(key);
62 auto end = mmap.end();
67 while (it2 != end && it2.key() == key) {
73 for (index_type i = idx + 1; i < nEl; ++i)
85static QString toString(
const UiQualifiedId *qualifiedId, QChar delimiter = QLatin1Char(
'.'))
89 for (
const UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) {
90 if (iter != qualifiedId)
99static QString typeToString(AST::Type *t)
102 QString res = toString(t->typeId);
104 if (UiQualifiedId *arg = t->typeArgument)
105 res += u'<' + toString(arg) + u'>';
110SourceLocation combineLocations(SourceLocation s1, SourceLocation s2)
112 return combine(s1, s2);
115SourceLocation combineLocations(Node *n)
117 return combineLocations(n->firstSourceLocation(), n->lastSourceLocation());
121 const SourceLocation &dotToken,
124 SourceLocation s1, s2;
125 left.visitConst([&s1](
auto &&el) { s1 = el->mainRegionLocation(); });
126 right.visitConst([&s2](
auto &&el) { s2 = el->mainRegionLocation(); });
129 result->addLocation(OperatorTokenRegion, dotToken);
131 result->setLeft(left);
132 result->setRight(right);
137
138
139
141fieldMemberExpressionForQualifiedId(
const AST::UiQualifiedId *qualifiedId)
145 for (
auto exp = qualifiedId; exp; exp = exp->next) {
146 const SourceLocation identifierLoc = exp->identifierToken;
148 id->setName(exp->name);
154 bindable = wrapIntoFieldMemberExpression(bindable, exp->dotToken,
155 ScriptElementVariant::fromElement(id));
163 Q_ASSERT_X(idx < nodeStack.size() && idx >= 0,
"currentQmlObjectOrComponentEl",
164 "Stack does not contain enough elements!");
165 int i = nodeStack.size() - idx;
167 DomType k = nodeStack.at(i).item.kind;
168 if (k == DomType::QmlObject || k == DomType::QmlComponent)
171 Q_ASSERT_X(
false,
"currentQmlObjectEl",
"No QmlObject or component in stack");
172 return nodeStack.last();
177 Q_ASSERT_X(i < nodeStack.size() && i >= 0,
"currentNode",
"Stack does not contain element!");
178 return nodeStack[nodeStack.size() - i - 1];
183 Q_ASSERT_X(i < scriptNodeStack.size() && i >= 0,
"currentNode",
184 "Stack does not contain element!");
185 return scriptNodeStack[scriptNodeStack.size() - i - 1];
190 Q_ASSERT_X(i < nodeStack.size() && i >= 0,
"currentNode",
191 "Stack does not contain element!");
192 return nodeStack[nodeStack.size() - i - 1].item;
197 Q_ASSERT_X(!nodeStack.isEmpty(), className,
"popCurrentNode() without any node");
199 Q_ASSERT(nodeStack.last().item.kind == *expectedType);
200 nodeStack.removeLast();
206 Q_ASSERT_X(!scriptNodeStack.isEmpty(), className,
207 "popCurrentScriptNode() without any node");
209 Q_ASSERT(scriptNodeStack.last().kind == *expectedType);
210 scriptNodeStack.removeLast();
214
215
216
217
218
219
220
221
222
223
224
229 auto e = element.base();
232 qCDebug(creatorLog) <<
"Finalizing script expression with path:"
233 << FileLocations::canonicalPathForTesting(ownerFileLocations)
234 .append(pathFromOwner.toString());
235 e->updatePathFromOwner(pathFromOwner);
236 e->createFileLocations(ownerFileLocations);
254 switch (currentNode().kind) {
263 qCWarning(domLog) <<
"unexpected type" << domTypeToString(currentNode().kind);
266 base = currentNodeEl().fileLocations;
270 && (p2.checkHeadName(Fields::children) || p2.checkHeadName(Fields::objects)
271 || p2.checkHeadName(Fields::value) || p2.checkHeadName(Fields::annotations)
272 || p2.checkHeadName(Fields::children)))
274 else if (p
.last().checkHeadName(Fields::value)
278 qCWarning(domLog) <<
"unexpected path to QmlObject in createMap" << p;
282 qCWarning(domLog) <<
"unexpected path to QmlObject in createMap" << p;
288 base = currentNodeEl().fileLocations;
301 base = currentEl<
QmlObject>().fileLocations;
309 qCWarning(domLog) <<
"Unexpected type in createMap:" << domTypeToString(k);
313 return createMap(base, relative, n);
325 QFileInfo fInfo(qmlFile.canonicalFilePath());
326 QString componentName = fInfo.baseName();
328 Path p = qmlFilePtr->addComponent(QmlComponent(componentName), AddOption::KeepExisting,
331 Q_ASSERT_X(newC
.item(), className,
"could not recover component added with addComponent");
335 pushEl(p, *cPtr, program);
337 auto envPtr = qmlFile.environment().ownerAs<DomEnvironment>();
338 const bool loadDependencies =
340 if (m_loadFileLazily && loadDependencies) {
341 envPtr->loadPendingDependencies();
342 envPtr->commitToBase(qmlFile.environment().item());
351 QmlComponent &comp = current<QmlComponent>();
352 for (
const Pragma &p : qmlFilePtr->pragmas()) {
353 if (p.name.compare(u"singleton", Qt::CaseInsensitive) == 0) {
354 comp.setIsSingleton(
true);
355 comp.setIsCreatable(
false);
358 *newC.mutableAs<QmlComponent>() = comp;
360 Q_ASSERT_X(nodeStack.isEmpty(), className,
"ui program did not finish node stack");
365 QStringList valueList;
366 for (
auto t = el->values; t; t = t->next)
367 valueList << t->value.toString();
369 auto fileLocation = createMap(
370 DomType::Pragma, qmlFilePtr->addPragma(Pragma(el->name.toString(), valueList)), el);
373 if (el->colonToken.isValid()) {
377 for (
auto t = el->values; t; t = t->next) {
378 auto subMap = createMap(fileLocation, Path().withField(Fields::values).withIndex(i), t);
388 Version v(Version::Latest, Version::Latest);
389 if (el->version && el->version->version.hasMajorVersion())
390 v.majorVersion = el->version->version.majorVersion();
391 if (el->version && el->version->version.hasMinorVersion())
392 v.minorVersion = el->version->version.minorVersion();
394 auto envPtr = qmlFile.environment().ownerAs<DomEnvironment>();
395 const bool loadDependencies =
398 if (el->importUri !=
nullptr) {
400 Import::fromUriString(toString(el->importUri), v, el->importId.toString());
401 fileLocation = createMap(DomType::Import, qmlFilePtr->addImport(import), el);
406 Import::fromFileString(el->fileName.toString(), el->importId.toString());
407 fileLocation = createMap(DomType::Import, qmlFilePtr->addImport(import), el);
411 if (m_loadFileLazily && loadDependencies) {
412 envPtr->loadPendingDependencies();
413 envPtr->commitToBase(qmlFile.environment().item());
416 if (el->importToken.isValid())
419 if (el->asToken.isValid())
422 if (el->importIdToken.isValid())
435 case AST::UiPublicMember::Signal: {
437 m.name = el->name.toString();
438 m.typeName = toString(el->memberType);
439 m.isReadonly = el->isReadonly();
441 m.methodType = MethodInfo::Signal;
442 m.isList = el->typeModifier == QLatin1String(
"list");
445 pushEl(p, *mPtr, el);
447 const auto fileLocations = nodeStack.last().fileLocations;
450 if (el->lparenToken.isValid())
452 if (el->rparenToken.isValid())
456 AST::UiParameterList *args = el->parameters;
459 param.name = args->name.toString();
460 param.typeName = args->type ? args->type->toString() : QString();
461 index_type idx = index_type(mInfo.parameters.size());
462 if (!args->colonToken.isValid())
464 mInfo.parameters.append(param);
466 Path::fromField(Fields::parameters).withIndex(idx));
470 if (args->colonToken.isValid())
478 case AST::UiPublicMember::Property: {
480 p.name = el->name.toString();
481 p.typeName = toString(el->memberType);
482 p.isReadonly = el->isReadonly();
485 p.isList = el->typeModifier == QLatin1String(
"list");
489 if (!el->typeModifier.isEmpty())
490 p.typeName = el->typeModifier.toString() + QChar(u'<') + p.typeName + QChar(u'>');
492 Path pPathFromOwner =
494 if (m_enableScriptExpressions) {
496 qmlObjectType->insertChild(Fields::typeName,
497 fieldMemberExpressionForQualifiedId(el->memberType));
500 pPathFromOwner.withField(Fields::nameIdentifiers), rootMap)
);
503 m_skipBindingIdentifiers = el->binding;
505 pushEl(pPathFromOwner, *pPtr, el);
507 el->propertyToken());
509 el->identifierToken);
513 if (el->typeModifierToken.isValid())
516 qmlFile.addError(std::move(astParseErrors()
517 .warning(tr(
"id is a special attribute, that should not be "
518 "used as property name"))
519 .withPath(currentNodeEl().path)));
530 el->overrideToken());
538 el->requiredToken());
542 el->readonlyToken());
545 ++m_nestedFunctionDepth;
547 SourceLocation loc = combineLocations(el->statement);
548 QStringView code = qmlFilePtr->code();
551 code.mid(loc.offset, loc.length), qmlFilePtr->engine(), el->statement,
552 qmlFilePtr->astComments(), ScriptExpression::ExpressionType::BindingExpression,
557 FileLocations::
Tree bLoc = createMap(DomType::Binding, bPathFromOwner, el->statement);
559 FileLocations::
Tree valueLoc = FileLocations::ensure(bLoc, Path::fromField(Fields::value));
563 nodeStack.append({ std::move(bPathFromOwner), *bPtr, std::move(bLoc) });
574 --m_nestedFunctionDepth;
576 if (m_enableScriptExpressions
577 && (scriptNodeStack.size() != 1 || scriptNodeStack.last().isList())) {
580 if (m_enableScriptExpressions) {
581 b.scriptExpressionValue()->setScriptElement(finalizeScriptExpression(
582 currentScriptNodeEl().takeVariant(), Path().withField(Fields::scriptElement),
583 FileLocations::ensure(currentNodeEl().fileLocations,
584 Path().withField(Fields::value))));
585 removeCurrentScriptNode({});
590 valueFromMultimap(containingObject.m_bindings, b.name(), currentIndex());
592 removeCurrentNode({});
594 Node::accept(el->parameters,
this);
596 if ((el->binding || el->statement)
597 && nodeStack.last().item.kind == DomType::PropertyDefinition) {
599 if (!pDef.annotations.isEmpty()) {
601 duplicate.setName(QLatin1String(
"duplicate"));
603 auto it = obj.m_bindings.find(pDef.name);
604 if (it != obj.m_bindings.end()) {
605 for (QmlObject ann : pDef.annotations) {
606 ann.addAnnotation(duplicate);
607 it->addAnnotation(currentEl<QmlObject>()
608 .path.withField(Fields::bindings)
610 .withIndex(obj.m_bindings.values(pDef.name).size() - 1),
617 QmlStackElement &sEl = nodeStack.last();
618 switch (sEl.item.kind) {
622 valueFromMultimap(obj.m_propertyDefs, pDef.name, sEl.path.last().headIndex());
624 *pDefPtr =
std::move(pDef);
628 MethodInfo *mPtr = valueFromMultimap(obj.m_methods, m.name, sEl.path.last().headIndex());
630 *mPtr =
std::move(m);
635 removeCurrentNode({});
640 endVisitForLists(list);
645 ++m_nestedFunctionDepth;
646 if (!m_enableScriptExpressions)
654 Q_ASSERT(!scriptNodeStack.isEmpty() || !fExpression->body);
656 if (fExpression->body) {
657 if (currentScriptNodeEl().isList()) {
661 combineLocations(fExpression->lbraceToken, fExpression->rbraceToken));
662 body->setStatements(currentScriptNodeEl().takeList());
663 if (
auto semanticScope = body->statements().semanticScope())
664 body->setSemanticScope(semanticScope);
666 removeCurrentScriptNode({});
669 auto result = currentScriptNodeEl().takeVariant();
670 removeCurrentScriptNode({});
673 Q_UNREACHABLE_RETURN({});
678 combineLocations(fExpression->lbraceToken, fExpression->rbraceToken));
684 --m_nestedFunctionDepth;
685 if (!m_enableScriptExpressions)
689 if (fExpression->identifierToken.isValid())
690 current->addLocation(IdentifierRegion, fExpression->identifierToken);
691 if (fExpression->functionToken.isValid())
692 current->addLocation(FunctionKeywordRegion, fExpression->functionToken);
693 if (fExpression->starToken.isValid())
694 current->addLocation(StarTokenRegion, fExpression->starToken);
695 if (fExpression->lparenToken.isValid())
696 current->addLocation(LeftParenthesisRegion, fExpression->lparenToken);
697 if (fExpression->rparenToken.isValid())
698 current->addLocation(RightParenthesisRegion, fExpression->rparenToken);
699 if (fExpression->lbraceToken.isValid())
700 current->addLocation(LeftBraceRegion, fExpression->lbraceToken);
701 if (fExpression->rbraceToken.isValid())
702 current->addLocation(RightBraceRegion, fExpression->rbraceToken);
703 if (fExpression->typeAnnotation) {
704 current->addLocation(TypeIdentifierRegion,
705 combineLocations(fExpression->typeAnnotation->type));
709 current->insertChild(Fields::body, prepareBodyForFunction(fExpression));
711 if (fExpression->typeAnnotation) {
713 current->insertChild(Fields::returnType, currentScriptNodeEl().takeVariant());
714 scriptNodeStack.removeLast();
716 if (fExpression->formals) {
718 current->insertChild(Fields::parameters, currentScriptNodeEl().takeList());
719 scriptNodeStack.removeLast();
722 if (!fExpression->name.isEmpty())
723 current->insertValue(Fields::name, fExpression->name);
725 pushScriptElement(current);
731 if (m_nestedFunctionDepth > 0) {
732 return visit(
static_cast<FunctionExpression *>(fDef));
734 ++m_nestedFunctionDepth;
735 const QStringView code(qmlFilePtr->code());
737 m.name = fDef->name.toString();
738 if (AST::TypeAnnotation *tAnn = fDef->typeAnnotation) {
739 if (AST::Type *t = tAnn->type)
740 m.typeName = typeToString(t);
743 m.methodType = MethodInfo::Method;
746 SourceLocation bodyLoc = fDef->body ? combineLocations(fDef->body)
747 : combineLocations(fDef->lbraceToken, fDef->rbraceToken);
749 code.mid(bodyLoc.offset, bodyLoc.length), qmlFilePtr->engine(), fDef->body,
750 qmlFilePtr->astComments(), ScriptExpression::ExpressionType::FunctionBody, bodyLoc);
752 if (fDef->typeAnnotation) {
753 SourceLocation typeLoc = combineLocations(fDef->typeAnnotation);
755 code.mid(typeLoc.offset, typeLoc.length), qmlFilePtr->engine(),
756 fDef->typeAnnotation, qmlFilePtr->astComments(),
757 ScriptExpression::ExpressionType::ReturnType, typeLoc);
762 pushEl(mPathFromOwner, *mPtr,
765 if (fDef->identifierToken.isValid())
769 if (fDef->functionToken.isValid())
771 if (fDef->starToken.isValid())
773 if (fDef->lparenToken.length != 0)
775 if (fDef->rparenToken.length != 0)
777 if (fDef->lbraceToken.length != 0)
779 if (fDef->rbraceToken.length != 0)
781 if (fDef->typeAnnotation)
784 AST::FormalParameterList *args = fDef->formals;
787 param.name = args->element->bindingIdentifier.toString();
788 if (AST::TypeAnnotation *tAnn = args->element->typeAnnotation) {
789 if (AST::Type *t = tAnn->type)
790 param.typeName = typeToString(t);
792 if (args->element->initializer) {
793 SourceLocation loc = combineLocations(args->element->initializer);
795 code.mid(loc.offset, loc.length), qmlFilePtr->engine(),
796 args->element->initializer, qmlFilePtr->astComments(),
797 ScriptExpression::ExpressionType::ArgInitializer, loc);
799 if (args->element->type == AST::PatternElement::SpreadElement)
801 SourceLocation parameterLoc = combineLocations(args->element);
803 code.mid(parameterLoc.offset, parameterLoc.length), qmlFilePtr->engine(),
804 args->element, qmlFilePtr->astComments(),
805 ScriptExpression::ExpressionType::ArgumentStructure, parameterLoc);
807 index_type idx = index_type(mInfo.parameters.size());
808 mInfo.parameters.append(param);
810 Path::fromField(Fields::parameters).withIndex(idx));
812 if (args->element->identifierToken.isValid())
814 if (args->element->typeAnnotation)
823 if (AST::cast<VariableStatement *>(el->sourceElement)) {
824 qmlFile.addError(astParseErrors().warning(
825 "JavaScript declarations are not allowed in QML elements"_L1));
833 if (
auto data = variant.data()) {
834 if (
auto genericElement =
835 std::get_if<std::shared_ptr<ScriptElements::GenericScriptElement>>(&*data)) {
844 if (m_nestedFunctionDepth > 1) {
845 endVisit(
static_cast<FunctionExpression *>(fDef));
848 --m_nestedFunctionDepth;
851 FileLocations::ensure(currentNodeEl().fileLocations, Path().withField(Fields::body));
852 const Path bodyPath =
Path().withField(Fields::scriptElement);
854 if (!m_enableScriptExpressions)
858 m.body->setScriptElement(
859 finalizeScriptExpression(prepareBodyForFunction(fDef), bodyPath, bodyTree));
861 if (fDef->typeAnnotation) {
863 Path().withField(Fields::returnType));
864 const Path pathToReturnType =
Path().withField(Fields::scriptElement);
868 finalizeScriptExpression(variant, pathToReturnType, argLoc);
869 m.returnType->setScriptElement(variant);
870 removeCurrentScriptNode({});
874 const auto parameterList = scriptNodeStack.takeLast().takeList();
875 const auto ¶meterQList = parameterList.qList();
876 size_t size = (size_t)parameterQList.size();
877 for (size_t idx = size - 1; idx < size; --idx) {
879 nodeStack.last().fileLocations,
880 Path().withField(Fields::parameters).withIndex(idx).withField(Fields::value));
881 const Path pathToArgument =
Path().withField(Fields::scriptElement);
884 setFormalParameterKind(variant);
885 finalizeScriptExpression(variant, pathToArgument, argLoc);
886 m.parameters[idx].value->setScriptElement(variant);
891 if (m_enableScriptExpressions && !scriptNodeStack.empty()) {
898 if (AST::cast<VariableStatement *>(el->sourceElement))
904 valueFromMultimap(obj.m_methods, m.name, nodeStack.last().path.last().headIndex());
913 scope.setName(toString(el->qualifiedTypeNameId));
917 if (!arrayBindingLevels.isEmpty() && nodeStack.size() == arrayBindingLevels.last()) {
919 QList<QmlObject> *vals =
std::get<
Binding>(currentNode().value).arrayValue();
921 int idx = vals->size();
923 sPathFromOwner = currentNodeEl().path.withField(Fields::value).withIndex(idx);
924 sPtr = &((*vals)[idx]);
927 Q_ASSERT_X(
false, className,
928 "expected an array binding with a valid QList<QmlScope> as value");
931 Q_ASSERT_X(
false, className,
"expected an array binding as last node on the stack");
934 DomValue &containingObject = currentQmlObjectOrComponentEl().item;
935 switch (containingObject.kind) {
937 sPathFromOwner =
std::get<QmlComponent>(containingObject.value).addObject(scope, &sPtr);
940 sPathFromOwner =
std::get<
QmlObject>(containingObject.value).addChild(scope, &sPtr);
945 Path pathFromContainingObject = sPathFromOwner.mid(currentNodeEl().path.length());
947 FileLocations::ensure(currentNodeEl().fileLocations, pathFromContainingObject);
949 el->qualifiedTypeNameId->identifierToken);
951 Q_ASSERT_X(sPtr, className,
"could not recover new scope");
953 if (m_enableScriptExpressions) {
954 auto qmlObjectType = makeGenericScriptElement(el->qualifiedTypeNameId,
DomType::ScriptType);
955 qmlObjectType->insertChild(Fields::typeName,
956 fieldMemberExpressionForQualifiedId(el->qualifiedTypeNameId));
959 sPathFromOwner.withField(Fields::nameIdentifiers), rootMap)
);
961 pushEl(sPathFromOwner, *sPtr, el);
963 if (el->initializer) {
965 el->initializer->lbraceToken);
967 el->initializer->rbraceToken);
976 int idx = currentIndex();
977 if (!arrayBindingLevels.isEmpty() && nodeStack.size() == arrayBindingLevels.last() + 1) {
980 QList<QmlObject> *vals = b.arrayValue();
981 Q_ASSERT_X(vals, className,
982 "expected an array binding with a valid QList<QmlScope> as value");
985 Q_ASSERT_X(
false, className,
"expected an array binding as last node on the stack");
988 DomValue &containingObject = currentNodeEl(1).item;
989 Path p = currentNodeEl().path;
990 switch (containingObject.kind) {
992 if (p
[p
.length() - 2
] == Path::fromField(Fields::objects))
993 std::get<QmlComponent>(containingObject.value).m_objects[idx] = obj;
998 if (p
[p
.length() - 2
] == Path::fromField(Fields::children))
999 std::get<
QmlObject>(containingObject.value).m_children[idx] = obj;
1011 const UiQualifiedId *identifiers,
Binding *bindingPtr)
1013 const bool skipBindingIdentifiers =
std::exchange(m_skipBindingIdentifiers,
false);
1014 if (!m_enableScriptExpressions || skipBindingIdentifiers)
1019 bindable, pathFromOwner.withField(Fields::bindingIdentifiers), rootMap)
);
1026 value.setName(toString(el->qualifiedTypeNameId));
1030 if (bPtr->name() == u"id")
1031 qmlFile.addError(std::move(astParseErrors()
1032 .warning(tr(
"id attributes should only be a lower case letter "
1033 "followed by letters, numbers or underscore, "
1034 "assuming they refer to an id property"))
1035 .withPath(bPathFromOwner)));
1036 setBindingIdentifiers(bPathFromOwner, el->qualifiedId, bPtr);
1038 pushEl(bPathFromOwner, *bPtr, el);
1044 loadAnnotations(el);
1046 Q_ASSERT_X(objValue, className,
"could not recover objectValue");
1047 objValue->setName(toString(el->qualifiedTypeNameId));
1049 if (m_enableScriptExpressions) {
1050 auto qmlObjectType = makeGenericScriptElement(el->qualifiedTypeNameId,
DomType::ScriptType);
1051 qmlObjectType->insertChild(Fields::typeName,
1052 fieldMemberExpressionForQualifiedId(el->qualifiedTypeNameId));
1055 bPathFromOwner.withField(Fields::value).withField(Fields::nameIdentifiers), rootMap)
);
1059 pushEl(bPathFromOwner.withField(Fields::value), *objValue, el->initializer);
1060 if (m_enableScriptExpressions && el->initializer) {
1062 el->initializer->lbraceToken);
1064 el->initializer->rbraceToken);
1077 index_type idx = currentNodeEl(1).path.last().headIndex();
1078 Binding *bPtr = valueFromMultimap(containingObj.m_bindings, b.name(), idx);
1087 ++m_nestedFunctionDepth;
1088 QStringView code = qmlFilePtr->code();
1089 SourceLocation loc = combineLocations(el->statement);
1091 code.mid(loc.offset, loc.length), qmlFilePtr->engine(), el->statement,
1092 qmlFilePtr->astComments(), ScriptExpression::ExpressionType::BindingExpression, loc);
1094 Binding *bindingPtr =
nullptr;
1095 Id *idPtr =
nullptr;
1097 if (bindingV.name() == u"id") {
1098 Node *exp = script->ast();
1099 if (ExpressionStatement *eStat = cast<ExpressionStatement *>(script->ast()))
1100 exp = eStat->expression;
1101 if (IdentifierExpression *iExp = cast<IdentifierExpression *>(exp)) {
1102 QmlStackElement &containingObjectEl = currentEl<
QmlObject>();
1104 QString idName = iExp->name.toString();
1105 Id idVal(idName, qmlFile.canonicalPath().withPath(containingObject.pathFromOwner()));
1106 idVal.value = script;
1107 containingObject.setIdStr(idName);
1109 combineLocations(el->qualifiedId));
1113 iExp->identifierToken);
1114 QmlComponent &comp = current<QmlComponent>();
1116 QRegularExpression idRe(QRegularExpression::anchoredPattern(
1117 QStringLiteral(uR"([[:lower:]_][[:lower:][:upper:]0-9_]*)")));
1118 auto m = idRe.matchView(iExp->name);
1119 if (!m.hasMatch()) {
1120 const auto m =
"id attributes should only be a lower case letter or an underscore "
1121 "followed by letters, numbers or underscores, not %1";
1122 qmlFile.addError(std::move(
1123 astParseErrors().warning(tr(m).arg(iExp->name)).withPath(pathFromOwner)));
1128 Q_ASSERT_X(bindingPtr, className,
"binding could not be retrieved");
1129 const auto m =
"id attributes should only be a lower case letter or an underscore "
1130 "followed by letters, numbers or underscores, not %1 %2, assuming they "
1131 "refer to a property";
1132 qmlFile.addError(std::move(
1134 .warning(tr(m).arg(script->code(), script->astRelocatableDump()))
1135 .withPath(pathFromOwner)));
1140 QmlStackElement &containingObjectEl = currentEl<
QmlObject>();
1142 Path pathFromContainingObject = pathFromOwner.mid(containingObjectEl.path.length());
1143 auto bindingFileLocation =
1146 el->qualifiedId->identifierToken);
1149 setBindingIdentifiers(pathFromOwner, el->qualifiedId, bindingPtr);
1151 Q_ASSERT_X(bindingPtr, className,
"binding could not be retrieved");
1154 pushEl(pathFromOwner, *bindingPtr, el);
1156 pushEl(pathFromOwner, *idPtr, el);
1159 loadAnnotations(el);
1167 if (m_enableScriptExpressions
1168 && (scriptNodeStack.size() != 1 || currentScriptNodeEl().isList()))
1170 if (m_enableScriptExpressions) {
1171 FileLocations::
Tree valueLoc = FileLocations::ensure(currentNodeEl().fileLocations,
1172 Path().withField(Fields::value));
1173 value->setScriptElement(finalizeScriptExpression(currentScriptNodeEl().takeVariant(),
1174 Path().withField(Fields::scriptElement),
1176 removeCurrentScriptNode({});
1182 --m_nestedFunctionDepth;
1183 DomValue &lastEl = currentNode();
1184 index_type idx = currentIndex();
1191 Binding *bPtr = valueFromMultimap(containingObject.m_bindings, b.name(), idx);
1195 Id &id =
std::get<
Id>(lastEl.value);
1197 setScriptExpression(id.value);
1199 QmlComponent &comp = current<QmlComponent>();
1200 Id *idPtr = valueFromMultimap(comp.m_ids, id.name, idx);
1207 if (m_enableScriptExpressions && !scriptNodeStack.empty()) {
1210 removeCurrentNode({});
1215 QList<QmlObject> value;
1218 Path bindingPathFromOwner =
1220 if (bindingV.name() == u"id")
1221 qmlFile.addError(std::move(
1223 .error(tr(
"id attributes should have only simple strings as values"))
1224 .withPath(bindingPathFromOwner)));
1226 setBindingIdentifiers(bindingPathFromOwner, el->qualifiedId, bindingPtr);
1228 pushEl(bindingPathFromOwner, *bindingPtr, el);
1230 loadAnnotations(el);
1232 createMap(currentNodeEl().fileLocations, Path::fromField(Fields::value),
nullptr);
1235 arrayBindingLevels.append(nodeStack.size());
1241 index_type idx = currentIndex();
1243 Binding *bPtr = valueFromMultimap(current<
QmlObject>().m_bindings, b.name(), idx);
1245 arrayBindingLevels.removeLast();
1251 endVisitForLists(list);
1261 endVisitForLists<AST::PatternElementList>(list, [](AST::PatternElementList *current) {
1263 toCollect +=
bool(current->elision);
1264 toCollect +=
bool(current->element);
1271 endVisitForLists(list);
1275
1276
1277
1278
1279
1283 expression->firstSourceLocation(), expression->lastSourceLocation());
1284 id->setName(expression->toString());
1291 if (!m_enableScriptExpressions)
1300 eDecl.setName(el->name.toString());
1302 Path enumPathFromOwner =
1304 pushEl(enumPathFromOwner, *ePtr, el);
1309 loadAnnotations(el);
1315 EnumDecl &e =
std::get<EnumDecl>(currentNode().value);
1317 valueFromMultimap(current<QmlComponent>().m_enumerations, e.name(), currentIndex());
1325 EnumItem it(el->member.toString(), el->value,
1328 EnumDecl &eDecl =
std::get<EnumDecl>(currentNode().value);
1330 const auto map = createMap(DomType::EnumItem, itPathFromDecl,
nullptr);
1331 if (el->commaToken.isValid())
1333 if (el->memberToken.isValid())
1335 if (el->equalToken.isValid())
1337 if (el->valueToken.isValid())
1340 map, MainRegion, combine(combine(el->memberToken, el->commaToken), el->valueToken));
1346 Node::accept(el->next,
this);
1351 QStringList els = current<QmlComponent>().name().split(QLatin1Char(
'.'));
1352 els.append(el->name.toString());
1353 QString cName = els.join(QLatin1Char(
'.'));
1354 QmlComponent *compPtr;
1355 Path p = qmlFilePtr->addComponent(QmlComponent(cName), AddOption::KeepExisting, &compPtr);
1357 if (m_enableScriptExpressions) {
1358 auto inlineComponentType =
1362 typeName->setName(el->name);
1363 inlineComponentType->insertChild(Fields::typeName,
1367 p.withField(Fields::nameIdentifiers), rootMap)
);
1370 pushEl(p, *compPtr, el);
1372 el->componentToken);
1374 loadAnnotations(el);
1380 QmlComponent &component =
std::get<QmlComponent>(currentNode().value);
1381 QStringList nameEls = component.name().split(QChar::fromLatin1(
'.'));
1382 QString key = nameEls.mid(1).join(QChar::fromLatin1(
'.'));
1383 QmlComponent *cPtr = valueFromMultimap(qmlFilePtr->lazyMembers().m_components, key, currentIndex());
1392 pDef.name = el->name.toString();
1395 Path pathFromOwner =
1397 createMap(DomType::PropertyDefinition, pathFromOwner, el);
1404 a.setName(QStringLiteral(u"@") + toString(el->qualifiedTypeNameId));
1406 DomValue &containingElement = currentNode();
1409 switch (containingElement.kind) {
1411 pathFromOwner =
std::get<
QmlObject>(containingElement.value).addAnnotation(a, &aPtr);
1414 pathFromOwner =
std::get<
Binding>(containingElement.value)
1415 .addAnnotation(currentNodeEl().path, a, &aPtr);
1419 std::get<
Id>(containingElement.value).addAnnotation(currentNodeEl().path, a, &aPtr);
1423 .addAnnotation(currentNodeEl().path, a, &aPtr);
1426 pathFromOwner =
std::get<
MethodInfo>(containingElement.value)
1427 .addAnnotation(currentNodeEl().path, a, &aPtr);
1430 qCWarning(domLog) <<
"Unexpected container object for annotation:"
1431 << domTypeToString(containingElement.kind);
1434 pushEl(pathFromOwner, *aPtr, el);
1440 DomValue &containingElement = currentNode(1);
1443 switch (containingElement.kind) {
1444 case DomType::QmlObject:
1445 std::get<QmlObject>(containingElement.value).m_annotations[currentIndex()] = a;
1447 case DomType::Binding:
1448 std::get<Binding>(containingElement.value).m_annotations[currentIndex()] = a;
1451 std::get<Id>(containingElement.value).annotations[currentIndex()] = a;
1453 case DomType::PropertyDefinition:
1454 std::get<PropertyDefinition>(containingElement.value).annotations[currentIndex()] = a;
1456 case DomType::MethodInfo:
1457 std::get<MethodInfo>(containingElement.value).annotations[currentIndex()] = a;
1467 qmlFile.addError(astParseErrors().error(
1468 tr(
"Maximum statement or expression depth exceeded in QmlDomAstCreator")));
1473 endVisitForLists(list);
1478 if (!m_enableScriptExpressions)
1486 if (!m_enableScriptExpressions)
1490 current->addLocation(OperatorTokenRegion, exp->operatorToken);
1492 current->setRight(currentScriptNodeEl().takeVariant());
1493 removeCurrentScriptNode({});
1495 current->setLeft(currentScriptNodeEl().takeVariant());
1496 removeCurrentScriptNode({});
1498 pushScriptElement(current);
1503 if (!m_enableScriptExpressions)
1511 if (!m_enableScriptExpressions)
1516 if (block->statements) {
1518 current->setStatements(currentScriptNodeEl().takeList());
1522 pushScriptElement(current);
1527 if (!m_enableScriptExpressions)
1535 if (!m_enableScriptExpressions)
1539 current->addLocation(FileLocationRegion::ForKeywordRegion, forStatement->forToken);
1540 current->addLocation(FileLocationRegion::LeftParenthesisRegion, forStatement->lparenToken);
1541 current->addLocation(FileLocationRegion::FirstSemicolonTokenRegion,
1542 forStatement->firstSemicolonToken);
1543 current->addLocation(FileLocationRegion::SecondSemicolonRegion,
1544 forStatement->secondSemicolonToken);
1545 current->addLocation(FileLocationRegion::RightParenthesisRegion, forStatement->rparenToken);
1547 if (forStatement->statement) {
1549 current->setBody(currentScriptNodeEl().takeVariant());
1550 removeCurrentScriptNode(
std::nullopt);
1553 if (forStatement->expression) {
1555 current->setExpression(currentScriptNodeEl().takeVariant());
1556 removeCurrentScriptNode(
std::nullopt);
1559 if (forStatement->condition) {
1561 current->setCondition(currentScriptNodeEl().takeVariant());
1562 removeCurrentScriptNode(
std::nullopt);
1565 if (forStatement->declarations) {
1567 auto variableDeclaration = makeGenericScriptElement(forStatement->declarations,
1573 variableDeclaration->insertChild(Fields::declarations,
std::move(list));
1574 removeCurrentScriptNode({});
1578 if (
auto pe = forStatement->declarations->declaration;
1579 pe && pe->declarationKindToken.isValid()) {
1580 current->addLocation(FileLocationRegion::TypeIdentifierRegion,
1581 pe->declarationKindToken);
1585 if (forStatement->initialiser) {
1587 current->setInitializer(currentScriptNodeEl().takeVariant());
1588 removeCurrentScriptNode(
std::nullopt);
1590 pushScriptElement(current);
1595 if (!m_enableScriptExpressions)
1599 current->setName(expression->name);
1600 pushScriptElement(current);
1606 if (!m_enableScriptExpressions)
1610 current->setLiteralValue(expression->value);
1611 pushScriptElement(current);
1617 if (!m_enableScriptExpressions)
1620 pushScriptElement(makeStringLiteral(expression->value, expression));
1626 if (!m_enableScriptExpressions)
1630 current->setLiteralValue(
nullptr);
1631 pushScriptElement(current);
1637 if (!m_enableScriptExpressions)
1641 current->setLiteralValue(
true);
1642 pushScriptElement(current);
1648 if (!m_enableScriptExpressions)
1652 current->setLiteralValue(
false);
1653 pushScriptElement(current);
1659 if (!m_enableScriptExpressions)
1663 current->setName(expression->id);
1664 pushScriptElement(current);
1670 if (!m_enableScriptExpressions)
1673 pushScriptElement(makeStringLiteral(expression->id, expression));
1679 if (!m_enableScriptExpressions)
1688 if (!m_enableScriptExpressions)
1692 current->insertValue(Fields::regExpPattern, literal->pattern);
1693 current->insertValue(Fields::regExpFlags, literal->flags);
1694 pushScriptElement(current);
1701 if (!m_enableScriptExpressions)
1705 if (expression->thisToken.isValid())
1706 current->addLocation(ThisKeywordRegion, expression->thisToken);
1707 pushScriptElement(current);
1713 if (!m_enableScriptExpressions)
1717 if (expression->superToken.isValid())
1718 current->addLocation(SuperKeywordRegion, expression->superToken);
1719 pushScriptElement(current);
1725 if (!m_enableScriptExpressions)
1729 current->setLiteralValue(expression->id);
1730 pushScriptElement(current);
1736 if (!m_enableScriptExpressions)
1745 const std::function<
int(T *)> &scriptElementsPerEntry)
1747 if (!m_enableScriptExpressions)
1750 auto current = makeScriptList(list);
1751 for (
auto it = list; it; it = it->next) {
1752 const int entriesToCollect = scriptElementsPerEntry ? scriptElementsPerEntry(it) : 1;
1753 for (
int i = 0; i < entriesToCollect; ++i) {
1755 auto last = scriptNodeStack.takeLast();
1757 current.append(last.takeList());
1759 current.append(last.takeVariant());
1764 pushScriptElement(current);
1769 endVisitForLists(list);
1774 if (!m_enableScriptExpressions)
1777 auto currentList = makeScriptList(list);
1779 for (
auto it = list; it; it = it->next) {
1783 pushScriptElement(currentList);
1791 if (!m_enableScriptExpressions)
1798
1799
1800
1801
1803 AST::PatternElement *pe,
1806 if (pe->equalToken.isValid())
1807 current->addLocation(FileLocationRegion::EqualTokenRegion, pe->equalToken);
1809 if (pe->identifierToken.isValid() && !pe->bindingIdentifier.isEmpty()) {
1812 identifier->setName(pe->bindingIdentifier);
1813 current->insertChild(Fields::identifier, ScriptElementVariant::fromElement(identifier));
1815 if (pe->initializer) {
1817 current->insertChild(Fields::initializer, scriptNodeStack.last().takeVariant());
1818 scriptNodeStack.removeLast();
1820 if (pe->typeAnnotation) {
1822 current->insertChild(Fields::type, scriptNodeStack.last().takeVariant());
1823 scriptNodeStack.removeLast();
1825 if (pe->bindingTarget) {
1827 current->insertChild(Fields::bindingElement, scriptNodeStack.last().takeVariant());
1828 scriptNodeStack.removeLast();
1834 if (!m_enableScriptExpressions)
1838 endVisitHelper(pe, element);
1840 if (!m_enableScriptExpressions)
1843 pushScriptElement(element);
1848 if (!m_enableScriptExpressions)
1856 if (!m_enableScriptExpressions)
1860 current->addLocation(LeftParenthesisRegion, ifStatement->lparenToken);
1861 current->addLocation(RightParenthesisRegion, ifStatement->rparenToken);
1862 current->addLocation(ElseKeywordRegion, ifStatement->elseToken);
1863 current->addLocation(IfKeywordRegion, ifStatement->ifToken);
1865 if (ifStatement->ko) {
1867 current->setAlternative(scriptNodeStack.last().takeVariant());
1868 scriptNodeStack.removeLast();
1871 if (ifStatement->ok) {
1873 current->setConsequence(scriptNodeStack.last().takeVariant());
1874 scriptNodeStack.removeLast();
1876 if (ifStatement->expression) {
1878 current->setCondition(scriptNodeStack.last().takeVariant());
1879 scriptNodeStack.removeLast();
1882 pushScriptElement(current);
1887 if (!m_enableScriptExpressions)
1895 if (!m_enableScriptExpressions)
1899 current->addLocation(ReturnKeywordRegion, returnStatement->returnToken);
1901 if (returnStatement->expression) {
1903 current->setExpression(currentScriptNodeEl().takeVariant());
1904 removeCurrentScriptNode({});
1907 pushScriptElement(current);
1912 if (!m_enableScriptExpressions)
1920 if (!m_enableScriptExpressions)
1924 current->addLocation(YieldKeywordRegion, yExpression->yieldToken);
1926 if (yExpression->expression) {
1928 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
1929 removeCurrentScriptNode({});
1932 pushScriptElement(current);
1937 if (!m_enableScriptExpressions)
1945 if (!m_enableScriptExpressions)
1950 current->addLocation(FileLocationRegion::OperatorTokenRegion, expression->dotToken);
1952 if (expression->base) {
1954 current->setLeft(currentScriptNodeEl().takeVariant());
1955 removeCurrentScriptNode({});
1958 auto scriptIdentifier =
1960 scriptIdentifier->setName(expression->name);
1963 pushScriptElement(current);
1968 if (!m_enableScriptExpressions)
1976 if (!m_enableScriptExpressions)
1981 current->addLocation(FileLocationRegion::OperatorTokenRegion, expression->lbracketToken);
1983 if (expression->expression) {
1987 current->setRight(currentScriptNodeEl().takeVariant());
1988 removeCurrentScriptNode({});
1991 if (expression->base) {
1993 current->setLeft(currentScriptNodeEl().takeVariant());
1994 removeCurrentScriptNode({});
1997 pushScriptElement(current);
2002 if (!m_enableScriptExpressions)
2010 if (!m_enableScriptExpressions)
2014 current->addLocation(LeftParenthesisRegion, exp->lparenToken);
2015 current->addLocation(RightParenthesisRegion, exp->rparenToken);
2017 if (exp->arguments) {
2019 current->insertChild(Fields::arguments, currentScriptNodeEl().takeList());
2020 removeCurrentScriptNode({});
2023 current->insertChild(Fields::arguments,
2029 current->insertChild(Fields::callee, currentScriptNodeEl().takeVariant());
2030 removeCurrentScriptNode({});
2033 pushScriptElement(current);
2038 if (!m_enableScriptExpressions)
2046 if (!m_enableScriptExpressions)
2051 if (exp->elements) {
2055 current->insertChild(Fields::elements,
std::move(list));
2057 removeCurrentScriptNode({});
2060 current->insertChild(Fields::elements,
2064 pushScriptElement(current);
2069 if (!m_enableScriptExpressions)
2077 if (!m_enableScriptExpressions)
2082 if (exp->properties) {
2084 current->insertChild(Fields::properties, currentScriptNodeEl().takeList());
2085 removeCurrentScriptNode({});
2088 current->insertChild(Fields::properties,
2092 pushScriptElement(current);
2097 if (!m_enableScriptExpressions)
2105 if (!m_enableScriptExpressions)
2111 endVisitHelper(
static_cast<PatternElement *>(exp), current);
2114 if (!m_enableScriptExpressions)
2119 current->insertChild(Fields::name, currentScriptNodeEl().takeVariant());
2120 removeCurrentScriptNode({});
2123 pushScriptElement(current);
2128 if (!m_enableScriptExpressions)
2136 if (!m_enableScriptExpressions)
2140 current->addLocation(FileLocationRegion::TypeIdentifierRegion, statement->declarationKindToken);
2142 if (statement->declarations) {
2148 current->insertChild(Fields::declarations,
std::move(list));
2150 removeCurrentScriptNode({});
2153 pushScriptElement(current);
2158 if (!m_enableScriptExpressions)
2166 if (!m_enableScriptExpressions)
2171 if (exp->typeArgument) {
2172 current->insertChild(Fields::typeArgumentName,
2173 fieldMemberExpressionForQualifiedId(exp->typeArgument));
2174 current->addLocation(FileLocationRegion::IdentifierRegion, combineLocations(exp->typeArgument));
2178 current->insertChild(Fields::typeName, fieldMemberExpressionForQualifiedId(exp->typeId));
2179 current->addLocation(FileLocationRegion::TypeIdentifierRegion, combineLocations(exp->typeId));
2182 pushScriptElement(current);
2187 if (!m_enableScriptExpressions)
2195 if (!m_enableScriptExpressions)
2199 current->addLocation(DefaultKeywordRegion, exp->defaultToken);
2200 current->addLocation(ColonTokenRegion, exp->colonToken);
2202 if (exp->statements) {
2204 current->insertChild(Fields::statements, currentScriptNodeEl().takeList());
2205 removeCurrentScriptNode({});
2208 pushScriptElement(current);
2213 if (!m_enableScriptExpressions)
2221 if (!m_enableScriptExpressions)
2225 current->addLocation(FileLocationRegion::CaseKeywordRegion, exp->caseToken);
2226 current->addLocation(FileLocationRegion::ColonTokenRegion, exp->colonToken);
2228 if (exp->statements) {
2230 current->insertChild(Fields::statements, currentScriptNodeEl().takeList());
2231 removeCurrentScriptNode({});
2234 if (exp->expression) {
2236 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2237 removeCurrentScriptNode({});
2240 pushScriptElement(current);
2245 if (!m_enableScriptExpressions)
2253 if (!m_enableScriptExpressions)
2256 auto current = makeScriptList(list);
2258 for (
auto it = list; it; it = it->next) {
2260 current.append(scriptNodeStack.takeLast().takeVariant());
2264 pushScriptElement(current);
2269 if (!m_enableScriptExpressions)
2277 if (!m_enableScriptExpressions)
2281 current->addLocation(FileLocationRegion::LeftBraceRegion, exp->lbraceToken);
2282 current->addLocation(FileLocationRegion::RightBraceRegion, exp->rbraceToken);
2284 if (exp->moreClauses) {
2286 current->insertChild(Fields::moreCaseClauses, currentScriptNodeEl().takeList());
2287 removeCurrentScriptNode({});
2290 if (exp->defaultClause) {
2292 current->insertChild(Fields::defaultClause, currentScriptNodeEl().takeVariant());
2293 removeCurrentScriptNode({});
2298 current->insertChild(Fields::caseClauses, currentScriptNodeEl().takeList());
2299 removeCurrentScriptNode({});
2301 pushScriptElement(current);
2306 if (!m_enableScriptExpressions)
2314 if (!m_enableScriptExpressions)
2318 current->addLocation(FileLocationRegion::SwitchKeywordRegion, exp->switchToken);
2319 current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
2320 current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
2324 current->insertChild(Fields::caseBlock, currentScriptNodeEl().takeVariant());
2325 removeCurrentScriptNode({});
2327 if (exp->expression) {
2329 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2330 removeCurrentScriptNode({});
2333 pushScriptElement(current);
2338 if (!m_enableScriptExpressions)
2346 if (!m_enableScriptExpressions)
2350 current->addLocation(FileLocationRegion::WhileKeywordRegion, exp->whileToken);
2351 current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
2352 current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
2354 if (exp->statement) {
2356 current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
2357 removeCurrentScriptNode({});
2360 if (exp->expression) {
2362 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2363 removeCurrentScriptNode({});
2366 pushScriptElement(current);
2371 if (!m_enableScriptExpressions)
2379 if (!m_enableScriptExpressions)
2383 current->addLocation(FileLocationRegion::DoKeywordRegion, exp->doToken);
2384 current->addLocation(FileLocationRegion::WhileKeywordRegion, exp->whileToken);
2385 current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
2386 current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
2388 if (exp->expression) {
2390 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2391 removeCurrentScriptNode({});
2394 if (exp->statement) {
2396 current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
2397 removeCurrentScriptNode({});
2400 pushScriptElement(current);
2405 if (!m_enableScriptExpressions)
2413 if (!m_enableScriptExpressions)
2417 current->addLocation(FileLocationRegion::ForKeywordRegion, exp->forToken);
2418 current->addLocation(FileLocationRegion::InOfTokenRegion, exp->inOfToken);
2419 current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
2420 current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
2422 if (exp->statement) {
2424 current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
2425 removeCurrentScriptNode({});
2427 if (exp->expression) {
2429 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2430 removeCurrentScriptNode({});
2435 current->insertChild(Fields::bindingElement, currentScriptNodeEl().takeVariant());
2436 removeCurrentScriptNode({});
2438 if (
auto pe = AST::cast<PatternElement *>(exp->lhs);
2439 pe && pe->declarationKindToken.isValid()) {
2440 current->addLocation(FileLocationRegion::TypeIdentifierRegion,
2441 pe->declarationKindToken);
2445 pushScriptElement(current);
2453 if (m_enableScriptExpressions)
2464 if (!m_enableScriptExpressions)
2468 current->insertChild(Fields::templateLiteral, scriptNodeStack.takeLast().takeVariant());
2470 current->insertChild(Fields::callee, scriptNodeStack.takeLast().takeVariant());
2471 pushScriptElement(current);
2475
2476
2477
2478
2479
2480enum TemplatePartPosition : quint8 {
2486Q_DECLARE_FLAGS(TemplatePartPositions, TemplatePartPosition)
2489
2490
2491
2492
2493static void extractDollarBraceSourceLocationInto(
2495 const SourceLocation &toBeSplit, QStringView code,
2496 TemplatePartPositions templatePartLocation)
2498 if (templatePartLocation & AtEnd || !currentExpression)
2501 const auto offset = toBeSplit.offset + toBeSplit.length - 2;
2502 constexpr auto length = quint32(
std::char_traits<
char>::length(
"${"));
2503 const auto [row, column] = SourceLocation::rowAndColumnFrom(code, offset, toBeSplit);
2504 currentExpression->addLocation(FileLocationRegion::DollarLeftBraceTokenRegion,
2505 SourceLocation{ offset, length, row, column });
2510
2511
2512
2513static void extractRightBacktickSourceLocationInto(
2515 const SourceLocation &toBeSplit, QStringView code,
2516 TemplatePartPositions templatePartLocation)
2518 if (!(templatePartLocation & AtEnd))
2521 const auto offset = toBeSplit.offset + toBeSplit.length - 1;
2522 constexpr auto length = quint32(
std::char_traits<
char>::length(
"`"));
2523 const auto [row, column] = SourceLocation::rowAndColumnFrom(code, offset, toBeSplit);
2524 currentTemplate->addLocation(FileLocationRegion::RightBacktickTokenRegion,
2525 SourceLocation{ offset, length, row, column });
2529
2530
2531
2532static void extractLeftBacktickSourceLocationInto(
2534 const SourceLocation &toBeSplit, TemplatePartPositions templatePartLocation)
2536 if (!(templatePartLocation & AtBeginning))
2539 constexpr auto length = quint32(
std::char_traits<
char>::length(
"`"));
2540 const QQmlJS::SourceLocation leftBacktick{ toBeSplit.offset, length, toBeSplit.startLine,
2541 toBeSplit.startColumn };
2542 currentTemplate->addLocation(FileLocationRegion::LeftBacktickTokenRegion, leftBacktick);
2546
2547
2548
2549
2550static SourceLocation extractRightBraceSourceLocation(
const SourceLocation &toBeSplit,
2551 TemplatePartPositions templatePartLocation)
2553 if (templatePartLocation & AtBeginning)
2554 return SourceLocation{};
2557 return SourceLocation{ toBeSplit.offset, 1, toBeSplit.startLine, toBeSplit.startColumn };
2561
2562
2563
2564
2565static SourceLocation extractStringLocation(
const SourceLocation &toBeSplit, QStringView code,
2566 TemplatePartPositions location)
2570 const quint32 length = toBeSplit.length - (location & AtEnd ? 2 : 3);
2571 const quint32 offset = toBeSplit.offset + 1;
2572 const auto [row, column] = SourceLocation::rowAndColumnFrom(code, offset, toBeSplit);
2573 return SourceLocation{ offset, length, row, column };
2578 if (!m_enableScriptExpressions)
2583 auto currentList = makeScriptList(literal);
2586 const auto children = [&literal]() {
2587 std::vector<AST::TemplateLiteral *> result;
2588 for (
auto it = literal; it; it = it->next) {
2589 result.push_back(it);
2594 SourceLocation rightBrace;
2595 for (
auto it = children.crbegin(); it != children.crend(); ++it) {
2597 const QQmlJS::SourceLocation toBeSplit = (*it)->literalToken;
2600 if ((*it)->expression) {
2602 currentExpression = makeGenericScriptElement((*it)->expression,
2605 currentExpression->insertChild(Fields::expression,
2606 scriptNodeStack.takeLast().takeVariant());
2607 if (rightBrace.isValid()) {
2608 currentExpression->addLocation(FileLocationRegion::RightBraceRegion,
2609 std::exchange(rightBrace, SourceLocation{}));
2614 if (!toBeSplit.isValid())
2617 const TemplatePartPositions location = [&it, &children]() {
2618 TemplatePartPositions result;
2619 if (it == children.crbegin())
2621 if (it ==
std::prev(children.crend()))
2622 result |= AtBeginning;
2626 extractRightBacktickSourceLocationInto(currentTemplate, toBeSplit, qmlFilePtr->code(),
2628 extractLeftBacktickSourceLocationInto(currentTemplate, toBeSplit, location);
2630 extractDollarBraceSourceLocationInto(currentExpression, toBeSplit, qmlFilePtr->code(),
2632 rightBrace = extractRightBraceSourceLocation(toBeSplit, location);
2634 if ((*it)->rawValue.isEmpty())
2637 const SourceLocation stringLocation =
2638 extractStringLocation(toBeSplit, qmlFilePtr->code(), location);
2639 auto currentString =
2641 currentString->insertValue(Fields::value, (*it)->rawValue);
2645 currentList.reverse();
2647 currentTemplate->insertChild(Fields::components, currentList);
2648 pushScriptElement(currentTemplate);
2653 return m_enableScriptExpressions;
2658 if (!m_enableScriptExpressions)
2662 current->addLocation(FileLocationRegion::TryKeywordRegion, statement->tryToken);
2664 if (
auto exp = statement->finallyExpression) {
2665 current->addLocation(FileLocationRegion::FinallyKeywordRegion, exp->finallyToken);
2668 current->insertChild(Fields::finallyBlock, currentScriptNodeEl().takeVariant());
2669 removeCurrentScriptNode({});
2672 if (
auto exp = statement->catchExpression) {
2673 current->addLocation(FileLocationRegion::CatchKeywordRegion, exp->catchToken);
2674 current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
2675 current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
2678 current->insertChild(Fields::catchBlock, currentScriptNodeEl().takeVariant());
2679 removeCurrentScriptNode({});
2681 current->insertChild(Fields::catchParameter, currentScriptNodeEl().takeVariant());
2682 removeCurrentScriptNode({});
2685 if (statement->statement) {
2687 current->insertChild(Fields::block, currentScriptNodeEl().takeVariant());
2688 removeCurrentScriptNode({});
2691 pushScriptElement(current);
2697 return m_enableScriptExpressions;
2708 return m_enableScriptExpressions;
2718 return m_enableScriptExpressions;
2723 if (!m_enableScriptExpressions)
2727 current->addLocation(FileLocationRegion::ThrowKeywordRegion, statement->throwToken);
2729 if (statement->expression) {
2731 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2732 removeCurrentScriptNode({});
2735 pushScriptElement(current);
2740 return m_enableScriptExpressions;
2745 if (!m_enableScriptExpressions)
2749 current->addLocation(FileLocationRegion::ColonTokenRegion, statement->colonToken);
2752 label->setName(statement->label);
2756 if (statement->statement) {
2758 current->insertChild(Fields::statement, currentScriptNodeEl().takeVariant());
2759 removeCurrentScriptNode({});
2762 pushScriptElement(current);
2767 return m_enableScriptExpressions;
2772 if (!m_enableScriptExpressions)
2776 current->addLocation(FileLocationRegion::BreakKeywordRegion, statement->breakToken);
2778 if (!statement->label.isEmpty()) {
2781 label->setName(statement->label);
2785 pushScriptElement(current);
2790 return m_enableScriptExpressions;
2795 if (!m_enableScriptExpressions)
2799 current->addLocation(OperatorTokenRegion, commaExpression->commaToken);
2801 if (commaExpression->right) {
2803 current->setRight(currentScriptNodeEl().takeVariant());
2804 removeCurrentScriptNode({});
2807 if (commaExpression->left) {
2809 current->setLeft(currentScriptNodeEl().takeVariant());
2810 removeCurrentScriptNode({});
2813 pushScriptElement(current);
2818 return m_enableScriptExpressions;
2823 if (!m_enableScriptExpressions)
2827 current->addLocation(FileLocationRegion::QuestionMarkTokenRegion, expression->questionToken);
2828 current->addLocation(FileLocationRegion::ColonTokenRegion, expression->colonToken);
2830 if (expression->ko) {
2832 current->insertChild(Fields::alternative, currentScriptNodeEl().takeVariant());
2833 removeCurrentScriptNode({});
2836 if (expression->ok) {
2838 current->insertChild(Fields::consequence, currentScriptNodeEl().takeVariant());
2839 removeCurrentScriptNode({});
2842 if (expression->expression) {
2844 current->insertChild(Fields::condition, currentScriptNodeEl().takeVariant());
2845 removeCurrentScriptNode({});
2848 pushScriptElement(current);
2853 return m_enableScriptExpressions;
2858 if (!m_enableScriptExpressions)
2862 current->addLocation(FileLocationRegion::ContinueKeywordRegion, statement->continueToken);
2864 if (!statement->label.isEmpty()) {
2867 label->setName(statement->label);
2871 pushScriptElement(current);
2875
2876
2877
2878
2880QQmlDomAstCreatorBase::makeUnaryExpression(AST::Node *expression, QQmlJS::SourceLocation operatorToken,
2881 bool hasExpression, UnaryExpressionKind kind)
2883 const DomType type = [&kind]() {
2893 auto current = makeGenericScriptElement(expression, type);
2894 current->addLocation(FileLocationRegion::OperatorTokenRegion, operatorToken);
2896 if (hasExpression) {
2901 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2902 removeCurrentScriptNode({});
2910 return m_enableScriptExpressions;
2915 if (!m_enableScriptExpressions)
2919 makeUnaryExpression(statement, statement->minusToken, statement->expression, Prefix);
2923 pushScriptElement(current);
2928 return m_enableScriptExpressions;
2933 if (!m_enableScriptExpressions)
2937 makeUnaryExpression(statement, statement->plusToken, statement->expression, Prefix);
2941 pushScriptElement(current);
2946 return m_enableScriptExpressions;
2951 if (!m_enableScriptExpressions)
2955 makeUnaryExpression(statement, statement->tildeToken, statement->expression, Prefix);
2959 pushScriptElement(current);
2964 return m_enableScriptExpressions;
2969 if (!m_enableScriptExpressions)
2973 makeUnaryExpression(statement, statement->notToken, statement->expression, Prefix);
2977 pushScriptElement(current);
2982 return m_enableScriptExpressions;
2987 if (!m_enableScriptExpressions)
2991 makeUnaryExpression(statement, statement->typeofToken, statement->expression, Prefix);
2995 pushScriptElement(current);
3000 return m_enableScriptExpressions;
3005 if (!m_enableScriptExpressions)
3009 makeUnaryExpression(statement, statement->deleteToken, statement->expression, Prefix);
3013 pushScriptElement(current);
3018 return m_enableScriptExpressions;
3023 if (!m_enableScriptExpressions)
3027 makeUnaryExpression(statement, statement->voidToken, statement->expression, Prefix);
3031 pushScriptElement(current);
3036 return m_enableScriptExpressions;
3041 if (!m_enableScriptExpressions)
3045 makeUnaryExpression(statement, statement->decrementToken, statement->base, Postfix);
3049 pushScriptElement(current);
3054 return m_enableScriptExpressions;
3059 if (!m_enableScriptExpressions)
3063 makeUnaryExpression(statement, statement->incrementToken, statement->base, Postfix);
3067 pushScriptElement(current);
3072 return m_enableScriptExpressions;
3077 if (!m_enableScriptExpressions)
3080 auto current = makeUnaryExpression(statement, statement->incrementToken, statement->expression,
3085 pushScriptElement(current);
3090 return m_enableScriptExpressions;
3095 if (!m_enableScriptExpressions)
3099 current->addLocation(FileLocationRegion::SemicolonTokenRegion, statement->semicolonToken);
3100 pushScriptElement(current);
3105 return m_enableScriptExpressions;
3110 if (!m_enableScriptExpressions)
3114 current->addLocation(FileLocationRegion::LeftParenthesisRegion, expression->lparenToken);
3115 current->addLocation(FileLocationRegion::RightParenthesisRegion, expression->rparenToken);
3117 if (expression->expression) {
3119 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
3120 removeCurrentScriptNode({});
3123 pushScriptElement(current);
3128 return m_enableScriptExpressions;
3133 if (!m_enableScriptExpressions)
3137 current->addLocation(FileLocationRegion::NewKeywordRegion, expression->newToken);
3139 if (expression->expression) {
3141 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
3142 removeCurrentScriptNode({});
3145 pushScriptElement(current);
3150 return m_enableScriptExpressions;
3155 if (!m_enableScriptExpressions)
3159 current->addLocation(FileLocationRegion::NewKeywordRegion, expression->newToken);
3160 current->addLocation(FileLocationRegion::LeftParenthesisRegion, expression->lparenToken);
3161 current->addLocation(FileLocationRegion::RightParenthesisRegion, expression->rparenToken);
3163 if (expression->arguments) {
3165 current->insertChild(Fields::arguments, scriptNodeStack.takeLast().takeList());
3167 if (expression->base) {
3169 current->insertChild(Fields::base, scriptNodeStack.takeLast().takeVariant());
3172 pushScriptElement(current);
3177 if (!m_enableScriptExpressions)
3182 if (ast->statement) {
3184 current->insertChild(Fields::statement, scriptNodeStack.takeLast().takeVariant());
3186 if (ast->expression) {
3188 current->insertChild(Fields::expression, scriptNodeStack.takeLast().takeVariant());
3191 pushScriptElement(current);
3196 return m_enableScriptExpressions;
3201 if (!m_enableScriptExpressions)
3204 auto current = makeUnaryExpression(statement, statement->decrementToken, statement->expression,
3209 pushScriptElement(current);
3213 QQmlJSLogger *logger,
3214 QQmlJSImporter *importer)
3225 bool QQmlDomAstCreatorWithQQmlJSScope::visit(name *node)
3227 return visitT(node);
3229 void QQmlDomAstCreatorWithQQmlJSScope::endVisit(name *node)
3233QQmlJSASTClassListToVisit
3238 const QQmlJSScope::ConstPtr scope = m_scopeCreator.m_currentScope;
3239 if (!m_domCreator.scriptNodeStack.isEmpty()) {
3240 auto topOfStack = m_domCreator.currentScriptNodeEl();
3241 switch (topOfStack.kind) {
3244 if (scope->scopeType() == QQmlJSScope::ScopeType::QMLScope)
3245 m_domCreator.currentScriptNodeEl().setSemanticScope(scope);
3248 case DomType::ScriptBlockStatement:
3249 case DomType::ScriptForStatement:
3250 case DomType::ScriptForEachStatement:
3251 case DomType::ScriptDoWhileStatement:
3252 case DomType::ScriptWhileStatement:
3254 m_domCreator.currentScriptNodeEl().setSemanticScope(scope);
3259 auto element = m_domCreator.currentScriptNodeEl().value;
3261 if (!scriptElementVariant || !scriptElementVariant->data())
3263 scriptElementVariant->visit([](
auto &&e) {
3264 using U = std::remove_cv_t<std::remove_reference_t<
decltype(e)>>;
3268 if constexpr (std::is_same_v<U,
3269 ScriptElement::PointerType<
3270 ScriptElements::GenericScriptElement>>) {
3271 if (
auto bodyPtr = e->elementChild(Fields::body)) {
3272 const auto bodyScope = bodyPtr.base()->semanticScope();
3273 e->setSemanticScope(bodyScope);
3284 }
else if (!m_domCreator.nodeStack.isEmpty()) {
3286 [&scope](
auto &&e) {
3287 using U = std::remove_cv_t<std::remove_reference_t<
decltype(e)>>;
3289 if constexpr (std::is_same_v<U, QmlObject>) {
3290 e.setSemanticScope(scope);
3291 }
else if constexpr (std::is_same_v<U, QmlComponent>) {
3292 e.setSemanticScope(scope);
3293 }
else if constexpr (std::is_same_v<U, MethodInfo>) {
3295 if (
auto scriptElement = e.body->scriptElement()) {
3296 scriptElement.base()->setSemanticScope(scope);
3299 e.setSemanticScope(scope);
3302 m_domCreator.currentNodeEl().item.value);
3308 const QQmlJSScope::ConstPtr scope = m_scopeCreator.m_currentScope;
3312 if (m_domCreator.nodeStack.size() > 1
3313 && m_domCreator.nodeStack.last().item.kind == DomType::Binding) {
3315 [&scope](
auto &&e) {
3316 using U = std::remove_cv_t<std::remove_reference_t<
decltype(e)>>;
3317 if constexpr (std::is_same_v<U, PropertyDefinition>) {
3323 const bool usePropertyDefinitionScopeInsteadOfTheBindingScope =
3324 QQmlSA::isFunctionScope(scope->scopeType())
3325 && scope->parentScope()
3326 && scope->parentScope()->scopeType() == QQmlSA::ScopeType::QMLScope;
3327 e.setSemanticScope(usePropertyDefinitionScopeInsteadOfTheBindingScope
3328 ? scope->parentScope()
3332 m_domCreator.currentNodeEl(1).item.value);
3334 if (m_domCreator.nodeStack.size() > 0) {
3336 [&scope](
auto &&e) {
3337 using U = std::remove_cv_t<std::remove_reference_t<
decltype(e)>>;
3338 if constexpr (std::is_same_v<U, PropertyDefinition>) {
3339 e.setSemanticScope(scope);
3340 Q_ASSERT(e.semanticScope());
3341 }
else if constexpr (std::is_same_v<U, MethodInfo>) {
3342 if (e.methodType == MethodInfo::Signal) {
3343 e.setSemanticScope(scope);
3347 m_domCreator.currentNodeEl().item.value);
3357 const auto types = m_scopeCreator.imports().types();
3358 auto environment = m_domCreator.currentEnvironment();
3359 for (
auto it = types.begin(), end = types.end(); it != end; ++it) {
3360 auto scope = it->scope;
3363 auto factory = scope.factory();
3364 if (!factory && !scope->isComposite())
3366 const QString filePath = QQmlJSUtils::qmlSourcePathFromBuildPath(
3367 m_importer->resourceFileMapper(),
3368 factory ? factory->filePath() : scope->filePath());
3369 if (!environment->hasFile(filePath))
3370 environment->loadFile(FileToLoad::fromFileSystem(environment, filePath), { });
3375 bool QQmlDomAstCreator::visit(AST::name *ast)
3377 return QQmlDomAstCreatorBase::visit(ast) && visitWithCustomListIteration(ast, this);
3385#undef Q_SCRIPTELEMENT_DISABLE
3386#undef Q_SCRIPTELEMENT_EXIT_IF
Binding & operator=(const Binding &)
void setBindingIdentifiers(const ScriptElementVariant &bindingIdentifiers)
QmlObject * objectValue()
std::shared_ptr< ScriptExpression > scriptExpressionValue()
Path addValue(const EnumItem &value)
Represents a set of tags grouping a set of related error messages.
TypeAnnotationStyle typeAnnotationStyle
Path operator[](int i) const
Path mid(int offset, int length) const
void setNameIdentifiers(const ScriptElementVariant &name)
QQmlDomAstCreatorBase(const MutableDomItem &qmlFile)
void endVisit(AST::UiProgram *) override
bool stackHasScriptList() const
void throwRecursionDepthError() override
void endVisitHelper(AST::PatternElement *pe, const std::shared_ptr< ScriptElements::GenericScriptElement > &element)
bool visit(AST::UiProgram *program) override
bool stackHasScriptVariant() const
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::shared_ptr< Node > Tree
@ ScriptVariableDeclarationEntry
@ ScriptContinueStatement
@ ScriptLabelledStatement
@ ScriptTemplateExpressionPart
@ ScriptParenthesizedExpression
@ ScriptNewMemberExpression
@ ScriptConditionalExpression
@ ScriptIdentifierExpression
@ ScriptTryCatchStatement
@ ScriptFunctionExpression
@ ScriptVariableDeclaration
@ ScriptTemplateStringPart
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)