17#include <QtQml/private/qqmljsast_p.h>
18#include <QtQmlCompiler/private/qqmljsutils_p.h>
21#include <QtCore/QFileInfo>
22#include <QtCore/QScopeGuard>
23#include <QtCore/QLoggingCategory>
34
35
36
37#define Q_SCRIPTELEMENT_DISABLE()
39 qDebug() << "Could not construct the JS DOM at" << __FILE__ << ":" << __LINE__
40 << ", skipping JS elements...";
41 disableScriptElements();
44#define Q_SCRIPTELEMENT_EXIT_IF(check)
46 if (m_enableScriptExpressions && (check)) {
47 Q_SCRIPTELEMENT_DISABLE();
58template<
typename K,
typename V>
59V *valueFromMultimap(QMultiMap<K, V> &mmap,
const K &key, index_type idx)
63 auto it = mmap.find(key);
64 auto end = mmap.end();
69 while (it2 != end && it2.key() == key) {
75 for (index_type i = idx + 1; i < nEl; ++i)
87static QString toString(
const UiQualifiedId *qualifiedId, QChar delimiter = QLatin1Char(
'.'))
91 for (
const UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) {
92 if (iter != qualifiedId)
101static QString typeToString(AST::Type *t)
104 QString res = toString(t->typeId);
106 if (UiQualifiedId *arg = t->typeArgument)
107 res += u'<' + toString(arg) + u'>';
112SourceLocation combineLocations(SourceLocation s1, SourceLocation s2)
114 return combine(s1, s2);
117SourceLocation combineLocations(Node *n)
119 return combineLocations(n->firstSourceLocation(), n->lastSourceLocation());
123 const SourceLocation &dotToken,
126 SourceLocation s1, s2;
127 left.visitConst([&s1](
auto &&el) { s1 = el->mainRegionLocation(); });
128 right.visitConst([&s2](
auto &&el) { s2 = el->mainRegionLocation(); });
130 auto result = std::make_shared<ScriptElements::BinaryExpression>(s1, s2);
131 result->addLocation(OperatorTokenRegion, dotToken);
133 result->setLeft(left);
134 result->setRight(right);
139
140
141
143fieldMemberExpressionForQualifiedId(
const AST::UiQualifiedId *qualifiedId)
147 for (
auto exp = qualifiedId; exp; exp = exp->next) {
148 const SourceLocation identifierLoc = exp->identifierToken;
150 id->setName(exp->name);
156 bindable = wrapIntoFieldMemberExpression(bindable, exp->dotToken,
157 ScriptElementVariant::fromElement(id));
165 Q_ASSERT_X(idx < nodeStack.size() && idx >= 0,
"currentQmlObjectOrComponentEl",
166 "Stack does not contain enough elements!");
167 int i = nodeStack.size() - idx;
169 DomType k = nodeStack.at(i).item.kind;
170 if (k == DomType::QmlObject || k == DomType::QmlComponent)
173 Q_ASSERT_X(
false,
"currentQmlObjectEl",
"No QmlObject or component in stack");
174 return nodeStack.last();
179 Q_ASSERT_X(i < nodeStack.size() && i >= 0,
"currentNode",
"Stack does not contain element!");
180 return nodeStack[nodeStack.size() - i - 1];
185 Q_ASSERT_X(i < scriptNodeStack.size() && i >= 0,
"currentNode",
186 "Stack does not contain element!");
187 return scriptNodeStack[scriptNodeStack.size() - i - 1];
192 Q_ASSERT_X(i < nodeStack.size() && i >= 0,
"currentNode",
193 "Stack does not contain element!");
194 return nodeStack[nodeStack.size() - i - 1].item;
199 Q_ASSERT_X(!nodeStack.isEmpty(), className,
"popCurrentNode() without any node");
201 Q_ASSERT(nodeStack.last().item.kind == *expectedType);
202 nodeStack.removeLast();
208 Q_ASSERT_X(!scriptNodeStack.isEmpty(), className,
209 "popCurrentScriptNode() without any node");
211 Q_ASSERT(scriptNodeStack.last().kind == *expectedType);
212 scriptNodeStack.removeLast();
216
217
218
219
220
221
222
223
224
225
226
231 auto e = element.base();
234 qCDebug(creatorLog) <<
"Finalizing script expression with path:"
235 << FileLocations::canonicalPathForTesting(ownerFileLocations)
236 .append(pathFromOwner.toString());
237 e->updatePathFromOwner(pathFromOwner);
238 e->createFileLocations(ownerFileLocations);
246 FileLocations::addRegion(res, MainRegion, combineLocations(n));
256 switch (currentNode().kind) {
265 qCWarning(domLog) <<
"unexpected type" << domTypeToString(currentNode().kind);
268 base = currentNodeEl().fileLocations;
272 && (p2.checkHeadName(Fields::children) || p2.checkHeadName(Fields::objects)
273 || p2.checkHeadName(Fields::value) || p2.checkHeadName(Fields::annotations)
274 || p2.checkHeadName(Fields::children)))
276 else if (p
.last().checkHeadName(Fields::value)
280 qCWarning(domLog) <<
"unexpected path to QmlObject in createMap" << p;
284 qCWarning(domLog) <<
"unexpected path to QmlObject in createMap" << p;
290 base = currentNodeEl().fileLocations;
303 base = currentEl<
QmlObject>().fileLocations;
311 qCWarning(domLog) <<
"Unexpected type in createMap:" << domTypeToString(k);
315 return createMap(base, relative, n);
327 QFileInfo fInfo(qmlFile.canonicalFilePath());
328 QString componentName = fInfo.baseName();
330 Path p = qmlFilePtr->addComponent(QmlComponent(componentName), AddOption::KeepExisting,
333 Q_ASSERT_X(newC
.item(), className,
"could not recover component added with addComponent");
336 FileLocations::addRegion(rootMap, MainRegion, combineLocations(program));
337 pushEl(p, *cPtr, program);
339 auto envPtr = qmlFile.environment().ownerAs<DomEnvironment>();
340 const bool loadDependencies =
343 if (!fInfo.canonicalPath().isEmpty()) {
344 Import selfDirImport(QmlUri::fromDirectoryString(fInfo.canonicalPath()));
346 qmlFilePtr->addImport(selfDirImport);
348 if (loadDependencies) {
349 const QString currentFile = envPtr->domCreationOption() == Extended
350 ? QQmlJSUtils::qmlBuildPathFromSourcePath(
351 envPtr->semanticAnalysis().m_mapper.get(),
352 qmlFile.canonicalFilePath())
353 : qmlFile.canonicalFilePath();
355 const QDir implicitImportDir = QFileInfo(currentFile).dir();
356 const QString implicitImportDirPath = implicitImportDir.canonicalPath();
357 envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, implicitImportDirPath),
361 if (implicitImportDir.exists(u"qmldir"_s)) {
362 const QString implicitImportQmldir = implicitImportDirPath + u"/qmldir"_s;
363 envPtr->loadFile(FileToLoad::fromFileSystem(envPtr, implicitImportQmldir),
369 for (Import i : qmlFile.environment().ownerAs<DomEnvironment>()->implicitImports()) {
371 qmlFilePtr->addImport(i);
373 if (loadDependencies)
374 envPtr->loadModuleDependency(i.uri.moduleUri(), i.version, DomItem::Callback());
376 if (m_loadFileLazily && loadDependencies) {
377 envPtr->loadPendingDependencies();
378 envPtr->commitToBase(qmlFile.environment().item());
387 QmlComponent &comp = current<QmlComponent>();
388 for (
const Pragma &p : qmlFilePtr->pragmas()) {
389 if (p.name.compare(u"singleton", Qt::CaseInsensitive) == 0) {
390 comp.setIsSingleton(
true);
391 comp.setIsCreatable(
false);
394 *newC.mutableAs<QmlComponent>() = comp;
396 Q_ASSERT_X(nodeStack.isEmpty(), className,
"ui program did not finish node stack");
401 QStringList valueList;
402 for (
auto t = el->values; t; t = t->next)
403 valueList << t->value.toString();
405 auto fileLocation = createMap(
406 DomType::Pragma, qmlFilePtr->addPragma(Pragma(el->name.toString(), valueList)), el);
407 FileLocations::addRegion(fileLocation, PragmaKeywordRegion, el->pragmaToken);
408 FileLocations::addRegion(fileLocation, IdentifierRegion, el->pragmaIdToken);
409 if (el->colonToken.isValid()) {
410 FileLocations::addRegion(fileLocation, ColonTokenRegion, el->colonToken);
413 for (
auto t = el->values; t; t = t->next) {
414 auto subMap = createMap(fileLocation, Path().withField(Fields::values).withIndex(i), t);
415 FileLocations::addRegion(subMap, PragmaValuesRegion, t->location);
424 Version v(Version::Latest, Version::Latest);
425 if (el->version && el->version->version.hasMajorVersion())
426 v.majorVersion = el->version->version.majorVersion();
427 if (el->version && el->version->version.hasMinorVersion())
428 v.minorVersion = el->version->version.minorVersion();
430 auto envPtr = qmlFile.environment().ownerAs<DomEnvironment>();
431 const bool loadDependencies =
434 if (el->importUri !=
nullptr) {
436 Import::fromUriString(toString(el->importUri), v, el->importId.toString());
437 fileLocation = createMap(DomType::Import, qmlFilePtr->addImport(import), el);
439 if (loadDependencies) {
440 envPtr->loadModuleDependency(import.uri.moduleUri(), import.version,
441 DomItem::Callback());
443 FileLocations::addRegion(fileLocation, ImportUriRegion, combineLocations(el->importUri));
446 Import::fromFileString(el->fileName.toString(), el->importId.toString());
447 fileLocation = createMap(DomType::Import, qmlFilePtr->addImport(import), el);
449 if (loadDependencies) {
450 const QString currentFileDir =
451 QFileInfo(qmlFile.canonicalFilePath()).dir().canonicalPath();
452 envPtr->loadFile(FileToLoad::fromFileSystem(
453 envPtr, import.uri.absoluteLocalPath(currentFileDir)),
456 FileLocations::addRegion(fileLocation, ImportUriRegion, el->fileNameToken);
458 if (m_loadFileLazily && loadDependencies) {
459 envPtr->loadPendingDependencies();
460 envPtr->commitToBase(qmlFile.environment().item());
463 if (el->importToken.isValid())
464 FileLocations::addRegion(fileLocation, ImportTokenRegion, el->importToken);
466 if (el->asToken.isValid())
467 FileLocations::addRegion(fileLocation, AsTokenRegion, el->asToken);
469 if (el->importIdToken.isValid())
470 FileLocations::addRegion(fileLocation, IdNameRegion, el->importIdToken);
473 FileLocations::addRegion(fileLocation, VersionRegion, combineLocations(el->version));
482 case AST::UiPublicMember::Signal: {
484 m.name = el->name.toString();
485 m.typeName = toString(el->memberType);
488 m.methodType = MethodInfo::Signal;
489 m
.isList = el->typeModifier == QLatin1String(
"list");
492 pushEl(p, *mPtr, el);
494 const auto fileLocations = nodeStack.last().fileLocations;
495 FileLocations::addRegion(fileLocations, SignalKeywordRegion, el->propertyToken());
496 FileLocations::addRegion(fileLocations, IdentifierRegion, el->identifierToken);
497 if (el->lparenToken.isValid())
498 FileLocations::addRegion(fileLocations, LeftParenthesisRegion, el->lparenToken);
499 if (el->rparenToken.isValid())
500 FileLocations::addRegion(fileLocations, RightParenthesisRegion, el->rparenToken);
503 AST::UiParameterList *args = el->parameters;
506 param.name = args->name.toString();
507 param.typeName = args->type ? args->type->toString() : QString();
508 index_type idx = index_type(mInfo.parameters.size());
509 if (!args->colonToken.isValid())
511 mInfo.parameters.append(param);
512 auto argLocs = FileLocations::ensure(nodeStack.last().fileLocations,
513 Path::fromField(Fields::parameters).withIndex(idx));
514 FileLocations::addRegion(argLocs, MainRegion, combineLocations(args));
515 FileLocations::addRegion(argLocs, IdentifierRegion, args->identifierToken);
517 if (args->colonToken.isValid())
518 FileLocations::addRegion(argLocs, ColonTokenRegion, args->colonToken);
519 FileLocations::addRegion(argLocs, TypeIdentifierRegion, args->propertyTypeToken);
525 case AST::UiPublicMember::Property: {
527 p.name = el->name.toString();
528 p.typeName = toString(el->memberType);
533 p
.isList = el->typeModifier == QLatin1String(
"list");
535 if (!el->typeModifier.isEmpty())
536 p.typeName = el->typeModifier.toString() + QChar(u'<') + p.typeName + QChar(u'>');
538 Path pPathFromOwner =
540 if (m_enableScriptExpressions) {
542 qmlObjectType->insertChild(Fields::typeName,
543 fieldMemberExpressionForQualifiedId(el->memberType));
544 pPtr->setNameIdentifiers(finalizeScriptExpression(
545 ScriptElementVariant::fromElement(qmlObjectType),
546 pPathFromOwner.withField(Fields::nameIdentifiers), rootMap));
549 m_skipBindingIdentifiers = el->binding;
551 pushEl(pPathFromOwner, *pPtr, el);
552 FileLocations::addRegion(nodeStack.last().fileLocations, PropertyKeywordRegion,
553 el->propertyToken());
554 FileLocations::addRegion(nodeStack.last().fileLocations, IdentifierRegion,
555 el->identifierToken);
556 FileLocations::addRegion(nodeStack.last().fileLocations, TypeIdentifierRegion,
558 FileLocations::addRegion(nodeStack.last().fileLocations, ColonTokenRegion, el->colonToken);
559 if (el->typeModifierToken.isValid())
560 FileLocations::addRegion(nodeStack.last().fileLocations, TypeModifierRegion, el->typeModifierToken);
562 qmlFile.addError(std::move(astParseErrors()
563 .warning(tr(
"id is a special attribute, that should not be "
564 "used as property name"))
565 .withPath(currentNodeEl().path)));
567 FileLocations::addRegion(nodeStack.last().fileLocations, DefaultKeywordRegion,
571 FileLocations::addRegion(nodeStack.last().fileLocations, FinalKeywordRegion,
575 FileLocations::addRegion(nodeStack.last().fileLocations, RequiredKeywordRegion,
576 el->requiredToken());
579 FileLocations::addRegion(nodeStack.last().fileLocations, ReadonlyKeywordRegion,
580 el->readonlyToken());
584 SourceLocation loc = combineLocations(el->statement);
585 QStringView code = qmlFilePtr->code();
587 auto script = std::make_shared<ScriptExpression>(
588 code.mid(loc.offset, loc.length), qmlFilePtr->engine(), el->statement,
589 qmlFilePtr->astComments(), ScriptExpression::ExpressionType::BindingExpression,
594 FileLocations::
Tree bLoc = createMap(DomType::Binding, bPathFromOwner, el->statement);
595 FileLocations::addRegion(bLoc, ColonTokenRegion, el->colonToken);
596 FileLocations::
Tree valueLoc = FileLocations::ensure(bLoc, Path::fromField(Fields::value));
597 FileLocations::addRegion(valueLoc, MainRegion, combineLocations(el->statement));
600 nodeStack.append({ std::move(bPathFromOwner), *bPtr, std::move(bLoc) });
612 if (m_enableScriptExpressions
613 && (scriptNodeStack.size() != 1 || scriptNodeStack.last().isList())) {
616 if (m_enableScriptExpressions) {
617 b.scriptExpressionValue()->setScriptElement(finalizeScriptExpression(
618 currentScriptNodeEl().takeVariant(), Path().withField(Fields::scriptElement),
619 FileLocations::ensure(currentNodeEl().fileLocations,
620 Path().withField(Fields::value))));
621 removeCurrentScriptNode({});
626 valueFromMultimap(containingObject.m_bindings, b.name(), currentIndex());
628 removeCurrentNode({});
630 Node::accept(el->parameters,
this);
632 if ((el->binding || el->statement)
633 && nodeStack.last().item.kind == DomType::PropertyDefinition) {
635 if (!pDef.annotations.isEmpty()) {
637 duplicate.setName(QLatin1String(
"duplicate"));
639 auto it = obj.m_bindings.find(pDef.name);
640 if (it != obj.m_bindings.end()) {
641 for (QmlObject ann : pDef.annotations) {
642 ann.addAnnotation(duplicate);
643 it->addAnnotation(currentEl<QmlObject>()
644 .path.withField(Fields::bindings)
646 .withIndex(obj.m_bindings.values(pDef.name).size() - 1),
653 QmlStackElement &sEl = nodeStack.last();
654 switch (sEl.item.kind) {
658 valueFromMultimap(obj.m_propertyDefs, pDef.name, sEl.path.last().headIndex());
660 *pDefPtr =
std::move(pDef);
664 MethodInfo *mPtr = valueFromMultimap(obj.m_methods, m.name, sEl.path.last().headIndex());
666 *mPtr =
std::move(m);
671 removeCurrentNode({});
676 endVisitForLists(list);
681 ++m_nestedFunctionDepth;
682 if (!m_enableScriptExpressions)
690 Q_ASSERT(!scriptNodeStack.isEmpty() || !fExpression->body);
692 if (fExpression->body) {
693 if (currentScriptNodeEl().isList()) {
696 auto body = std::make_shared<ScriptElements::BlockStatement>(
697 combineLocations(fExpression->lbraceToken, fExpression->rbraceToken));
698 body->setStatements(currentScriptNodeEl().takeList());
699 if (
auto semanticScope = body->statements().semanticScope())
700 body->setSemanticScope(semanticScope);
702 removeCurrentScriptNode({});
705 auto result = currentScriptNodeEl().takeVariant();
706 removeCurrentScriptNode({});
709 Q_UNREACHABLE_RETURN({});
713 auto body = std::make_shared<ScriptElements::BlockStatement>(
714 combineLocations(fExpression->lbraceToken, fExpression->rbraceToken));
720 --m_nestedFunctionDepth;
721 if (!m_enableScriptExpressions)
725 if (fExpression->identifierToken.isValid())
726 current->addLocation(IdentifierRegion, fExpression->identifierToken);
727 if (fExpression->functionToken.isValid())
728 current->addLocation(FunctionKeywordRegion, fExpression->functionToken);
729 if (fExpression->starToken.isValid())
730 current->addLocation(StarTokenRegion, fExpression->starToken);
731 if (fExpression->lparenToken.isValid())
732 current->addLocation(LeftParenthesisRegion, fExpression->lparenToken);
733 if (fExpression->rparenToken.isValid())
734 current->addLocation(RightParenthesisRegion, fExpression->rparenToken);
735 if (fExpression->lbraceToken.isValid())
736 current->addLocation(LeftBraceRegion, fExpression->lbraceToken);
737 if (fExpression->rbraceToken.isValid())
738 current->addLocation(RightBraceRegion, fExpression->rbraceToken);
739 if (fExpression->typeAnnotation) {
740 current->addLocation(TypeIdentifierRegion,
741 combineLocations(fExpression->typeAnnotation->type));
745 current->insertChild(Fields::body, prepareBodyForFunction(fExpression));
747 if (fExpression->typeAnnotation) {
749 current->insertChild(Fields::returnType, currentScriptNodeEl().takeVariant());
750 scriptNodeStack.removeLast();
752 if (fExpression->formals) {
754 current->insertChild(Fields::parameters, currentScriptNodeEl().takeList());
755 scriptNodeStack.removeLast();
758 if (!fExpression->name.isEmpty())
759 current->insertValue(Fields::name, fExpression->name);
761 pushScriptElement(current);
767 if (m_nestedFunctionDepth > 0) {
768 return visit(
static_cast<FunctionExpression *>(fDef));
770 ++m_nestedFunctionDepth;
771 const QStringView code(qmlFilePtr->code());
773 m.name = fDef->name.toString();
774 if (AST::TypeAnnotation *tAnn = fDef->typeAnnotation) {
775 if (AST::Type *t = tAnn->type)
776 m.typeName = typeToString(t);
779 m.methodType = MethodInfo::Method;
781 SourceLocation bodyLoc = fDef->body ? combineLocations(fDef->body)
782 : combineLocations(fDef->lbraceToken, fDef->rbraceToken);
783 m.body = std::make_shared<ScriptExpression>(
784 code.mid(bodyLoc.offset, bodyLoc.length), qmlFilePtr->engine(), fDef->body,
785 qmlFilePtr->astComments(), ScriptExpression::ExpressionType::FunctionBody, bodyLoc);
787 if (fDef->typeAnnotation) {
788 SourceLocation typeLoc = combineLocations(fDef->typeAnnotation);
789 m.returnType = std::make_shared<ScriptExpression>(
790 code.mid(typeLoc.offset, typeLoc.length), qmlFilePtr->engine(),
791 fDef->typeAnnotation, qmlFilePtr->astComments(),
792 ScriptExpression::ExpressionType::ReturnType, typeLoc);
797 pushEl(mPathFromOwner, *mPtr,
800 if (fDef->identifierToken.isValid())
801 FileLocations::addRegion(fLoc, IdentifierRegion, fDef->identifierToken);
803 FileLocations::addRegion(bodyTree, MainRegion, bodyLoc);
804 if (fDef->functionToken.isValid())
805 FileLocations::addRegion(fLoc, FunctionKeywordRegion, fDef->functionToken);
806 if (fDef->starToken.isValid())
807 FileLocations::addRegion(fLoc, StarTokenRegion, fDef->starToken);
808 if (fDef->lparenToken.length != 0)
809 FileLocations::addRegion(fLoc, LeftParenthesisRegion, fDef->lparenToken);
810 if (fDef->rparenToken.length != 0)
811 FileLocations::addRegion(fLoc, RightParenthesisRegion, fDef->rparenToken);
812 if (fDef->lbraceToken.length != 0)
813 FileLocations::addRegion(fLoc, LeftBraceRegion, fDef->lbraceToken);
814 if (fDef->rbraceToken.length != 0)
815 FileLocations::addRegion(fLoc, RightBraceRegion, fDef->rbraceToken);
816 if (fDef->typeAnnotation)
817 FileLocations::addRegion(fLoc, TypeIdentifierRegion, combineLocations(fDef->typeAnnotation->type));
819 AST::FormalParameterList *args = fDef->formals;
822 param.name = args->element->bindingIdentifier.toString();
823 if (AST::TypeAnnotation *tAnn = args->element->typeAnnotation) {
824 if (AST::Type *t = tAnn->type)
825 param.typeName = typeToString(t);
827 if (args->element->initializer) {
828 SourceLocation loc = combineLocations(args->element->initializer);
829 param.defaultValue = std::make_shared<ScriptExpression>(
830 code.mid(loc.offset, loc.length), qmlFilePtr->engine(),
831 args->element->initializer, qmlFilePtr->astComments(),
832 ScriptExpression::ExpressionType::ArgInitializer, loc);
834 if (args->element->type == AST::PatternElement::SpreadElement)
836 SourceLocation parameterLoc = combineLocations(args->element);
837 param.value = std::make_shared<ScriptExpression>(
838 code.mid(parameterLoc.offset, parameterLoc.length), qmlFilePtr->engine(),
839 args->element, qmlFilePtr->astComments(),
840 ScriptExpression::ExpressionType::ArgumentStructure, parameterLoc);
842 index_type idx = index_type(mInfo.parameters.size());
843 mInfo.parameters.append(param);
844 auto argLocs = FileLocations::ensure(nodeStack.last().fileLocations,
845 Path::fromField(Fields::parameters).withIndex(idx));
846 FileLocations::addRegion(argLocs, MainRegion, combineLocations(args));
847 if (args->element->identifierToken.isValid())
848 FileLocations::addRegion(argLocs, IdentifierRegion, args->element->identifierToken);
849 if (args->element->typeAnnotation)
850 FileLocations::addRegion(argLocs, TypeIdentifierRegion, combineLocations(args->element->typeAnnotation->type));
858 if (!cast<FunctionDeclaration *>(el->sourceElement)) {
859 qCWarning(creatorLog) <<
"unhandled source el:" <<
static_cast<AST::Node *>(el);
867 if (
auto data = variant.data()) {
868 if (
auto genericElement =
869 std::get_if<std::shared_ptr<ScriptElements::GenericScriptElement>>(&*data)) {
878 if (m_nestedFunctionDepth > 1) {
879 endVisit(
static_cast<FunctionExpression *>(fDef));
882 --m_nestedFunctionDepth;
885 FileLocations::ensure(currentNodeEl().fileLocations, Path().withField(Fields::body));
886 const Path bodyPath =
Path().withField(Fields::scriptElement);
888 if (!m_enableScriptExpressions)
892 m.body->setScriptElement(
893 finalizeScriptExpression(prepareBodyForFunction(fDef), bodyPath, bodyTree));
895 if (fDef->typeAnnotation) {
896 auto argLoc = FileLocations::ensure(nodeStack.last().fileLocations,
897 Path().withField(Fields::returnType));
898 const Path pathToReturnType =
Path().withField(Fields::scriptElement);
902 finalizeScriptExpression(variant, pathToReturnType, argLoc);
903 m.returnType->setScriptElement(variant);
904 removeCurrentScriptNode({});
908 const auto parameterList = scriptNodeStack.takeLast().takeList();
909 const auto ¶meterQList = parameterList.qList();
910 size_t size = (size_t)parameterQList.size();
911 for (size_t idx = size - 1; idx < size; --idx) {
912 auto argLoc = FileLocations::ensure(
913 nodeStack.last().fileLocations,
914 Path().withField(Fields::parameters).withIndex(idx).withField(Fields::value));
915 const Path pathToArgument =
Path().withField(Fields::scriptElement);
918 setFormalParameterKind(variant);
919 finalizeScriptExpression(variant, pathToArgument, argLoc);
920 m.parameters[idx].value->setScriptElement(variant);
925 if (m_enableScriptExpressions && !scriptNodeStack.empty()) {
936 valueFromMultimap(obj.m_methods, m.name, nodeStack.last().path.last().headIndex());
945 scope.setName(toString(el->qualifiedTypeNameId));
949 if (!arrayBindingLevels.isEmpty() && nodeStack.size() == arrayBindingLevels.last()) {
951 QList<QmlObject> *vals =
std::get<
Binding>(currentNode().value).arrayValue();
953 int idx = vals->size();
955 sPathFromOwner = currentNodeEl().path.withField(Fields::value).withIndex(idx);
956 sPtr = &((*vals)[idx]);
959 Q_ASSERT_X(
false, className,
960 "expected an array binding with a valid QList<QmlScope> as value");
963 Q_ASSERT_X(
false, className,
"expected an array binding as last node on the stack");
966 DomValue &containingObject = currentQmlObjectOrComponentEl().item;
967 switch (containingObject.kind) {
969 sPathFromOwner =
std::get<QmlComponent>(containingObject.value).addObject(scope, &sPtr);
972 sPathFromOwner =
std::get<
QmlObject>(containingObject.value).addChild(scope, &sPtr);
977 Path pathFromContainingObject = sPathFromOwner.mid(currentNodeEl().path.length());
979 FileLocations::ensure(currentNodeEl().fileLocations, pathFromContainingObject);
980 FileLocations::addRegion(fLoc, IdentifierRegion,
981 el->qualifiedTypeNameId->identifierToken);
983 Q_ASSERT_X(sPtr, className,
"could not recover new scope");
985 if (m_enableScriptExpressions) {
986 auto qmlObjectType = makeGenericScriptElement(el->qualifiedTypeNameId,
DomType::ScriptType);
987 qmlObjectType->insertChild(Fields::typeName,
988 fieldMemberExpressionForQualifiedId(el->qualifiedTypeNameId));
989 sPtr->setNameIdentifiers(
990 finalizeScriptExpression(ScriptElementVariant::fromElement(qmlObjectType),
991 sPathFromOwner.withField(Fields::nameIdentifiers), rootMap));
993 pushEl(sPathFromOwner, *sPtr, el);
995 if (el->initializer) {
996 FileLocations::addRegion(nodeStack.last().fileLocations, LeftBraceRegion,
997 el->initializer->lbraceToken);
998 FileLocations::addRegion(nodeStack.last().fileLocations, RightBraceRegion,
999 el->initializer->rbraceToken);
1001 loadAnnotations(el);
1008 int idx = currentIndex();
1009 if (!arrayBindingLevels.isEmpty() && nodeStack.size() == arrayBindingLevels.last() + 1) {
1012 QList<QmlObject> *vals = b.arrayValue();
1013 Q_ASSERT_X(vals, className,
1014 "expected an array binding with a valid QList<QmlScope> as value");
1017 Q_ASSERT_X(
false, className,
"expected an array binding as last node on the stack");
1020 DomValue &containingObject = currentNodeEl(1).item;
1021 Path p = currentNodeEl().path;
1022 switch (containingObject.kind) {
1024 if (p
[p
.length() - 2
] == Path::fromField(Fields::objects))
1025 std::get<QmlComponent>(containingObject.value).m_objects[idx] = obj;
1030 if (p
[p
.length() - 2
] == Path::fromField(Fields::children))
1031 std::get<
QmlObject>(containingObject.value).m_children[idx] = obj;
1043 const UiQualifiedId *identifiers,
Binding *bindingPtr)
1045 const bool skipBindingIdentifiers =
std::exchange(m_skipBindingIdentifiers,
false);
1046 if (!m_enableScriptExpressions || skipBindingIdentifiers)
1050 bindingPtr->setBindingIdentifiers(finalizeScriptExpression(
1051 bindable, pathFromOwner.withField(Fields::bindingIdentifiers), rootMap));
1058 value.setName(toString(el->qualifiedTypeNameId));
1060 Path bPathFromOwner = current<QmlObject>().addBinding(
1061 Binding(toString(el->qualifiedId), value, bType), AddOption::KeepExisting, &bPtr);
1062 if (bPtr->name() == u"id")
1063 qmlFile.addError(std::move(astParseErrors()
1064 .warning(tr(
"id attributes should only be a lower case letter "
1065 "followed by letters, numbers or underscore, "
1066 "assuming they refer to an id property"))
1067 .withPath(bPathFromOwner)));
1068 setBindingIdentifiers(bPathFromOwner, el->qualifiedId, bPtr);
1070 pushEl(bPathFromOwner, *bPtr, el);
1072 FileLocations::addRegion(nodeStack.last().fileLocations, OnTokenRegion, el->colonToken);
1074 FileLocations::addRegion(nodeStack.last().fileLocations, ColonTokenRegion, el->colonToken);
1075 FileLocations::addRegion(nodeStack.last().fileLocations, IdentifierRegion, combineLocations(el->qualifiedId));
1076 loadAnnotations(el);
1078 Q_ASSERT_X(objValue, className,
"could not recover objectValue");
1079 objValue->setName(toString(el->qualifiedTypeNameId));
1081 if (m_enableScriptExpressions) {
1082 auto qmlObjectType = makeGenericScriptElement(el->qualifiedTypeNameId,
DomType::ScriptType);
1083 qmlObjectType->insertChild(Fields::typeName,
1084 fieldMemberExpressionForQualifiedId(el->qualifiedTypeNameId));
1085 objValue->setNameIdentifiers(finalizeScriptExpression(
1086 ScriptElementVariant::fromElement(qmlObjectType),
1087 bPathFromOwner.withField(Fields::value).withField(Fields::nameIdentifiers), rootMap));
1091 pushEl(bPathFromOwner.withField(Fields::value), *objValue, el->initializer);
1092 if (m_enableScriptExpressions && el->initializer) {
1093 FileLocations::addRegion(nodeStack.last().fileLocations, LeftBraceRegion,
1094 el->initializer->lbraceToken);
1095 FileLocations::addRegion(nodeStack.last().fileLocations, RightBraceRegion,
1096 el->initializer->rbraceToken);
1109 index_type idx = currentNodeEl(1).path.last().headIndex();
1110 Binding *bPtr = valueFromMultimap(containingObj.m_bindings, b.name(), idx);
1119 ++m_nestedFunctionDepth;
1120 QStringView code = qmlFilePtr->code();
1121 SourceLocation loc = combineLocations(el->statement);
1122 const auto script = std::make_shared<ScriptExpression>(
1123 code.mid(loc.offset, loc.length), qmlFilePtr->engine(), el->statement,
1124 qmlFilePtr->astComments(), ScriptExpression::ExpressionType::BindingExpression, loc);
1126 Binding *bindingPtr =
nullptr;
1127 Id *idPtr =
nullptr;
1129 if (bindingV.name() == u"id") {
1130 Node *exp = script->ast();
1131 if (ExpressionStatement *eStat = cast<ExpressionStatement *>(script->ast()))
1132 exp = eStat->expression;
1133 if (IdentifierExpression *iExp = cast<IdentifierExpression *>(exp)) {
1134 QmlStackElement &containingObjectEl = currentEl<
QmlObject>();
1136 QString idName = iExp->name.toString();
1137 Id idVal(idName, qmlFile.canonicalPath().withPath(containingObject.pathFromOwner()));
1138 idVal.value = script;
1139 containingObject.setIdStr(idName);
1140 FileLocations::addRegion(containingObjectEl.fileLocations, IdTokenRegion,
1141 combineLocations(el->qualifiedId));
1142 FileLocations::addRegion(containingObjectEl.fileLocations, IdColonTokenRegion,
1144 FileLocations::addRegion(containingObjectEl.fileLocations, IdNameRegion,
1145 combineLocations(el->statement));
1146 QmlComponent &comp = current<QmlComponent>();
1148 QRegularExpression idRe(QRegularExpression::anchoredPattern(
1149 QStringLiteral(uR"([[:lower:]][[:lower:][:upper:]0-9_]*)")));
1150 auto m = idRe.matchView(iExp->name);
1151 if (!m.hasMatch()) {
1152 qmlFile.addError(std::move(
1154 .warning(tr(
"id attributes should only be a lower case letter "
1155 "followed by letters, numbers or underscore, not %1")
1157 .withPath(pathFromOwner)));
1162 Q_ASSERT_X(bindingPtr, className,
"binding could not be retrieved");
1163 qmlFile.addError(std::move(
1165 .warning(tr(
"id attributes should only be a lower case letter "
1166 "followed by letters, numbers or underscore, not %1 "
1167 "%2, assuming they refer to a property")
1168 .arg(script->code(), script->astRelocatableDump()))
1169 .withPath(pathFromOwner)));
1174 QmlStackElement &containingObjectEl = currentEl<
QmlObject>();
1176 Path pathFromContainingObject = pathFromOwner.mid(containingObjectEl.path.length());
1177 auto bindingFileLocation =
1179 FileLocations::addRegion(bindingFileLocation, IdentifierRegion,
1180 el->qualifiedId->identifierToken);
1181 FileLocations::addRegion(bindingFileLocation, ColonTokenRegion, el->colonToken);
1183 setBindingIdentifiers(pathFromOwner, el->qualifiedId, bindingPtr);
1185 Q_ASSERT_X(bindingPtr, className,
"binding could not be retrieved");
1188 pushEl(pathFromOwner, *bindingPtr, el);
1190 pushEl(pathFromOwner, *idPtr, el);
1193 loadAnnotations(el);
1195 FileLocations::addRegion(nodeStack.last().fileLocations, ColonTokenRegion, el->colonToken);
1201 if (m_enableScriptExpressions
1202 && (scriptNodeStack.size() != 1 || currentScriptNodeEl().isList()))
1204 if (m_enableScriptExpressions) {
1205 FileLocations::
Tree valueLoc = FileLocations::ensure(currentNodeEl().fileLocations,
1206 Path().withField(Fields::value));
1207 value->setScriptElement(finalizeScriptExpression(currentScriptNodeEl().takeVariant(),
1208 Path().withField(Fields::scriptElement),
1210 removeCurrentScriptNode({});
1216 --m_nestedFunctionDepth;
1217 DomValue &lastEl = currentNode();
1218 index_type idx = currentIndex();
1225 Binding *bPtr = valueFromMultimap(containingObject.m_bindings, b.name(), idx);
1229 Id &id =
std::get<
Id>(lastEl.value);
1231 setScriptExpression(id.value);
1233 QmlComponent &comp = current<QmlComponent>();
1234 Id *idPtr = valueFromMultimap(comp.m_ids, id.name, idx);
1241 if (m_enableScriptExpressions && !scriptNodeStack.empty()) {
1244 removeCurrentNode({});
1249 QList<QmlObject> value;
1252 Path bindingPathFromOwner =
1254 if (bindingV.name() == u"id")
1255 qmlFile.addError(std::move(
1257 .error(tr(
"id attributes should have only simple strings as values"))
1258 .withPath(bindingPathFromOwner)));
1260 setBindingIdentifiers(bindingPathFromOwner, el->qualifiedId, bindingPtr);
1262 pushEl(bindingPathFromOwner, *bindingPtr, el);
1263 FileLocations::addRegion(currentNodeEl().fileLocations, ColonTokenRegion, el->colonToken);
1264 loadAnnotations(el);
1266 createMap(currentNodeEl().fileLocations, Path::fromField(Fields::value),
nullptr);
1267 FileLocations::addRegion(arrayList, LeftBracketRegion, el->lbracketToken);
1268 FileLocations::addRegion(arrayList, RightBracketRegion, el->rbracketToken);
1269 arrayBindingLevels.append(nodeStack.size());
1275 index_type idx = currentIndex();
1277 Binding *bPtr = valueFromMultimap(current<
QmlObject>().m_bindings, b.name(), idx);
1279 arrayBindingLevels.removeLast();
1285 endVisitForLists(list);
1295 endVisitForLists<AST::PatternElementList>(list, [](AST::PatternElementList *current) {
1297 toCollect +=
bool(current->elision);
1298 toCollect +=
bool(current->element);
1305 endVisitForLists(list);
1309
1310
1311
1312
1313
1317 expression->firstSourceLocation(), expression->lastSourceLocation());
1318 id->setName(expression->toString());
1325 if (!m_enableScriptExpressions)
1334 eDecl.setName(el->name.toString());
1336 Path enumPathFromOwner =
1338 pushEl(enumPathFromOwner, *ePtr, el);
1339 FileLocations::addRegion(nodeStack.last().fileLocations, EnumKeywordRegion, el->enumToken);
1340 FileLocations::addRegion(nodeStack.last().fileLocations, IdentifierRegion, el->identifierToken);
1341 FileLocations::addRegion(nodeStack.last().fileLocations, LeftBraceRegion, el->lbraceToken);
1342 FileLocations::addRegion(nodeStack.last().fileLocations, RightBraceRegion, el->rbraceToken);
1343 loadAnnotations(el);
1349 EnumDecl &e =
std::get<EnumDecl>(currentNode().value);
1351 valueFromMultimap(current<QmlComponent>().m_enumerations, e.name(), currentIndex());
1359 EnumItem it(el->member.toString(), el->value,
1362 EnumDecl &eDecl =
std::get<EnumDecl>(currentNode().value);
1364 const auto map = createMap(DomType::EnumItem, itPathFromDecl,
nullptr);
1365 if (el->commaToken.isValid())
1366 FileLocations::addRegion(map, CommaTokenRegion, el->commaToken);
1367 if (el->memberToken.isValid())
1368 FileLocations::addRegion(map, IdentifierRegion, el->memberToken);
1369 if (el->equalToken.isValid())
1370 FileLocations::addRegion(map, EqualTokenRegion, el->equalToken);
1371 if (el->valueToken.isValid())
1372 FileLocations::addRegion(map, EnumValueRegion, el->valueToken);
1373 FileLocations::addRegion(
1374 map, MainRegion, combine(combine(el->memberToken, el->commaToken), el->valueToken));
1380 Node::accept(el->next,
this);
1385 QStringList els = current<QmlComponent>().name().split(QLatin1Char(
'.'));
1386 els.append(el->name.toString());
1387 QString cName = els.join(QLatin1Char(
'.'));
1388 QmlComponent *compPtr;
1389 Path p = qmlFilePtr->addComponent(QmlComponent(cName), AddOption::KeepExisting, &compPtr);
1391 if (m_enableScriptExpressions) {
1392 auto inlineComponentType =
1396 typeName->setName(el->name);
1397 inlineComponentType->insertChild(Fields::typeName,
1399 compPtr->setNameIdentifiers(
1400 finalizeScriptExpression(ScriptElementVariant::fromElement(inlineComponentType),
1401 p.withField(Fields::nameIdentifiers), rootMap));
1404 pushEl(p, *compPtr, el);
1405 FileLocations::addRegion(nodeStack.last().fileLocations, ComponentKeywordRegion,
1406 el->componentToken);
1407 FileLocations::addRegion(nodeStack.last().fileLocations, IdentifierRegion, el->identifierToken);
1408 loadAnnotations(el);
1414 QmlComponent &component =
std::get<QmlComponent>(currentNode().value);
1415 QStringList nameEls = component.name().split(QChar::fromLatin1(
'.'));
1416 QString key = nameEls.mid(1).join(QChar::fromLatin1(
'.'));
1417 QmlComponent *cPtr = valueFromMultimap(qmlFilePtr->lazyMembers().m_components, key, currentIndex());
1426 pDef.name = el->name.toString();
1429 Path pathFromOwner =
1431 createMap(DomType::PropertyDefinition, pathFromOwner, el);
1438 a.setName(QStringLiteral(u"@") + toString(el->qualifiedTypeNameId));
1440 DomValue &containingElement = currentNode();
1443 switch (containingElement.kind) {
1445 pathFromOwner =
std::get<
QmlObject>(containingElement.value).addAnnotation(a, &aPtr);
1448 pathFromOwner =
std::get<
Binding>(containingElement.value)
1449 .addAnnotation(currentNodeEl().path, a, &aPtr);
1453 std::get<
Id>(containingElement.value).addAnnotation(currentNodeEl().path, a, &aPtr);
1457 .addAnnotation(currentNodeEl().path, a, &aPtr);
1460 pathFromOwner =
std::get<
MethodInfo>(containingElement.value)
1461 .addAnnotation(currentNodeEl().path, a, &aPtr);
1464 qCWarning(domLog) <<
"Unexpected container object for annotation:"
1465 << domTypeToString(containingElement.kind);
1468 pushEl(pathFromOwner, *aPtr, el);
1474 DomValue &containingElement = currentNode(1);
1477 switch (containingElement.kind) {
1478 case DomType::QmlObject:
1479 std::get<QmlObject>(containingElement.value).m_annotations[currentIndex()] = a;
1481 case DomType::Binding:
1482 std::get<Binding>(containingElement.value).m_annotations[currentIndex()] = a;
1485 std::get<Id>(containingElement.value).annotations[currentIndex()] = a;
1487 case DomType::PropertyDefinition:
1488 std::get<PropertyDefinition>(containingElement.value).annotations[currentIndex()] = a;
1490 case DomType::MethodInfo:
1491 std::get<MethodInfo>(containingElement.value).annotations[currentIndex()] = a;
1501 qmlFile.addError(astParseErrors().error(
1502 tr(
"Maximum statement or expression depth exceeded in QmlDomAstCreator")));
1507 endVisitForLists(list);
1512 if (!m_enableScriptExpressions)
1520 if (!m_enableScriptExpressions)
1524 current->addLocation(OperatorTokenRegion, exp->operatorToken);
1526 current->setRight(currentScriptNodeEl().takeVariant());
1527 removeCurrentScriptNode({});
1529 current->setLeft(currentScriptNodeEl().takeVariant());
1530 removeCurrentScriptNode({});
1532 pushScriptElement(current);
1537 if (!m_enableScriptExpressions)
1545 if (!m_enableScriptExpressions)
1550 if (block->statements) {
1552 current->setStatements(currentScriptNodeEl().takeList());
1556 pushScriptElement(current);
1561 if (!m_enableScriptExpressions)
1569 if (!m_enableScriptExpressions)
1573 current->addLocation(FileLocationRegion::ForKeywordRegion, forStatement->forToken);
1574 current->addLocation(FileLocationRegion::LeftParenthesisRegion, forStatement->lparenToken);
1575 current->addLocation(FileLocationRegion::FirstSemicolonTokenRegion,
1576 forStatement->firstSemicolonToken);
1577 current->addLocation(FileLocationRegion::SecondSemicolonRegion,
1578 forStatement->secondSemicolonToken);
1579 current->addLocation(FileLocationRegion::RightParenthesisRegion, forStatement->rparenToken);
1581 if (forStatement->statement) {
1583 current->setBody(currentScriptNodeEl().takeVariant());
1584 removeCurrentScriptNode(
std::nullopt);
1587 if (forStatement->expression) {
1589 current->setExpression(currentScriptNodeEl().takeVariant());
1590 removeCurrentScriptNode(
std::nullopt);
1593 if (forStatement->condition) {
1595 current->setCondition(currentScriptNodeEl().takeVariant());
1596 removeCurrentScriptNode(
std::nullopt);
1599 if (forStatement->declarations) {
1601 auto variableDeclaration = makeGenericScriptElement(forStatement->declarations,
1607 variableDeclaration->insertChild(Fields::declarations,
std::move(list));
1608 removeCurrentScriptNode({});
1612 if (
auto pe = forStatement->declarations->declaration;
1613 pe && pe->declarationKindToken.isValid()) {
1614 current->addLocation(FileLocationRegion::TypeIdentifierRegion,
1615 pe->declarationKindToken);
1619 if (forStatement->initialiser) {
1621 current->setInitializer(currentScriptNodeEl().takeVariant());
1622 removeCurrentScriptNode(
std::nullopt);
1624 pushScriptElement(current);
1629 if (!m_enableScriptExpressions)
1633 current->setName(expression->name);
1634 pushScriptElement(current);
1640 if (!m_enableScriptExpressions)
1644 current->setLiteralValue(expression->value);
1645 pushScriptElement(current);
1651 if (!m_enableScriptExpressions)
1654 pushScriptElement(makeStringLiteral(expression->value, expression));
1660 if (!m_enableScriptExpressions)
1664 current->setLiteralValue(
nullptr);
1665 pushScriptElement(current);
1671 if (!m_enableScriptExpressions)
1675 current->setLiteralValue(
true);
1676 pushScriptElement(current);
1682 if (!m_enableScriptExpressions)
1686 current->setLiteralValue(
false);
1687 pushScriptElement(current);
1693 if (!m_enableScriptExpressions)
1697 current->setName(expression->id);
1698 pushScriptElement(current);
1704 if (!m_enableScriptExpressions)
1707 pushScriptElement(makeStringLiteral(expression->id, expression));
1713 if (!m_enableScriptExpressions)
1722 if (!m_enableScriptExpressions)
1726 current->insertValue(Fields::regExpPattern, literal->pattern);
1727 current->insertValue(Fields::regExpFlags, literal->flags);
1728 pushScriptElement(current);
1735 if (!m_enableScriptExpressions)
1739 if (expression->thisToken.isValid())
1740 current->addLocation(ThisKeywordRegion, expression->thisToken);
1741 pushScriptElement(current);
1747 if (!m_enableScriptExpressions)
1751 if (expression->superToken.isValid())
1752 current->addLocation(SuperKeywordRegion, expression->superToken);
1753 pushScriptElement(current);
1759 if (!m_enableScriptExpressions)
1763 current->setLiteralValue(expression->id);
1764 pushScriptElement(current);
1770 if (!m_enableScriptExpressions)
1779 const std::function<
int(T *)> &scriptElementsPerEntry)
1781 if (!m_enableScriptExpressions)
1784 auto current = makeScriptList(list);
1785 for (
auto it = list; it; it = it->next) {
1786 const int entriesToCollect = scriptElementsPerEntry ? scriptElementsPerEntry(it) : 1;
1787 for (
int i = 0; i < entriesToCollect; ++i) {
1789 auto last = scriptNodeStack.takeLast();
1791 current.append(last.takeList());
1793 current.append(last.takeVariant());
1798 pushScriptElement(current);
1803 endVisitForLists(list);
1808 if (!m_enableScriptExpressions)
1811 auto currentList = makeScriptList(list);
1813 for (
auto it = list; it; it = it->next) {
1817 pushScriptElement(currentList);
1825 if (!m_enableScriptExpressions)
1832
1833
1834
1835
1837 AST::PatternElement *pe,
1840 if (pe->equalToken.isValid())
1841 current->addLocation(FileLocationRegion::EqualTokenRegion, pe->equalToken);
1843 if (pe->identifierToken.isValid() && !pe->bindingIdentifier.isEmpty()) {
1846 identifier->setName(pe->bindingIdentifier);
1847 current->insertChild(Fields::identifier, ScriptElementVariant::fromElement(identifier));
1849 if (pe->initializer) {
1851 current->insertChild(Fields::initializer, scriptNodeStack.last().takeVariant());
1852 scriptNodeStack.removeLast();
1854 if (pe->typeAnnotation) {
1856 current->insertChild(Fields::type, scriptNodeStack.last().takeVariant());
1857 scriptNodeStack.removeLast();
1859 if (pe->bindingTarget) {
1861 current->insertChild(Fields::bindingElement, scriptNodeStack.last().takeVariant());
1862 scriptNodeStack.removeLast();
1868 if (!m_enableScriptExpressions)
1872 endVisitHelper(pe, element);
1874 if (!m_enableScriptExpressions)
1877 pushScriptElement(element);
1882 if (!m_enableScriptExpressions)
1890 if (!m_enableScriptExpressions)
1894 current->addLocation(LeftParenthesisRegion, ifStatement->lparenToken);
1895 current->addLocation(RightParenthesisRegion, ifStatement->rparenToken);
1896 current->addLocation(ElseKeywordRegion, ifStatement->elseToken);
1897 current->addLocation(IfKeywordRegion, ifStatement->ifToken);
1899 if (ifStatement->ko) {
1901 current->setAlternative(scriptNodeStack.last().takeVariant());
1902 scriptNodeStack.removeLast();
1905 if (ifStatement->ok) {
1907 current->setConsequence(scriptNodeStack.last().takeVariant());
1908 scriptNodeStack.removeLast();
1910 if (ifStatement->expression) {
1912 current->setCondition(scriptNodeStack.last().takeVariant());
1913 scriptNodeStack.removeLast();
1916 pushScriptElement(current);
1921 if (!m_enableScriptExpressions)
1929 if (!m_enableScriptExpressions)
1933 current->addLocation(ReturnKeywordRegion, returnStatement->returnToken);
1935 if (returnStatement->expression) {
1937 current->setExpression(currentScriptNodeEl().takeVariant());
1938 removeCurrentScriptNode({});
1941 pushScriptElement(current);
1946 if (!m_enableScriptExpressions)
1954 if (!m_enableScriptExpressions)
1958 current->addLocation(YieldKeywordRegion, yExpression->yieldToken);
1960 if (yExpression->expression) {
1962 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
1963 removeCurrentScriptNode({});
1966 pushScriptElement(current);
1971 if (!m_enableScriptExpressions)
1979 if (!m_enableScriptExpressions)
1984 current->addLocation(FileLocationRegion::OperatorTokenRegion, expression->dotToken);
1986 if (expression->base) {
1988 current->setLeft(currentScriptNodeEl().takeVariant());
1989 removeCurrentScriptNode({});
1992 auto scriptIdentifier =
1994 scriptIdentifier->setName(expression->name);
1997 pushScriptElement(current);
2002 if (!m_enableScriptExpressions)
2010 if (!m_enableScriptExpressions)
2015 current->addLocation(FileLocationRegion::OperatorTokenRegion, expression->lbracketToken);
2017 if (expression->expression) {
2021 current->setRight(currentScriptNodeEl().takeVariant());
2022 removeCurrentScriptNode({});
2025 if (expression->base) {
2027 current->setLeft(currentScriptNodeEl().takeVariant());
2028 removeCurrentScriptNode({});
2031 pushScriptElement(current);
2036 if (!m_enableScriptExpressions)
2044 if (!m_enableScriptExpressions)
2048 current->addLocation(LeftParenthesisRegion, exp->lparenToken);
2049 current->addLocation(RightParenthesisRegion, exp->rparenToken);
2051 if (exp->arguments) {
2053 current->insertChild(Fields::arguments, currentScriptNodeEl().takeList());
2054 removeCurrentScriptNode({});
2057 current->insertChild(Fields::arguments,
2063 current->insertChild(Fields::callee, currentScriptNodeEl().takeVariant());
2064 removeCurrentScriptNode({});
2067 pushScriptElement(current);
2072 if (!m_enableScriptExpressions)
2080 if (!m_enableScriptExpressions)
2085 if (exp->elements) {
2089 current->insertChild(Fields::elements,
std::move(list));
2091 removeCurrentScriptNode({});
2094 current->insertChild(Fields::elements,
2098 pushScriptElement(current);
2103 if (!m_enableScriptExpressions)
2111 if (!m_enableScriptExpressions)
2116 if (exp->properties) {
2118 current->insertChild(Fields::properties, currentScriptNodeEl().takeList());
2119 removeCurrentScriptNode({});
2122 current->insertChild(Fields::properties,
2126 pushScriptElement(current);
2131 if (!m_enableScriptExpressions)
2139 if (!m_enableScriptExpressions)
2145 endVisitHelper(
static_cast<PatternElement *>(exp), current);
2148 if (!m_enableScriptExpressions)
2153 current->insertChild(Fields::name, currentScriptNodeEl().takeVariant());
2154 removeCurrentScriptNode({});
2157 pushScriptElement(current);
2162 if (!m_enableScriptExpressions)
2170 if (!m_enableScriptExpressions)
2174 current->addLocation(FileLocationRegion::TypeIdentifierRegion, statement->declarationKindToken);
2176 if (statement->declarations) {
2182 current->insertChild(Fields::declarations,
std::move(list));
2184 removeCurrentScriptNode({});
2187 pushScriptElement(current);
2192 if (!m_enableScriptExpressions)
2200 if (!m_enableScriptExpressions)
2205 if (exp->typeArgument) {
2206 current->insertChild(Fields::typeArgumentName,
2207 fieldMemberExpressionForQualifiedId(exp->typeArgument));
2208 current->addLocation(FileLocationRegion::IdentifierRegion, combineLocations(exp->typeArgument));
2212 current->insertChild(Fields::typeName, fieldMemberExpressionForQualifiedId(exp->typeId));
2213 current->addLocation(FileLocationRegion::TypeIdentifierRegion, combineLocations(exp->typeId));
2216 pushScriptElement(current);
2221 if (!m_enableScriptExpressions)
2229 if (!m_enableScriptExpressions)
2233 current->addLocation(DefaultKeywordRegion, exp->defaultToken);
2234 current->addLocation(ColonTokenRegion, exp->colonToken);
2236 if (exp->statements) {
2238 current->insertChild(Fields::statements, currentScriptNodeEl().takeList());
2239 removeCurrentScriptNode({});
2242 pushScriptElement(current);
2247 if (!m_enableScriptExpressions)
2255 if (!m_enableScriptExpressions)
2259 current->addLocation(FileLocationRegion::CaseKeywordRegion, exp->caseToken);
2260 current->addLocation(FileLocationRegion::ColonTokenRegion, exp->colonToken);
2262 if (exp->statements) {
2264 current->insertChild(Fields::statements, currentScriptNodeEl().takeList());
2265 removeCurrentScriptNode({});
2268 if (exp->expression) {
2270 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2271 removeCurrentScriptNode({});
2274 pushScriptElement(current);
2279 if (!m_enableScriptExpressions)
2287 if (!m_enableScriptExpressions)
2290 auto current = makeScriptList(list);
2292 for (
auto it = list; it; it = it->next) {
2294 current.append(scriptNodeStack.takeLast().takeVariant());
2298 pushScriptElement(current);
2303 if (!m_enableScriptExpressions)
2311 if (!m_enableScriptExpressions)
2315 current->addLocation(FileLocationRegion::LeftBraceRegion, exp->lbraceToken);
2316 current->addLocation(FileLocationRegion::RightBraceRegion, exp->rbraceToken);
2318 if (exp->moreClauses) {
2320 current->insertChild(Fields::moreCaseClauses, currentScriptNodeEl().takeList());
2321 removeCurrentScriptNode({});
2324 if (exp->defaultClause) {
2326 current->insertChild(Fields::defaultClause, currentScriptNodeEl().takeVariant());
2327 removeCurrentScriptNode({});
2332 current->insertChild(Fields::caseClauses, currentScriptNodeEl().takeList());
2333 removeCurrentScriptNode({});
2335 pushScriptElement(current);
2340 if (!m_enableScriptExpressions)
2348 if (!m_enableScriptExpressions)
2352 current->addLocation(FileLocationRegion::SwitchKeywordRegion, exp->switchToken);
2353 current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
2354 current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
2358 current->insertChild(Fields::caseBlock, currentScriptNodeEl().takeVariant());
2359 removeCurrentScriptNode({});
2361 if (exp->expression) {
2363 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2364 removeCurrentScriptNode({});
2367 pushScriptElement(current);
2372 if (!m_enableScriptExpressions)
2380 if (!m_enableScriptExpressions)
2384 current->addLocation(FileLocationRegion::WhileKeywordRegion, exp->whileToken);
2385 current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
2386 current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
2388 if (exp->statement) {
2390 current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
2391 removeCurrentScriptNode({});
2394 if (exp->expression) {
2396 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2397 removeCurrentScriptNode({});
2400 pushScriptElement(current);
2405 if (!m_enableScriptExpressions)
2413 if (!m_enableScriptExpressions)
2417 current->addLocation(FileLocationRegion::DoKeywordRegion, exp->doToken);
2418 current->addLocation(FileLocationRegion::WhileKeywordRegion, exp->whileToken);
2419 current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
2420 current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
2422 if (exp->expression) {
2424 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2425 removeCurrentScriptNode({});
2428 if (exp->statement) {
2430 current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
2431 removeCurrentScriptNode({});
2434 pushScriptElement(current);
2439 if (!m_enableScriptExpressions)
2447 if (!m_enableScriptExpressions)
2451 current->addLocation(FileLocationRegion::ForKeywordRegion, exp->forToken);
2452 current->addLocation(FileLocationRegion::InOfTokenRegion, exp->inOfToken);
2453 current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
2454 current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
2456 if (exp->statement) {
2458 current->insertChild(Fields::body, currentScriptNodeEl().takeVariant());
2459 removeCurrentScriptNode({});
2461 if (exp->expression) {
2463 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2464 removeCurrentScriptNode({});
2469 current->insertChild(Fields::bindingElement, currentScriptNodeEl().takeVariant());
2470 removeCurrentScriptNode({});
2472 if (
auto pe = AST::cast<PatternElement *>(exp->lhs);
2473 pe && pe->declarationKindToken.isValid()) {
2474 current->addLocation(FileLocationRegion::TypeIdentifierRegion,
2475 pe->declarationKindToken);
2479 pushScriptElement(current);
2487 if (m_enableScriptExpressions)
2498 if (!m_enableScriptExpressions)
2502 current->insertChild(Fields::templateLiteral, scriptNodeStack.takeLast().takeVariant());
2504 current->insertChild(Fields::callee, scriptNodeStack.takeLast().takeVariant());
2505 pushScriptElement(current);
2509
2510
2511
2512
2513
2514enum TemplatePartPosition : quint8 {
2520Q_DECLARE_FLAGS(TemplatePartPositions, TemplatePartPosition)
2523
2524
2525
2526
2527static void extractDollarBraceSourceLocationInto(
2529 const SourceLocation &toBeSplit, QStringView code,
2530 TemplatePartPositions templatePartLocation)
2532 if (templatePartLocation & AtEnd || !currentExpression)
2535 const auto offset = toBeSplit.offset + toBeSplit.length - 2;
2536 constexpr auto length = quint32(
std::char_traits<
char>::length(
"${"));
2537 const auto [row, column] = SourceLocation::rowAndColumnFrom(code, offset, toBeSplit);
2538 currentExpression->addLocation(FileLocationRegion::DollarLeftBraceTokenRegion,
2539 SourceLocation{ offset, length, row, column });
2544
2545
2546
2547static void extractRightBacktickSourceLocationInto(
2549 const SourceLocation &toBeSplit, QStringView code,
2550 TemplatePartPositions templatePartLocation)
2552 if (!(templatePartLocation & AtEnd))
2555 const auto offset = toBeSplit.offset + toBeSplit.length - 1;
2556 constexpr auto length = quint32(
std::char_traits<
char>::length(
"`"));
2557 const auto [row, column] = SourceLocation::rowAndColumnFrom(code, offset, toBeSplit);
2558 currentTemplate->addLocation(FileLocationRegion::RightBacktickTokenRegion,
2559 SourceLocation{ offset, length, row, column });
2563
2564
2565
2566static void extractLeftBacktickSourceLocationInto(
2568 const SourceLocation &toBeSplit, TemplatePartPositions templatePartLocation)
2570 if (!(templatePartLocation & AtBeginning))
2573 constexpr auto length = quint32(
std::char_traits<
char>::length(
"`"));
2574 const QQmlJS::SourceLocation leftBacktick{ toBeSplit.offset, length, toBeSplit.startLine,
2575 toBeSplit.startColumn };
2576 currentTemplate->addLocation(FileLocationRegion::LeftBacktickTokenRegion, leftBacktick);
2580
2581
2582
2583
2584static SourceLocation extractRightBraceSourceLocation(
const SourceLocation &toBeSplit,
2585 TemplatePartPositions templatePartLocation)
2587 if (templatePartLocation & AtBeginning)
2588 return SourceLocation{};
2591 return SourceLocation{ toBeSplit.offset, 1, toBeSplit.startLine, toBeSplit.startColumn };
2595
2596
2597
2598
2599static SourceLocation extractStringLocation(
const SourceLocation &toBeSplit, QStringView code,
2600 TemplatePartPositions location)
2604 const quint32 length = toBeSplit.length - (location & AtEnd ? 2 : 3);
2605 const quint32 offset = toBeSplit.offset + 1;
2606 const auto [row, column] = SourceLocation::rowAndColumnFrom(code, offset, toBeSplit);
2607 return SourceLocation{ offset, length, row, column };
2612 if (!m_enableScriptExpressions)
2617 auto currentList = makeScriptList(literal);
2620 const auto children = [&literal]() {
2621 std::vector<AST::TemplateLiteral *> result;
2622 for (
auto it = literal; it; it = it->next) {
2623 result.push_back(it);
2628 SourceLocation rightBrace;
2629 for (
auto it = children.crbegin(); it != children.crend(); ++it) {
2631 const QQmlJS::SourceLocation toBeSplit = (*it)->literalToken;
2634 if ((*it)->expression) {
2636 currentExpression = makeGenericScriptElement((*it)->expression,
2639 currentExpression->insertChild(Fields::expression,
2640 scriptNodeStack.takeLast().takeVariant());
2641 if (rightBrace.isValid()) {
2642 currentExpression->addLocation(FileLocationRegion::RightBraceRegion,
2643 std::exchange(rightBrace, SourceLocation{}));
2648 if (!toBeSplit.isValid())
2651 const TemplatePartPositions location = [&it, &children]() {
2652 TemplatePartPositions result;
2653 if (it == children.crbegin())
2655 if (it ==
std::prev(children.crend()))
2656 result |= AtBeginning;
2660 extractRightBacktickSourceLocationInto(currentTemplate, toBeSplit, qmlFilePtr->code(),
2662 extractLeftBacktickSourceLocationInto(currentTemplate, toBeSplit, location);
2664 extractDollarBraceSourceLocationInto(currentExpression, toBeSplit, qmlFilePtr->code(),
2666 rightBrace = extractRightBraceSourceLocation(toBeSplit, location);
2668 if ((*it)->rawValue.isEmpty())
2671 const SourceLocation stringLocation =
2672 extractStringLocation(toBeSplit, qmlFilePtr->code(), location);
2673 auto currentString =
2675 currentString->insertValue(Fields::value, (*it)->rawValue);
2679 currentList.reverse();
2681 currentTemplate->insertChild(Fields::components, currentList);
2682 pushScriptElement(currentTemplate);
2687 return m_enableScriptExpressions;
2692 if (!m_enableScriptExpressions)
2696 current->addLocation(FileLocationRegion::TryKeywordRegion, statement->tryToken);
2698 if (
auto exp = statement->finallyExpression) {
2699 current->addLocation(FileLocationRegion::FinallyKeywordRegion, exp->finallyToken);
2702 current->insertChild(Fields::finallyBlock, currentScriptNodeEl().takeVariant());
2703 removeCurrentScriptNode({});
2706 if (
auto exp = statement->catchExpression) {
2707 current->addLocation(FileLocationRegion::CatchKeywordRegion, exp->catchToken);
2708 current->addLocation(FileLocationRegion::LeftParenthesisRegion, exp->lparenToken);
2709 current->addLocation(FileLocationRegion::RightParenthesisRegion, exp->rparenToken);
2712 current->insertChild(Fields::catchBlock, currentScriptNodeEl().takeVariant());
2713 removeCurrentScriptNode({});
2715 current->insertChild(Fields::catchParameter, currentScriptNodeEl().takeVariant());
2716 removeCurrentScriptNode({});
2719 if (statement->statement) {
2721 current->insertChild(Fields::block, currentScriptNodeEl().takeVariant());
2722 removeCurrentScriptNode({});
2725 pushScriptElement(current);
2731 return m_enableScriptExpressions;
2742 return m_enableScriptExpressions;
2752 return m_enableScriptExpressions;
2757 if (!m_enableScriptExpressions)
2761 current->addLocation(FileLocationRegion::ThrowKeywordRegion, statement->throwToken);
2763 if (statement->expression) {
2765 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2766 removeCurrentScriptNode({});
2769 pushScriptElement(current);
2774 return m_enableScriptExpressions;
2779 if (!m_enableScriptExpressions)
2783 current->addLocation(FileLocationRegion::ColonTokenRegion, statement->colonToken);
2786 label->setName(statement->label);
2790 if (statement->statement) {
2792 current->insertChild(Fields::statement, currentScriptNodeEl().takeVariant());
2793 removeCurrentScriptNode({});
2796 pushScriptElement(current);
2801 return m_enableScriptExpressions;
2806 if (!m_enableScriptExpressions)
2810 current->addLocation(FileLocationRegion::BreakKeywordRegion, statement->breakToken);
2812 if (!statement->label.isEmpty()) {
2815 label->setName(statement->label);
2819 pushScriptElement(current);
2824 return m_enableScriptExpressions;
2829 if (!m_enableScriptExpressions)
2833 current->addLocation(OperatorTokenRegion, commaExpression->commaToken);
2835 if (commaExpression->right) {
2837 current->setRight(currentScriptNodeEl().takeVariant());
2838 removeCurrentScriptNode({});
2841 if (commaExpression->left) {
2843 current->setLeft(currentScriptNodeEl().takeVariant());
2844 removeCurrentScriptNode({});
2847 pushScriptElement(current);
2852 return m_enableScriptExpressions;
2857 if (!m_enableScriptExpressions)
2861 current->addLocation(FileLocationRegion::QuestionMarkTokenRegion, expression->questionToken);
2862 current->addLocation(FileLocationRegion::ColonTokenRegion, expression->colonToken);
2864 if (expression->ko) {
2866 current->insertChild(Fields::alternative, currentScriptNodeEl().takeVariant());
2867 removeCurrentScriptNode({});
2870 if (expression->ok) {
2872 current->insertChild(Fields::consequence, currentScriptNodeEl().takeVariant());
2873 removeCurrentScriptNode({});
2876 if (expression->expression) {
2878 current->insertChild(Fields::condition, currentScriptNodeEl().takeVariant());
2879 removeCurrentScriptNode({});
2882 pushScriptElement(current);
2887 return m_enableScriptExpressions;
2892 if (!m_enableScriptExpressions)
2896 current->addLocation(FileLocationRegion::ContinueKeywordRegion, statement->continueToken);
2898 if (!statement->label.isEmpty()) {
2901 label->setName(statement->label);
2905 pushScriptElement(current);
2909
2910
2911
2912
2914QQmlDomAstCreatorBase::makeUnaryExpression(AST::Node *expression, QQmlJS::SourceLocation operatorToken,
2915 bool hasExpression, UnaryExpressionKind kind)
2917 const DomType type = [&kind]() {
2927 auto current = makeGenericScriptElement(expression, type);
2928 current->addLocation(FileLocationRegion::OperatorTokenRegion, operatorToken);
2930 if (hasExpression) {
2935 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
2936 removeCurrentScriptNode({});
2944 return m_enableScriptExpressions;
2949 if (!m_enableScriptExpressions)
2953 makeUnaryExpression(statement, statement->minusToken, statement->expression, Prefix);
2957 pushScriptElement(current);
2962 return m_enableScriptExpressions;
2967 if (!m_enableScriptExpressions)
2971 makeUnaryExpression(statement, statement->plusToken, statement->expression, Prefix);
2975 pushScriptElement(current);
2980 return m_enableScriptExpressions;
2985 if (!m_enableScriptExpressions)
2989 makeUnaryExpression(statement, statement->tildeToken, statement->expression, Prefix);
2993 pushScriptElement(current);
2998 return m_enableScriptExpressions;
3003 if (!m_enableScriptExpressions)
3007 makeUnaryExpression(statement, statement->notToken, statement->expression, Prefix);
3011 pushScriptElement(current);
3016 return m_enableScriptExpressions;
3021 if (!m_enableScriptExpressions)
3025 makeUnaryExpression(statement, statement->typeofToken, statement->expression, Prefix);
3029 pushScriptElement(current);
3034 return m_enableScriptExpressions;
3039 if (!m_enableScriptExpressions)
3043 makeUnaryExpression(statement, statement->deleteToken, statement->expression, Prefix);
3047 pushScriptElement(current);
3052 return m_enableScriptExpressions;
3057 if (!m_enableScriptExpressions)
3061 makeUnaryExpression(statement, statement->voidToken, statement->expression, Prefix);
3065 pushScriptElement(current);
3070 return m_enableScriptExpressions;
3075 if (!m_enableScriptExpressions)
3079 makeUnaryExpression(statement, statement->decrementToken, statement->base, Postfix);
3083 pushScriptElement(current);
3088 return m_enableScriptExpressions;
3093 if (!m_enableScriptExpressions)
3097 makeUnaryExpression(statement, statement->incrementToken, statement->base, Postfix);
3101 pushScriptElement(current);
3106 return m_enableScriptExpressions;
3111 if (!m_enableScriptExpressions)
3114 auto current = makeUnaryExpression(statement, statement->incrementToken, statement->expression,
3119 pushScriptElement(current);
3124 return m_enableScriptExpressions;
3129 if (!m_enableScriptExpressions)
3133 current->addLocation(FileLocationRegion::SemicolonTokenRegion, statement->semicolonToken);
3134 pushScriptElement(current);
3139 return m_enableScriptExpressions;
3144 if (!m_enableScriptExpressions)
3148 current->addLocation(FileLocationRegion::LeftParenthesisRegion, expression->lparenToken);
3149 current->addLocation(FileLocationRegion::RightParenthesisRegion, expression->rparenToken);
3151 if (expression->expression) {
3153 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
3154 removeCurrentScriptNode({});
3157 pushScriptElement(current);
3162 return m_enableScriptExpressions;
3167 if (!m_enableScriptExpressions)
3171 current->addLocation(FileLocationRegion::NewKeywordRegion, expression->newToken);
3173 if (expression->expression) {
3175 current->insertChild(Fields::expression, currentScriptNodeEl().takeVariant());
3176 removeCurrentScriptNode({});
3179 pushScriptElement(current);
3184 return m_enableScriptExpressions;
3189 if (!m_enableScriptExpressions)
3193 current->addLocation(FileLocationRegion::NewKeywordRegion, expression->newToken);
3194 current->addLocation(FileLocationRegion::LeftParenthesisRegion, expression->lparenToken);
3195 current->addLocation(FileLocationRegion::RightParenthesisRegion, expression->rparenToken);
3197 if (expression->arguments) {
3199 current->insertChild(Fields::arguments, scriptNodeStack.takeLast().takeList());
3201 if (expression->base) {
3203 current->insertChild(Fields::base, scriptNodeStack.takeLast().takeVariant());
3206 pushScriptElement(current);
3211 if (!m_enableScriptExpressions)
3216 if (ast->statement) {
3218 current->insertChild(Fields::statement, scriptNodeStack.takeLast().takeVariant());
3220 if (ast->expression) {
3222 current->insertChild(Fields::expression, scriptNodeStack.takeLast().takeVariant());
3225 pushScriptElement(current);
3230 return m_enableScriptExpressions;
3235 if (!m_enableScriptExpressions)
3238 auto current = makeUnaryExpression(statement, statement->decrementToken, statement->expression,
3243 pushScriptElement(current);
3246static const DomEnvironment *environmentFrom(
MutableDomItem &qmlFile)
3248 auto top = qmlFile
.top();
3252 auto domEnvironment = top.as<DomEnvironment>();
3253 if (!domEnvironment) {
3256 return domEnvironment;
3261 if (
auto env = environmentFrom(qmlFile))
3262 return env->qmldirFiles();
3269 QQmlJSLogger *logger,
3270 QQmlJSImporter *importer)
3283 bool QQmlDomAstCreatorWithQQmlJSScope::visit(name *node)
3285 return visitT(node);
3287 void QQmlDomAstCreatorWithQQmlJSScope::endVisit(name *node)
3291QQmlJSASTClassListToVisit
3296 const QQmlJSScope::ConstPtr scope = m_scopeCreator.m_currentScope;
3297 if (!m_domCreator.scriptNodeStack.isEmpty()) {
3298 auto topOfStack = m_domCreator.currentScriptNodeEl();
3299 switch (topOfStack.kind) {
3302 if (scope->scopeType() == QQmlJSScope::ScopeType::QMLScope)
3303 m_domCreator.currentScriptNodeEl().setSemanticScope(scope);
3306 case DomType::ScriptBlockStatement:
3307 case DomType::ScriptForStatement:
3308 case DomType::ScriptForEachStatement:
3309 case DomType::ScriptDoWhileStatement:
3310 case DomType::ScriptWhileStatement:
3312 m_domCreator.currentScriptNodeEl().setSemanticScope(scope);
3317 auto element = m_domCreator.currentScriptNodeEl().value;
3319 if (!scriptElementVariant || !scriptElementVariant->data())
3321 scriptElementVariant->visit([](
auto &&e) {
3322 using U = std::remove_cv_t<std::remove_reference_t<
decltype(e)>>;
3326 if constexpr (std::is_same_v<U,
3327 ScriptElement::PointerType<
3328 ScriptElements::GenericScriptElement>>) {
3329 if (
auto bodyPtr = e->elementChild(Fields::body)) {
3330 const auto bodyScope = bodyPtr.base()->semanticScope();
3331 e->setSemanticScope(bodyScope);
3342 }
else if (!m_domCreator.nodeStack.isEmpty()) {
3344 [&scope](
auto &&e) {
3345 using U = std::remove_cv_t<std::remove_reference_t<
decltype(e)>>;
3347 if constexpr (std::is_same_v<U, QmlObject>) {
3348 e.setSemanticScope(scope);
3349 }
else if constexpr (std::is_same_v<U, QmlComponent>) {
3350 e.setSemanticScope(scope);
3351 }
else if constexpr (std::is_same_v<U, MethodInfo>) {
3353 if (
auto scriptElement = e.body->scriptElement()) {
3354 scriptElement.base()->setSemanticScope(scope);
3357 e.setSemanticScope(scope);
3360 m_domCreator.currentNodeEl().item.value);
3366 const QQmlJSScope::ConstPtr scope = m_scopeCreator.m_currentScope;
3370 if (m_domCreator.nodeStack.size() > 1
3371 && m_domCreator.nodeStack.last().item.kind == DomType::Binding) {
3373 [&scope](
auto &&e) {
3374 using U = std::remove_cv_t<std::remove_reference_t<
decltype(e)>>;
3375 if constexpr (std::is_same_v<U, PropertyDefinition>) {
3381 const bool usePropertyDefinitionScopeInsteadOfTheBindingScope =
3382 QQmlSA::isFunctionScope(scope->scopeType())
3383 && scope->parentScope()
3384 && scope->parentScope()->scopeType() == QQmlSA::ScopeType::QMLScope;
3385 e.setSemanticScope(usePropertyDefinitionScopeInsteadOfTheBindingScope
3386 ? scope->parentScope()
3390 m_domCreator.currentNodeEl(1).item.value);
3392 if (m_domCreator.nodeStack.size() > 0) {
3394 [&scope](
auto &&e) {
3395 using U = std::remove_cv_t<std::remove_reference_t<
decltype(e)>>;
3396 if constexpr (std::is_same_v<U, PropertyDefinition>) {
3397 e.setSemanticScope(scope);
3398 Q_ASSERT(e.semanticScope());
3399 }
else if constexpr (std::is_same_v<U, MethodInfo>) {
3400 if (e.methodType == MethodInfo::Signal) {
3401 e.setSemanticScope(scope);
3405 m_domCreator.currentNodeEl().item.value);
3414 bool QQmlDomAstCreator::visit(AST::name *ast)
3416 return QQmlDomAstCreatorBase::visit(ast) && visitWithCustomListIteration(ast, this);
3424#undef Q_SCRIPTELEMENT_DISABLE
3425#undef Q_SCRIPTELEMENT_EXIT_IF
Binding & operator=(const Binding &)
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
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(const QQmlJSScope::Ptr ¤t, MutableDomItem &qmlFile, QQmlJSLogger *logger, QQmlJSImporter *importer)
Path addId(const Id &id, AddOption option=AddOption::Overwrite, Id **idPtr=nullptr)
void updatePathFromOwner(const Path &newPath) override
static constexpr DomType kindValue
Path addPrototypePath(const Path &prototypePath)
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.
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
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
#define Q_SCRIPTELEMENT_EXIT_IF(check)
#define Q_SCRIPTELEMENT_DISABLE()
#define NewErrorGroup(name)