21#include <QtQml/private/qqmljslexer_p.h>
22#include <QtQml/private/qqmljsparser_p.h>
23#include <QtQml/private/qqmljsengine_p.h>
24#include <QtQml/private/qqmljsastvisitor_p.h>
25#include <QtQml/private/qqmljsast_p.h>
27#include <QtCore/QCborArray>
28#include <QtCore/QCborMap>
29#include <QtCore/QDebug>
31#include <QtCore/QFile>
32#include <QtCore/QFileInfo>
33#include <QtCore/QJsonDocument>
34#include <QtCore/QJsonValue>
35#include <QtCore/QMutexLocker>
36#include <QtCore/QPair>
37#include <QtCore/QRegularExpression>
38#include <QtCore/QScopeGuard>
39#include <QtCore/QtGlobal>
40#include <QtCore/QTimeZone>
52template<
class... TypeList>
53struct CheckDomElementT;
56struct CheckDomElementT<
std::
variant<Ts...>> : std::conjunction<IsInlineDom<Ts>...>
78static_assert(CheckDomElementT<ElementT>::value,
79 "Types in ElementT must either be a pointer to a class inheriting "
80 "from DomBase or (for internal Dom structures) implement a smart "
81 "pointer pointing to a class inheriting from DomBase");
137 static QMap<DomType,QString>
map = [](){
138 QMetaEnum metaEnum = QMetaEnum::fromType<DomType>();
139 QMap<DomType,QString>
res;
140 for (
int i = 0;
i < metaEnum.keyCount(); ++
i) {
159 static QMap<DomKind, QString>
map = []() {
160 QMetaEnum metaEnum = QMetaEnum::fromType<DomKind>();
161 QMap<DomKind, QString>
res;
162 for (
int i = 0;
i < metaEnum.keyCount(); ++
i) {
235 return parent.canonicalFilePath();
242 <<
self.canonicalPath();
249bool ConstantData::iterateDirectSubpaths(
const DomItem &self, DirectVisitor visitor)
const
251 static QHash<QString, QString> knownFields;
255 if (!knownFields.contains(
f))
257 return knownFields[
f];
259 if (m_value.isMap()) {
265 PathEls::PathComponent comp;
267 case ConstantData::Options::MapIsMap:
268 comp = PathEls::Key(
key);
270 case ConstantData::Options::FirstMapIsFields:
271 comp = PathEls::Field(toField(
key));
274 auto val =
it.value();
275 if (!
self.dvValue(visitor, comp,
val))
280 }
else if (m_value.isArray()){
286 if (!
self.dvValue(visitor, PathEls::Index(
i++), *
it++))
300DomKind ConstantData::domKind()
const
302 if (m_value.isMap()) {
304 case ConstantData::Options::MapIsMap:
306 case ConstantData::Options::FirstMapIsFields:
307 return DomKind::Object;
310 if (m_value.isArray())
311 return DomKind::List;
312 return DomKind::Value;
350FileToLoad::FileToLoad(
const std::weak_ptr<DomEnvironment> &environment,
352 const std::optional<InMemoryContents> &content)
353 : m_environment(environment),
355 m_logicalPath(logicalPath),
360FileToLoad FileToLoad::fromMemory(
const std::weak_ptr<DomEnvironment> &environment,
368 InMemoryContents{
code },
372FileToLoad FileToLoad::fromFileSystem(
const std::weak_ptr<DomEnvironment> &environment,
390 static ErrorGroups
res = {{domErrorGroup}};
402 Path
res = visitEl([
this](
auto &&
el) {
return el->canonicalPath(*
this); });
403 if (!(!
res ||
res.headKind() == Path::Kind::Root)) {
404 qCWarning(domLog) <<
"non anchored canonical path:" <<
res.toString();
413 return visitEl([
this](
auto &&
el) {
return el->containingObject(*
this); });
424 if (
DomItem res = filterUp([](DomType k,
const DomItem &) {
return k == DomType::QmlObject; },
427 if (options == GoTo::MostLikely) {
437 DomType k =
res.internalKind();
438 if (k == DomType::List || k == DomType::Map) {
439 res =
res.containingObject();
440 k =
res.internalKind();
442 if (k == DomType::ExternalItemInfo || (options == GoTo::MostLikely && k == DomType::ExternalItemPair))
443 return field(Fields::currentItem);
445 k =
res.internalKind();
446 while (k != DomType::Empty) {
447 if (k == DomType::QmlFile || k == DomType::QmldirFile || k == DomType::QmltypesFile
448 || k == DomType::JsFile)
450 res =
res.containingObject();
452 k =
res.internalKind();
459 return qmlObject(options, FilterUpOptions::ReturnInner);
464 Path
path = pathFromOwner();
467 Source
s =
path.split();
468 if (
s.pathFromSource.length() > 1)
469 return containingObject().path(
s.pathFromSource.dropTail());
470 return containingObject();
475 if (internalKind() == DomType::GlobalScope)
478 if (shared_ptr<DomEnvironment> envPtr = env.ownerAs<DomEnvironment>()) {
479 return env.copy(envPtr->ensureGlobalScopeWithName(env, envPtr->globalScopeName())->current,
493 return std::visit([
this](
auto &&
el) {
494 if constexpr (std::is_same_v<std::decay_t<
decltype(
el)>, std::monostate>)
497 return DomItem(this->m_top,
el, this->m_ownerPath,
el.get());
505 return std::visit([](
auto &&
el) {
506 if constexpr (std::is_same_v<std::decay_t<
decltype(
el)>, std::monostate>)
516 if (
res.internalKind() == DomType::DomEnvironment)
524 if (
res.internalKind() == DomType::DomUniverse)
526 if (
res.internalKind() == DomType::DomEnvironment)
527 return res.field(Fields::universe);
539 if (
DomItem res = filterUp([](DomType k,
const DomItem &) {
return k == DomType::ScriptExpression; },
540 FilterUpOptions::ReturnOuter))
553 if (
DomItem res = filterUp([](DomType k,
const DomItem &) {
return k == DomType::QmlFile; },
554 FilterUpOptions::ReturnOuter))
568 top().field(Fields::qmlFileWithPath).key(
canonicalPath).field(Fields::currentItem);
580 if (
path.length() <
n + 1)
603 if (options == FilterUpOptions::ReturnOuter &&
filter(internalKind(), *
this)) {
608 case FilterUpOptions::ReturnOuter:
609 case FilterUpOptions::ReturnOuterNoSelf: {
611 previous = current, current = current.directParent()) {
612 if (
filter(current.internalKind(), current)) {
613 if (options != FilterUpOptions::ReturnOuterNoSelf || current != *
this)
619 case FilterUpOptions::ReturnInner:
622 current = current.path(currentPath);
623 if (
filter(current.internalKind(), current))
642 scope =
item.semanticScope();
652 using T = std::remove_cv_t<std::remove_reference_t<
decltype(e)>>;
653 if constexpr (std::is_same_v<T, const QmlObject *>) {
654 return e->semanticScope();
655 }
else if constexpr (std::is_same_v<T, const QmlComponent *>) {
656 return e->semanticScope();
657 }
else if constexpr (std::is_same_v<T, const QmltypesComponent *>) {
658 return e->semanticScope();
659 }
else if constexpr (std::is_same_v<T, SimpleObjectWrap>) {
660 if (
const MethodInfo *mi = e->template as<MethodInfo>()) {
661 return mi->semanticScope();
663 if (
const auto *propertyDefinition = e->template as<PropertyDefinition>()) {
664 return propertyDefinition->semanticScope();
666 }
else if constexpr (std::is_same_v<T, ScriptElementDomWrapper>) {
667 return e.element().base()->semanticScope();
677 if (
const Reference *refPtr = as<Reference>())
678 return refPtr->
get(*
this,
h, visitedRefs);
682QList<DomItem>
DomItem::getAll(
const ErrorHandler &
h, QList<Path> *visitedRefs)
const
684 if (
const Reference *refPtr = as<Reference>())
685 return refPtr->getAll(*
this,
h, visitedRefs);
694 switch (
el.internalKind()) {
695 case DomType::Binding:
696 pInfo.bindings.append(el);
698 case DomType::PropertyDefinition:
699 pInfo.propertyDefs.append(el);
724 [](DomType kind,
const DomItem &) {
725 return kind == DomType::QmlComponent || kind == DomType::QmltypesComponent
726 || kind == DomType::GlobalComponent;
728 FilterUpOptions::ReturnInner))
730 if (options == GoTo::MostLikely) {
732 DomType kind =
item.internalKind();
733 if (kind == DomType::List || kind == DomType::Map) {
735 kind =
item.internalKind();
738 case DomType::ExternalItemPair:
739 case DomType::ExternalItemInfo:
740 item = fileObject(options);
742 case DomType::QmlFile:
743 return item.field(Fields::components).key(
QString()).index(0);
756static QMap<LookupType, QString> lookupTypeToStringMap()
758 static QMap<LookupType, QString>
map = []() {
759 QMetaEnum metaEnum = QMetaEnum::fromType<LookupType>();
760 QMap<LookupType, QString>
res;
761 for (
int i = 0;
i < metaEnum.keyCount(); ++
i) {
770 ResolveOptions options,
const Path &fullPath, QList<Path> *visitedRefs)
const
773 Path fPath = fullPath;
774 if (fullPath.length() == 0)
776 if (
path.length()==0)
777 return visitor(fPath, *
this);
778 QList<QSet<quintptr>> visited(
path.length() + 1);
780 QVector<ResolveToDo> toDos(1);
781 if (
path.headKind() == Path::Kind::Root) {
785 case PathRoot::Modules:
786 root = root.environment().field(Fields::moduleIndexWithUri);
789 root = root.environment()[Fields::qmltypesFileWithPath];
792 root = root.environment()[Fields::plugins];
798 root = root.environment();
800 case PathRoot::Universe:
801 root = root.environment()[u
"universe"];
803 case PathRoot::Other:
804 myResolveErrors().error(
tr(
"Root context %1 is not known").
arg(
path.headName())).handle(errorHandler);
807 toDos[0] = {std::move(root), 1};
809 toDos[0] = {*
this, 0};
811 while (!toDos.isEmpty()) {
812 const ResolveToDo toDo = toDos.takeLast();
814 auto idNow = toDo.item.id();
815 if (idNow ==
quintptr(0) && toDo.item == *
this)
820 int iPath = toDo.pathIndex;
822 bool branchExhausted =
false;
823 while (iPath <
path.length() &&
it && !branchExhausted) {
824 auto idNow =
it.id();
825 if (idNow ==
quintptr() && toDo.item == *
this)
829 if (visited[vPair.second].contains(vPair.first))
831 visited[vPair.second].insert(vPair.first);
833 if (options & ResolveOption::TraceVisit && !visitor(
path.mid(0,iPath),
it))
835 auto cNow =
path[iPath++];
836 switch (cNow.headKind()) {
837 case Path::Kind::Key:
838 it =
it.key(cNow.headName());
840 case Path::Kind::Field:
841 if (cNow.checkHeadName(Fields::get) &&
it.internalKind() == DomType::Reference) {
842 Path toResolve =
it.as<
Reference>()->referredObjectPath;
843 Path refRef =
it.canonicalPath();
844 if (visitedRefs ==
nullptr) {
845 visitedRefs = &vRefs;
847 if (visitedRefs->contains(refRef)) {
849 .error([visitedRefs, refRef](
const Sink &
sink) {
852 for (
const Path &vPath : *visitedRefs) {
862 visitedRefs->append(refRef);
866 [&resolveRes](Path,
const DomItem &
r) {
870 errorHandler, ResolveOption::None, toResolve, visitedRefs);
874 it =
it.field(cNow.headName());
877 case Path::Kind::Index:
878 it =
it.index(cNow.headIndex());
880 case Path::Kind::Empty:
885 if (iPath >=
path.length()) {
886 myResolveErrors().warning(
tr(
"Resolve with path ending with empty path, matches nothing."))
887 .handle(errorHandler);
888 branchExhausted =
true;
891 toFind =
path[iPath++];
892 }
while (toFind.headKind() == Path::Kind::Empty);
893 QVector<Path::Kind> validFind({Path::Kind::Key, Path::Kind::Field, Path::Kind::Field, Path::Kind::Index});
894 if (!validFind.contains(toFind.headKind())) {
895 myResolveErrors().error(
tr(
"After an empty path only key, field or indexes are supported, not %1.").
arg(toFind.toString()))
896 .handle(errorHandler);
897 branchExhausted =
true;
900 if (!branchExhausted)
903 [&toFind, &toDos, iPath](Path,
const DomItem &
item,
bool) {
907 toDos.append({ std::move(newItem), iPath });
910 VisitOption::VisitSelf | VisitOption::Recurse
911 | VisitOption::VisitAdopted | VisitOption::NoPath);
912 branchExhausted =
true;
915 case Path::Kind::Root:
916 myResolveErrors().error(
tr(
"Root path is supported only at the beginning, and only once, found %1 at %2 in %3")
917 .
arg(cNow.toString()).arg(iPath -1).arg(
path.toString())).handle(errorHandler);
919 case Path::Kind::Current:
923 case PathCurrent::Other:
925 case PathCurrent::Obj:
926 if (domKind() != DomKind::Object)
927 it =
it.containingObject();
929 case PathCurrent::ObjChain: {
930 bool cont =
it.visitPrototypeChain(
931 [&toDos, iPath](
const DomItem &subEl) {
932 toDos.append({ subEl, iPath });
935 VisitPrototypesOption::Normal, errorHandler,
nullptr,
939 branchExhausted =
true;
942 case PathCurrent::ScopeChain: {
943 bool cont =
it.visitScopeChain(
944 [&toDos, iPath](
const DomItem &subEl) {
945 toDos.append({ subEl, iPath });
948 LookupOption::Normal, errorHandler);
951 branchExhausted =
true;
954 case PathCurrent::Component:
957 case PathCurrent::Module:
958 case PathCurrent::Ids:
959 it =
it.component().ids();
961 case PathCurrent::Types:
962 it =
it.component()[Fields::exports];
964 case PathCurrent::LookupStrict:
965 case PathCurrent::LookupDynamic:
966 case PathCurrent::Lookup: {
967 LookupOptions
opt = LookupOption::Normal;
968 if (current == PathCurrent::Lookup) {
970 DomItem strict = comp.field(u
"~strictLookup~");
973 strict = env.field(u
"defaultStrictLookup");
975 if (strict && strict.value().toBool())
976 opt =
opt | LookupOption::Strict;
977 }
else if (current == PathCurrent::LookupStrict) {
978 opt =
opt | LookupOption::Strict;
980 if (
it.internalKind() == DomType::ScriptExpression) {
982 .error(
tr(
"Javascript lookups not yet implemented"))
983 .handle(errorHandler);
987 auto idNow =
it.id();
988 if (idNow ==
quintptr(0) && toDo.item == *
this)
992 if (visited[vPair.second].contains(vPair.first))
994 visited[vPair.second].insert(vPair.first);
996 if (options & ResolveOption::TraceVisit && !visitor(
path.mid(0, iPath),
it))
998 if (iPath + 1 >=
path.length()) {
1000 .error(
tr(
"Premature end of path, expected a field specifying the "
1001 "type, and a key specifying the name to search after a "
1002 "lookup directive in %2")
1004 .handle(errorHandler);
1007 Path cNow =
path[iPath++];
1008 if (cNow.headKind() != Path::Kind::Field) {
1010 .error(
tr(
"Expected a key path specifying the type to search after "
1011 "a lookup directive, not %1 at component %2 of %3")
1012 .
arg(cNow.toString())
1014 .arg(
path.toString()))
1015 .handle(errorHandler);
1018 QString expectedType = cNow.headName();
1022 auto m = lookupTypeToStringMap();
1027 lookupType =
it.key();
1034 it = lookupTypeToStringMap().
begin();
1036 if (!
types.isEmpty())
1042 .error(
tr(
"Type for lookup was expected to be one of '%1', not "
1045 .handle(errorHandler);
1049 cNow =
path[iPath++];
1050 if (cNow.headKind() != Path::Kind::Key) {
1052 .error(
tr(
"Expected a key specifying the path to search after the "
1053 "@lookup directive and type, not %1 at component %2 of "
1055 .
arg(cNow.toString())
1057 .arg(
path.toString()))
1058 .handle(errorHandler);
1064 .warning(
tr(
"Path with empty lookup at component %1 of %2 will "
1065 "match nothing in %3.")
1068 .arg(
it.canonicalPath().toString()))
1069 .handle(errorHandler);
1074 [&toDos, iPath](
const DomItem &subEl) {
1075 toDos.append({ subEl, iPath });
1078 lookupType,
opt, errorHandler, &(visited[iPath]), visitedRefs);
1079 branchExhausted =
true;
1085 case Path::Kind::Any:
1088 [&toDos, iPath](Path,
const DomItem &
item,
bool) {
1089 toDos.append({
item, iPath });
1092 VisitOption::VisitSelf | VisitOption::Recurse | VisitOption::VisitAdopted);
1093 branchExhausted =
true;
1095 case Path::Kind::Filter:
1096 if (cNow.headFilter() && !cNow.headFilter()(
it))
1097 branchExhausted =
true;
1102 if (!branchExhausted && iPath ==
path.length() && !visitor(fPath,
it))
1122 return path(Path::fromString(
p, errorHandler));
1127 return path(Path::fromString(
p, errorHandler));
1132 return visitEl([
this](
auto &&
el) {
return el->fields(*
this); });
1137 return visitEl([
this,
name](
auto &&
el) {
return el->field(*
this,
name); });
1142 return visitEl([
this](
auto &&
el) {
return el->indexes(*
this); });
1147 return visitEl([
this,
i](
auto &&
el) {
return el->index(*
this,
i); });
1153 int nIndexes = indexes();
1154 for (
int i = 0;
i < nIndexes; ++
i) {
1164 return visitEl([
this](
auto &&
el) {
return el->keys(*
this); });
1169 QSet<QString> ks =
keys();
1171 std::sort(sortedKs.begin(), sortedKs.end());
1177 return visitEl([
this,
name](
auto &&
el) {
return el->key(*
this,
name); });
1195 visitEl([
this, &
res](
const auto &
el) {
1196 return el->iterateDirectSubpathsConst(
1197 *
this, [&
res](
const PathEls::PathComponent &, function_ref<
DomItem()>
item) {
1207 if (hasAnnotations()) {
1208 DomItem anns = field(Fields::annotations);
1209 for (
const auto &ann : anns.
values()) {
1210 if (ann.annotations().indexes() == 0) {
1215 DomItem annAnn = ann.annotations();
1216 Q_ASSERT_X(annAnn.indexes() == 1 && annAnn.index(0).name() == u
"duplicate",
1217 "DomItem::writeOutPre",
"Unexpected annotation of annotation");
1221 ow.itemStart(*
this);
1227 visitEl([
this, &ow](
auto &&
el) {
el->writeOut(*
this, ow); });
1236DomItem::WriteOutCheckResult DomItem::performWriteOutChecks(
const DomItem &original,
const DomItem &reformatted,
1238 WriteOutChecks extraChecks)
const
1243 if (extraChecks & WriteOutCheck::DumpOnFailure) {
1248 obj.dump(objDumpPath);
1249 dumped.
append(objDumpPath);
1253 auto dumpedDumper = [&dumped](
const Sink &
s) {
1254 if (dumped.isEmpty())
1257 for (
const auto &dumpPath : dumped) {
1266 if (!diffList.isEmpty()) {
1267 maybeDump(obj1, obj1Name);
1268 maybeDump(obj2, obj2Name);
1269 qCWarning(writeOutLog).noquote().nospace()
1270 << obj2Name <<
" writeOut of " << this->canonicalFilePath() <<
" has changes:\n"
1271 << diffList.join(
QString()) << dumpedDumper;
1276 auto checkStability = [&maybeDump, &dumpedDumper, &dumped, &ow,
1278 LineWriter lw2([](
QStringView) {}, ow.lineWriter.fileName(), ow.lineWriter.options());
1280 ow2.indentNextlines =
true;
1284 DomItem fObj = this->fileObject();
1285 maybeDump(fObj, u
"initial");
1286 maybeDump(
obj, objName);
1287 qCWarning(writeOutLog).noquote().nospace()
1288 << objName <<
" non stable writeOut of " << this->canonicalFilePath() <<
":"
1296 if ((extraChecks & WriteOutCheck::UpdatedDomCompare)
1297 && !
compare(original, u
"initial", reformatted, u
"reformatted",
1298 FieldFilter::noLocationFilter()))
1299 return WriteOutCheckResult::Failed;
1301 if (extraChecks & WriteOutCheck::UpdatedDomStable) {
1302 checkStability(ow.writtenStr, reformatted, u
"reformatted");
1306 & (WriteOutCheck::Reparse | WriteOutCheck::ReparseCompare | WriteOutCheck::ReparseStable)) {
1307 DomItem newEnv = environment().makeCopy().item();
1308 std::shared_ptr<DomEnvironment> newEnvPtr = newEnv.ownerAs<
DomEnvironment>();
1310 return WriteOutCheckResult::Failed;
1312 auto newFilePtr = std::make_shared<QmlFile>(canonicalFilePath(), ow.writtenStr);
1314 return WriteOutCheckResult::Failed;
1315 newEnvPtr->addQmlFile(newFilePtr, AddOption::Overwrite);
1317 DomItem newFile = newEnv.copy(newFilePtr, Path());
1318 if (newFilePtr->isValid()) {
1319 if (extraChecks & (WriteOutCheck::ReparseCompare | WriteOutCheck::ReparseStable)) {
1320 newEnvPtr->populateFromQmlFile(newFile);
1321 if ((extraChecks & WriteOutCheck::ReparseCompare)
1322 && !
compare(reformatted, u
"reformatted", newFile, u
"reparsed",
1323 FieldFilter::compareNoCommentsFilter()))
1324 return WriteOutCheckResult::Failed;
1325 if ((extraChecks & WriteOutCheck::ReparseStable))
1326 checkStability(ow.writtenStr, newFile, u
"reparsed");
1329 const auto iterateErrors = [&newFile](
const Sink &
s) {
1330 newFile.iterateErrors(
1339 qCWarning(writeOutLog).noquote().nospace()
1340 <<
"writeOut of " << canonicalFilePath()
1341 <<
" created invalid code:\n----------\n"
1342 << ow.writtenStr <<
"\n----------" << iterateErrors;
1343 return WriteOutCheckResult::Failed;
1346 return WriteOutCheckResult::Success;
1361 ow.indentNextlines =
true;
1365 auto currentFileItem = fileObject();
1366 auto writtenFileItem = ow.restoreWrittenFileItem(currentFileItem);
1367 WriteOutCheckResult
result = WriteOutCheckResult::Success;
1368 if (extraChecks & WriteOutCheck::All)
1369 result = performWriteOutChecks(currentFileItem, writtenFileItem, ow, extraChecks);
1370 return result == WriteOutCheckResult::Success ? bool(writtenFileItem) :
false;
1374 FileWriter *fw, WriteOutChecks extraChecks)
const
1379 auto status = fw->write(
1384 return writeOutForFile(ow, extraChecks);
1388 case FileWriter::Status::DidWrite:
1389 case FileWriter::Status::SkippedEqual:
1391 case FileWriter::Status::ShouldWrite:
1392 case FileWriter::Status::SkippedDueToFailure:
1396 qCWarning(writeOutLog) <<
"Unknown FileWriter::Status ";
1404 bool isChild =
false;
1405 if (
item.isOwningItem()) {
1410 isChild = itemOw == selfOw &&
item.pathFromOwner().dropTail() == pathFromOwner();
1417 bool hasAnnotations =
false;
1418 DomType iKind = internalKind();
1421 if (
const Id *myPtr = as<Id>())
1422 hasAnnotations = !myPtr->annotations.isEmpty();
1424 case DomType::PropertyDefinition:
1425 if (
const PropertyDefinition *myPtr = as<PropertyDefinition>())
1426 hasAnnotations = !myPtr->annotations.isEmpty();
1428 case DomType::MethodInfo:
1429 if (
const MethodInfo *myPtr = as<MethodInfo>())
1430 hasAnnotations = !myPtr->annotations.isEmpty();
1432 case DomType::QmlObject:
1433 if (
const QmlObject *myPtr = as<QmlObject>())
1434 hasAnnotations = !myPtr->annotations().isEmpty();
1436 case DomType::Binding:
1437 if (
const Binding *myPtr = as<Binding>())
1438 hasAnnotations = !myPtr->annotations().isEmpty();
1443 return hasAnnotations;
1474 if (options & VisitOption::VisitSelf && !visitor(basePath, *
this,
true))
1476 if (options & VisitOption::VisitSelf && !openingVisitor(basePath, *
this,
true))
1478 auto atEnd =
qScopeGuard([closingVisitor, basePath,
this, options]() {
1479 if (options & VisitOption::VisitSelf) {
1480 closingVisitor(basePath, *
this,
true);
1483 return visitEl([
this, basePath, visitor, openingVisitor, closingVisitor, options,
1485 return el->iterateDirectSubpathsConst(
1487 [
this, basePath, visitor, openingVisitor, closingVisitor, options,
1488 &
filter](
const PathEls::PathComponent &
c, function_ref<
DomItem()> itemF) {
1490 if (!(options & VisitOption::NoPath)) {
1492 pNow = pNow.appendComponent(
c);
1497 bool directChild = isCanonicalChild(
item);
1498 if (!directChild && !(options & VisitOption::VisitAdopted))
1500 if (!directChild || !(options & VisitOption::Recurse)) {
1501 if (!visitor(pNow,
item, directChild))
1506 if (!openingVisitor(pNow,
item, directChild))
1508 closingVisitor(pNow,
item, directChild);
1510 return item.visitTree(pNow, visitor, options | VisitOption::VisitSelf,
1511 openingVisitor, closingVisitor,
filter);
1517static bool visitPrototypeIndex(QList<DomItem> &toDo,
const DomItem ¤t,
1518 const DomItem &derivedFromPrototype,
const ErrorHandler &
h,
1519 QList<Path> *visitedRefs, VisitPrototypesOptions options,
1522 Path elId = prototype.canonicalPath();
1523 if (visitedRefs->contains(elId))
1526 visitedRefs->append(elId);
1527 QList<DomItem>
protos = prototype.getAll(
h, visitedRefs);
1529 if (std::shared_ptr<DomEnvironment> envPtr =
1530 derivedFromPrototype.environment().ownerAs<DomEnvironment>())
1531 if (!(envPtr->options() & DomEnvironment::Option::NoDependencies))
1532 derivedFromPrototype.myErrors()
1533 .warning(derivedFromPrototype.tr(
"could not resolve prototype %1 (%2)")
1534 .arg(current.canonicalPath().toString(),
1535 prototype.field(Fields::referredObjectPath)
1538 .withItem(derivedFromPrototype)
1545 derivedFromPrototype.myErrors()
1546 .warning(derivedFromPrototype
1547 .
tr(
"Multiple definitions found, using first only, resolving "
1548 "prototype %1 (%2): %3")
1549 .
arg(current.canonicalPath().toString(),
1550 prototype.field(Fields::referredObjectPath)
1554 .withItem(derivedFromPrototype)
1559 for (
int i = nProtos;
i != 0;) {
1561 if (proto.internalKind() == DomType::Export) {
1562 if (!(options & VisitPrototypesOption::ManualProceedToScope))
1563 proto = proto.proceedToScope(
h, visitedRefs);
1565 }
else if (proto.internalKind() == DomType::QmlObject
1566 || proto.internalKind() == DomType::QmlComponent) {
1569 derivedFromPrototype.myErrors()
1570 .warning(derivedFromPrototype.tr(
"Unexpected prototype type %1 (%2)")
1571 .arg(current.canonicalPath().toString(),
1572 prototype.field(Fields::referredObjectPath)
1575 .withItem(derivedFromPrototype)
1584 VisitPrototypesOptions options,
const ErrorHandler &
h,
1585 QSet<quintptr> *visited, QList<Path> *visitedRefs)
const
1587 QSet<quintptr> visitedLocal;
1589 visited = &visitedLocal;
1590 QList<Path> refsLocal;
1592 visitedRefs = &refsLocal;
1593 bool shouldVisit = !(options & VisitPrototypesOption::SkipFirst);
1594 DomItem current = qmlObject();
1596 myErrors().warning(
tr(
"Prototype chain called outside object")).withItem(*this).handle(
h);
1599 QList<DomItem> toDo({ current });
1600 while (!toDo.isEmpty()) {
1601 current = toDo.takeLast();
1602 current = current.proceedToScope(
h, visitedRefs);
1603 if (visited->contains(current.id())) {
1607 if (options & VisitPrototypesOption::RevisitWarn)
1609 .warning(
tr(
"Detected multiple visit of %1 visiting prototypes of %2")
1610 .
arg(current.canonicalPath().toString(),
1616 visited->insert(current.id());
1617 if (shouldVisit && !visitor(current))
1620 current.field(Fields::prototypes)
1621 .visitIndexes([&toDo, ¤t,
this, &
h, visitedRefs, options](
const DomItem &
el) {
1622 return visitPrototypeIndex(toDo, current, *
this,
h, visitedRefs, options,
el);
1629 function_ref<
bool(
const DomItem &)> visitor, VisitPrototypesOptions options,
1630 const ErrorHandler &
h, QSet<quintptr> *visited, QList<Path> *visitedRefs)
const
1634 DomType k = internalKind();
1635 if (k == DomType::QmlObject)
1636 return visitPrototypeChain(visitor, options,
h, visited, visitedRefs);
1637 if (visited &&
id() != 0) {
1638 if (visited->contains(
id()))
1640 visited->insert(
id());
1642 if (k == DomType::Id || k == DomType::Reference || k == DomType::Export) {
1644 DomItem v = proceedToScope(
h, visitedRefs);
1645 if (
v.internalKind() == DomType::QmlObject)
1646 return v.visitPrototypeChain(visitor, options,
h, visited, visitedRefs);
1648 if (k == DomType::Binding) {
1651 if (
v.internalKind() == DomType::QmlObject)
1652 return v.visitPrototypeChain(visitor, options,
h, visited, visitedRefs);
1654 if (k == DomType::PropertyDefinition) {
1656 DomItem t = field(Fields::type).proceedToScope(
h, visitedRefs);
1657 if (
t.internalKind() == DomType::QmlObject)
1658 return t.visitPrototypeChain(visitor, options,
h, visited, visitedRefs);
1660 if (!(options & VisitPrototypesOption::SkipFirst) && isScope() && !visitor(*
this))
1676 function_ref<
bool(
const DomItem &)> visitor, VisitPrototypesOptions options,
1677 const ErrorHandler &
h, QSet<quintptr> *visited, QList<Path> *visitedRefs)
const
1679 QSet<quintptr> visitedLocal;
1681 visited = &visitedLocal;
1682 DomItem current = qmlObject();
1683 DomItem comp = current.component();
1684 if (comp.field(Fields::isSingleton).value().toBool(
false)
1685 && !current.visitPrototypeChain(visitor, options,
h, visited, visitedRefs))
1687 if (
DomItem attachedT = current.component().field(Fields::attachedType).field(Fields::get))
1688 if (!attachedT.visitPrototypeChain(
1689 visitor, options & ~VisitPrototypesOptions(VisitPrototypesOption::SkipFirst),
h,
1690 visited, visitedRefs))
1701 while (
p.length() > 0) {
1703 if (!visitor(current))
1714 function_ref<
bool(
const DomItem &)> visitor, LookupOptions options,
const ErrorHandler &
h,
1715 QSet<quintptr> *visited, QList<Path> *visitedRefs)
const
1717 QSet<quintptr> visitedLocal;
1719 visited = &visitedLocal;
1720 QList<Path> visitedRefsLocal;
1722 visitedRefs = &visitedRefsLocal;
1725 myResolveErrors().warning(
tr(
"Called visitScopeChain outside scopes")).handle(
h);
1728 QList<DomItem> toDo { current };
1729 bool visitFirst = !(options & LookupOption::SkipFirstScope);
1730 bool visitCurrent = visitFirst;
1732 QSet<quintptr> alreadyAddedComponentMaps;
1733 while (!toDo.isEmpty()) {
1734 DomItem current = toDo.takeLast();
1735 if (visited->contains(current.id()))
1737 visited->insert(current.id());
1738 if (visitCurrent && !visitor(current))
1740 visitCurrent =
true;
1741 switch (current.internalKind()) {
1742 case DomType::QmlObject: {
1743 if (!current.visitPrototypeChain(visitor, VisitPrototypesOption::SkipFirst,
h, visited,
1746 DomItem root = current.rootQmlObject();
1747 if (root && root != current) {
1751 FilterUpOptions::ReturnOuterNoSelf)) {
1755 case DomType::ScriptExpression:
1757 if (
DomItem next = current.scope(FilterUpOptions::ReturnOuterNoSelf))
1760 case DomType::QmlComponent: {
1761 if ((options & LookupOption::Strict) == 0) {
1762 if (
DomItem comp = current.field(Fields::nextComponent))
1765 if (
first && visitFirst && (options & LookupOption::VisitTopClassType)
1766 && *
this == current) {
1767 if (
DomItem attachedT = current.field(Fields::attachedType).field(Fields::get))
1768 toDo.append(attachedT);
1770 if (
DomItem next = current.scope(FilterUpOptions::ReturnOuterNoSelf))
1773 DomItem owner = current.owner();
1774 Path pathToComponentMap = current.pathFromOwner().dropTail(2);
1775 DomItem componentMap = owner.path(pathToComponentMap);
1776 if (alreadyAddedComponentMaps.contains(componentMap.id()))
1778 alreadyAddedComponentMaps.insert(componentMap.id());
1779 const auto keys = componentMap.keys();
1781 DomItem componentList = componentMap.key(
x);
1782 for (
int i = 0;
i < componentList.indexes(); ++
i) {
1791 case DomType::QmlFile:
1793 current.field(Fields::importScope))
1794 toDo.append(iScope);
1797 case DomType::MethodInfo:
1799 if (
DomItem next = current.scope(FilterUpOptions::ReturnOuterNoSelf))
1802 case DomType::ImportScope:
1804 if (
auto globalC = globalScope().field(Fields::rootComponent))
1805 toDo.append(globalC);
1807 case DomType::JsResource:
1808 case DomType::GlobalComponent:
1810 if (
DomItem next = current.field(Fields::objects).index(0))
1813 case DomType::QmltypesComponent:
1819 .error(
tr(
"Unexpected non scope object %1 (%2) reached in visitScopeChain")
1821 current.canonicalPath().toString()))
1831 const QString &symbolName, function_ref<
bool(
const DomItem &)> visitor, LookupOptions opts,
1832 const ErrorHandler &
h, QSet<quintptr> *visited, QList<Path> *visitedRefs)
const
1834 return visitScopeChain(
1836 return obj.visitLocalSymbolsNamed(symbolName,
1837 [visitor](
const DomItem &
el) {
return visitor(
el); });
1839 opts,
h, visited, visitedRefs);
1846 CppTypeInfo() =
default;
1852 uR
"(QList<(?<list>[a-zA-Z_0-9:]+) *(?<listPtr>\*?)>|QMap< *(?<mapKey>[a-zA-Z_0-9:]+) *, *(?<mapValue>[a-zA-Z_0-9:]+) *(?<mapPtr>\*?)>|(?<baseType>[a-zA-Z_0-9:]+) *(?<ptr>\*?))"));
1855 if (!
m.hasMatch()) {
1857 .error(
tr(
"Unexpected complex CppType %1").
arg(
target))
1860 res.baseType =
m.captured(u
"baseType");
1861 res.isPointer = !
m.captured(u
"ptr").isEmpty();
1862 if (!
m.captured(u
"list").isEmpty()) {
1864 res.baseType =
m.captured(u
"list");
1865 res.isPointer = !
m.captured(u
"listPtr").isEmpty();
1867 if (!
m.captured(u
"mapValue").isEmpty()) {
1869 if (
m.captured(u
"mapKey") != u
"QString") {
1871 .error(
tr(
"Unexpected complex CppType %1 (map with non QString key)")
1875 res.baseType =
m.captured(u
"mapValue");
1876 res.isPointer = !
m.captured(u
"mapPtr").isEmpty();
1882 bool isPointer =
false;
1884 bool isList =
false;
1887static bool visitForLookupType(
const DomItem &
el, LookupType lookupType,
1888 function_ref<
bool(
const DomItem &)> visitor)
1890 bool correctType =
false;
1891 DomType iType =
el.internalKind();
1892 switch (lookupType) {
1893 case LookupType::Binding:
1894 correctType = (iType == DomType::Binding);
1896 case LookupType::Method:
1897 correctType = (iType == DomType::MethodInfo);
1899 case LookupType::Property:
1900 correctType = (iType == DomType::PropertyDefinition || iType == DomType::Binding);
1902 case LookupType::PropertyDef:
1903 correctType = (iType == DomType::PropertyDefinition);
1905 case LookupType::Type:
1906 correctType = (iType == DomType::Export);
1917static bool visitQualifiedNameLookup(
1919 function_ref<
bool(
const DomItem &)> visitor, LookupType lookupType,
1920 const ErrorHandler &errorHandler, QList<Path> *visitedRefs)
1922 QVector<ResolveToDo> lookupToDos(
1923 { ResolveToDo{ newIt, 1 } });
1925 QList<QSet<quintptr>> lookupVisited(subpath.size() + 1);
1926 while (!lookupToDos.isEmpty()) {
1927 ResolveToDo tNow = lookupToDos.takeFirst();
1928 auto vNow =
qMakePair(tNow.item.id(), tNow.pathIndex);
1930 int iSubPath = tNow.pathIndex;
1931 Q_ASSERT(iSubPath < subpath.size());
1932 QString subPathNow = subpath[iSubPath++];
1933 DomItem scope = subNow.proceedToScope();
1934 if (iSubPath < subpath.size()) {
1935 if (vNow.first != 0) {
1936 if (lookupVisited[vNow.second].contains(vNow.first))
1939 lookupVisited[vNow.second].insert(vNow.first);
1941 if (scope.internalKind() == DomType::QmlObject)
1942 scope.visitDirectAccessibleScopes(
1943 [&lookupToDos, &subPathNow, iSubPath](
const DomItem &
el) {
1944 return el.visitLocalSymbolsNamed(
1945 subPathNow, [&lookupToDos, iSubPath](
const DomItem &subEl) {
1946 lookupToDos.append({ subEl, iSubPath });
1950 VisitPrototypesOption::Normal, errorHandler, &(lookupVisited[vNow.second]),
1953 bool cont = scope.visitDirectAccessibleScopes(
1954 [&visitor, &subPathNow, lookupType](
const DomItem &
el) ->
bool {
1955 if (lookupType == LookupType::Symbol)
1956 return el.visitLocalSymbolsNamed(subPathNow, visitor);
1958 return el.visitLocalSymbolsNamed(
1959 subPathNow, [lookupType, &visitor](
const DomItem &
el) ->
bool {
1960 return visitForLookupType(
el, lookupType, visitor);
1963 VisitPrototypesOption::Normal, errorHandler, &(lookupVisited[vNow.second]),
1974 LookupOptions opts,
const ErrorHandler &errorHandler, QSet<quintptr> *visited,
1975 QList<Path> *visitedRefs)
const
1979 switch (lookupType) {
1980 case LookupType::Binding:
1981 case LookupType::Method:
1982 case LookupType::Property:
1983 case LookupType::PropertyDef:
1984 case LookupType::Symbol:
1985 case LookupType::Type: {
1987 if (subpath.size() == 1) {
1988 return visitLookup1(subpath.first(), visitor, opts, errorHandler, visited, visitedRefs);
1990 return visitLookup1(
1992 [&subpath, visitor, lookupType, &errorHandler,
1993 visitedRefs](
const DomItem &newIt) ->
bool {
1994 return visitQualifiedNameLookup(newIt, subpath, visitor, lookupType,
1995 errorHandler, visitedRefs);
1997 opts, errorHandler, visited, visitedRefs);
2001 case LookupType::CppType: {
2002 QString baseTarget = CppTypeInfo::fromString(
target, errorHandler).baseType;
2003 DomItem localQmltypes = owner();
2004 while (localQmltypes && localQmltypes.internalKind() != DomType::QmltypesFile) {
2005 localQmltypes = localQmltypes.containingObject();
2006 localQmltypes = localQmltypes.owner();
2008 if (localQmltypes) {
2009 if (
DomItem localTypes = localQmltypes.field(Fields::components).key(baseTarget)) {
2010 bool cont = localTypes.visitIndexes([&visitor](
const DomItem &els) {
2011 return els.visitIndexes([&visitor](
const DomItem &
el) {
2013 return visitor(
obj);
2021 DomItem qmltypes = environment().field(Fields::qmltypesFileWithPath);
2022 return qmltypes.visitKeys([baseTarget, &visitor](
const QString &,
const DomItem &els) {
2024 els.field(Fields::currentItem).field(Fields::components).
key(baseTarget);
2025 return comps.visitIndexes([&visitor](
const DomItem &
el) {
2027 return visitor(
obj);
2051 switch (current.internalKind()) {
2052 case DomType::Reference: {
2053 Path currentPath = current.canonicalPath();
2054 current = current.get(
h, visitedRefs);
2057 case DomType::Export:
2058 current = current.field(Fields::type);
2061 current = current.field(Fields::referredObject);
2064 return current.scope();
2072 const ErrorHandler &errorHandler)
const
2081 type, opts, errorHandler);
2086 const ErrorHandler &errorHandler)
const
2095 type, opts, errorHandler);
2101 return visitEl([](
auto &&
b) {
return b->id(); });
2106 return visitEl([
this](
auto &&e) {
return e->pathFromOwner(*
this); });
2111 return visitEl([
this](
auto &&e) {
return e->canonicalFilePath(*
this); });
2116 if (
DomItem l = field(Fields::fileLocationsTree))
2118 auto res = FileLocations::findAttachedInfo(*
this);
2119 if (
res &&
res.foundTreePath) {
2120 return copy(
res.foundTree,
res.foundTreePath);
2127 return fileLocationsTree().
field(Fields::infoItem);
2132 if (m_kind == DomType::Empty)
2133 return MutableDomItem();
2135 if (
option == CopyOption::EnvDisconnected) {
2136 DomItem newItem = std::visit([
this, &
o](
auto &&
el) {
2137 if constexpr (std::is_same_v<std::decay_t<
decltype(
el)>, std::monostate>) {
2140 auto copyPtr =
el->makeCopy(
o);
2141 return DomItem(m_top, copyPtr, m_ownerPath, copyPtr.get());
2144 return MutableDomItem(newItem.path(pathFromOwner()));
2147 std::shared_ptr<DomEnvironment> newEnvPtr;
2148 if (std::shared_ptr<DomEnvironment> envPtr = env.ownerAs<DomEnvironment>()) {
2149 newEnvPtr = std::make_shared<DomEnvironment>(envPtr, envPtr->loadPaths(), envPtr->options(),
2150 envPtr->domCreationOptions());
2151 DomBase *eBase = envPtr.get();
2152 if (std::holds_alternative<const DomEnvironment *>(m_element) && eBase
2153 && std::get<const DomEnvironment *>(m_element) == eBase)
2154 return MutableDomItem(
DomItem(newEnvPtr));
2155 }
else if (std::shared_ptr<DomUniverse> univPtr =
top().ownerAs<DomUniverse>()) {
2156 newEnvPtr = std::make_shared<DomEnvironment>(
2158 DomEnvironment::Option::SingleThreaded | DomEnvironment::Option::NoDependencies,
2159 DomCreationOption::None, univPtr);
2165 [
this, newEnvPtr, &
o](
auto &&
el) {
2166 if constexpr (std::is_same_v<std::decay_t<
decltype(
el)>, std::monostate>) {
2169 auto copyPtr =
el->makeCopy(
o);
2170 return DomItem(newEnvPtr, copyPtr, m_ownerPath, copyPtr.get());
2175 switch (
o.internalKind()) {
2176 case DomType::QmlDirectory:
2177 newEnvPtr->addQmlDirectory(newItem.ownerAs<QmlDirectory>(), AddOption::Overwrite);
2179 case DomType::JsFile:
2180 newEnvPtr->addJsFile(newItem.ownerAs<JsFile>(), AddOption::Overwrite);
2182 case DomType::QmlFile:
2183 newEnvPtr->addQmlFile(newItem.ownerAs<QmlFile>(), AddOption::Overwrite);
2185 case DomType::QmltypesFile:
2186 newEnvPtr->addQmltypesFile(newItem.ownerAs<QmltypesFile>(), AddOption::Overwrite);
2188 case DomType::GlobalScope: {
2189 newEnvPtr->addGlobalScope(newItem.ownerAs<GlobalScope>(), AddOption::Overwrite);
2191 case DomType::ModuleIndex:
2192 case DomType::MockOwner:
2193 case DomType::ScriptExpression:
2194 case DomType::AstComments:
2195 case DomType::LoadInfo:
2196 case DomType::AttachedInfo:
2197 case DomType::DomEnvironment:
2198 case DomType::DomUniverse:
2199 qCWarning(domLog) <<
"DomItem::makeCopy " << internalKindStr()
2200 <<
" does not support binding to environment";
2202 return MutableDomItem();
2204 qCWarning(domLog) <<
"DomItem::makeCopy(" << internalKindStr()
2205 <<
") is not an known OwningItem";
2207 return MutableDomItem();
2210 Q_ASSERT(newEnv.path(
o.canonicalPath()).m_owner == newItem.m_owner);
2211 return MutableDomItem(newItem.path(pathFromOwner()));
2217 if (std::shared_ptr<DomEnvironment> envPtr = env.ownerAs<DomEnvironment>()) {
2218 return envPtr->commitToBase(env, validEnvPtr);
2232 switch (internalKind()) {
2233 case DomType::QmlObject:
2234 f = field(Fields::propertyDefs);
2236 if (!
v.visitIndexes(visitor))
2238 f = field(Fields::bindings);
2240 if (!
v.visitIndexes(visitor))
2242 f = field(Fields::methods);
2244 if (!
v.visitIndexes(visitor))
2247 case DomType::ScriptExpression:
2250 case DomType::QmlComponent:
2251 f = field(Fields::ids);
2253 if (!
v.visitIndexes(visitor))
2256 case DomType::JsResource:
2257 case DomType::GlobalComponent:
2258 case DomType::QmltypesComponent:
2259 f = field(Fields::enumerations);
2261 if (!
v.visitIndexes(visitor))
2264 case DomType::MethodInfo: {
2267 const MethodParameter *pPtr = p.as<MethodParameter>();
2268 if (pPtr->name == name && !visitor(p))
2275 case DomType::QmlFile: {
2276 f = field(Fields::components);
2278 if (!
v.visitIndexes(visitor))
2282 case DomType::ImportScope: {
2283 f = field(Fields::imported);
2285 if (!
v.visitIndexes(visitor))
2287 f = field(Fields::qualifiedImports);
2289 if (
v && !visitor(
v))
2302 if (internalKind() == DomType::Map)
2304 return field(cName);
2309 if (internalKind() == DomType::Map)
2310 return key(cName.toString());
2311 return field(cName);
2321 return base()->value();
2326 sink(u
"DomItem{ topPtr:");
2328 sink(u
", ownerPtr:");
2330 sink(u
", ownerPath:");
2331 m_ownerPath.dump(
sink);
2338 const Sink &
s,
int indent,
2339 function_ref<
bool(
const DomItem &,
const PathEls::PathComponent &,
const DomItem &)>
filter)
const
2341 visitEl([
this,
s, indent,
filter](
auto &&e) { e->dump(*
this,
s, indent,
filter); });
2347 int nBackups,
int indent, FileWriter *fw)
const
2355 this->dump([&ts](QStringView s) { ts << s; }, indent,
filter);
2359 case FileWriter::Status::ShouldWrite:
2360 case FileWriter::Status::SkippedDueToFailure:
2363 case FileWriter::Status::DidWrite:
2364 case FileWriter::Status::SkippedEqual:
2377 return std::visit([](
auto &&ow) {
2378 if constexpr (std::is_same_v<std::decay_t<
decltype(ow)>, std::monostate>)
2381 return ow->derivedFrom();
2387 return std::visit([](
auto &&ow) {
2388 if constexpr (std::is_same_v<std::decay_t<
decltype(ow)>, std::monostate>)
2391 return ow->revision();
2397 return std::visit([](
auto &&ow) {
2398 if constexpr (std::is_same_v<std::decay_t<
decltype(ow)>, std::monostate>)
2401 return ow->createdAt();
2407 return std::visit([](
auto &&ow) {
2408 if constexpr (std::is_same_v<std::decay_t<
decltype(ow)>, std::monostate>)
2411 return ow->frozenAt();
2417 return std::visit([](
auto &&ow) {
2418 if constexpr (std::is_same_v<std::decay_t<
decltype(ow)>, std::monostate>)
2421 return ow->lastDataUpdateAt();
2427 std::visit([
this, &msg](
auto &&ow) {
2428 if constexpr (std::is_same_v<std::decay_t<
decltype(ow)>, std::monostate>)
2431 ow->addError(owner(), std::move(msg.withItem(*
this)));
2443 std::visit([&
groups](
auto &&ow) {
2444 if constexpr (!std::is_same_v<std::decay_t<
decltype(ow)>, std::monostate>)
2460 if (!std::visit([
this, visitor, inPath](
auto &&
el) {
2461 if constexpr (std::is_same_v<std::decay_t<
decltype(
el)>, std::monostate>)
2464 return el->iterateErrors(owner(), visitor, inPath);
2469 if (iterate && !iterateSubOwners([inPath, visitor](
const DomItem &
i) {
2470 return i.iterateErrors(visitor,
true, inPath);
2480 return std::visit([
this, visitor](
auto &&
o) {
2481 if constexpr (std::is_same_v<std::decay_t<
decltype(
o)>, std::monostate>)
2484 return o->iterateSubOwners(owner(), visitor);
2491 [
this,
v](
auto &&
el) {
return el->iterateDirectSubpaths(*
this,
v); });
2497 List::fromQList<Path>(pathFromOwner().appendComponent(
c),
paths,
2498 [](
const DomItem &
list,
const PathEls::PathComponent &
p,
const Path &
el) {
2499 return list.subReferenceItem(
p,
el);
2506 return DomItem(m_top, m_owner, m_ownerPath,
Reference(referencedObject, Path(
c)));
2508 return DomItem(m_top, m_owner, m_ownerPath,
2509 Reference(referencedObject, pathFromOwner().appendComponent(
c)));
2515 return std::visit([](
auto &&
el) -> shared_ptr<DomTop> {
2516 if constexpr (std::is_same_v<std::decay_t<
decltype(
el)>, std::monostate>)
2525 return std::visit([](
auto &&
el) -> shared_ptr<OwningItem> {
2526 if constexpr (std::is_same_v<std::decay_t<
decltype(
el)>, std::monostate>)
2537const DomBase *DomItem::base()
const
2539 return visitEl([](
auto &&
el) ->
const DomBase * {
return el->domBase(); });
2543 DomItem(envPtr, envPtr, Path(), envPtr.
get())
2548 DomItem(universePtr, universePtr, Path(), universePtr.
get())
2572 FileToLoad::fromMemory(env,
QString(), code),
2573 [&tFile](Path,
const DomItem &,
const DomItem &newIt) { tFile = newIt; },
2575 env->loadPendingDependencies();
2576 return tFile.fileObject();
2582Path Empty::pathFromOwner(
const DomItem &)
const
2587Path Empty::canonicalPath(
const DomItem &)
const
2592bool Empty::iterateDirectSubpaths(
const DomItem &, DirectVisitor)
const
2603 const DomItem &,
const Sink &
s,
int,
2604 function_ref<
bool(
const DomItem &,
const PathEls::PathComponent &,
const DomItem &)>)
const
2609Map::Map(
const Path &pathFromOwner,
const Map::LookupFunction &lookup,
2611 : DomElement(pathFromOwner), m_lookup(lookup), m_keys(
keys), m_targetType(targetType)
2619bool Map::iterateDirectSubpaths(
const DomItem &self, DirectVisitor visitor)
const
2623 std::sort(ksList.begin(), ksList.end());
2624 for (
const QString &k :
std::as_const(ksList)) {
2625 if (!visitor(PathEls::Key(k), [&
self,
this, k]() {
return key(
self, k); }))
2631const QSet<QString> Map::keys(
const DomItem &self)
const
2633 return m_keys(
self);
2642 const DomItem &self,
const Sink &
sink,
int indent,
2643 function_ref<
bool(
const DomItem &,
const PathEls::PathComponent &,
const DomItem &)>
filter)
const
2648 case DomKind::Object:
2649 sink(u
"{ \"~type~\":");
2653 case DomKind::Value:
2658 else if (
v.isBool())
2663 else if (
v.isDouble())
2664 if (
value().isInteger())
2673 case DomKind::Empty:
2682 case DomKind::ScriptElement:
2689 case DomKind::Object:
2693 case DomKind::Value:
2695 case DomKind::Empty:
2705 case DomKind::ScriptElement:
2711 self.iterateDirectSubpaths(
2712 [&comma, &idx, dK,
sink, indent, &self,
filter](
const PathEls::PathComponent &
c,
2713 function_ref<
DomItem()> itemF) {
2722 case Path::Kind::Field:
2724 if (dK != DomKind::Object)
2725 sink(u
"UNEXPECTED ENTRY ERROR:");
2729 case Path::Kind::Key:
2731 if (dK != DomKind::Map)
2732 sink(u
"UNEXPECTED ENTRY ERROR:");
2736 case Path::Kind::Index:
2738 if (dK != DomKind::List)
2739 sink(u
"UNEXPECTED ENTRY ERROR:");
2740 else if (idx++ !=
c.index())
2741 sink(u
"OUT OF ORDER ARRAY:");
2745 sink(u
"UNEXPECTED PATH KIND ERROR (ignored)");
2748 if (
self.isCanonicalChild(
i)) {
2751 sink(uR
"({ "~type~": "Reference", "immediate": true, "referredObjectPath":")");
2761List::List(
const Path &pathFromOwner,
const List::LookupFunction &lookup,
2762 const List::Length &
length,
const List::IteratorFunction &iterator,
2764 DomElement(pathFromOwner), m_lookup(lookup), m_length(
length), m_iterator(
iterator),
2774 const DomItem &self,
const Sink &
sink,
int indent,
2775 function_ref<
bool(
const DomItem &,
const PathEls::PathComponent &,
const DomItem &)>
filter)
const
2779 iterateDirectSubpaths(
2782 function_ref<
DomItem()> itemF) {
2797bool List::iterateDirectSubpaths(
const DomItem &self, DirectVisitor visitor)
const
2800 return m_iterator(self, [visitor](index_type
i, function_ref<
DomItem()> itemF) {
2801 return visitor(PathEls::Index(
i), itemF);
2805 for (index_type
i = 0;
i <
len; ++
i) {
2806 if (!visitor(PathEls::Index(
i), [
this, &self,
i]() {
return index(self,
i); }))
2814 return m_length(self);
2819 return m_lookup(self,
index);
2822void List::writeOut(
const DomItem &self, OutWriter &ow,
bool compact)
const
2824 ow.writeRegion(LeftBracketRegion);
2825 int baseIndent = ow.increaseIndent(1);
2827 iterateDirectSubpaths(
2829 [&ow, &
first, compact](
const PathEls::PathComponent &, function_ref<
DomItem()> elF) {
2833 ow.write(u
", ", LineWriter::TextAddType::Extra);
2835 ow.ensureNewline(1);
2840 if (!compact && !
first)
2842 ow.decreaseIndent(1, baseIndent);
2843 ow.writeRegion(RightBracketRegion);
2846DomElement::DomElement(
const Path &pathFromOwner) : m_pathFromOwner(pathFromOwner) { }
2848Path DomElement::pathFromOwner(
const DomItem &)
const
2850 Q_ASSERT(m_pathFromOwner &&
"uninitialized DomElement");
2851 return m_pathFromOwner;
2854Path DomElement::canonicalPath(
const DomItem &self)
const
2856 Q_ASSERT(m_pathFromOwner &&
"uninitialized DomElement");
2857 return self.owner().canonicalPath().path(m_pathFromOwner);
2862 Q_ASSERT(m_pathFromOwner &&
"uninitialized DomElement");
2863 return DomBase::containingObject(self);
2866void DomElement::updatePathFromOwner(
const Path &newPath)
2869 m_pathFromOwner = newPath;
2872bool Reference::shouldCache()
const
2874 for (
const Path &
p : referredObjectPath) {
2875 switch (
p.headKind()) {
2876 case Path::Kind::Current:
2877 switch (
p.headCurrent()) {
2878 case PathCurrent::Lookup:
2879 case PathCurrent::LookupDynamic:
2880 case PathCurrent::LookupStrict:
2881 case PathCurrent::ObjChain:
2882 case PathCurrent::ScopeChain:
2888 case Path::Kind::Empty:
2889 case Path::Kind::Any:
2890 case Path::Kind::Filter:
2899Reference::Reference(
const Path &referredObject,
const Path &pathFromOwner,
const SourceLocation &)
2900 : DomElement(pathFromOwner), referredObjectPath(referredObject)
2909bool Reference::iterateDirectSubpaths(
const DomItem &self, DirectVisitor visitor)
const
2912 cont = cont &&
self.dvValueLazyField(visitor, Fields::referredObjectPath, [
this]() {
2913 return referredObjectPath.toString();
2916 &&
self.dvItemField(visitor, Fields::get, [
this, &self]() {
return this->
get(self); });
2922 if (Fields::referredObjectPath ==
name)
2923 return self.subDataItemField(Fields::referredObjectPath, referredObjectPath.toString());
2924 if (Fields::get ==
name)
2929QList<QString> Reference::fields(
const DomItem &)
const
2944DomItem Reference::get(
const DomItem &self,
const ErrorHandler &
h, QList<Path> *visitedRefs)
const
2947 if (referredObjectPath) {
2951 if (shouldCache()) {
2952 env =
self.environment();
2954 selfPath =
self.canonicalPath();
2955 RefCacheEntry cached = RefCacheEntry::forPath(self, selfPath);
2956 switch (cached.cached) {
2957 case RefCacheEntry::Cached::None:
2959 case RefCacheEntry::Cached::First:
2960 case RefCacheEntry::Cached::All:
2961 if (!cached.canonicalPaths.isEmpty())
2962 cachedPath = cached.canonicalPaths.first();
2968 res = env.path(cachedPath);
2970 qCWarning(refLog) <<
"referenceCache outdated, reference at " << selfPath
2971 <<
" leads to invalid path " << cachedPath;
2977 QList<Path> visitedRefsLocal;
2984 h, ResolveOption::None, referredObjectPath,
2985 (visitedRefs ? visitedRefs : &visitedRefsLocal));
2987 RefCacheEntry::addForPath(
2988 env, selfPath, RefCacheEntry { RefCacheEntry::Cached::First, { cachedPath } });
2993QList<DomItem> Reference::getAll(
2994 const DomItem &self,
const ErrorHandler &
h, QList<Path> *visitedRefs)
const
2997 if (referredObjectPath) {
3000 QList<Path> cachedPaths;
3001 if (shouldCache()) {
3003 env =
self.environment();
3004 RefCacheEntry cached = RefCacheEntry::forPath(env, selfPath);
3005 switch (cached.cached) {
3006 case RefCacheEntry::Cached::None:
3007 case RefCacheEntry::Cached::First:
3009 case RefCacheEntry::Cached::All:
3010 cachedPaths += cached.canonicalPaths;
3011 if (cachedPaths.isEmpty())
3015 if (!cachedPaths.isEmpty()) {
3016 bool outdated =
false;
3017 for (
const Path &
p : cachedPaths) {
3021 qCWarning(refLog) <<
"referenceCache outdated, reference at " << selfPath
3022 <<
" leads to invalid path " <<
p;
3040 h, ResolveOption::None, referredObjectPath, visitedRefs);
3042 QList<Path> canonicalPaths;
3045 canonicalPaths.append(
i.canonicalPath());
3048 <<
"getAll of reference at " << selfPath <<
" visits empty items.";
3050 RefCacheEntry::addForPath(
3052 RefCacheEntry { RefCacheEntry::Cached::All, std::move(canonicalPaths) });
3075OwningItem::OwningItem(
int derivedFrom)
3076 : m_derivedFrom(derivedFrom),
3077 m_revision(nextRevision()),
3078 m_createdAt(
QDateTime::currentDateTimeUtc()),
3079 m_lastDataUpdateAt(m_createdAt),
3083OwningItem::OwningItem(
int derivedFrom,
const QDateTime &lastDataUpdateAt)
3084 : m_derivedFrom(derivedFrom),
3085 m_revision(nextRevision()),
3086 m_createdAt(
QDateTime::currentDateTimeUtc()),
3087 m_lastDataUpdateAt(lastDataUpdateAt),
3091OwningItem::OwningItem(
const OwningItem &
o)
3092 : m_derivedFrom(
o.revision()),
3093 m_revision(nextRevision()),
3094 m_createdAt(
QDateTime::currentDateTimeUtc()),
3095 m_lastDataUpdateAt(
o.lastDataUpdateAt()),
3098 QMultiMap<Path, ErrorMessage> my_errors;
3101 my_errors =
o.m_errors;
3106 m_errors = my_errors;
3111int OwningItem::nextRevision()
3117bool OwningItem::iterateDirectSubpaths(
const DomItem &self, DirectVisitor visitor)
const
3120 cont = cont &&
self.dvItemField(visitor, Fields::errors, [&self,
this]() {
3121 QMultiMap<Path, ErrorMessage> myErrors = localErrors();
3123 self.pathFromOwner().field(Fields::errors),
3125 auto it = myErrors.find(Path::fromString(key));
3126 if (it != myErrors.end())
3127 return map.subDataItem(PathEls::Key(key), it->toCbor(),
3128 ConstantData::Options::FirstMapIsFields);
3134 auto it = myErrors.keyBegin();
3135 auto end = myErrors.keyEnd();
3137 res.insert(it++->toString());
3148 if (
s.pathFromSource) {
3149 if (!
s.pathToSource)
3151 return self.path(
s.pathToSource);
3156int OwningItem::derivedFrom()
const
3158 return m_derivedFrom;
3161int OwningItem::revision()
const
3166bool OwningItem::frozen()
const
3168 return m_frozenAt > m_createdAt;
3171bool OwningItem::freeze()
3175 if (m_frozenAt <= m_createdAt)
3176 m_frozenAt = m_createdAt.addSecs(1);
3187QDateTime OwningItem::lastDataUpdateAt()
const
3189 return m_lastDataUpdateAt;
3197void OwningItem::refreshedDataAt(
QDateTime tNew)
3199 if (m_lastDataUpdateAt < tNew)
3200 m_lastDataUpdateAt = tNew;
3205 addErrorLocal(std::move(msg));
3214 m_errors.insert(msg.path, msg);
3217void OwningItem::clearErrors(
const ErrorGroups &
groups)
3221 while (
it != m_errors.
end()) {
3229bool OwningItem::iterateErrors(
3233 QMultiMap<Path, ErrorMessage> myErrors;
3236 myErrors = m_errors;
3238 auto it = myErrors.lowerBound(inPath);
3239 auto end = myErrors.end();
3240 while (
it !=
end &&
it.key().mid(0, inPath.length()) == inPath) {
3241 if (!visitor(self, *
it++))
3247bool OwningItem::iterateSubOwners(
const DomItem &self, function_ref<
bool(
const DomItem &owner)> visitor)
3249 return self.iterateDirectSubpaths(
3250 [&self, visitor](
const PathEls::PathComponent &, function_ref<
DomItem()> iF) {
3252 if (
i.owningItemPtr() !=
self.owningItemPtr()) {
3254 if (container.id() ==
self.id())
3263 if (o1.m_kind != o2.m_kind)
3265 return o1.visitEl([&o1, &o2](
auto &&el1) {
3266 auto &&el2 = std::get<std::decay_t<
decltype(el1)>>(o2.m_element);
3267 auto id1 = el1->id();
3268 auto id2 = el2->id();
3273 if (o1.m_owner != o2.m_owner)
3275 Path
p1 = el1->pathFromOwner(o1);
3276 Path
p2 = el2->pathFromOwner(o2);
3285 MutableDomItem
self;
3289MutableDomItem MutableDomItem::addPrototypePath(
const Path &prototypePath)
3291 if (QmlObject *
el = mutableAs<QmlObject>()) {
3292 return path(
el->addPrototypePath(prototypePath));
3294 Q_ASSERT(
false &&
"setPrototypePath on non qml scope");
3299MutableDomItem MutableDomItem::setNextScopePath(
const Path &nextScopePath)
3301 if (QmlObject *
el = mutableAs<QmlObject>()) {
3302 el->setNextScopePath(nextScopePath);
3303 return field(Fields::nextScope);
3305 Q_ASSERT(
false &&
"setNextScopePath on non qml scope");
3310MutableDomItem MutableDomItem::setPropertyDefs(QMultiMap<QString, PropertyDefinition> propertyDefs)
3312 if (QmlObject *
el = mutableAs<QmlObject>()) {
3313 el->setPropertyDefs(propertyDefs);
3314 return field(Fields::propertyDefs);
3316 Q_ASSERT(
false &&
"setPropertyDefs on non qml scope");
3321MutableDomItem MutableDomItem::setBindings(QMultiMap<QString, Binding> bindings)
3323 if (QmlObject *
el = mutableAs<QmlObject>()) {
3324 el->setBindings(bindings);
3325 return field(Fields::bindings);
3327 Q_ASSERT(
false &&
"setBindings on non qml scope");
3332MutableDomItem MutableDomItem::setMethods(QMultiMap<QString, MethodInfo> functionDefs)
3334 if (QmlObject *
el = mutableAs<QmlObject>())
3335 el->setMethods(functionDefs);
3337 Q_ASSERT(
false &&
"setMethods on non qml scope");
3341MutableDomItem MutableDomItem::setChildren(
const QList<QmlObject> &children)
3343 if (QmlObject *
el = mutableAs<QmlObject>()) {
3344 el->setChildren(children);
3345 return field(Fields::children);
3347 Q_ASSERT(
false &&
"setChildren on non qml scope");
3351MutableDomItem MutableDomItem::setAnnotations(
const QList<QmlObject> &annotations)
3353 if (QmlObject *
el = mutableAs<QmlObject>())
3354 el->setAnnotations(annotations);
3355 else if (
Binding *
el = mutableAs<Binding>()) {
3356 el->setAnnotations(annotations);
3357 el->updatePathFromOwner(pathFromOwner());
3358 }
else if (PropertyDefinition *
el = mutableAs<PropertyDefinition>()) {
3359 el->annotations = annotations;
3360 el->updatePathFromOwner(pathFromOwner());
3361 }
else if (MethodInfo *
el = mutableAs<MethodInfo>()) {
3362 el->annotations = annotations;
3363 el->updatePathFromOwner(pathFromOwner());
3364 }
else if (EnumDecl *
el = mutableAs<EnumDecl>()) {
3365 el->setAnnotations(annotations);
3366 el->updatePathFromOwner(pathFromOwner());
3367 }
else if (!annotations.isEmpty()) {
3368 Q_ASSERT(
false &&
"setAnnotations on element not supporting them");
3370 return field(Fields::annotations);
3372MutableDomItem MutableDomItem::setScript(
const std::shared_ptr<ScriptExpression> &exp)
3374 switch (internalKind()) {
3375 case DomType::Binding:
3376 if (
Binding *
b = mutableAs<Binding>()) {
3377 b->setValue(std::make_unique<BindingValue>(exp));
3378 return field(Fields::value);
3381 case DomType::MethodInfo:
3382 if (MethodInfo *
m = mutableAs<MethodInfo>()) {
3384 return field(Fields::body);
3387 case DomType::MethodParameter:
3388 if (MethodParameter *
p = mutableAs<MethodParameter>()) {
3389 if (exp->expressionType() == ScriptExpression::ExpressionType::ArgInitializer) {
3390 p->defaultValue = exp;
3391 return field(Fields::defaultValue);
3393 if (exp->expressionType() == ScriptExpression::ExpressionType::ArgumentStructure) {
3395 return field(Fields::value);
3399 case DomType::ScriptExpression:
3400 return container().setScript(exp);
3402 qCWarning(domLog) <<
"setScript called on" << internalKindStr();
3404 "setScript supported only on Binding, MethodInfo, MethodParameter, and "
3405 "ScriptExpression contained in them");
3407 return MutableDomItem();
3410MutableDomItem MutableDomItem::setCode(
const QString &code)
3413 switch (
it.internalKind()) {
3414 case DomType::Binding:
3415 if (
Binding *
b = mutableAs<Binding>()) {
3416 auto exp = std::make_shared<ScriptExpression>(
3417 code, ScriptExpression::ExpressionType::BindingExpression);
3418 b->setValue(std::make_unique<BindingValue>(exp));
3419 return field(Fields::value);
3422 case DomType::MethodInfo:
3423 if (MethodInfo *
m = mutableAs<MethodInfo>()) {
3426 m->body = std::make_shared<ScriptExpression>(
3427 code, ScriptExpression::ExpressionType::FunctionBody, 0, pre,
post);
3428 return field(Fields::body);
3431 case DomType::MethodParameter:
3432 if (MethodParameter *
p = mutableAs<MethodParameter>()) {
3433 p->defaultValue = std::make_shared<ScriptExpression>(
3434 code, ScriptExpression::ExpressionType::ArgInitializer);
3435 return field(Fields::defaultValue);
3438 case DomType::ScriptExpression:
3439 if (std::shared_ptr<ScriptExpression> exp = ownerAs<ScriptExpression>()) {
3440 std::shared_ptr<ScriptExpression> newExp = exp->copyWithUpdatedCode(
it, code);
3441 return container().setScript(newExp);
3445 qCWarning(domLog) <<
"setCode called on" << internalKindStr();
3448 "setCode supported only on Binding, MethodInfo, MethodParameter, ScriptExpression");
3450 return MutableDomItem();
3453MutableDomItem MutableDomItem::addPropertyDef(
3454 const PropertyDefinition &propertyDef, AddOption
option)
3456 if (QmlObject *
el = mutableAs<QmlObject>())
3457 return el->addPropertyDef(*
this, propertyDef,
option);
3459 Q_ASSERT(
false &&
"addPropertyDef on non qml scope");
3460 return MutableDomItem();
3463MutableDomItem MutableDomItem::addBinding(
Binding binding, AddOption
option)
3465 if (QmlObject *
el = mutableAs<QmlObject>())
3466 return el->addBinding(*
this, binding,
option);
3468 Q_ASSERT(
false &&
"addBinding on non qml scope");
3469 return MutableDomItem();
3472MutableDomItem MutableDomItem::addMethod(
const MethodInfo &functionDef, AddOption
option)
3474 if (QmlObject *
el = mutableAs<QmlObject>())
3475 return el->addMethod(*
this, functionDef,
option);
3477 Q_ASSERT(
false &&
"addMethod on non qml scope");
3478 return MutableDomItem();
3481MutableDomItem MutableDomItem::addChild(QmlObject
child)
3483 if (QmlObject *
el = mutableAs<QmlObject>()) {
3484 return el->addChild(*
this,
child);
3485 }
else if (QmlComponent *
el = mutableAs<QmlComponent>()) {
3487 return owner().path(
p);
3489 Q_ASSERT(
false &&
"addChild on non qml scope");
3491 return MutableDomItem();
3494MutableDomItem MutableDomItem::addAnnotation(QmlObject annotation)
3497 switch (internalKind()) {
3498 case DomType::QmlObject: {
3500 res =
el->addAnnotation(annotation);
3502 case DomType::Binding: {
3505 res =
el->addAnnotation(m_pathFromOwner, annotation);
3507 case DomType::PropertyDefinition: {
3509 res =
el->addAnnotation(m_pathFromOwner, annotation);
3511 case DomType::MethodInfo: {
3513 res =
el->addAnnotation(m_pathFromOwner, annotation);
3516 Id *
el = mutableAs<Id>();
3517 res =
el->addAnnotation(m_pathFromOwner, annotation);
3520 Q_ASSERT(
false &&
"addAnnotation on element not supporting them");
3522 return MutableDomItem(owner().
item(),
res);
3525MutableDomItem MutableDomItem::addPreComment(
const Comment &comment, FileLocationRegion region)
3528 MutableDomItem rC = field(Fields::comments);
3529 if (
auto rcPtr = rC.mutableAs<RegionComments>()) {
3530 auto commentedElement = rcPtr->regionComments()[region];
3531 idx = commentedElement.preComments().size();
3532 commentedElement.addComment(comment);
3533 MutableDomItem
res =
path(Path::Field(Fields::comments)
3534 .field(Fields::regionComments)
3536 .field(Fields::preComments)
3541 return MutableDomItem();
3544MutableDomItem MutableDomItem::addPostComment(
const Comment &comment, FileLocationRegion region)
3547 MutableDomItem rC = field(Fields::comments);
3548 if (
auto rcPtr = rC.mutableAs<RegionComments>()) {
3549 auto commentedElement = rcPtr->regionComments()[region];
3550 idx = commentedElement.postComments().size();
3551 commentedElement.addComment(comment);
3552 MutableDomItem
res =
path(Path::Field(Fields::comments)
3553 .field(Fields::regionComments)
3555 .field(Fields::postComments)
3560 return MutableDomItem();
3571 MutableDomItem cc(
c);
3573 <<
", " << cc.canonicalPath().toString() <<
")";
3576bool ListPBase::iterateDirectSubpaths(
const DomItem &self, DirectVisitor
v)
const
3579 for (index_type
i = 0;
i <
len; ++
i) {
3580 if (!
v(PathEls::Index(
i), [
this, &self,
i] {
return this->
index(self,
i); }))
3586void ListPBase::writeOut(
const DomItem &self, OutWriter &ow,
bool compact)
const
3588 ow.writeRegion(LeftBracketRegion);
3589 int baseIndent = ow.increaseIndent(1);
3592 for (index_type
i = 0;
i <
len; ++
i) {
3596 ow.write(u
", ", LineWriter::TextAddType::Extra);
3598 ow.ensureNewline(1);
3602 if (!compact && !
first)
3604 ow.decreaseIndent(1, baseIndent);
3605 ow.writeRegion(RightBracketRegion);
3623ScriptElement::PointerType<ScriptElement> ScriptElementVariant::base()
const
3631 return std::shared_ptr<ScriptElement>(
3642#include "moc_qqmldomitem_p.cpp"
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
static QDateTime fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone)
static QDateTime currentDateTimeUtc()
static QString tempPath()
Returns the absolute canonical path of the system's temporary directory.
QString filePath(const QString &fileName) const
Returns the path name of a file in the directory.
QString baseName() const
Returns the base name of the file without the path.
QString canonicalFilePath() const
Returns the file system entry's canonical path, including the entry's name, that is,...
static QJsonDocument fromVariant(const QVariant &variant)
Creates a QJsonDocument from the QVariant variant.
\inmodule QtCore\reentrant
const_iterator cend() const
const_iterator cbegin() const
ConstantData(const Path &pathFromOwner, const QCborValue &value, Options options=Options::MapIsMap)
virtual DomType kind() const =0
virtual void writeOut(const DomItem &self, OutWriter &lw) const
virtual DomItem containingObject(const DomItem &self) const
virtual QString canonicalFilePath(const DomItem &self) const
DomItem fileLocations() const
DomItem fileLocationsTree() const
bool visitKeys(function_ref< bool(const QString &, const DomItem &)> visitor) const
static ErrorGroup domErrorGroup
bool isCanonicalChild(const DomItem &child) const
QSet< QString > propertyInfoNames() const
QSet< QString > keys() const
bool visitLookup1(const QString &symbolName, function_ref< bool(const DomItem &)> visitor, LookupOptions=LookupOption::Normal, const ErrorHandler &h=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
static ErrorGroups myResolveErrors()
static ErrorGroups myErrors()
DomItem fileObject(GoTo option=GoTo::Strict) const
DomItem environment() const
DomItem directParent() const
bool commitToBase(const std::shared_ptr< DomEnvironment > &validPtr=nullptr) const
DomItem container() const
index_type indexes() const
DomItem field(QStringView name) const
Path pathFromOwner() const
QDateTime createdAt() const
QStringList sortedKeys() const
bool visitIndexes(function_ref< bool(const DomItem &)> visitor) const
bool visitPrototypeChain(function_ref< bool(const DomItem &)> visitor, VisitPrototypesOptions options=VisitPrototypesOption::Normal, const ErrorHandler &h=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
bool visitDirectAccessibleScopes(function_ref< bool(const DomItem &)> visitor, VisitPrototypesOptions options=VisitPrototypesOption::Normal, const ErrorHandler &h=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
DomItem containingObject() const
bool writeOutForFile(OutWriter &ow, WriteOutChecks extraChecks) const
bool visitLookup(const QString &symbolName, function_ref< bool(const DomItem &)> visitor, LookupType type=LookupType::Symbol, LookupOptions=LookupOption::Normal, const ErrorHandler &errorHandler=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
DomItem rootQmlObject(GoTo option=GoTo::Strict) const
DomItem get(const ErrorHandler &h=nullptr, QList< Path > *visitedRefs=nullptr) const
void addError(ErrorMessage &&msg) const
DomItem path(const Path &p, const ErrorHandler &h=&defaultErrorHandler) const
std::shared_ptr< OwningItem > owningItemPtr() const
function_ref< bool(const Path &, const DomItem &)> Visitor
bool iterateDirectSubpaths(DirectVisitor v) const
std::shared_ptr< DomTop > topPtr() const
DomItem lookupFirst(const QString &symbolName, LookupType type=LookupType::Symbol, LookupOptions=LookupOption::Normal, const ErrorHandler &errorHandler=nullptr) const
DomItem operator[](const Path &path) const
DomItem filterUp(function_ref< bool(DomType k, const DomItem &)> filter, FilterUpOptions options) const
DomItem subReferenceItem(const PathEls::PathComponent &c, const Path &referencedObject) const
DomItem containingScriptExpression() const
void clearErrors(const ErrorGroups &groups=ErrorGroups({}), bool iterate=true) const
QQmlJSScope::ConstPtr nearestSemanticScope() const
MutableDomItem makeCopy(CopyOption option=CopyOption::EnvConnected) const
bool visitScopeChain(function_ref< bool(const DomItem &)> visitor, LookupOptions=LookupOption::Normal, const ErrorHandler &h=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
DomItem scope(FilterUpOptions options=FilterUpOptions::ReturnOuter) const
QDateTime lastDataUpdateAt() const
bool visitStaticTypePrototypeChains(function_ref< bool(const DomItem &)> visitor, VisitPrototypesOptions options=VisitPrototypesOption::Normal, const ErrorHandler &h=nullptr, QSet< quintptr > *visited=nullptr, QList< Path > *visitedRefs=nullptr) const
DomItem globalScope() const
QString canonicalFilePath() const
bool visitTree(const Path &basePath, ChildrenVisitor visitor, VisitOptions options=VisitOption::Default, ChildrenVisitor openingVisitor=emptyChildrenVisitor, ChildrenVisitor closingVisitor=emptyChildrenVisitor, const FieldFilter &filter=FieldFilter::noFilter()) const
bool resolve(const Path &path, Visitor visitor, const ErrorHandler &errorHandler, ResolveOptions options=ResolveOption::None, const Path &fullPath=Path(), QList< Path > *visitedRefs=nullptr) const
bool iterateSubOwners(function_ref< bool(const DomItem &owner)> visitor) const
QDateTime frozenAt() const
QList< DomItem > getAll(const ErrorHandler &h=nullptr, QList< Path > *visitedRefs=nullptr) const
DomItem proceedToScope(const ErrorHandler &h=nullptr, QList< Path > *visitedRefs=nullptr) const
QList< DomItem > values() const
ErrorHandler errorHandler() const
DomItem index(index_type) const
Path canonicalPath() const
bool hasAnnotations() const
void writeOut(OutWriter &lw) const
bool visitUp(function_ref< bool(const DomItem &)> visitor) const
QList< DomItem > lookup(const QString &symbolName, LookupType type=LookupType::Symbol, LookupOptions=LookupOption::Normal, const ErrorHandler &errorHandler=nullptr) const
static DomItem fromCode(const QString &code, DomType fileType=DomType::QmlFile)
DomItem containingFile() const
void dump(const Sink &, int indent=0, function_ref< bool(const DomItem &, const PathEls::PathComponent &, const DomItem &)> filter=noFilter) const
function_ref< bool(const Path &, const DomItem &, bool)> ChildrenVisitor
QList< QString > fields() const
DomItem goToFile(const QString &filePath) const
DomItem component(GoTo option=GoTo::Strict) const
void writeOutPost(OutWriter &lw) const
void writeOutPre(OutWriter &lw) const
bool iterateErrors(function_ref< bool(const DomItem &, const ErrorMessage &)> visitor, bool iterate, Path inPath=Path()) const
PropertyInfo propertyInfoWithName(const QString &name) const
bool visitLocalSymbolsNamed(const QString &name, function_ref< bool(const DomItem &)> visitor) const
DomItem subReferencesItem(const PathEls::PathComponent &c, const QList< Path > &paths) const
void dumpPtr(const Sink &sink) const
DomItem qmlObject(GoTo option=GoTo::Strict, FilterUpOptions options=FilterUpOptions::ReturnOuter) const
DomItem key(const QString &name) const
QQmlJSScope::ConstPtr semanticScope() const
Class that represent a filter on DomItem, when dumping or comparing.
\inmodule QtCore \reentrant
\inmodule QtCore \reentrant
static QString anchoredPattern(const QString &expression)
iterator erase(const_iterator i)
const_iterator cbegin() const noexcept
\macro QT_RESTRICTED_CAST_FROM_ASCII
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
static QString fromUtf16(const char16_t *, qsizetype size=-1)
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
void clear()
Clears the contents of the string and makes it null.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString & append(QChar c)
QMap< QString, QString > map
[6]
list append(new Employee("Blackpool", "Stephen"))
QSet< QString >::iterator it
typename C::iterator iterator
constexpr bool domTypeIsOwningItem(DomType)
void sinkEscaped(const Sink &sink, QStringView s, EscapeOptions options)
dumps a string as quoted string (escaping things like quotes or newlines)
QMLDOM_EXPORT QString domTypeToString(DomType k)
void defaultErrorHandler(const ErrorMessage &error)
Calls the default error handler (by default errorToQDebug)
QMLDOM_EXPORT bool domTypeIsScope(DomType k)
QMLDOM_EXPORT bool domTypeIsExternalItem(DomType k)
void sinkNewline(const Sink &s, int indent)
sinks a neline and indents by the given amount
QString fileLocationRegionName(FileLocationRegion region)
QString dumperToString(const Dumper &writer)
Converts a dumper to a string.
QStringList domCompareStrList(const DomItem &i1, const DomItem &i2, function_ref< bool(const DomItem &, const PathEls::PathComponent &, const DomItem &) const > filter, DomCompareStrList stopAtFirstDiff)
QMLDOM_EXPORT QMap< DomType, QString > domTypeToStringMap()
void dumperToQDebug(const Dumper &dumper, QDebug debug)
function_ref< void(QStringView)> Sink
QMLDOM_EXPORT bool domTypeIsTopItem(DomType k)
std::function< void(const ErrorMessage &)> ErrorHandler
QString lineDiff(QString s1, QString s2, int nContext)
QMLDOM_EXPORT QString domKindToString(DomKind k)
QMLDOM_EXPORT bool domTypeIsContainer(DomType k)
QMLDOM_EXPORT QMap< DomKind, QString > domKindToStringMap()
Combined button and popup list for selecting options.
static jboolean copy(JNIEnv *, jobject)
SharedPointerFileDialogOptions m_options
QList< QString > QStringList
Constructs a string list that contains the given string, str.
#define Q_DECLARE_TR_FUNCTIONS(context)
static QDBusError::ErrorType get(const char *name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
static bool contains(const QJsonArray &haystack, unsigned needle)
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLuint64 GLenum void * handle
GLint GLint GLint GLint GLint x
[0]
GLsizei GLenum GLenum * types
GLenum GLuint GLenum GLsizei length
GLdouble GLdouble GLdouble GLdouble top
GLsizei const GLuint * paths
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLfloat GLfloat GLfloat GLfloat h
GLsizei const GLchar *const * path
GLsizei GLenum GLboolean sink
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
static qreal component(const QPointF &point, unsigned int i)
#define NewErrorGroup(name)
static bool fromString(const QMetaObject *mo, QString s, Allocate &&allocate)
static const QQmlJSScope * resolve(const QQmlJSScope *current, const QStringList &names)
QQmlJS::Dom::DomItem DomItem
bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
#define Q_ASSERT_X(cond, x, msg)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
static QString dump(const QByteArray &)
SSL_CTX int void DUMMYARG SSL const unsigned char * protos
static QString canonicalPath(const QString &rootPath)
QLatin1StringView QLatin1String
static FileType fileType(const QFileInfo &fi)
static int compare(quint64 a, quint64 b)
QList< std::pair< QString, QString > > Map
static double UTC(double t, double localTZA)
manager post(request, myJson, this, [this](QRestReply &reply) { if(!reply.isSuccess()) { } if(std::optional json=reply.readJson()) { } })
char * toString(const MyType &t)
[31]
\inmodule QtCore \reentrant